Teach FortranCInterface to load outside results
We split the main detection logic into a Detect.cmake support module and load it only when detection results are not already available. This allows results computed by the main project to be used in try-compile projects without recomputing them. The call to try_compile() need only to pass FortranCInterface_BINARY_DIR through the CMAKE_FLAGS option.
This commit is contained in:
parent
40ddd53543
commit
14f7a043e3
|
@ -85,170 +85,12 @@ foreach(lang C Fortran)
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
#-----------------------------------------------------------------------------
|
#-----------------------------------------------------------------------------
|
||||||
# Set up an interface detection project.
|
|
||||||
set(FortranCInterface_SOURCE_DIR ${CMAKE_ROOT}/Modules/FortranCInterface)
|
set(FortranCInterface_SOURCE_DIR ${CMAKE_ROOT}/Modules/FortranCInterface)
|
||||||
set(FortranCInterface_BINARY_DIR ${CMAKE_BINARY_DIR}/CMakeFiles/FortranCInterface)
|
|
||||||
configure_file(${FortranCInterface_SOURCE_DIR}/Input.cmake.in
|
|
||||||
${FortranCInterface_BINARY_DIR}/Input.cmake @ONLY)
|
|
||||||
|
|
||||||
# Detect the Fortran/C interface on the first run or when the
|
# Create the interface detection project if it does not exist.
|
||||||
# configuration changes.
|
if(NOT FortranCInterface_BINARY_DIR)
|
||||||
if(${FortranCInterface_BINARY_DIR}/Input.cmake
|
set(FortranCInterface_BINARY_DIR ${CMAKE_BINARY_DIR}/CMakeFiles/FortranCInterface)
|
||||||
IS_NEWER_THAN ${FortranCInterface_BINARY_DIR}/Output.cmake
|
include(${FortranCInterface_SOURCE_DIR}/Detect.cmake)
|
||||||
OR ${FortranCInterface_SOURCE_DIR}/Output.cmake.in
|
|
||||||
IS_NEWER_THAN ${FortranCInterface_BINARY_DIR}/Output.cmake
|
|
||||||
OR ${FortranCInterface_SOURCE_DIR}/CMakeLists.txt
|
|
||||||
IS_NEWER_THAN ${FortranCInterface_BINARY_DIR}/Output.cmake
|
|
||||||
OR ${CMAKE_CURRENT_LIST_FILE}
|
|
||||||
IS_NEWER_THAN ${FortranCInterface_BINARY_DIR}/Output.cmake
|
|
||||||
)
|
|
||||||
message(STATUS "Detecting Fortran/C Interface")
|
|
||||||
set(_result)
|
|
||||||
|
|
||||||
# Build a sample project which reports symbols.
|
|
||||||
try_compile(FortranCInterface_COMPILED
|
|
||||||
${FortranCInterface_BINARY_DIR}
|
|
||||||
${FortranCInterface_SOURCE_DIR}
|
|
||||||
FortranCInterface
|
|
||||||
OUTPUT_VARIABLE FortranCInterface_OUTPUT)
|
|
||||||
set(FortranCInterface_COMPILED ${FortranCInterface_COMPILED})
|
|
||||||
unset(FortranCInterface_COMPILED CACHE)
|
|
||||||
|
|
||||||
# Locate the sample project executable.
|
|
||||||
if(FortranCInterface_COMPILED)
|
|
||||||
find_program(FortranCInterface_EXE
|
|
||||||
NAMES FortranCInterface
|
|
||||||
PATHS ${FortranCInterface_BINARY_DIR} ${FortranCInterface_BINARY_DIR}/Debug
|
|
||||||
NO_DEFAULT_PATH
|
|
||||||
)
|
|
||||||
set(FortranCInterface_EXE ${FortranCInterface_EXE})
|
|
||||||
unset(FortranCInterface_EXE CACHE)
|
|
||||||
else()
|
|
||||||
set(_result "Failed to compile")
|
|
||||||
set(FortranCInterface_EXE)
|
|
||||||
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
|
|
||||||
"Fortran/C interface test project failed with the following output:\n"
|
|
||||||
"${FortranCInterface_OUTPUT}\n")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Load symbols from INFO:symbol[] strings in the executable.
|
|
||||||
set(FortranCInterface_SYMBOLS)
|
|
||||||
if(FortranCInterface_EXE)
|
|
||||||
file(STRINGS "${FortranCInterface_EXE}" _info_strings
|
|
||||||
LIMIT_COUNT 8 REGEX "INFO:[^[]*\\[")
|
|
||||||
foreach(info ${_info_strings})
|
|
||||||
if("${info}" MATCHES ".*INFO:symbol\\[([^]]*)\\].*")
|
|
||||||
string(REGEX REPLACE ".*INFO:symbol\\[([^]]*)\\].*" "\\1" symbol "${info}")
|
|
||||||
list(APPEND FortranCInterface_SYMBOLS ${symbol})
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
elseif(NOT _result)
|
|
||||||
set(_result "Failed to load sample executable")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(_case_mysub "LOWER")
|
|
||||||
set(_case_my_sub "LOWER")
|
|
||||||
set(_case_MYSUB "UPPER")
|
|
||||||
set(_case_MY_SUB "UPPER")
|
|
||||||
set(_global_regex "^(_*)(mysub|MYSUB)([_$]*)$")
|
|
||||||
set(_global__regex "^(_*)(my_sub|MY_SUB)([_$]*)$")
|
|
||||||
set(_module_regex "^(_*)(mymodule|MYMODULE)([A-Za-z_$]*)(mysub|MYSUB)([_$]*)$")
|
|
||||||
set(_module__regex "^(_*)(my_module|MY_MODULE)([A-Za-z_$]*)(my_sub|MY_SUB)([_$]*)$")
|
|
||||||
|
|
||||||
# Parse the symbol names.
|
|
||||||
foreach(symbol ${FortranCInterface_SYMBOLS})
|
|
||||||
foreach(form "" "_")
|
|
||||||
# Look for global symbols.
|
|
||||||
string(REGEX REPLACE "${_global_${form}regex}"
|
|
||||||
"\\1;\\2;\\3" pieces "${symbol}")
|
|
||||||
list(LENGTH pieces len)
|
|
||||||
if(len EQUAL 3)
|
|
||||||
set(FortranCInterface_GLOBAL_${form}SYMBOL "${symbol}")
|
|
||||||
list(GET pieces 0 FortranCInterface_GLOBAL_${form}PREFIX)
|
|
||||||
list(GET pieces 1 name)
|
|
||||||
list(GET pieces 2 FortranCInterface_GLOBAL_${form}SUFFIX)
|
|
||||||
set(FortranCInterface_GLOBAL_${form}CASE "${_case_${name}}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Look for module symbols.
|
|
||||||
string(REGEX REPLACE "${_module_${form}regex}"
|
|
||||||
"\\1;\\2;\\3;\\4;\\5" pieces "${symbol}")
|
|
||||||
list(LENGTH pieces len)
|
|
||||||
if(len EQUAL 5)
|
|
||||||
set(FortranCInterface_MODULE_${form}SYMBOL "${symbol}")
|
|
||||||
list(GET pieces 0 FortranCInterface_MODULE_${form}PREFIX)
|
|
||||||
list(GET pieces 1 module)
|
|
||||||
list(GET pieces 2 FortranCInterface_MODULE_${form}MIDDLE)
|
|
||||||
list(GET pieces 3 name)
|
|
||||||
list(GET pieces 4 FortranCInterface_MODULE_${form}SUFFIX)
|
|
||||||
set(FortranCInterface_MODULE_${form}CASE "${_case_${name}}")
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
# Construct mangling macro definitions.
|
|
||||||
set(_name_LOWER "name")
|
|
||||||
set(_name_UPPER "NAME")
|
|
||||||
foreach(form "" "_")
|
|
||||||
if(FortranCInterface_GLOBAL_${form}SYMBOL)
|
|
||||||
if(FortranCInterface_GLOBAL_${form}PREFIX)
|
|
||||||
set(_prefix "${FortranCInterface_GLOBAL_${form}PREFIX}##")
|
|
||||||
else()
|
|
||||||
set(_prefix "")
|
|
||||||
endif()
|
|
||||||
if(FortranCInterface_GLOBAL_${form}SUFFIX)
|
|
||||||
set(_suffix "##${FortranCInterface_GLOBAL_${form}SUFFIX}")
|
|
||||||
else()
|
|
||||||
set(_suffix "")
|
|
||||||
endif()
|
|
||||||
set(_name "${_name_${FortranCInterface_GLOBAL_${form}CASE}}")
|
|
||||||
set(FortranCInterface_GLOBAL${form}_MACRO
|
|
||||||
"(name,NAME) ${_prefix}${_name}${_suffix}")
|
|
||||||
endif()
|
|
||||||
if(FortranCInterface_MODULE_${form}SYMBOL)
|
|
||||||
if(FortranCInterface_MODULE_${form}PREFIX)
|
|
||||||
set(_prefix "${FortranCInterface_MODULE_${form}PREFIX}##")
|
|
||||||
else()
|
|
||||||
set(_prefix "")
|
|
||||||
endif()
|
|
||||||
if(FortranCInterface_MODULE_${form}SUFFIX)
|
|
||||||
set(_suffix "##${FortranCInterface_MODULE_${form}SUFFIX}")
|
|
||||||
else()
|
|
||||||
set(_suffix "")
|
|
||||||
endif()
|
|
||||||
set(_name "${_name_${FortranCInterface_MODULE_${form}CASE}}")
|
|
||||||
set(_middle "##${FortranCInterface_MODULE_${form}MIDDLE}##")
|
|
||||||
set(FortranCInterface_MODULE${form}_MACRO
|
|
||||||
"(mod_name,name, mod_NAME,NAME) ${_prefix}mod_${_name}${_middle}${_name}${_suffix}")
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
# Summarize what is available.
|
|
||||||
foreach(scope GLOBAL MODULE)
|
|
||||||
if(FortranCInterface_${scope}_SYMBOL AND
|
|
||||||
FortranCInterface_${scope}__SYMBOL)
|
|
||||||
set(FortranCInterface_${scope}_FOUND 1)
|
|
||||||
else()
|
|
||||||
set(FortranCInterface_${scope}_FOUND 0)
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
# Record the detection results.
|
|
||||||
configure_file(${FortranCInterface_SOURCE_DIR}/Output.cmake.in
|
|
||||||
${FortranCInterface_BINARY_DIR}/Output.cmake @ONLY)
|
|
||||||
file(APPEND ${FortranCInterface_BINARY_DIR}/Output.cmake "\n")
|
|
||||||
|
|
||||||
# Report the results.
|
|
||||||
if(FortranCInterface_GLOBAL_FOUND)
|
|
||||||
if(FortranCInterface_MODULE_FOUND)
|
|
||||||
set(_result "Found GLOBAL and MODULE mangling")
|
|
||||||
else(FortranCInterface_MODULE_FOUND)
|
|
||||||
set(_result "Found GLOBAL but not MODULE mangling")
|
|
||||||
endif()
|
|
||||||
elseif(NOT _result)
|
|
||||||
set(_result "Failed to recognize symbols")
|
|
||||||
endif()
|
|
||||||
message(STATUS "Detecting Fortran/C Interface - ${_result}")
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Load the detection results.
|
# Load the detection results.
|
||||||
|
|
|
@ -0,0 +1,165 @@
|
||||||
|
configure_file(${FortranCInterface_SOURCE_DIR}/Input.cmake.in
|
||||||
|
${FortranCInterface_BINARY_DIR}/Input.cmake @ONLY)
|
||||||
|
|
||||||
|
# Detect the Fortran/C interface on the first run or when the
|
||||||
|
# configuration changes.
|
||||||
|
if(${FortranCInterface_BINARY_DIR}/Input.cmake
|
||||||
|
IS_NEWER_THAN ${FortranCInterface_BINARY_DIR}/Output.cmake
|
||||||
|
OR ${FortranCInterface_SOURCE_DIR}/Output.cmake.in
|
||||||
|
IS_NEWER_THAN ${FortranCInterface_BINARY_DIR}/Output.cmake
|
||||||
|
OR ${FortranCInterface_SOURCE_DIR}/CMakeLists.txt
|
||||||
|
IS_NEWER_THAN ${FortranCInterface_BINARY_DIR}/Output.cmake
|
||||||
|
OR ${CMAKE_CURRENT_LIST_FILE}
|
||||||
|
IS_NEWER_THAN ${FortranCInterface_BINARY_DIR}/Output.cmake
|
||||||
|
)
|
||||||
|
message(STATUS "Detecting Fortran/C Interface")
|
||||||
|
else()
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(_result)
|
||||||
|
|
||||||
|
# Build a sample project which reports symbols.
|
||||||
|
try_compile(FortranCInterface_COMPILED
|
||||||
|
${FortranCInterface_BINARY_DIR}
|
||||||
|
${FortranCInterface_SOURCE_DIR}
|
||||||
|
FortranCInterface
|
||||||
|
OUTPUT_VARIABLE FortranCInterface_OUTPUT)
|
||||||
|
set(FortranCInterface_COMPILED ${FortranCInterface_COMPILED})
|
||||||
|
unset(FortranCInterface_COMPILED CACHE)
|
||||||
|
|
||||||
|
# Locate the sample project executable.
|
||||||
|
if(FortranCInterface_COMPILED)
|
||||||
|
find_program(FortranCInterface_EXE
|
||||||
|
NAMES FortranCInterface
|
||||||
|
PATHS ${FortranCInterface_BINARY_DIR} ${FortranCInterface_BINARY_DIR}/Debug
|
||||||
|
NO_DEFAULT_PATH
|
||||||
|
)
|
||||||
|
set(FortranCInterface_EXE ${FortranCInterface_EXE})
|
||||||
|
unset(FortranCInterface_EXE CACHE)
|
||||||
|
else()
|
||||||
|
set(_result "Failed to compile")
|
||||||
|
set(FortranCInterface_EXE)
|
||||||
|
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
|
||||||
|
"Fortran/C interface test project failed with the following output:\n"
|
||||||
|
"${FortranCInterface_OUTPUT}\n")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Load symbols from INFO:symbol[] strings in the executable.
|
||||||
|
set(FortranCInterface_SYMBOLS)
|
||||||
|
if(FortranCInterface_EXE)
|
||||||
|
file(STRINGS "${FortranCInterface_EXE}" _info_strings
|
||||||
|
LIMIT_COUNT 8 REGEX "INFO:[^[]*\\[")
|
||||||
|
foreach(info ${_info_strings})
|
||||||
|
if("${info}" MATCHES ".*INFO:symbol\\[([^]]*)\\].*")
|
||||||
|
string(REGEX REPLACE ".*INFO:symbol\\[([^]]*)\\].*" "\\1" symbol "${info}")
|
||||||
|
list(APPEND FortranCInterface_SYMBOLS ${symbol})
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
elseif(NOT _result)
|
||||||
|
set(_result "Failed to load sample executable")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(_case_mysub "LOWER")
|
||||||
|
set(_case_my_sub "LOWER")
|
||||||
|
set(_case_MYSUB "UPPER")
|
||||||
|
set(_case_MY_SUB "UPPER")
|
||||||
|
set(_global_regex "^(_*)(mysub|MYSUB)([_$]*)$")
|
||||||
|
set(_global__regex "^(_*)(my_sub|MY_SUB)([_$]*)$")
|
||||||
|
set(_module_regex "^(_*)(mymodule|MYMODULE)([A-Za-z_$]*)(mysub|MYSUB)([_$]*)$")
|
||||||
|
set(_module__regex "^(_*)(my_module|MY_MODULE)([A-Za-z_$]*)(my_sub|MY_SUB)([_$]*)$")
|
||||||
|
|
||||||
|
# Parse the symbol names.
|
||||||
|
foreach(symbol ${FortranCInterface_SYMBOLS})
|
||||||
|
foreach(form "" "_")
|
||||||
|
# Look for global symbols.
|
||||||
|
string(REGEX REPLACE "${_global_${form}regex}"
|
||||||
|
"\\1;\\2;\\3" pieces "${symbol}")
|
||||||
|
list(LENGTH pieces len)
|
||||||
|
if(len EQUAL 3)
|
||||||
|
set(FortranCInterface_GLOBAL_${form}SYMBOL "${symbol}")
|
||||||
|
list(GET pieces 0 FortranCInterface_GLOBAL_${form}PREFIX)
|
||||||
|
list(GET pieces 1 name)
|
||||||
|
list(GET pieces 2 FortranCInterface_GLOBAL_${form}SUFFIX)
|
||||||
|
set(FortranCInterface_GLOBAL_${form}CASE "${_case_${name}}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Look for module symbols.
|
||||||
|
string(REGEX REPLACE "${_module_${form}regex}"
|
||||||
|
"\\1;\\2;\\3;\\4;\\5" pieces "${symbol}")
|
||||||
|
list(LENGTH pieces len)
|
||||||
|
if(len EQUAL 5)
|
||||||
|
set(FortranCInterface_MODULE_${form}SYMBOL "${symbol}")
|
||||||
|
list(GET pieces 0 FortranCInterface_MODULE_${form}PREFIX)
|
||||||
|
list(GET pieces 1 module)
|
||||||
|
list(GET pieces 2 FortranCInterface_MODULE_${form}MIDDLE)
|
||||||
|
list(GET pieces 3 name)
|
||||||
|
list(GET pieces 4 FortranCInterface_MODULE_${form}SUFFIX)
|
||||||
|
set(FortranCInterface_MODULE_${form}CASE "${_case_${name}}")
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
# Construct mangling macro definitions.
|
||||||
|
set(_name_LOWER "name")
|
||||||
|
set(_name_UPPER "NAME")
|
||||||
|
foreach(form "" "_")
|
||||||
|
if(FortranCInterface_GLOBAL_${form}SYMBOL)
|
||||||
|
if(FortranCInterface_GLOBAL_${form}PREFIX)
|
||||||
|
set(_prefix "${FortranCInterface_GLOBAL_${form}PREFIX}##")
|
||||||
|
else()
|
||||||
|
set(_prefix "")
|
||||||
|
endif()
|
||||||
|
if(FortranCInterface_GLOBAL_${form}SUFFIX)
|
||||||
|
set(_suffix "##${FortranCInterface_GLOBAL_${form}SUFFIX}")
|
||||||
|
else()
|
||||||
|
set(_suffix "")
|
||||||
|
endif()
|
||||||
|
set(_name "${_name_${FortranCInterface_GLOBAL_${form}CASE}}")
|
||||||
|
set(FortranCInterface_GLOBAL${form}_MACRO
|
||||||
|
"(name,NAME) ${_prefix}${_name}${_suffix}")
|
||||||
|
endif()
|
||||||
|
if(FortranCInterface_MODULE_${form}SYMBOL)
|
||||||
|
if(FortranCInterface_MODULE_${form}PREFIX)
|
||||||
|
set(_prefix "${FortranCInterface_MODULE_${form}PREFIX}##")
|
||||||
|
else()
|
||||||
|
set(_prefix "")
|
||||||
|
endif()
|
||||||
|
if(FortranCInterface_MODULE_${form}SUFFIX)
|
||||||
|
set(_suffix "##${FortranCInterface_MODULE_${form}SUFFIX}")
|
||||||
|
else()
|
||||||
|
set(_suffix "")
|
||||||
|
endif()
|
||||||
|
set(_name "${_name_${FortranCInterface_MODULE_${form}CASE}}")
|
||||||
|
set(_middle "##${FortranCInterface_MODULE_${form}MIDDLE}##")
|
||||||
|
set(FortranCInterface_MODULE${form}_MACRO
|
||||||
|
"(mod_name,name, mod_NAME,NAME) ${_prefix}mod_${_name}${_middle}${_name}${_suffix}")
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
# Summarize what is available.
|
||||||
|
foreach(scope GLOBAL MODULE)
|
||||||
|
if(FortranCInterface_${scope}_SYMBOL AND
|
||||||
|
FortranCInterface_${scope}__SYMBOL)
|
||||||
|
set(FortranCInterface_${scope}_FOUND 1)
|
||||||
|
else()
|
||||||
|
set(FortranCInterface_${scope}_FOUND 0)
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
# Record the detection results.
|
||||||
|
configure_file(${FortranCInterface_SOURCE_DIR}/Output.cmake.in
|
||||||
|
${FortranCInterface_BINARY_DIR}/Output.cmake @ONLY)
|
||||||
|
file(APPEND ${FortranCInterface_BINARY_DIR}/Output.cmake "\n")
|
||||||
|
|
||||||
|
# Report the results.
|
||||||
|
if(FortranCInterface_GLOBAL_FOUND)
|
||||||
|
if(FortranCInterface_MODULE_FOUND)
|
||||||
|
set(_result "Found GLOBAL and MODULE mangling")
|
||||||
|
else(FortranCInterface_MODULE_FOUND)
|
||||||
|
set(_result "Found GLOBAL but not MODULE mangling")
|
||||||
|
endif()
|
||||||
|
elseif(NOT _result)
|
||||||
|
set(_result "Failed to recognize symbols")
|
||||||
|
endif()
|
||||||
|
message(STATUS "Detecting Fortran/C Interface - ${_result}")
|
Loading…
Reference in New Issue