summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc Chevrier <marc.chevrier@gmail.com>2024-09-29 13:56:04 (GMT)
committerBrad King <brad.king@kitware.com>2024-10-02 14:17:08 (GMT)
commitcd418d4bb62bbcc805bd734a01f5b0737292cc88 (patch)
treea89cbf7a116f8769c7273045bdb98045e5568ba0
parent9b5c805bf608623b52e1155837ddcca390cf0220 (diff)
downloadCMake-cd418d4bb62bbcc805bd734a01f5b0737292cc88.zip
CMake-cd418d4bb62bbcc805bd734a01f5b0737292cc88.tar.gz
CMake-cd418d4bb62bbcc805bd734a01f5b0737292cc88.tar.bz2
Static libraries de-duplication: keep first occurrence
Fixes: #26335
-rw-r--r--Help/manual/cmake-policies.7.rst1
-rw-r--r--Help/policy/CMP0156.rst5
-rw-r--r--Help/policy/CMP0179.rst28
-rw-r--r--Help/release/dev/static-libraries-deduplication.rst6
-rw-r--r--Help/variable/CMAKE_LINK_LIBRARIES_STRATEGY.rst2
-rw-r--r--Source/cmComputeLinkDepends.cxx65
-rw-r--r--Source/cmPolicies.h9
-rw-r--r--Tests/RunCMake/LinkLibrariesStrategy/RunCMakeTest.cmake41
-rw-r--r--Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt1
9 files changed, 134 insertions, 24 deletions
diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst
index 796ce8b..c6fcc1f 100644
--- a/Help/manual/cmake-policies.7.rst
+++ b/Help/manual/cmake-policies.7.rst
@@ -57,6 +57,7 @@ Policies Introduced by CMake 3.31
.. toctree::
:maxdepth: 1
+ CMP0179: De-duplication of static libraries on link lines keeps first occurrence. </policy/CMP0179>
CMP0178: Test command lines preserve empty arguments. </policy/CMP0178>
CMP0177: install() DESTINATION paths are normalized. </policy/CMP0177>
CMP0176: execute_process() ENCODING is UTF-8 by default. </policy/CMP0176>
diff --git a/Help/policy/CMP0156.rst b/Help/policy/CMP0156.rst
index d2ce291..7956742 100644
--- a/Help/policy/CMP0156.rst
+++ b/Help/policy/CMP0156.rst
@@ -34,6 +34,11 @@ are de-duplicated by keeping their first occurrence, thus respecting the
project-specified order. This policy provides compatibility with projects
that have not been updated to expect the latter behavior.
+.. note::
+
+ When this policy is set to ``NEW``, the policy :policy:`CMP0179` controls
+ which occurrence of the static libraries is kept when they are de-duplicated.
+
The ``OLD`` behavior for this policy is to always repeat static libraries
as if using a traditional linker, and always de-duplicate shared libraries
by keeping the last occurrence of each. The ``NEW`` behavior for this policy
diff --git a/Help/policy/CMP0179.rst b/Help/policy/CMP0179.rst
new file mode 100644
index 0000000..7c9498f
--- /dev/null
+++ b/Help/policy/CMP0179.rst
@@ -0,0 +1,28 @@
+CMP0179
+-------
+
+.. versionadded:: 3.31
+
+De-duplication of static libraries on link lines keeps first occurrence.
+This policy is only relevant when policy :policy:`CMP0156` is set to ``NEW``.
+
+Based on the linker capabilities, the static libraries can
+be de-duplicated. See policy :policy:`CMP0156` for more information.
+
+CMake 3.30 and below may choose to keep, on some platforms, the last occurrence
+of the static libraries rather than the fist occurrence when they are
+de-duplicated.
+
+CMake 3.31 and above prefer to keep, on all platforms, the first occurrence of
+the static libraries when they are de-duplicated.
+
+The ``OLD`` behavior for this policy is to keep, on some platforms, the last
+occurrence of the static libraries when they are de-duplicated. The ``NEW``
+behavior for this policy is to keep the first occurrence of the static
+libraries when they are de-duplicated, regardless of the platform.
+
+.. |INTRODUCED_IN_CMAKE_VERSION| replace:: 3.31
+.. |WARNS_OR_DOES_NOT_WARN| replace:: does *not* warn
+.. include:: STANDARD_ADVICE.txt
+
+.. include:: DEPRECATED.txt
diff --git a/Help/release/dev/static-libraries-deduplication.rst b/Help/release/dev/static-libraries-deduplication.rst
new file mode 100644
index 0000000..e388579
--- /dev/null
+++ b/Help/release/dev/static-libraries-deduplication.rst
@@ -0,0 +1,6 @@
+static-libraries-deduplication
+------------------------------
+
+* When static libraries on link lines are de-duplicated (by policy
+ :policy:`CMP0156`), the first occurrence is now kept on all platforms.
+ See policy :policy:`CMP0179`.
diff --git a/Help/variable/CMAKE_LINK_LIBRARIES_STRATEGY.rst b/Help/variable/CMAKE_LINK_LIBRARIES_STRATEGY.rst
index 1ba6b27..42c3260 100644
--- a/Help/variable/CMAKE_LINK_LIBRARIES_STRATEGY.rst
+++ b/Help/variable/CMAKE_LINK_LIBRARIES_STRATEGY.rst
@@ -65,4 +65,4 @@ The supported strategies are:
Regardless of the strategy used, the actual linker invocation for
some platforms may de-duplicate entries based on linker capabilities.
- See policy :policy:`CMP0156`.
+ See policies :policy:`CMP0156` and :policy:`CMP0179`.
diff --git a/Source/cmComputeLinkDepends.cxx b/Source/cmComputeLinkDepends.cxx
index 70e992e..5d92549 100644
--- a/Source/cmComputeLinkDepends.cxx
+++ b/Source/cmComputeLinkDepends.cxx
@@ -381,6 +381,34 @@ public:
target->GetBacktrace());
CM_FALLTHROUGH;
case cmPolicies::NEW: {
+ // Policy 0179 applies only when policy 0156 is new
+ switch (target->GetPolicyStatusCMP0179()) {
+ case cmPolicies::WARN:
+ if (!makefile->GetCMakeInstance()->GetIsInTryCompile() &&
+ makefile->PolicyOptionalWarningEnabled(
+ "CMAKE_POLICY_WARNING_CMP0179")) {
+ makefile->GetCMakeInstance()->IssueMessage(
+ MessageType::AUTHOR_WARNING,
+ cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0179),
+ "\nSince the policy is not set, static libraries "
+ "de-duplication will keep the last occurrence of the "
+ "static libraries."),
+ target->GetBacktrace());
+ }
+ CM_FALLTHROUGH;
+ case cmPolicies::OLD:
+ break;
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ makefile->GetCMakeInstance()->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0179),
+ target->GetBacktrace());
+ CM_FALLTHROUGH;
+ case cmPolicies::NEW:
+ break;
+ }
+
if (auto libProcessing = makefile->GetDefinition(cmStrCat(
"CMAKE_", linkLanguage, "_LINK_LIBRARIES_PROCESSING"))) {
// UNICITY keyword is just for compatibility with previous
@@ -444,9 +472,42 @@ public:
void AddLibraries(const std::vector<size_t>& libEntries)
{
if (this->Order == Reverse) {
+ std::vector<size_t> entries;
+ if (this->Deduplication == All &&
+ this->Target->GetPolicyStatusCMP0179() == cmPolicies::NEW) {
+ // keep the first occurrence of the static libraries
+ std::set<size_t> emitted{ this->Emitted };
+ std::set<std::string> importedEmitted;
+ for (auto index : libEntries) {
+ LinkEntry const& entry = this->Entries[index];
+ if (!entry.Target ||
+ entry.Target->GetType() != cmStateEnums::STATIC_LIBRARY) {
+ entries.emplace_back(index);
+ continue;
+ }
+ if (this->IncludeEntry(entry)) {
+ entries.emplace_back(index);
+ continue;
+ }
+ if (entry.Target->IsImported()) {
+ if (emitted.insert(index).second &&
+ importedEmitted
+ .insert(cmSystemTools::GetRealPath(entry.Item.Value))
+ .second) {
+ entries.emplace_back(index);
+ }
+ continue;
+ }
+ if (emitted.insert(index).second) {
+ entries.emplace_back(index);
+ }
+ }
+ } else {
+ entries = libEntries;
+ }
// Iterate in reverse order so we can keep only the last occurrence
- // of a library.
- this->AddLibraries(cmReverseRange(libEntries));
+ // of the shared libraries.
+ this->AddLibraries(cmReverseRange(entries));
} else {
this->AddLibraries(cmMakeRange(libEntries));
}
diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h
index e2254fe..55fce2e 100644
--- a/Source/cmPolicies.h
+++ b/Source/cmPolicies.h
@@ -545,7 +545,11 @@ class cmMakefile;
SELECT(POLICY, CMP0177, "install() DESTINATION paths are normalized.", 3, \
31, 0, cmPolicies::WARN) \
SELECT(POLICY, CMP0178, "Test command lines preserve empty arguments.", 3, \
- 31, 0, cmPolicies::WARN)
+ 31, 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0179, \
+ "De-duplication of static libraries on link lines keeps first " \
+ "occurrence.", \
+ 3, 31, 0, cmPolicies::WARN)
#define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
#define CM_FOR_EACH_POLICY_ID(POLICY) \
@@ -589,7 +593,8 @@ class cmMakefile;
F(CMP0156) \
F(CMP0157) \
F(CMP0160) \
- F(CMP0162)
+ F(CMP0162) \
+ F(CMP0179)
#define CM_FOR_EACH_CUSTOM_COMMAND_POLICY(F) \
F(CMP0116) \
diff --git a/Tests/RunCMake/LinkLibrariesStrategy/RunCMakeTest.cmake b/Tests/RunCMake/LinkLibrariesStrategy/RunCMakeTest.cmake
index 8ceb25d..eb107ed 100644
--- a/Tests/RunCMake/LinkLibrariesStrategy/RunCMakeTest.cmake
+++ b/Tests/RunCMake/LinkLibrariesStrategy/RunCMakeTest.cmake
@@ -16,29 +16,32 @@ include("${RunCMake_BINARY_DIR}/Inspect-build/info.cmake")
run_cmake(Unknown)
function(run_strategy case exe)
- set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${case}-build)
- if("DEDUPLICATION=ALL" IN_LIST CMAKE_C_LINK_LIBRARIES_PROCESSING)
- if("ORDER=REVERSE" IN_LIST CMAKE_C_LINK_LIBRARIES_PROCESSING)
- set(RunCMake-stderr-file ${case}-stderr-dedup-reverse.txt)
- else()
- set(RunCMake-stderr-file ${case}-stderr-dedup.txt)
- endif()
- endif()
- run_cmake(${case})
- unset(RunCMake-stderr-file)
- set(RunCMake_TEST_NO_CLEAN 1)
- run_cmake_command(${case}-build ${CMAKE_COMMAND} --build . --config Debug)
- if(exe)
+ foreach(cmp0179 OLD NEW)
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${case}-CMP0179-${cmp0179}-build)
+ set(RunCMake_TEST_VARIANT_DESCRIPTION "...CMP0179-${cmp0179}")
if("DEDUPLICATION=ALL" IN_LIST CMAKE_C_LINK_LIBRARIES_PROCESSING)
- if("ORDER=REVERSE" IN_LIST CMAKE_C_LINK_LIBRARIES_PROCESSING)
- set(RunCMake-stdout-file ${case}-run-stdout-dedup-reverse.txt)
+ if("ORDER=REVERSE" IN_LIST CMAKE_C_LINK_LIBRARIES_PROCESSING AND cmp0179 STREQUAL "OLD")
+ set(RunCMake-stderr-file ${case}-stderr-dedup-reverse.txt)
else()
- set(RunCMake-stdout-file ${case}-run-stdout-dedup.txt)
+ set(RunCMake-stderr-file ${case}-stderr-dedup.txt)
+ endif()
+ endif()
+ run_cmake_with_options(${case} -DCMAKE_POLICY_DEFAULT_CMP0179=${cmp0179})
+ unset(RunCMake-stderr-file)
+ set(RunCMake_TEST_NO_CLEAN 1)
+ run_cmake_command(${case}-build ${CMAKE_COMMAND} --build . --config Debug)
+ if(exe)
+ if("DEDUPLICATION=ALL" IN_LIST CMAKE_C_LINK_LIBRARIES_PROCESSING)
+ if("ORDER=REVERSE" IN_LIST CMAKE_C_LINK_LIBRARIES_PROCESSING AND cmp0179 STREQUAL "OLD")
+ set(RunCMake-stdout-file ${case}-run-stdout-dedup-reverse.txt)
+ else()
+ set(RunCMake-stdout-file ${case}-run-stdout-dedup.txt)
+ endif()
endif()
+ run_cmake_command(${case}-run ${RunCMake_TEST_BINARY_DIR}/${exe})
+ unset(RunCMake-stdout-file)
endif()
- run_cmake_command(${case}-run ${RunCMake_TEST_BINARY_DIR}/${exe})
- unset(RunCMake-stdout-file)
- endif()
+ endforeach()
endfunction()
run_strategy(Basic-PRESERVE_ORDER "main")
diff --git a/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt b/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt
index 415f404..4015ae8 100644
--- a/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt
+++ b/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt
@@ -43,6 +43,7 @@
\* CMP0157
\* CMP0160
\* CMP0162
+ \* CMP0179
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)