mirror of
https://github.com/reactos/CMake.git
synced 2024-11-24 12:09:48 +00:00
d6877e6c40
The cmake_parse_arguments command is builtin with version 3.5. The CMakeParseArguments module is empty and exists for backwards compatibility with CMake 3.4 and lower. Remove the includes of CMakeParseArguments from CMake's modules. The modules are always used with the current version of CMake. Leave the includes in the tests, as the tests may be run with an older version of CMake.
203 lines
7.3 KiB
CMake
203 lines
7.3 KiB
CMake
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
|
# file Copyright.txt or https://cmake.org/licensing for details.
|
|
|
|
#.rst:
|
|
# CMakeAddFortranSubdirectory
|
|
# ---------------------------
|
|
#
|
|
# Use MinGW gfortran from VS if a fortran compiler is not found.
|
|
#
|
|
# The 'add_fortran_subdirectory' function adds a subdirectory to a
|
|
# project that contains a fortran only sub-project. 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 BUILD_SHARED_LIBS is turned on in the project.
|
|
# In addition the CMAKE_GNUtoMS option is set to on, so that the MS .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".
|
|
|
|
set(_MS_MINGW_SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR})
|
|
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(
|
|
${_MS_MINGW_SOURCE_DIR}/CMakeAddFortranSubdirectory/config_mingw.cmake.in
|
|
${build_dir}/config_mingw.cmake
|
|
@ONLY)
|
|
configure_file(
|
|
${_MS_MINGW_SOURCE_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
|
|
INSTALL_COMMAND ""
|
|
)
|
|
# make the external project always run make with each build
|
|
externalproject_add_step(${project_name}_build forcebuild
|
|
COMMAND ${CMAKE_COMMAND}
|
|
-E remove
|
|
${CMAKE_CURRENT_BUILD_DIR}/${project_name}-prefix/src/${project_name}-stamp/${project_name}-build
|
|
DEPENDEES configure
|
|
DEPENDERS build
|
|
ALWAYS 1
|
|
)
|
|
# 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()
|