Procházet zdrojové kódy

ENH: add fortran link discovery module

Bill Hoffman před 17 roky
rodič
revize
3a97e4699c
2 změnil soubory, kde provedl 144 přidání a 0 odebrání
  1. 135 0
      Modules/FortranCInterface.cmake
  2. 9 0
      Modules/FortranCInterface.h.in

+ 135 - 0
Modules/FortranCInterface.cmake

@@ -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
+#
+# 

+ 9 - 0
Modules/FortranCInterface.h.in

@@ -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@
+
+
+