diff options
author | Brad King <brad.king@kitware.com> | 2009-08-05 17:40:29 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2009-08-05 17:40:29 (GMT) |
commit | 80f0201b37576a4229ec9453a31d3be804abbcb4 (patch) | |
tree | 55229acdf15a513e9acaa6058178f6e76c36c61a /Modules/FortranCInterface | |
parent | 7b36fd637cf9fa3fdc70edec924a48a4ca76f5ac (diff) | |
download | CMake-80f0201b37576a4229ec9453a31d3be804abbcb4.zip CMake-80f0201b37576a4229ec9453a31d3be804abbcb4.tar.gz CMake-80f0201b37576a4229ec9453a31d3be804abbcb4.tar.bz2 |
Rewrite FortranCInterface module
This is a new FortranCInterface.cmake module to replace the previous
prototype. All module support files lie in a FortranCInterface
directory next to it.
This module uses a new approach to detect Fortran symbol mangling. We
build a single test project which defines symbols in a Fortran library
(one per object-file) and calls them from a Fortran executable. The
executable links to a C library which defines symbols encoding all known
manglings (one per object-file). The C library falls back to the
Fortran library for symbols it cannot provide. Therefore the executable
will always link, but prefers the C-implemented symbols when they match.
These symbols store string literals of the form INFO:symbol[<name>] so
we can parse them out of the executable.
This module also provides a simpler interface. It always detects the
mangling as soon as it is included. A single macro is provided to
generate mangling macros and optionally pre-mangled symbols.
Diffstat (limited to 'Modules/FortranCInterface')
-rw-r--r-- | Modules/FortranCInterface/CMakeLists.txt | 74 | ||||
-rw-r--r-- | Modules/FortranCInterface/Input.cmake.in | 3 | ||||
-rw-r--r-- | Modules/FortranCInterface/Macro.h.in | 4 | ||||
-rw-r--r-- | Modules/FortranCInterface/Output.cmake.in | 33 | ||||
-rw-r--r-- | Modules/FortranCInterface/call_mod.f90 | 6 | ||||
-rw-r--r-- | Modules/FortranCInterface/call_sub.f | 4 | ||||
-rw-r--r-- | Modules/FortranCInterface/main.F | 6 | ||||
-rw-r--r-- | Modules/FortranCInterface/my_module.f90 | 8 | ||||
-rw-r--r-- | Modules/FortranCInterface/my_sub.f | 2 | ||||
-rw-r--r-- | Modules/FortranCInterface/mymodule.f90 | 8 | ||||
-rw-r--r-- | Modules/FortranCInterface/mysub.f | 2 | ||||
-rw-r--r-- | Modules/FortranCInterface/symbol.c.in | 4 |
12 files changed, 154 insertions, 0 deletions
diff --git a/Modules/FortranCInterface/CMakeLists.txt b/Modules/FortranCInterface/CMakeLists.txt new file mode 100644 index 0000000..4bc7a10 --- /dev/null +++ b/Modules/FortranCInterface/CMakeLists.txt @@ -0,0 +1,74 @@ +cmake_minimum_required(VERSION 2.6.3) +project(FortranCInterface C Fortran) +include(${FortranCInterface_BINARY_DIR}/Input.cmake OPTIONAL) + +# Check if the C compiler supports '$' in identifiers. +include(CheckCSourceCompiles) +check_c_source_compiles(" +extern int dollar$(void); +int main() { return 0; } +" C_SUPPORTS_DOLLAR) + +# List manglings of global symbol names to try. +set(global_symbols + my_sub_ # GNU, Intel, HP, SunPro, MIPSpro + my_sub # VisualAge + mysub_ # GNU, Intel, HP, SunPro, MIPSpro + mysub # VisualAge + ${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 + __my_module_NMOD_my_sub # VisualAge + __mymodule_MOD_mysub # GNU + __mymodule_NMOD_mysub # VisualAge + my_module$my_sub # HP + my_module_mp_my_sub_ # Intel + mymodule$mysub # HP + mymodule_mp_mysub_ # Intel + ${FortranCInterface_MODULE_SYMBOLS} + ) +list(REMOVE_DUPLICATES module_symbols) + +# Note that some compiler manglings cannot be invoked from C: +# MIPSpro uses "MY_SUB.in.MY_MODULE" +# SunPro uses "my_module.my_sub_" + +# 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. +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 myfort) + +# Require symbols through Fortran. +add_executable(FortranCInterface main.F call_sub.f ${call_mod}) +target_link_libraries(FortranCInterface symbols) diff --git a/Modules/FortranCInterface/Input.cmake.in b/Modules/FortranCInterface/Input.cmake.in new file mode 100644 index 0000000..f261e3b --- /dev/null +++ b/Modules/FortranCInterface/Input.cmake.in @@ -0,0 +1,3 @@ +set(CMAKE_Fortran_COMPILER_ID "@CMAKE_Fortran_COMPILER_ID@") +set(FortranCInterface_GLOBAL_SYMBOLS "@FortranCInterface_GLOBAL_SYMBOLS@") +set(FortranCInterface_MODULE_SYMBOLS "@FortranCInterface_MODULE_SYMBOLS@") diff --git a/Modules/FortranCInterface/Macro.h.in b/Modules/FortranCInterface/Macro.h.in new file mode 100644 index 0000000..d015a62 --- /dev/null +++ b/Modules/FortranCInterface/Macro.h.in @@ -0,0 +1,4 @@ +#ifndef @MACRO_NAMESPACE@HEADER_INCLUDED +#define @MACRO_NAMESPACE@HEADER_INCLUDED +@HEADER_CONTENT@ +#endif diff --git a/Modules/FortranCInterface/Output.cmake.in b/Modules/FortranCInterface/Output.cmake.in new file mode 100644 index 0000000..bce410e --- /dev/null +++ b/Modules/FortranCInterface/Output.cmake.in @@ -0,0 +1,33 @@ +# Global symbol without underscore. +set(FortranCInterface_GLOBAL_SYMBOL "@FortranCInterface_GLOBAL_SYMBOL@") +set(FortranCInterface_GLOBAL_PREFIX "@FortranCInterface_GLOBAL_PREFIX@") +set(FortranCInterface_GLOBAL_SUFFIX "@FortranCInterface_GLOBAL_SUFFIX@") +set(FortranCInterface_GLOBAL_CASE "@FortranCInterface_GLOBAL_CASE@") +set(FortranCInterface_GLOBAL_MACRO "@FortranCInterface_GLOBAL_MACRO@") + +# Global symbol with underscore. +set(FortranCInterface_GLOBAL__SYMBOL "@FortranCInterface_GLOBAL__SYMBOL@") +set(FortranCInterface_GLOBAL__PREFIX "@FortranCInterface_GLOBAL__PREFIX@") +set(FortranCInterface_GLOBAL__SUFFIX "@FortranCInterface_GLOBAL__SUFFIX@") +set(FortranCInterface_GLOBAL__CASE "@FortranCInterface_GLOBAL__CASE@") +set(FortranCInterface_GLOBAL__MACRO "@FortranCInterface_GLOBAL__MACRO@") + +# Module symbol without underscore. +set(FortranCInterface_MODULE_SYMBOL "@FortranCInterface_MODULE_SYMBOL@") +set(FortranCInterface_MODULE_PREFIX "@FortranCInterface_MODULE_PREFIX@") +set(FortranCInterface_MODULE_MIDDLE "@FortranCInterface_MODULE_MIDDLE@") +set(FortranCInterface_MODULE_SUFFIX "@FortranCInterface_MODULE_SUFFIX@") +set(FortranCInterface_MODULE_CASE "@FortranCInterface_MODULE_CASE@") +set(FortranCInterface_MODULE_MACRO "@FortranCInterface_MODULE_MACRO@") + +# Module symbol with underscore. +set(FortranCInterface_MODULE__SYMBOL "@FortranCInterface_MODULE__SYMBOL@") +set(FortranCInterface_MODULE__PREFIX "@FortranCInterface_MODULE__PREFIX@") +set(FortranCInterface_MODULE__MIDDLE "@FortranCInterface_MODULE__MIDDLE@") +set(FortranCInterface_MODULE__SUFFIX "@FortranCInterface_MODULE__SUFFIX@") +set(FortranCInterface_MODULE__CASE "@FortranCInterface_MODULE__CASE@") +set(FortranCInterface_MODULE__MACRO "@FortranCInterface_MODULE__MACRO@") + +# Summarize what was found. +set(FortranCInterface_GLOBAL_FOUND @FortranCInterface_GLOBAL_FOUND@) +set(FortranCInterface_MODULE_FOUND @FortranCInterface_MODULE_FOUND@) diff --git a/Modules/FortranCInterface/call_mod.f90 b/Modules/FortranCInterface/call_mod.f90 new file mode 100644 index 0000000..9b6af64 --- /dev/null +++ b/Modules/FortranCInterface/call_mod.f90 @@ -0,0 +1,6 @@ +subroutine call_mod + use mymodule + use my_module + call mysub() + call my_sub() +end subroutine call_mod diff --git a/Modules/FortranCInterface/call_sub.f b/Modules/FortranCInterface/call_sub.f new file mode 100644 index 0000000..ce3d50b --- /dev/null +++ b/Modules/FortranCInterface/call_sub.f @@ -0,0 +1,4 @@ + subroutine call_sub + call mysub() + call my_sub() + end diff --git a/Modules/FortranCInterface/main.F b/Modules/FortranCInterface/main.F new file mode 100644 index 0000000..84991b0 --- /dev/null +++ b/Modules/FortranCInterface/main.F @@ -0,0 +1,6 @@ + program main + call call_sub() +#ifdef CALL_MOD + call call_mod() +#endif + end diff --git a/Modules/FortranCInterface/my_module.f90 b/Modules/FortranCInterface/my_module.f90 new file mode 100644 index 0000000..82713b4 --- /dev/null +++ b/Modules/FortranCInterface/my_module.f90 @@ -0,0 +1,8 @@ +module my_module + interface my_interface + module procedure my_sub + end interface +contains + subroutine my_sub + end subroutine my_sub +end module my_module diff --git a/Modules/FortranCInterface/my_sub.f b/Modules/FortranCInterface/my_sub.f new file mode 100644 index 0000000..247ba06 --- /dev/null +++ b/Modules/FortranCInterface/my_sub.f @@ -0,0 +1,2 @@ + subroutine my_sub + end diff --git a/Modules/FortranCInterface/mymodule.f90 b/Modules/FortranCInterface/mymodule.f90 new file mode 100644 index 0000000..ef6281a --- /dev/null +++ b/Modules/FortranCInterface/mymodule.f90 @@ -0,0 +1,8 @@ +module mymodule + interface myinterface + module procedure mysub + end interface +contains + subroutine mysub + end subroutine mysub +end module mymodule diff --git a/Modules/FortranCInterface/mysub.f b/Modules/FortranCInterface/mysub.f new file mode 100644 index 0000000..1c27ff4 --- /dev/null +++ b/Modules/FortranCInterface/mysub.f @@ -0,0 +1,2 @@ + subroutine mysub + end diff --git a/Modules/FortranCInterface/symbol.c.in b/Modules/FortranCInterface/symbol.c.in new file mode 100644 index 0000000..369fa45 --- /dev/null +++ b/Modules/FortranCInterface/symbol.c.in @@ -0,0 +1,4 @@ +const char* @symbol@(void) +{ + return "INFO:symbol[@symbol@]"; +} |