@@ -139,6 +139,12 @@ module fpm_compiler
139139 procedure :: check_flags_supported
140140 procedure :: with_xdp
141141 procedure :: with_qp
142+ ! > C feature support
143+ procedure :: check_c_source_runs
144+ procedure :: check_c_flags_supported
145+ ! > C++ feature support
146+ procedure :: check_cxx_source_runs
147+ procedure :: check_cxx_flags_supported
142148 ! > Return compiler name
143149 procedure :: name = > compiler_name
144150
@@ -1817,6 +1823,146 @@ logical function check_fortran_source_runs(self, input, compile_flags, link_flag
18171823
18181824end function check_fortran_source_runs
18191825
1826+ ! > Check if the given C source code compiles, links, and runs successfully
1827+ logical function check_c_source_runs (self , input , compile_flags , link_flags ) result(success)
1828+ ! > Instance of the compiler object
1829+ class(compiler_t), intent (in ) :: self
1830+ ! > C program source
1831+ character (len=* ), intent (in ) :: input
1832+ ! > Optional build and link flags
1833+ character (len=* ), optional , intent (in ) :: compile_flags, link_flags
1834+ integer :: stat,unit
1835+ character (:), allocatable :: source,object,logf,exe,flags,ldflags
1836+
1837+ success = .false.
1838+
1839+ ! > Create temporary source file
1840+ exe = get_temp_filename()
1841+ source = exe// ' .c'
1842+ object = exe// ' .o'
1843+ logf = exe// ' .log'
1844+
1845+ open (newunit= unit, file= source, action= ' readwrite' , iostat= stat)
1846+ if (stat/= 0 ) return
1847+
1848+ ! > Write contents
1849+ write (unit,' (a)' ) input
1850+ close (unit)
1851+
1852+ ! > Get flags
1853+ flags = " "
1854+ ldflags = " "
1855+ if (present (compile_flags)) flags = flags// " " // compile_flags
1856+ if (present (link_flags)) ldflags = ldflags// " " // link_flags
1857+
1858+ ! > Compile
1859+ call self% compile_c(source,object,flags,logf,stat,dry_run= .false. )
1860+ if (stat/= 0 ) return
1861+
1862+ ! > Link using C compiler for pure C programs
1863+ call run(self% cc// " " // ldflags// " " // object// " -o " // exe, &
1864+ echo= self% echo, verbose= self% verbose, redirect= logf, exitstat= stat)
1865+ if (stat/= 0 ) return
1866+
1867+ ! > Run
1868+ call run(exe// " > " // logf// " 2>&1" ,echo= .false. ,exitstat= stat)
1869+ success = (stat == 0 )
1870+
1871+ ! > Delete temporary files
1872+ open (newunit= unit, file= source, action= ' readwrite' , iostat= stat)
1873+ close (unit,status= ' delete' )
1874+ open (newunit= unit, file= object, action= ' readwrite' , iostat= stat)
1875+ close (unit,status= ' delete' )
1876+ open (newunit= unit, file= logf, action= ' readwrite' , iostat= stat)
1877+ close (unit,status= ' delete' )
1878+ open (newunit= unit, file= exe, action= ' readwrite' , iostat= stat)
1879+ close (unit,status= ' delete' )
1880+
1881+ end function check_c_source_runs
1882+
1883+ ! > Check if the given C++ source code compiles, links, and runs successfully
1884+ logical function check_cxx_source_runs (self , input , compile_flags , link_flags ) result(success)
1885+ ! > Instance of the compiler object
1886+ class(compiler_t), intent (in ) :: self
1887+ ! > C++ program source
1888+ character (len=* ), intent (in ) :: input
1889+ ! > Optional build and link flags
1890+ character (len=* ), optional , intent (in ) :: compile_flags, link_flags
1891+ integer :: stat,unit
1892+ character (:), allocatable :: source,object,logf,exe,flags,ldflags
1893+
1894+ success = .false.
1895+
1896+ ! > Create temporary source file
1897+ exe = get_temp_filename()
1898+ source = exe// ' .cpp'
1899+ object = exe// ' .o'
1900+ logf = exe// ' .log'
1901+
1902+ open (newunit= unit, file= source, action= ' readwrite' , iostat= stat)
1903+ if (stat/= 0 ) return
1904+
1905+ ! > Write contents
1906+ write (unit,' (a)' ) input
1907+ close (unit)
1908+
1909+ ! > Get flags
1910+ flags = " "
1911+ ldflags = " "
1912+ if (present (compile_flags)) flags = flags// " " // compile_flags
1913+ if (present (link_flags)) ldflags = ldflags// " " // link_flags
1914+
1915+ ! > Compile
1916+ call self% compile_cpp(source,object,flags,logf,stat,dry_run= .false. )
1917+ if (stat/= 0 ) return
1918+
1919+ ! > Link using C++ compiler for pure C++ programs
1920+ call run(self% cxx// " " // ldflags// " " // object// " -o " // exe, &
1921+ echo= self% echo, verbose= self% verbose, redirect= logf, exitstat= stat)
1922+ if (stat/= 0 ) return
1923+
1924+ ! > Run
1925+ call run(exe// " > " // logf// " 2>&1" ,echo= .false. ,exitstat= stat)
1926+ success = (stat == 0 )
1927+
1928+ ! > Delete temporary files
1929+ open (newunit= unit, file= source, action= ' readwrite' , iostat= stat)
1930+ close (unit,status= ' delete' )
1931+ open (newunit= unit, file= object, action= ' readwrite' , iostat= stat)
1932+ close (unit,status= ' delete' )
1933+ open (newunit= unit, file= logf, action= ' readwrite' , iostat= stat)
1934+ close (unit,status= ' delete' )
1935+ open (newunit= unit, file= exe, action= ' readwrite' , iostat= stat)
1936+ close (unit,status= ' delete' )
1937+
1938+ end function check_cxx_source_runs
1939+
1940+ ! > Check if the given C compile and/or link flags are accepted by the C compiler
1941+ logical function check_c_flags_supported (self , compile_flags , link_flags )
1942+ class(compiler_t), intent (in ) :: self
1943+ character (len=* ), optional , intent (in ) :: compile_flags, link_flags
1944+
1945+ ! Minimal C program that always compiles
1946+ character (len=* ), parameter :: hello_world_c = &
1947+ " #include <stdio.h>" // new_line(' a' ) // &
1948+ " int main() { printf("" Hello, World!"" ); return 0; }"
1949+
1950+ check_c_flags_supported = self% check_c_source_runs(hello_world_c, compile_flags, link_flags)
1951+ end function check_c_flags_supported
1952+
1953+ ! > Check if the given C++ compile and/or link flags are accepted by the C++ compiler
1954+ logical function check_cxx_flags_supported (self , compile_flags , link_flags )
1955+ class(compiler_t), intent (in ) :: self
1956+ character (len=* ), optional , intent (in ) :: compile_flags, link_flags
1957+
1958+ ! Minimal C++ program that always compiles
1959+ character (len=* ), parameter :: hello_world_cxx = &
1960+ " #include <cstdio>" // new_line(' a' ) // &
1961+ " int main() { printf("" Hello, World!"" ); return 0; }"
1962+
1963+ check_cxx_flags_supported = self% check_cxx_source_runs(hello_world_cxx, compile_flags, link_flags)
1964+ end function check_cxx_flags_supported
1965+
18201966! > Check if the given compile and/or link flags are accepted by the compiler
18211967logical function check_flags_supported (self , compile_flags , link_flags )
18221968 class(compiler_t), intent (in ) :: self
0 commit comments