@@ -139,6 +139,12 @@ module fpm_compiler
139
139
procedure :: check_flags_supported
140
140
procedure :: with_xdp
141
141
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
142
148
! > Return compiler name
143
149
procedure :: name = > compiler_name
144
150
@@ -1817,6 +1823,146 @@ logical function check_fortran_source_runs(self, input, compile_flags, link_flag
1817
1823
1818
1824
end function check_fortran_source_runs
1819
1825
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
+
1820
1966
! > Check if the given compile and/or link flags are accepted by the compiler
1821
1967
logical function check_flags_supported (self , compile_flags , link_flags )
1822
1968
class(compiler_t), intent (in ) :: self
0 commit comments