summaryrefslogtreecommitdiff
path: root/share/cmake-3.22/Modules/CMakeAddFortranSubdirectory.cmake
diff options
context:
space:
mode:
Diffstat (limited to 'share/cmake-3.22/Modules/CMakeAddFortranSubdirectory.cmake')
-rw-r--r--share/cmake-3.22/Modules/CMakeAddFortranSubdirectory.cmake194
1 files changed, 194 insertions, 0 deletions
diff --git a/share/cmake-3.22/Modules/CMakeAddFortranSubdirectory.cmake b/share/cmake-3.22/Modules/CMakeAddFortranSubdirectory.cmake
new file mode 100644
index 0000000..69a8417
--- /dev/null
+++ b/share/cmake-3.22/Modules/CMakeAddFortranSubdirectory.cmake
@@ -0,0 +1,194 @@
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+#[=======================================================================[.rst:
+CMakeAddFortranSubdirectory
+---------------------------
+
+Add a fortran-only subdirectory, find a fortran compiler, and build.
+
+The ``cmake_add_fortran_subdirectory`` function adds a subdirectory
+to a project that contains a fortran-only subproject. The module will
+check the current compiler and see if it can support fortran. If no
+fortran compiler is found and the compiler is MSVC, then this module
+will find the MinGW gfortran. It will then use an external project to
+build with the MinGW tools. It will also create imported targets for
+the libraries created. This will only work if the fortran code is
+built into a dll, so :variable:`BUILD_SHARED_LIBS` is turned on in
+the project. In addition the :variable:`CMAKE_GNUtoMS` option is set
+to on, so that Microsoft ``.lib`` files are created. Usage is as follows:
+
+::
+
+ cmake_add_fortran_subdirectory(
+ <subdir> # name of subdirectory
+ PROJECT <project_name> # project name in subdir top CMakeLists.txt
+ ARCHIVE_DIR <dir> # dir where project places .lib files
+ RUNTIME_DIR <dir> # dir where project places .dll files
+ LIBRARIES <lib>... # names of library targets to import
+ LINK_LIBRARIES # link interface libraries for LIBRARIES
+ [LINK_LIBS <lib> <dep>...]...
+ CMAKE_COMMAND_LINE ... # extra command line flags to pass to cmake
+ NO_EXTERNAL_INSTALL # skip installation of external project
+ )
+
+Relative paths in ``ARCHIVE_DIR`` and ``RUNTIME_DIR`` are interpreted with
+respect to the build directory corresponding to the source directory
+in which the function is invoked.
+
+Limitations:
+
+``NO_EXTERNAL_INSTALL`` is required for forward compatibility with a
+future version that supports installation of the external project
+binaries during ``make install``.
+#]=======================================================================]
+
+include(CheckLanguage)
+include(ExternalProject)
+
+function(_setup_mingw_config_and_build source_dir build_dir)
+ # Look for a MinGW gfortran.
+ find_program(MINGW_GFORTRAN
+ NAMES gfortran
+ PATHS
+ c:/MinGW/bin
+ "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\MinGW;InstallLocation]/bin"
+ )
+ if(NOT MINGW_GFORTRAN)
+ message(FATAL_ERROR
+ "gfortran not found, please install MinGW with the gfortran option."
+ "Or set the cache variable MINGW_GFORTRAN to the full path. "
+ " This is required to build")
+ endif()
+
+ # Validate the MinGW gfortran we found.
+ if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+ set(_mingw_target "Target:.*64.*mingw")
+ else()
+ set(_mingw_target "Target:.*mingw32")
+ endif()
+ execute_process(COMMAND "${MINGW_GFORTRAN}" -v
+ ERROR_VARIABLE out ERROR_STRIP_TRAILING_WHITESPACE)
+ if(NOT "${out}" MATCHES "${_mingw_target}")
+ string(REPLACE "\n" "\n " out " ${out}")
+ message(FATAL_ERROR
+ "MINGW_GFORTRAN is set to\n"
+ " ${MINGW_GFORTRAN}\n"
+ "which is not a MinGW gfortran for this architecture. "
+ "The output from -v does not match \"${_mingw_target}\":\n"
+ "${out}\n"
+ "Set MINGW_GFORTRAN to a proper MinGW gfortran for this architecture."
+ )
+ endif()
+
+ # Configure scripts to run MinGW tools with the proper PATH.
+ get_filename_component(MINGW_PATH ${MINGW_GFORTRAN} PATH)
+ file(TO_NATIVE_PATH "${MINGW_PATH}" MINGW_PATH)
+ string(REPLACE "\\" "\\\\" MINGW_PATH "${MINGW_PATH}")
+ configure_file(
+ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/CMakeAddFortranSubdirectory/config_mingw.cmake.in
+ ${build_dir}/config_mingw.cmake
+ @ONLY)
+ configure_file(
+ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/CMakeAddFortranSubdirectory/build_mingw.cmake.in
+ ${build_dir}/build_mingw.cmake
+ @ONLY)
+endfunction()
+
+function(_add_fortran_library_link_interface library depend_library)
+ set_target_properties(${library} PROPERTIES
+ IMPORTED_LINK_INTERFACE_LIBRARIES_NOCONFIG "${depend_library}")
+endfunction()
+
+
+function(cmake_add_fortran_subdirectory subdir)
+ # Parse arguments to function
+ set(options NO_EXTERNAL_INSTALL)
+ set(oneValueArgs PROJECT ARCHIVE_DIR RUNTIME_DIR)
+ set(multiValueArgs LIBRARIES LINK_LIBRARIES CMAKE_COMMAND_LINE)
+ cmake_parse_arguments(ARGS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+ if(NOT ARGS_NO_EXTERNAL_INSTALL)
+ message(FATAL_ERROR
+ "Option NO_EXTERNAL_INSTALL is required (for forward compatibility) "
+ "but was not given."
+ )
+ endif()
+
+ # if we are not using MSVC without fortran support
+ # then just use the usual add_subdirectory to build
+ # the fortran library
+ check_language(Fortran)
+ if(NOT (MSVC AND (NOT CMAKE_Fortran_COMPILER)))
+ add_subdirectory(${subdir})
+ return()
+ endif()
+
+ # if we have MSVC without Intel fortran then setup
+ # external projects to build with mingw fortran
+
+ set(source_dir "${CMAKE_CURRENT_SOURCE_DIR}/${subdir}")
+ set(project_name "${ARGS_PROJECT}")
+ set(library_dir "${ARGS_ARCHIVE_DIR}")
+ set(binary_dir "${ARGS_RUNTIME_DIR}")
+ set(libraries ${ARGS_LIBRARIES})
+ # use the same directory that add_subdirectory would have used
+ set(build_dir "${CMAKE_CURRENT_BINARY_DIR}/${subdir}")
+ foreach(dir_var library_dir binary_dir)
+ if(NOT IS_ABSOLUTE "${${dir_var}}")
+ get_filename_component(${dir_var}
+ "${CMAKE_CURRENT_BINARY_DIR}/${${dir_var}}" ABSOLUTE)
+ endif()
+ endforeach()
+ # create build and configure wrapper scripts
+ _setup_mingw_config_and_build("${source_dir}" "${build_dir}")
+ # create the external project
+ externalproject_add(${project_name}_build
+ SOURCE_DIR ${source_dir}
+ BINARY_DIR ${build_dir}
+ CONFIGURE_COMMAND ${CMAKE_COMMAND}
+ -P ${build_dir}/config_mingw.cmake
+ BUILD_COMMAND ${CMAKE_COMMAND}
+ -P ${build_dir}/build_mingw.cmake
+ BUILD_ALWAYS 1
+ INSTALL_COMMAND ""
+ )
+ # create imported targets for all libraries
+ foreach(lib ${libraries})
+ add_library(${lib} SHARED IMPORTED GLOBAL)
+ set_property(TARGET ${lib} APPEND PROPERTY IMPORTED_CONFIGURATIONS NOCONFIG)
+ set_target_properties(${lib} PROPERTIES
+ IMPORTED_IMPLIB_NOCONFIG "${library_dir}/lib${lib}.lib"
+ IMPORTED_LOCATION_NOCONFIG "${binary_dir}/lib${lib}.dll"
+ )
+ add_dependencies(${lib} ${project_name}_build)
+ endforeach()
+
+ # now setup link libraries for targets
+ set(start FALSE)
+ set(target)
+ foreach(lib ${ARGS_LINK_LIBRARIES})
+ if("${lib}" STREQUAL "LINK_LIBS")
+ set(start TRUE)
+ else()
+ if(start)
+ if(DEFINED target)
+ # process current target and target_libs
+ _add_fortran_library_link_interface(${target} "${target_libs}")
+ # zero out target and target_libs
+ set(target)
+ set(target_libs)
+ endif()
+ # save the current target and set start to FALSE
+ set(target ${lib})
+ set(start FALSE)
+ else()
+ # append the lib to target_libs
+ list(APPEND target_libs "${lib}")
+ endif()
+ endif()
+ endforeach()
+ # process anything that is left in target and target_libs
+ if(DEFINED target)
+ _add_fortran_library_link_interface(${target} "${target_libs}")
+ endif()
+endfunction()