# Distributed under the OSI-approved BSD 3-Clause License. See accompanying # file Copyright.txt or https://cmake.org/licensing for details. cmake_minimum_required(VERSION ${CMAKE_VERSION}) project(FortranCInterface C Fortran) include(${FortranCInterface_BINARY_DIR}/Input.cmake OPTIONAL) # Check if the C compiler supports '$' in identifiers. include(CheckSourceCompiles) check_source_compiles(C "extern int dollar$(void); int main() { return 0; }" C_SUPPORTS_DOLLAR) # List manglings of global symbol names to try. set(global_symbols my_sub # VisualAge my_sub_ # GNU, Intel, HP, SunPro, PGI my_sub__ # GNU g77 MY_SUB # Intel on Windows mysub # VisualAge mysub_ # GNU, Intel, HP, SunPro, PGI MYSUB # Intel on Windows ${FortranCInterface_GLOBAL_SYMBOLS} ) list(REMOVE_DUPLICATES global_symbols) # List manglings of module symbol names to try. set(module_symbols __my_module_MOD_my_sub # GNU 4.3 __my_module_NMOD_my_sub # VisualAge __my_module__my_sub # GNU 4.2 __mymodule_MOD_mysub # GNU 4.3 __mymodule_NMOD_mysub # VisualAge __mymodule__mysub # GNU 4.2 my_module$my_sub # HP my_module_mp_my_sub_ # Intel MY_MODULE_mp_MY_SUB # Intel on Windows my_module_my_sub_ # PGI my_module_MP_my_sub # NAG mymodule$mysub # HP mymodule_mp_mysub_ # Intel MYMODULE_mp_MYSUB # Intel on Windows mymodule_mysub_ # PGI mymodule_MP_mysub # NAG _QMmy_modulePmy_sub # LLVMFlang _QMmymodulePmysub # LLVMFlang ${FortranCInterface_MODULE_SYMBOLS} ) list(REMOVE_DUPLICATES module_symbols) # Note that some compiler manglings cannot be invoked from C: # SunPro uses "my_module.my_sub_" # PathScale uses "MY_SUB.in.MY_MODULE" # Add module symbols only with Fortran90. if(CMAKE_Fortran_COMPILER_SUPPORTS_F90) set(myfort_modules mymodule.f90 my_module.f90) set(call_mod call_mod.f90) set_property(SOURCE main.F PROPERTY COMPILE_DEFINITIONS CALL_MOD) else() set(module_symbols) endif() # Generate C symbol sources. set(symbol_sources) if(NOT CMAKE_Fortran_COMPILER_ID MATCHES "^(PathScale|Cray)$") # Provide mymodule_ and my_module_ init symbols because: # - PGI Fortran uses module init symbols # but not for: # - PathScale Fortran uses module init symbols but module symbols # use '.in.' so we cannot provide them anyway. # - Cray Fortran >= 7.3.2 uses module init symbols but module symbols # use 'mysub$mymodule_' so we cannot provide them anyway. list(APPEND symbol_sources mymodule_.c my_module_.c MY_MODULE.c MYMODULE.c) endif() foreach(symbol IN LISTS global_symbols module_symbols) # Skip symbols with '$' if C cannot handle them. if(C_SUPPORTS_DOLLAR OR NOT "${symbol}" MATCHES "\\$") if("${symbol}" MATCHES "SUB") set(upper "-UPPER") else() set(upper) endif() string(REPLACE "$" "S" name "${symbol}") set(source ${CMAKE_CURRENT_BINARY_DIR}/symbols/${name}${upper}.c) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/symbol.c.in ${source} @ONLY) list(APPEND symbol_sources ${source}) endif() endforeach() # Provide symbols through Fortran. add_library(myfort STATIC mysub.f my_sub.f ${myfort_modules}) # Provide symbols through C but fall back to Fortran. add_library(symbols STATIC ${symbol_sources}) target_link_libraries(symbols PUBLIC myfort) # In case the Fortran compiler produces PIC by default make sure # the C compiler produces PIC even if it is not its default. set_property(TARGET symbols PROPERTY POSITION_INDEPENDENT_CODE 1) # Require symbols through Fortran. add_executable(FortranCInterface main.F call_sub.f ${call_mod}) target_link_libraries(FortranCInterface PUBLIC symbols) # If IPO is enabled here, GCC gfortran >= 12.0 will obfuscate # the strings of the return values in the compiled executable, # which we use to regex match against later. # The static libraries must be build with IPO and non-IPO objects, # as that will ensure the verify step will operate on IPO objects, # if requested by the system compiler flags. if(CMAKE_Fortran_COMPILER_ID STREQUAL "GNU" AND CMAKE_Fortran_COMPILER_VERSION VERSION_GREATER_EQUAL 12) target_compile_options(FortranCInterface PRIVATE "-fno-lto") target_compile_options(myfort PRIVATE "-flto=auto" "-ffat-lto-objects") endif() if(CMAKE_C_COMPILER_ID STREQUAL "GNU" AND CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 12) target_compile_options(symbols PRIVATE "-flto=auto" "-ffat-lto-objects") endif() file(GENERATE OUTPUT exe-$.cmake CONTENT [[ set(FortranCInterface_EXE "$") ]])