ENH: add fortran link discovery module

This commit is contained in:
Bill Hoffman 2008-10-27 15:23:14 -04:00
parent 1ed93e0a0e
commit 3a97e4699c
2 changed files with 144 additions and 0 deletions

View File

@ -0,0 +1,135 @@
# FortranCInterface.cmake
#
# This file defines the function create_fortran_c_interface.
# this function is used to create a configured header file
# that contains a mapping from C to a Fortran function using
# the correct name mangling scheme as defined by the current
# fortran compiler.
#
# The function tages a list of functions and the name of
# a header file to configure.
#
# This file also defines some helper functions that are used
# to detect the fortran name mangling scheme used by the
# current Fortran compiler.
# test_fortran_mangling - test a single fortran mangling
# discover_fortran_mangling - loop over all combos of fortran
# name mangling and call test_fortran_mangling until one of them
# works.
#
function(test_fortran_mangling PREFIX ISUPPER POSTFIX RESULT)
if(ISUPPER)
set(FUNCTION "${PREFIX}SUB${POSTFIX}")
else(ISUPPER)
set(FUNCTION "${PREFIX}sub${POSTFIX}")
endif(ISUPPER)
# create a fortran file with sub called sub
#
set(TMP_DIR
"${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckFortranLink")
file(REMOVE_RECURSE "${TMP_DIR}")
file(WRITE "${TMP_DIR}/test.f"
"
subroutine sub
end subroutine sub
"
)
message(STATUS "checking Fortran linkage: ${FUNCTION}")
file(WRITE "${TMP_DIR}/ctof.c"
"
extern ${FUNCTION}();
int main() { ${FUNCTION}(); return 0;}
"
)
file(WRITE "${TMP_DIR}/CMakeLists.txt"
"
project(testf C Fortran)
add_library(flib test.f)
add_executable(ctof ctof.c)
target_link_libraries(ctof flib)
"
)
set(FORTRAN_NAME_MANGLE_TEST FALSE)
try_compile(FORTRAN_NAME_MANGLE_TEST "${TMP_DIR}" "${TMP_DIR}"
testf
OUTPUT_VARIABLE output)
if(FORTRAN_NAME_MANGLE_TEST)
set(${RESULT} TRUE PARENT_SCOPE)
else()
set(${RESULT} FALSE PARENT_SCOPE)
endif()
endfunction(test_fortran_mangling)
function(discover_fortran_mangling prefix isupper suffix found )
foreach(pre "_" "" "__")
foreach(isup TRUE FALSE)
foreach(post "" "_")
set(worked FALSE)
test_fortran_mangling("${pre}" ${isup} "${post}" worked )
if(worked)
message(STATUS "found Fotran linkage")
set(${isupper} "${isup}" PARENT_SCOPE)
set(${prefix} "${pre}" PARENT_SCOPE)
set(${suffix} "${post}" PARENT_SCOPE)
set(${found} TRUE PARENT_SCOPE)
return()
endif()
endforeach()
endforeach()
endforeach()
set(${found} FALSE PARENT_SCOPE)
endfunction(discover_fortran_mangling)
function(create_fortran_c_interface NAMESPACE FUNCTIONS HEADER)
if(NOT FORTRAN_C_MANGLING_FOUND)
discover_fortran_mangling(prefix isupper suffix found)
if(NOT found)
message(SEND_ERROR "Could not find fortran c name mangling.")
return()
endif(NOT found)
set(FORTRAN_C_PREFIX "${prefix}" CACHE INTERNAL
"PREFIX for Fortran to c name mangling")
set(FORTRAN_C_SUFFIX "${suffix}" CACHE INTERNAL
"SUFFIX for Fortran to c name mangling")
set(FORTRAN_C_MANGLING_UPPERCASE ${isupper} CACHE INTERNAL
"Was fortran to c mangling found" )
set(FORTRAN_C_MANGLING_FOUND TRUE CACHE INTERNAL
"Was fortran to c mangling found" )
endif(NOT FORTRAN_C_MANGLING_FOUND)
foreach(f ${${FUNCTIONS}})
if(${FORTRAN_C_MANGLING_UPPERCASE})
string(TOUPPER "${f}" ff)
else()
string(TOLOWER "${f}" ff)
endif()
set(function "${FORTRAN_C_PREFIX}${ff}${FORTRAN_C_SUFFIX}")
set(HEADER_CONTENT "${HEADER_CONTENT}
#define ${NAMESPACE}${f} ${function}
")
endforeach(f)
configure_file(
"${CMAKE_ROOT}/Modules/FortranCInterface.h.in"
${HEADER} @ONLY)
message(STATUS "created ${HEADER}")
endfunction()
# TODO
# need to add support for module linking
# module test_interface
#
# interface dummy
# module procedure module_function
# end interface
#
# contains
#
# subroutine module_function
# end subroutine
#
# end module test_interface
#
# produces this:
# __test_interface_MOD_module_function
#
#

View File

@ -0,0 +1,9 @@
/* This file is automatically generated by CMake, DO NOT EDIT.
It contains a mapping from Fortran functions so they can
be called from C or C++. */
@HEADER_CONTENT@