diff --git a/Source/cmComputeLinkDepends.cxx b/Source/cmComputeLinkDepends.cxx index 0583aba25c..f12bcdb30f 100644 --- a/Source/cmComputeLinkDepends.cxx +++ b/Source/cmComputeLinkDepends.cxx @@ -33,6 +33,7 @@ #include "cmState.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" +#include "cmSystemTools.h" #include "cmTarget.h" #include "cmValue.h" #include "cmake.h" @@ -540,7 +541,22 @@ private: { for (auto index : libEntries) { LinkEntry const& entry = this->Entries[index]; - if (this->IncludeEntry(entry) || this->Emitted.insert(index).second) { + if (this->IncludeEntry(entry)) { + this->FinalEntries.emplace_back(entry); + continue; + } + if (entry.Target && entry.Target->IsImported()) { + // Different imported targets can point to the same library so check + // also library paths + if (this->Emitted.insert(index).second && + this->ImportedEmitted + .insert(cmSystemTools::GetRealPath(entry.Item.Value)) + .second) { + this->FinalEntries.emplace_back(entry); + } + continue; + } + if (this->Emitted.insert(index).second) { this->FinalEntries.emplace_back(entry); } } @@ -553,6 +569,7 @@ private: EntryVector& Entries; EntryVector& FinalEntries; std::set Emitted; + std::set ImportedEmitted; const std::map>* Groups = nullptr; }; } diff --git a/Tests/RunCMake/CMP0156/CMP0156-Common-Imported.cmake b/Tests/RunCMake/CMP0156/CMP0156-Common-Imported.cmake new file mode 100644 index 0000000000..0c0e34f63e --- /dev/null +++ b/Tests/RunCMake/CMP0156/CMP0156-Common-Imported.cmake @@ -0,0 +1,21 @@ + +enable_language(C) + +add_library(lib1 STATIC lib1.c) +set_property(TARGET lib1 PROPERTY ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/$") + +# This function simulates a find_package call for the third-party lib +# by making an imported target with non-global scope. +function(find_package_lib1) + add_library(lib1::lib1 STATIC IMPORTED) + + set_target_properties(lib1::lib1 PROPERTIES + IMPORTED_LOCATION "${CMAKE_BINARY_DIR}/Release/${CMAKE_STATIC_LIBRARY_PREFIX}lib1${CMAKE_STATIC_LIBRARY_SUFFIX}" + ) + + add_dependencies(lib1::lib1 lib1) +endfunction() + +# ------------------------------------------------------------------------------ +add_subdirectory(subdir1) +add_subdirectory(subdir2) diff --git a/Tests/RunCMake/CMP0156/CMP0156-NEW-AppleClang-Imported.cmake b/Tests/RunCMake/CMP0156/CMP0156-NEW-AppleClang-Imported.cmake new file mode 100644 index 0000000000..bdfc7b80da --- /dev/null +++ b/Tests/RunCMake/CMP0156/CMP0156-NEW-AppleClang-Imported.cmake @@ -0,0 +1,5 @@ + +cmake_policy(SET CMP0156 NEW) +set(APPLE_TEST TRUE) + +include (CMP0156-Common-Imported.cmake) diff --git a/Tests/RunCMake/CMP0156/CMP0156-NEW-Imported.cmake b/Tests/RunCMake/CMP0156/CMP0156-NEW-Imported.cmake new file mode 100644 index 0000000000..92101d0f47 --- /dev/null +++ b/Tests/RunCMake/CMP0156/CMP0156-NEW-Imported.cmake @@ -0,0 +1,4 @@ + +cmake_policy(SET CMP0156 NEW) + +include (CMP0156-Common-Imported.cmake) diff --git a/Tests/RunCMake/CMP0156/RunCMakeTest.cmake b/Tests/RunCMake/CMP0156/RunCMakeTest.cmake index bd5183015b..052547c4e2 100644 --- a/Tests/RunCMake/CMP0156/RunCMakeTest.cmake +++ b/Tests/RunCMake/CMP0156/RunCMakeTest.cmake @@ -3,10 +3,14 @@ include(RunCMake) # CMP0156 control how libraries are specified for the link step # a sensible configuration is how circular dependency is handled +if(NOT RunCMake_GENERATOR_IS_MULTI_CONFIG) + set(OPTIONS -DCMAKE_BUILD_TYPE=Release) +endif() + macro(run_cmake_and_build test) set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${test}-build) set(RunCMake_TEST_OUTPUT_MERGE TRUE) - run_cmake(${test}) + run_cmake_with_options(${test} ${OPTIONS}) set(RunCMake_TEST_NO_CLEAN TRUE) run_cmake_command(${test}-build ${CMAKE_COMMAND} --build . --config Release) unset(RunCMake_TEST_NO_CLEAN) @@ -24,3 +28,12 @@ if (CMAKE_C_COMPILER_ID STREQUAL "AppleClang" run_cmake_and_build(CMP0156-OLD-AppleClang) run_cmake_and_build(CMP0156-NEW-AppleClang) endif() + + +run_cmake_and_build(CMP0156-NEW-Imported) + +if (CMAKE_C_COMPILER_ID STREQUAL "AppleClang" + AND CMAKE_C_COMPILER_VERSION GREATER_EQUAL "15.0") + # special case for Apple: with CMP0156=OLD, linker will warning on duplicate libraries + run_cmake_and_build(CMP0156-NEW-AppleClang-Imported) +endif() diff --git a/Tests/RunCMake/CMP0156/subdir1/CMakeLists.txt b/Tests/RunCMake/CMP0156/subdir1/CMakeLists.txt new file mode 100644 index 0000000000..0e88cd50f7 --- /dev/null +++ b/Tests/RunCMake/CMP0156/subdir1/CMakeLists.txt @@ -0,0 +1,5 @@ + +find_package_lib1() + +add_library(lib2 STATIC ../lib2.c) +target_link_libraries(lib2 PUBLIC lib1::lib1) diff --git a/Tests/RunCMake/CMP0156/subdir2/CMakeLists.txt b/Tests/RunCMake/CMP0156/subdir2/CMakeLists.txt new file mode 100644 index 0000000000..724483ccee --- /dev/null +++ b/Tests/RunCMake/CMP0156/subdir2/CMakeLists.txt @@ -0,0 +1,14 @@ + +find_package_lib1() + +# ----------------------------------- +# This target depends on the third-party lib1 both +# directly and transitively. +add_executable(main ../main.c) +target_link_libraries(main PRIVATE lib1::lib1 lib2) + +if (APPLE_TEST) + target_link_options(main PRIVATE "LINKER:-fatal_warnings") +else() + target_link_options(main PRIVATE "$<$>,$,$,15.0>>:LINKER:-no_warn_duplicate_libraries>") +endif()