ENH: add support for module functions

This commit is contained in:
Bill Hoffman 2008-10-27 21:42:41 -04:00
parent 749dbcdc6e
commit 2866984b4d

View File

@ -16,9 +16,21 @@
# discover_fortran_mangling - loop over all combos of fortran # discover_fortran_mangling - loop over all combos of fortran
# name mangling and call test_fortran_mangling until one of them # name mangling and call test_fortran_mangling until one of them
# works. # works.
# discover_fortran_module_mangling - try different types of
# fortran modle name mangling to find one that works
# #
#
function(test_fortran_mangling PREFIX ISUPPER POSTFIX RESULT) #
# this function tests a single fortran mangling.
# CODE - test code to try should define a subroutine called "sub"
# PREFIX - string to put in front of sub
# POSTFIX - string to put after sub
# ISUPPER - if TRUE then sub will be called as SUB
# DOC - string used in status checking Fortran ${DOC} linkage
# RESULT place to store result TRUE if this linkage works, FALSE
# if not.
#
function(test_fortran_mangling CODE PREFIX ISUPPER POSTFIX DOC RESULT)
if(ISUPPER) if(ISUPPER)
set(FUNCTION "${PREFIX}SUB${POSTFIX}") set(FUNCTION "${PREFIX}SUB${POSTFIX}")
else(ISUPPER) else(ISUPPER)
@ -29,13 +41,8 @@ function(test_fortran_mangling PREFIX ISUPPER POSTFIX RESULT)
set(TMP_DIR set(TMP_DIR
"${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckFortranLink") "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckFortranLink")
file(REMOVE_RECURSE "${TMP_DIR}") file(REMOVE_RECURSE "${TMP_DIR}")
file(WRITE "${TMP_DIR}/test.f" file(WRITE "${TMP_DIR}/test.f" "${CODE}" )
" message(STATUS "checking Fortran ${DOC} linkage: ${FUNCTION}")
subroutine sub
end subroutine sub
"
)
message(STATUS "checking Fortran linkage: ${FUNCTION}")
file(WRITE "${TMP_DIR}/ctof.c" file(WRITE "${TMP_DIR}/ctof.c"
" "
extern ${FUNCTION}(); extern ${FUNCTION}();
@ -61,14 +68,52 @@ function(test_fortran_mangling PREFIX ISUPPER POSTFIX RESULT)
endif() endif()
endfunction(test_fortran_mangling) endfunction(test_fortran_mangling)
# this function discovers the name mangling scheme used
# for functions in a fortran module.
function(discover_fortran_module_mangling prefix suffix found)
set(CODE
"
module test_interface
interface dummy
module procedure sub
end interface
contains
subroutine sub
end subroutine
end module test_interface
")
foreach(interface
"test_interface$"
".__test_interface_NMOD_"
"__test_interface_MOD_")
test_fortran_mangling("${CODE}" "${interface}"
${FORTRAN_C_MANGLING_UPPERCASE} "" "module" worked)
if(worked)
string(REGEX REPLACE "(.*)test_interface(.*)" "\\1" pre "${interface}")
string(REGEX REPLACE "(.*)test_interface(.*)" "\\2" post "${interface}")
set(${prefix} "${pre}" PARENT_SCOPE)
set(${suffix} "${post}" PARENT_SCOPE)
set(${found} TRUE PARENT_SCOPE)
return()
endif(worked)
endforeach(interface)
endfunction(discover_fortran_module_mangling)
function(discover_fortran_mangling prefix isupper suffix found ) function(discover_fortran_mangling prefix isupper suffix found )
set(CODE
"
subroutine sub
end subroutine sub
")
foreach(pre "_" "" "__") foreach(pre "_" "" "__")
foreach(isup TRUE FALSE) foreach(isup TRUE FALSE)
foreach(post "" "_") foreach(post "" "_")
set(worked FALSE) set(worked FALSE)
test_fortran_mangling("${pre}" ${isup} "${post}" worked ) test_fortran_mangling("${CODE}" "${pre}" ${isup} "${post}" "function" worked )
if(worked) if(worked)
message(STATUS "found Fotran linkage") message(STATUS "found Fortran function linkage")
set(${isupper} "${isup}" PARENT_SCOPE) set(${isupper} "${isup}" PARENT_SCOPE)
set(${prefix} "${pre}" PARENT_SCOPE) set(${prefix} "${pre}" PARENT_SCOPE)
set(${suffix} "${post}" PARENT_SCOPE) set(${suffix} "${post}" PARENT_SCOPE)
@ -83,11 +128,13 @@ endfunction(discover_fortran_mangling)
function(create_fortran_c_interface NAMESPACE FUNCTIONS HEADER) function(create_fortran_c_interface NAMESPACE FUNCTIONS HEADER)
if(NOT FORTRAN_C_MANGLING_FOUND) if(NOT FORTRAN_C_MANGLING_FOUND)
# find regular fortran function mangling
discover_fortran_mangling(prefix isupper suffix found) discover_fortran_mangling(prefix isupper suffix found)
if(NOT found) if(NOT found)
message(SEND_ERROR "Could not find fortran c name mangling.") message(SEND_ERROR "Could not find fortran c name mangling.")
return() return()
endif(NOT found) endif(NOT found)
# find fortran module function mangling
set(FORTRAN_C_PREFIX "${prefix}" CACHE INTERNAL set(FORTRAN_C_PREFIX "${prefix}" CACHE INTERNAL
"PREFIX for Fortran to c name mangling") "PREFIX for Fortran to c name mangling")
set(FORTRAN_C_SUFFIX "${suffix}" CACHE INTERNAL set(FORTRAN_C_SUFFIX "${suffix}" CACHE INTERNAL
@ -96,6 +143,22 @@ function(create_fortran_c_interface NAMESPACE FUNCTIONS HEADER)
"Was fortran to c mangling found" ) "Was fortran to c mangling found" )
set(FORTRAN_C_MANGLING_FOUND TRUE CACHE INTERNAL set(FORTRAN_C_MANGLING_FOUND TRUE CACHE INTERNAL
"Was fortran to c mangling found" ) "Was fortran to c mangling found" )
set(prefix )
set(suffix )
set(found FALSE)
discover_fortran_module_mangling(prefix suffix found)
if(found)
message(STATUS "found Fortran module linkage")
set(FORTRAN_C_MODULE_PREFIX "${prefix}" CACHE INTERNAL
"PREFIX for Fortran to c name mangling")
set(FORTRAN_C_MODULE_SUFFIX "${suffix}" CACHE INTERNAL
"SUFFIX for Fortran to c name mangling")
set(FORTRAN_C_MODULE_MANGLING_FOUND TRUE CACHE INTERNAL
"SUFFIX for Fortran to c name mangling")
else(found)
set(FORTRAN_C_MODULE_MANGLING_FOUND FALSE CACHE INTERNAL
"SUFFIX for Fortran to c name mangling")
endif(found)
endif(NOT FORTRAN_C_MANGLING_FOUND) endif(NOT FORTRAN_C_MANGLING_FOUND)
foreach(f ${${FUNCTIONS}}) foreach(f ${${FUNCTIONS}})
if(${FORTRAN_C_MANGLING_UPPERCASE}) if(${FORTRAN_C_MANGLING_UPPERCASE})
@ -103,10 +166,18 @@ function(create_fortran_c_interface NAMESPACE FUNCTIONS HEADER)
else() else()
string(TOLOWER "${f}" ff) string(TOLOWER "${f}" ff)
endif() endif()
if("${f}" MATCHES ":")
string(REGEX REPLACE "(.*):(.*)" "\\1" module "${f}")
string(REGEX REPLACE "(.*):(.*)" "\\2" function "${f}")
set(HEADER_CONTENT "${HEADER_CONTENT}
#define ${NAMESPACE}${module}_${function} ${FORTRAN_C_MODULE_PREFIX}${module}${FORTRAN_C_MODULE_SUFFIX}${function}
")
else("${f}" MATCHES ":")
set(function "${FORTRAN_C_PREFIX}${ff}${FORTRAN_C_SUFFIX}") set(function "${FORTRAN_C_PREFIX}${ff}${FORTRAN_C_SUFFIX}")
set(HEADER_CONTENT "${HEADER_CONTENT} set(HEADER_CONTENT "${HEADER_CONTENT}
#define ${NAMESPACE}${f} ${function} #define ${NAMESPACE}${f} ${function}
") ")
endif("${f}" MATCHES ":")
endforeach(f) endforeach(f)
configure_file( configure_file(
"${CMAKE_ROOT}/Modules/FortranCInterface.h.in" "${CMAKE_ROOT}/Modules/FortranCInterface.h.in"
@ -114,22 +185,3 @@ function(create_fortran_c_interface NAMESPACE FUNCTIONS HEADER)
message(STATUS "created ${HEADER}") message(STATUS "created ${HEADER}")
endfunction() 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
#
#