Parcourir la source

Optionally exclude implicit link libraries via environment

CMake detects libraries that the compiler driver implicitly passes to
the linker, and stores them in `CMAKE_<LANG>_IMPLICIT_LINK_LIBRARIES`
for use in constructing mixed-language link lines.  Some compiler driver
flags add implicitly linked libraries that should not be used during
mixed-language linking because they are handled by similar flags passed
to the other language's compiler driver.  Add an environment variable
that users can set to avoid undesired implicit link libraries in such
scenarios.

Follow the pattern from commit 023de565d3 (Optionally exclude implicit
link directories via environment, 2023-05-25, v3.27.0-rc1~54^2).

Fixes: #26911
Brad King il y a 5 mois
Parent
commit
805a40b668

+ 3 - 0
Help/envvar/CMAKE_LANG_IMPLICIT_LINK_DIRECTORIES_EXCLUDE.rst

@@ -11,3 +11,6 @@ variable when it is automatically detected from the ``<LANG>`` compiler.
 
 This may be used to work around misconfigured compiler drivers that pass
 extraneous implicit link directories to their linker.
+
+See also the :envvar:`CMAKE_<LANG>_IMPLICIT_LINK_LIBRARIES_EXCLUDE`
+environment variable.

+ 17 - 0
Help/envvar/CMAKE_LANG_IMPLICIT_LINK_LIBRARIES_EXCLUDE.rst

@@ -0,0 +1,17 @@
+CMAKE_<LANG>_IMPLICIT_LINK_LIBRARIES_EXCLUDE
+--------------------------------------------
+
+.. versionadded:: 4.1
+
+.. include:: include/ENV_VAR.rst
+
+A :ref:`semicolon-separated list <CMake Language Lists>` of libraries
+to exclude from the :variable:`CMAKE_<LANG>_IMPLICIT_LINK_LIBRARIES`
+variable when it is automatically detected from the ``<LANG>`` compiler.
+
+This may be used to work around detection limitations that result in
+extraneous implicit link libraries, e.g., when using compiler driver
+flags that affect the set of implicitly linked libraries.
+
+See also the :envvar:`CMAKE_<LANG>_IMPLICIT_LINK_DIRECTORIES_EXCLUDE`
+environment variable.

+ 1 - 0
Help/manual/cmake-env-variables.7.rst

@@ -61,6 +61,7 @@ Environment Variables that Control the Build
    /envvar/CMAKE_INSTALL_PREFIX
    /envvar/CMAKE_LANG_COMPILER_LAUNCHER
    /envvar/CMAKE_LANG_IMPLICIT_LINK_DIRECTORIES_EXCLUDE
+   /envvar/CMAKE_LANG_IMPLICIT_LINK_LIBRARIES_EXCLUDE
    /envvar/CMAKE_LANG_LINKER_LAUNCHER
    /envvar/CMAKE_MSVCIDE_RUN_PATH
    /envvar/CMAKE_NO_VERBOSE

+ 6 - 0
Help/release/dev/implicit-link-lib-exclude.rst

@@ -0,0 +1,6 @@
+implicit-link-lib-exclude
+-------------------------
+
+* The :envvar:`CMAKE_<LANG>_IMPLICIT_LINK_LIBRARIES_EXCLUDE` environment
+  variable was added to optionally exclude specific libraries from the
+  detected set of :variable:`CMAKE_<LANG>_IMPLICIT_LINK_LIBRARIES`.

+ 8 - 4
Help/variable/CMAKE_LANG_IMPLICIT_LINK_LIBRARIES.rst

@@ -5,10 +5,14 @@ Implicit link libraries and flags detected for language ``<LANG>``.
 
 Compilers typically pass language runtime library names and other
 flags when they invoke a linker.  These flags are implicit link
-options for the compiler's language.  For each language enabled
-by the :command:`project` or :command:`enable_language` command,
-CMake automatically detects these libraries and flags and reports
-the results in this variable.
+options for the compiler's language.
+
+For each language enabled by the :command:`project` or
+:command:`enable_language` command, CMake automatically detects these
+libraries and flags and reports the results in this variable.
+The :envvar:`CMAKE_<LANG>_IMPLICIT_LINK_LIBRARIES_EXCLUDE` environment
+variable may be set to exclude specific libraries from the automatically
+detected results.
 
 When linking to a static library, CMake adds the implicit link libraries and
 flags from this variable for each language used in the static library (except

+ 4 - 1
Modules/CMakeDetermineCompilerABI.cmake

@@ -287,7 +287,10 @@ function(CMAKE_DETERMINE_COMPILER_ABI lang src)
         list(REMOVE_ITEM implicit_dirs ${CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES_EXCLUDE})
       endif()
 
-      # Filter out implicit link directories excluded by the environment.
+      # Filter out implicit link information excluded by the environment.
+      if(DEFINED ENV{CMAKE_${lang}_IMPLICIT_LINK_LIBRARIES_EXCLUDE})
+        list(REMOVE_ITEM implicit_libs $ENV{CMAKE_${lang}_IMPLICIT_LINK_LIBRARIES_EXCLUDE})
+      endif()
       if(DEFINED ENV{CMAKE_${lang}_IMPLICIT_LINK_DIRECTORIES_EXCLUDE})
         list(REMOVE_ITEM implicit_dirs $ENV{CMAKE_${lang}_IMPLICIT_LINK_DIRECTORIES_EXCLUDE})
       endif()

+ 13 - 0
Tests/RunCMake/ParseImplicitLinkInfo/ExcludeLibs.cmake

@@ -0,0 +1,13 @@
+block()
+  include("${info}")
+  set(INFO_CMAKE_C_IMPLICIT_LINK_LIBRARIES "${CMAKE_C_IMPLICIT_LINK_LIBRARIES}" PARENT_SCOPE)
+endblock()
+list(GET INFO_CMAKE_C_IMPLICIT_LINK_LIBRARIES -1 last_lib)
+set(ENV{CMAKE_C_IMPLICIT_LINK_LIBRARIES_EXCLUDE} "${last_lib}")
+enable_language(C)
+message(STATUS "INFO_CMAKE_C_IMPLICIT_LINK_LIBRARIES=[${INFO_CMAKE_C_IMPLICIT_LINK_LIBRARIES}]")
+message(STATUS "ENV{CMAKE_C_IMPLICIT_LINK_LIBRARIES_EXCLUDE}=[$ENV{CMAKE_C_IMPLICIT_LINK_LIBRARIES_EXCLUDE}]")
+message(STATUS "CMAKE_C_IMPLICIT_LINK_LIBRARIES=[${CMAKE_C_IMPLICIT_LINK_LIBRARIES}]")
+if("${last_lib}" IN_LIST CMAKE_C_IMPLICIT_LINK_LIBRARIES)
+  message(FATAL_ERROR "${last_lib} was not excluded!")
+endif()

+ 1 - 0
Tests/RunCMake/ParseImplicitLinkInfo/Inspect.cmake

@@ -9,6 +9,7 @@ foreach(var
     CMAKE_C_COMPILER_LINKER
     CMAKE_C_COMPILER_LINKER_ID
     CMAKE_C_COMPILER_LINKER_VERSION
+    CMAKE_C_IMPLICIT_LINK_LIBRARIES
     CMAKE_C_IMPLICIT_LINK_DIRECTORIES
     )
   if(DEFINED ${var})

+ 4 - 0
Tests/RunCMake/ParseImplicitLinkInfo/RunCMakeTest.cmake

@@ -10,6 +10,7 @@ run_cmake(ParseImplicitLinkInfo)
 # - CMAKE_C_COMPILER_LINKER
 # - CMAKE_C_COMPILER_LINKER_ID
 # - CMAKE_C_COMPILER_LINKER_VERSION
+# - CMAKE_C_IMPLICIT_LINK_LIBRARIES
 # - CMAKE_C_IMPLICIT_LINK_DIRECTORIES
 run_cmake(Inspect)
 set(info "${RunCMake_BINARY_DIR}/Inspect-build/info.cmake")
@@ -19,6 +20,9 @@ if(CMAKE_HOST_UNIX)
   run_cmake_script(DetermineLinkerId)
 endif()
 
+if(CMAKE_C_IMPLICIT_LINK_LIBRARIES MATCHES ";")
+  run_cmake_with_options(ExcludeLibs "-Dinfo=${RunCMake_BINARY_DIR}/Inspect-build/info.cmake")
+endif()
 if(CMAKE_C_IMPLICIT_LINK_DIRECTORIES MATCHES ";")
   run_cmake_with_options(ExcludeDirs "-Dinfo=${RunCMake_BINARY_DIR}/Inspect-build/info.cmake")
 endif()