Jelajahi Sumber

add_library: Reject shared libraries on platforms that do not support them

Add policy CMP0164 to provide compatibility.

Fixes: #25759
Asit Dhal 1 tahun lalu
induk
melakukan
a61c9afdf8

+ 7 - 0
Help/command/add_library.rst

@@ -84,6 +84,13 @@ See also :prop_sf:`HEADER_FILE_ONLY` on what to do if some sources are
 pre-processed, and you want to have the original sources reachable from
 within IDE.
 
+.. versionchanged:: 3.30
+
+  On platforms that do not support shared libraries, ``add_library``
+  now fails on calls creating ``SHARED`` libraries instead of
+  automatically converting them to ``STATIC`` libraries as before.
+  See policy :policy:`CMP0164`.
+
 Object Libraries
 ^^^^^^^^^^^^^^^^
 

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

@@ -57,6 +57,7 @@ Policies Introduced by CMake 3.30
 .. toctree::
    :maxdepth: 1
 
+   CMP0164: add_library() rejects SHARED libraries when not supported by the platform. </policy/CMP0164>
    CMP0163: The GENERATED source file property is now visible in all directories. </policy/CMP0163>
    CMP0162: Visual Studio generators add UseDebugLibraries indicators by default. </policy/CMP0162>
 

+ 31 - 0
Help/policy/CMP0164.rst

@@ -0,0 +1,31 @@
+CMP0164
+-------
+
+.. versionadded:: 3.30
+
+:command:`add_library` rejects ``SHARED`` libraries when not supported by
+the platform.
+
+In CMake 3.29 and below, on platforms that do not support shared libraries
+(:prop_gbl:`TARGET_SUPPORTS_SHARED_LIBS` is ``false``), the
+:command:`add_library` command automatically converted ``SHARED`` libraries to
+``STATIC`` libraries to help users build projects on such platforms.  However,
+the semantics of shared and static libraries are different enough that such
+automatic conversion cannot work in general.  Projects using shared libraries
+need to be ported to such platforms on a case-by-case basis.
+
+In CMake 3.30 and above, :command:`add_library` prefers to reject creation
+of shared libraries on platforms that do not support them, and fail with a
+fatal error message.  This policy provides compatibility for projects that
+happened to work with the automatic conversion to static libraries and have
+not been updated with an explicit port.
+
+The ``OLD`` behavior for this policy is to implicitly create a static
+library with a developer warning.  The ``NEW`` behavior for this policy is
+to fail.
+
+.. |INTRODUCED_IN_CMAKE_VERSION| replace:: 3.30
+.. |WARNS_OR_DOES_NOT_WARN| replace:: does *not* warn about the behavior change
+.. include:: STANDARD_ADVICE.txt
+
+.. include:: DEPRECATED.txt

+ 6 - 0
Help/release/dev/add_library-no-static-fallback.rst

@@ -0,0 +1,6 @@
+add_library-no-static-fallback
+------------------------------
+
+* On platforms that do not support shared libraries, the :command:`add_library`
+  command now rejects creation of shared libraries instead of automatically
+  converting them to static libraries.  See policy :policy:`CMP0164`.

+ 30 - 8
Source/cmAddLibraryCommand.cxx

@@ -11,6 +11,7 @@
 #include "cmState.h"
 #include "cmStateTypes.h"
 #include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
 #include "cmTarget.h"
 #include "cmValue.h"
 
@@ -226,14 +227,35 @@ bool cmAddLibraryCommand(std::vector<std::string> const& args,
   if ((type == cmStateEnums::SHARED_LIBRARY ||
        type == cmStateEnums::MODULE_LIBRARY) &&
       !mf.GetState()->GetGlobalPropertyAsBool("TARGET_SUPPORTS_SHARED_LIBS")) {
-    mf.IssueMessage(
-      MessageType::AUTHOR_WARNING,
-      cmStrCat(
-        "ADD_LIBRARY called with ",
-        (type == cmStateEnums::SHARED_LIBRARY ? "SHARED" : "MODULE"),
-        " option but the target platform does not support dynamic linking. ",
-        "Building a STATIC library instead. This may lead to problems."));
-    type = cmStateEnums::STATIC_LIBRARY;
+    switch (status.GetMakefile().GetPolicyStatus(cmPolicies::CMP0164)) {
+      case cmPolicies::WARN:
+        mf.IssueMessage(
+          MessageType::AUTHOR_WARNING,
+          cmStrCat(
+            "ADD_LIBRARY called with ",
+            (type == cmStateEnums::SHARED_LIBRARY ? "SHARED" : "MODULE"),
+            " option but the target platform does not support dynamic "
+            "linking. ",
+            "Building a STATIC library instead. This may lead to problems."));
+        CM_FALLTHROUGH;
+      case cmPolicies::OLD:
+        type = cmStateEnums::STATIC_LIBRARY;
+        break;
+      case cmPolicies::NEW:
+      case cmPolicies::REQUIRED_IF_USED:
+      case cmPolicies::REQUIRED_ALWAYS:
+        mf.IssueMessage(
+          MessageType::FATAL_ERROR,
+          cmStrCat(
+            "ADD_LIBRARY called with ",
+            (type == cmStateEnums::SHARED_LIBRARY ? "SHARED" : "MODULE"),
+            " option but the target platform does not support dynamic "
+            "linking."));
+        cmSystemTools::SetFatalErrorOccurred();
+        return false;
+      default:
+        break;
+    }
   }
 
   // Handle imported target creation.

+ 5 - 1
Source/cmPolicies.h

@@ -501,7 +501,11 @@ class cmMakefile;
   SELECT(                                                                     \
     POLICY, CMP0163,                                                          \
     "The GENERATED source file property is now visible in all directories.",  \
-    3, 30, 0, cmPolicies::WARN)
+    3, 30, 0, cmPolicies::WARN)                                               \
+  SELECT(POLICY, CMP0164,                                                     \
+         "add_library() rejects SHARED libraries when not supported by the "  \
+         "platform.",                                                         \
+         3, 30, 0, cmPolicies::WARN)
 
 #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
 #define CM_FOR_EACH_POLICY_ID(POLICY)                                         \

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

@@ -22,3 +22,7 @@ run_cmake(STATICwithNoSourcesButLinkObjects)
 run_cmake(SHAREDwithNoSourcesButLinkObjects)
 run_cmake(MODULEwithNoSourcesButLinkObjects)
 run_cmake(UNKNOWNwithNoSourcesButLinkObjects)
+
+run_cmake(TARGET_SUPPORTS_SHARED_LIBS_CMP0164_OLD)
+run_cmake(TARGET_SUPPORTS_SHARED_LIBS_CMP0164_NEW)
+run_cmake(TARGET_SUPPORTS_SHARED_LIBS_CMP0164_WARN)

+ 1 - 0
Tests/RunCMake/add_library/TARGET_SUPPORTS_SHARED_LIBS_CMP0164_NEW-result.txt

@@ -0,0 +1 @@
+1

+ 5 - 0
Tests/RunCMake/add_library/TARGET_SUPPORTS_SHARED_LIBS_CMP0164_NEW-stderr.txt

@@ -0,0 +1,5 @@
+^CMake Error at TARGET_SUPPORTS_SHARED_LIBS_CMP0164_NEW.cmake:[0-9]+ \(add_library\):
+  ADD_LIBRARY called with SHARED option but the target platform does not
+  support dynamic linking.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:[0-9]+ \(include\)$

+ 4 - 0
Tests/RunCMake/add_library/TARGET_SUPPORTS_SHARED_LIBS_CMP0164_NEW.cmake

@@ -0,0 +1,4 @@
+enable_language(CXX)
+cmake_policy(SET CMP0164 NEW)
+set_property(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS FALSE)
+add_library(someLib SHARED test.cpp)

+ 9 - 0
Tests/RunCMake/add_library/TARGET_SUPPORTS_SHARED_LIBS_CMP0164_OLD.cmake

@@ -0,0 +1,9 @@
+enable_language(CXX)
+cmake_policy(SET CMP0164 OLD)
+set_property(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS FALSE)
+
+add_library(someLib SHARED test.cpp)
+get_target_property(someLibType someLib TYPE)
+if(NOT someLibType STREQUAL  "STATIC_LIBRARY")
+  message(FATAL_ERROR "expected type does not match")
+endif()

+ 7 - 0
Tests/RunCMake/add_library/TARGET_SUPPORTS_SHARED_LIBS_CMP0164_WARN-stderr.txt

@@ -0,0 +1,7 @@
+^CMake Warning \(dev\) at TARGET_SUPPORTS_SHARED_LIBS_CMP0164_WARN.cmake:[0-9]+ \(add_library\):
+  ADD_LIBRARY called with SHARED option but the target platform does not
+  support dynamic linking.  Building a STATIC library instead.  This may lead
+  to problems.
+Call Stack \(most recent call first\):
+  CMakeLists.txt:[0-9]+ \(include\)
+This warning is for project developers.  Use -Wno-dev to suppress it.$

+ 3 - 0
Tests/RunCMake/add_library/TARGET_SUPPORTS_SHARED_LIBS_CMP0164_WARN.cmake

@@ -0,0 +1,3 @@
+enable_language(CXX)
+set_property(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS FALSE)
+add_library(someLib SHARED test.cpp)