diff options
-rw-r--r-- | Modules/FortranCInterface.cmake | 76 | ||||
-rw-r--r-- | Modules/FortranCInterface/Detect.cmake | 4 | ||||
-rw-r--r-- | Modules/FortranCInterface/Verify/CMakeLists.txt | 16 | ||||
-rw-r--r-- | Modules/FortranCInterface/Verify/VerifyC.c | 5 | ||||
-rw-r--r-- | Modules/FortranCInterface/Verify/VerifyCXX.cxx | 4 | ||||
-rw-r--r-- | Modules/FortranCInterface/Verify/VerifyFortran.f | 3 | ||||
-rw-r--r-- | Modules/FortranCInterface/Verify/main.c | 16 | ||||
-rw-r--r-- | Tests/Fortran/CMakeLists.txt | 2 |
8 files changed, 126 insertions, 0 deletions
diff --git a/Modules/FortranCInterface.cmake b/Modules/FortranCInterface.cmake index 126b117..3980c56 100644 --- a/Modules/FortranCInterface.cmake +++ b/Modules/FortranCInterface.cmake @@ -51,6 +51,18 @@ # macros as the previous example plus preprocessor symbols FC_mysub # and FC_mymod_my_sub. # +# Another function is provided to verify that the Fortran and C/C++ +# compilers work together: +# FortranCInterface_VERIFY([CXX] [QUIET]) +# It tests whether a simple test executable using Fortran and C (and +# C++ when the CXX option is given) compiles and links successfully. +# The result is stored in the cache entry FortranCInterface_VERIFIED_C +# (or FortranCInterface_VERIFIED_CXX if CXX is given) as a boolean. +# If the check fails and QUIET is not given the function terminates +# with a FATAL_ERROR message describing the problem. The purpose of +# this check is to stop a build early for incompatible compiler +# combinations. +# # FortranCInterface is aware of possible GLOBAL and MODULE manglings # for many Fortran compilers, but it also provides an interface to # specify new possible manglings. Set the variables @@ -183,3 +195,67 @@ ${_desc_${macro}} # Store the content. configure_file(${FortranCInterface_SOURCE_DIR}/Macro.h.in ${FILE} @ONLY) endfunction() + +function(FortranCInterface_VERIFY) + # Check arguments. + + set(lang C) + set(quiet 0) + set(verify_cxx 0) + foreach(arg ${ARGN}) + if("${arg}" STREQUAL "QUIET") + set(quiet 1) + elseif("${arg}" STREQUAL "CXX") + set(lang CXX) + set(verify_cxx 1) + else() + message(FATAL_ERROR + "FortranCInterface_VERIFY - called with unknown argument:\n ${arg}") + endif() + endforeach() + + if(NOT CMAKE_${lang}_COMPILER_LOADED) + message(FATAL_ERROR + "FortranCInterface_VERIFY(${lang}) requires ${lang} to be enabled.") + endif() + + # Build the verification project if not yet built. + if(NOT DEFINED FortranCInterface_VERIFIED_${lang}) + set(_desc "Verifying Fortran/${lang} Compiler Compatibility") + message(STATUS "${_desc}") + + # Build a sample project which reports symbols. + try_compile(FortranCInterface_VERIFY_${lang}_COMPILED + ${FortranCInterface_BINARY_DIR}/Verify${lang} + ${FortranCInterface_SOURCE_DIR}/Verify + VerifyFortranC + CMAKE_FLAGS -DVERIFY_CXX=${verify_cxx} + OUTPUT_VARIABLE _output) + file(WRITE "${FortranCInterface_BINARY_DIR}/Verify${lang}/output.txt" "${_output}") + + # Report results. + if(FortranCInterface_VERIFY_${lang}_COMPILED) + message(STATUS "${_desc} - Success") + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log + "${_desc} passed with the following output:\n${_output}\n\n") + set(FortranCInterface_VERIFIED_${lang} 1 CACHE INTERNAL "Fortran/${lang} compatibility") + else() + message(STATUS "${_desc} - Failed") + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log + "${_desc} failed with the following output:\n${_output}\n\n") + set(FortranCInterface_VERIFIED_${lang} 0 CACHE INTERNAL "Fortran/${lang} compatibility") + endif() + unset(FortranCInterface_VERIFY_${lang}_COMPILED CACHE) + endif() + + # Error if compilers are incompatible. + if(NOT FortranCInterface_VERIFIED_${lang} AND NOT quiet) + file(READ "${FortranCInterface_BINARY_DIR}/Verify${lang}/output.txt" _output) + string(REGEX REPLACE "\n" "\n " _output "${_output}") + message(FATAL_ERROR + "The Fortran compiler:\n ${CMAKE_Fortran_COMPILER}\n" + "and the ${lang} compiler:\n ${CMAKE_${lang}_COMPILER}\n" + "failed to compile a simple test project using both languages. " + "The output was:\n ${_output}") + endif() +endfunction() diff --git a/Modules/FortranCInterface/Detect.cmake b/Modules/FortranCInterface/Detect.cmake index b848d33..abc012e 100644 --- a/Modules/FortranCInterface/Detect.cmake +++ b/Modules/FortranCInterface/Detect.cmake @@ -17,6 +17,10 @@ else() return() endif() +# Invalidate verification results. +unset(FortranCInterface_VERIFIED_C CACHE) +unset(FortranCInterface_VERIFIED_CXX CACHE) + set(_result) # Build a sample project which reports symbols. diff --git a/Modules/FortranCInterface/Verify/CMakeLists.txt b/Modules/FortranCInterface/Verify/CMakeLists.txt new file mode 100644 index 0000000..69fde2d --- /dev/null +++ b/Modules/FortranCInterface/Verify/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 2.7) +project(VerifyFortranC C Fortran) + +option(VERIFY_CXX "Whether to verify C++ and Fortran" OFF) +if(VERIFY_CXX) + enable_language(CXX) + set(VerifyCXX VerifyCXX.cxx) + add_definitions(-DVERIFY_CXX) +endif() + +include(FortranCInterface) + +FortranCInterface_HEADER(VerifyFortran.h SYMBOLS VerifyFortran) +include_directories(${VerifyFortranC_BINARY_DIR}) + +add_executable(VerifyFortranC main.c VerifyC.c VerifyFortran.f ${VerifyCXX}) diff --git a/Modules/FortranCInterface/Verify/VerifyC.c b/Modules/FortranCInterface/Verify/VerifyC.c new file mode 100644 index 0000000..7f847ef --- /dev/null +++ b/Modules/FortranCInterface/Verify/VerifyC.c @@ -0,0 +1,5 @@ +#include <stdio.h> +void VerifyC(void) +{ + printf("VerifyC\n"); +} diff --git a/Modules/FortranCInterface/Verify/VerifyCXX.cxx b/Modules/FortranCInterface/Verify/VerifyCXX.cxx new file mode 100644 index 0000000..689fac5 --- /dev/null +++ b/Modules/FortranCInterface/Verify/VerifyCXX.cxx @@ -0,0 +1,4 @@ +extern "C" void VerifyCXX(void) +{ + delete new int; +} diff --git a/Modules/FortranCInterface/Verify/VerifyFortran.f b/Modules/FortranCInterface/Verify/VerifyFortran.f new file mode 100644 index 0000000..a17e48d --- /dev/null +++ b/Modules/FortranCInterface/Verify/VerifyFortran.f @@ -0,0 +1,3 @@ + subroutine VerifyFortran + print *, 'VerifyFortran' + end diff --git a/Modules/FortranCInterface/Verify/main.c b/Modules/FortranCInterface/Verify/main.c new file mode 100644 index 0000000..582ef1d --- /dev/null +++ b/Modules/FortranCInterface/Verify/main.c @@ -0,0 +1,16 @@ +extern void VerifyC(void); +#ifdef VERIFY_CXX +extern void VerifyCXX(void); +#endif +#include "VerifyFortran.h" +extern void VerifyFortran(void); + +int main(void) +{ + VerifyC(); +#ifdef VERIFY_CXX + VerifyCXX(); +#endif + VerifyFortran(); + return 0; +} diff --git a/Tests/Fortran/CMakeLists.txt b/Tests/Fortran/CMakeLists.txt index 312b4d7..5f58f77 100644 --- a/Tests/Fortran/CMakeLists.txt +++ b/Tests/Fortran/CMakeLists.txt @@ -14,6 +14,8 @@ function(test_fortran_c_interface_module) message(STATUS "Testing FortranCInterface module") # test the C to Fortran interface module include(FortranCInterface) + FortranCInterface_VERIFY(QUIET) + FortranCInterface_VERIFY(QUIET CXX) if(CMAKE_Fortran_COMPILER_SUPPORTS_F90) if(NOT CMAKE_Fortran_COMPILER_ID MATCHES "SunPro|MIPSpro") set(module_expected 1) |