diff options
author | Marc Chevrier <marc.chevrier@gmail.com> | 2024-09-29 13:56:04 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2024-10-02 14:17:08 (GMT) |
commit | cd418d4bb62bbcc805bd734a01f5b0737292cc88 (patch) | |
tree | a89cbf7a116f8769c7273045bdb98045e5568ba0 | |
parent | 9b5c805bf608623b52e1155837ddcca390cf0220 (diff) | |
download | CMake-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.rst | 1 | ||||
-rw-r--r-- | Help/policy/CMP0156.rst | 5 | ||||
-rw-r--r-- | Help/policy/CMP0179.rst | 28 | ||||
-rw-r--r-- | Help/release/dev/static-libraries-deduplication.rst | 6 | ||||
-rw-r--r-- | Help/variable/CMAKE_LINK_LIBRARIES_STRATEGY.rst | 2 | ||||
-rw-r--r-- | Source/cmComputeLinkDepends.cxx | 65 | ||||
-rw-r--r-- | Source/cmPolicies.h | 9 | ||||
-rw-r--r-- | Tests/RunCMake/LinkLibrariesStrategy/RunCMakeTest.cmake | 41 | ||||
-rw-r--r-- | Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt | 1 |
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\) |