瀏覽代碼

Merge topic 'CheckLinkerFlag-module'

af96c0f4fa CheckLinkerFlag: Add module to check validity of linker flags
3c4cc77d55 Tests: Extend Fortran compiler information

Acked-by: Kitware Robot <[email protected]>
Merge-request: !4777
Brad King 5 年之前
父節點
當前提交
a354b7f21e

+ 1 - 0
Help/manual/cmake-modules.7.rst

@@ -36,6 +36,7 @@ These modules are loaded using the :command:`include` command.
    /module/CheckIncludeFiles
    /module/CheckLanguage
    /module/CheckLibraryExists
+   /module/CheckLinkerFlag
    /module/CheckOBJCCompilerFlag
    /module/CheckOBJCSourceCompiles
    /module/CheckOBJCSourceRuns

+ 1 - 0
Help/module/CheckLinkerFlag.rst

@@ -0,0 +1 @@
+.. cmake-module:: ../../Modules/CheckLinkerFlag.cmake

+ 5 - 0
Help/release/dev/CheckLinkerFlag.rst

@@ -0,0 +1,5 @@
+CheckLinkerFlag
+---------------
+
+* New :module:`CheckLinkerFlag` module has been added to provide a facility to
+  check validity of link flags.

+ 81 - 0
Modules/CheckLinkerFlag.cmake

@@ -0,0 +1,81 @@
+# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+#[=======================================================================[.rst:
+CheckLinkerFlag
+---------------
+
+Check whether the compiler supports a given link flag.
+
+.. command:: check_linker_flag
+
+  .. code-block:: cmake
+
+    check_linker_flag(<lang> <flag> <var>)
+
+Check that the link ``<flag>`` is accepted by the ``<lang>`` compiler without
+a diagnostic.  Stores the result in an internal cache entry named ``<var>``.
+
+This command temporarily sets the ``CMAKE_REQUIRED_LINK_OPTIONS`` variable
+and calls the ``check_<lang>_source_compiles`` macro from the
+``Check<lang>SourceCompiles`` module (:module:`CheckCSourceCompiles`,
+:module:`CheckCSourceCompiles`, :module:`CheckCXXSourceCompiles`,
+:module:`CheckOBJCSourceCompiles`, :module:`CheckOBJCXXSourceCompiles` or
+:module:`CheckFortranSourceCompiles`).  See documentation of these
+modules for a listing of variables that can otherwise modify the build.
+
+The underlying implementation rely on :prop_tgt:`LINK_OPTIONS` property to
+check the specified flag. The ``LINKER:`` prefix, as described in
+:command:`target_link_options` command, can be used as well.
+
+A positive result from this check indicates only that the compiler did not
+issue a diagnostic message when given the link flag.  Whether the flag has any
+effect or even a specific one is beyond the scope of this module.
+
+.. note::
+  Since the :command:`try_compile` command forwards flags from variables
+  like :variable:`CMAKE_<LANG>_FLAGS`, unknown flags in such variables may
+  cause a false negative for this check.
+#]=======================================================================]
+
+include_guard(GLOBAL)
+
+include(CMakeCheckCompilerFlagCommonPatterns)
+
+function(CHECK_LINKER_FLAG _lang _flag _var)
+  get_property (_supported_languages GLOBAL PROPERTY ENABLED_LANGUAGES)
+  if (NOT _lang IN_LIST _supported_languages)
+    message (SEND_ERROR "check_linker_flag: ${_lang}: unknown language.")
+    return()
+  endif()
+
+  include (Check${_lang}SourceCompiles)
+
+  set(CMAKE_REQUIRED_LINK_OPTIONS "${_flag}")
+
+  # Normalize locale during test compilation.
+  set(_locale_vars LC_ALL LC_MESSAGES LANG)
+  foreach(v IN LISTS _locale_vars)
+    set(_locale_vars_saved_${v} "$ENV{${v}}")
+    set(ENV{${v}} C)
+  endforeach()
+
+  if (_lang MATCHES "^(C|CXX)$")
+    set (_source "int main() { return 0; }")
+  elseif (_lang STREQUAL "Fortran")
+    set (_source "       program test\n       stop\n       end program")
+  elseif (_lang MATCHES "^(OBJC|OBJCXX)$")
+    set (_source "#ifndef __OBJC__\n#  error \"Not an Objective-C++ compiler\"\n#endif\nint main(void) { return 0; }")
+  else()
+    message (SEND_ERROR "check_linker_flag: ${_lang}: unsupported language.")
+    return()
+  endif()
+  check_compiler_flag_common_patterns(_common_patterns)
+
+  cmake_language (CALL check_${_lang}_source_compiles "${_source}" ${_var} ${_common_patterns})
+
+  foreach(v IN LISTS _locale_vars)
+    set(ENV{${v}} ${_locale_vars_saved_${v}})
+  endforeach()
+  set(${_var} "${${_var}}" PARENT_SCOPE)
+endfunction()

+ 3 - 0
Tests/CheckFortran.cmake

@@ -11,6 +11,7 @@ if(NOT DEFINED CMAKE_Fortran_COMPILER)
 project(CheckFortran Fortran)
 file(WRITE \"\${CMAKE_CURRENT_BINARY_DIR}/result.cmake\"
   \"set(CMAKE_Fortran_COMPILER \\\"\${CMAKE_Fortran_COMPILER}\\\")\\n\"
+  \"set(CMAKE_Fortran_COMPILER_ID \\\"\${CMAKE_Fortran_COMPILER_ID}\\\")\\n\"
   \"set(CMAKE_Fortran_FLAGS \\\"\${CMAKE_Fortran_FLAGS}\\\")\\n\"
   \"set(CMAKE_Fortran_COMPILER_SUPPORTS_F90 \\\"\${CMAKE_Fortran_COMPILER_SUPPORTS_F90}\\\")\\n\"
   )
@@ -45,6 +46,8 @@ file(WRITE \"\${CMAKE_CURRENT_BINARY_DIR}/result.cmake\"
   message(STATUS "${_desc} - ${CMAKE_Fortran_COMPILER}")
   set(CMAKE_Fortran_COMPILER "${CMAKE_Fortran_COMPILER}" CACHE FILEPATH "Fortran compiler")
   mark_as_advanced(CMAKE_Fortran_COMPILER)
+  set(CMAKE_Fortran_COMPILER_ID "${CMAKE_Fortran_COMPILER_ID}" CACHE STRING "Fortran compiler Id")
+  mark_as_advanced(CMAKE_Fortran_COMPILER_ID)
   set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS}" CACHE STRING "Fortran flags")
   mark_as_advanced(CMAKE_Fortran_FLAGS)
   set(CMAKE_Fortran_COMPILER_SUPPORTS_F90 "${CMAKE_Fortran_COMPILER_SUPPORTS_F90}" CACHE BOOL "Fortran compiler supports F90")

+ 6 - 0
Tests/RunCMake/CMakeLists.txt

@@ -488,6 +488,12 @@ add_RunCMake_test(target_include_directories)
 add_RunCMake_test(target_sources)
 add_RunCMake_test(CheckModules)
 add_RunCMake_test(CheckIPOSupported)
+if (CMAKE_SYSTEM_NAME MATCHES "(Linux|Darwin)"
+    AND (CMAKE_C_COMPILER_ID MATCHES "Clang|GNU" OR CMAKE_Fortran_COMPILER_ID MATCHES "GNU"))
+  add_RunCMake_test(CheckLinkerFlag -DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID}
+                                    -DCMAKE_Fortran_COMPILER_ID=${CMAKE_Fortran_COMPILER_ID})
+endif()
+
 add_RunCMake_test(CommandLine -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME} -DCYGWIN=${CYGWIN} -DPYTHON_EXECUTABLE=${PYTHON_EXECUTABLE})
 add_RunCMake_test(CommandLineTar)
 

+ 5 - 0
Tests/RunCMake/CheckLinkerFlag/CMakeLists.txt

@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 3.13)
+
+project(${RunCMake_TEST} LANGUAGES NONE)
+
+include(${RunCMake_TEST}.cmake)

+ 3 - 0
Tests/RunCMake/CheckLinkerFlag/CheckCLinkerFlag.cmake

@@ -0,0 +1,3 @@
+
+set (CHECK_LANGUAGE C)
+include ("${CMAKE_CURRENT_SOURCE_DIR}/CheckLinkerFlag.cmake")

+ 3 - 0
Tests/RunCMake/CheckLinkerFlag/CheckCXXLinkerFlag.cmake

@@ -0,0 +1,3 @@
+
+set (CHECK_LANGUAGE CXX)
+include ("${CMAKE_CURRENT_SOURCE_DIR}/CheckLinkerFlag.cmake")

+ 3 - 0
Tests/RunCMake/CheckLinkerFlag/CheckFortranLinkerFlag.cmake

@@ -0,0 +1,3 @@
+
+set (CHECK_LANGUAGE Fortran)
+include ("${CMAKE_CURRENT_SOURCE_DIR}/CheckLinkerFlag.cmake")

+ 14 - 0
Tests/RunCMake/CheckLinkerFlag/CheckLinkerFlag.cmake

@@ -0,0 +1,14 @@
+
+enable_language (${CHECK_LANGUAGE})
+
+include(CheckLinkerFlag)
+
+check_linker_flag(${CHECK_LANGUAGE} "LINKER:-L,/dir" VALID_LINKER_FLAG)
+if(NOT VALID_LINKER_FLAG)
+  message(SEND_ERROR "Test fail for valid linker flag.")
+endif()
+
+check_linker_flag(${CHECK_LANGUAGE} "LINKER:-D" INVALID_LINKER_FLAG)
+if(INVALID_LINKER_FLAG)
+  message(SEND_ERROR "Test fail for invalid linker flag.")
+endif()

+ 3 - 0
Tests/RunCMake/CheckLinkerFlag/CheckOBJCLinkerFlag.cmake

@@ -0,0 +1,3 @@
+
+set (CHECK_LANGUAGE OBJC)
+include ("${CMAKE_CURRENT_SOURCE_DIR}/CheckLinkerFlag.cmake")

+ 3 - 0
Tests/RunCMake/CheckLinkerFlag/CheckOBJCXXLinkerFlag.cmake

@@ -0,0 +1,3 @@
+
+set (CHECK_LANGUAGE OBJCXX)
+include ("${CMAKE_CURRENT_SOURCE_DIR}/CheckLinkerFlag.cmake")

+ 14 - 0
Tests/RunCMake/CheckLinkerFlag/RunCMakeTest.cmake

@@ -0,0 +1,14 @@
+include(RunCMake)
+
+if (CMAKE_C_COMPILER_ID MATCHES "Clang|GNU")
+  run_cmake(CheckCLinkerFlag)
+  run_cmake(CheckCXXLinkerFlag)
+  if (APPLE)
+    run_cmake(CheckOBJCLinkerFlag)
+    run_cmake(CheckOBJCXXLinkerFlag)
+  endif()
+endif()
+
+if (CMAKE_Fortran_COMPILER_ID MATCHES "GNU")
+  run_cmake(CheckFortranLinkerFlag)
+endif()