Ensure imported targets in sibling dirs are deduplicated

Fixes: #26284
This commit is contained in:
Marc Chevrier
2024-09-15 12:22:00 +02:00
parent b346afce4f
commit 502610733f
7 changed files with 81 additions and 2 deletions

View File

@@ -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<size_t> Emitted;
std::set<std::string> ImportedEmitted;
const std::map<size_t, std::vector<size_t>>* Groups = nullptr;
};
}

View File

@@ -0,0 +1,21 @@
enable_language(C)
add_library(lib1 STATIC lib1.c)
set_property(TARGET lib1 PROPERTY ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/$<CONFIG>")
# 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)

View File

@@ -0,0 +1,5 @@
cmake_policy(SET CMP0156 NEW)
set(APPLE_TEST TRUE)
include (CMP0156-Common-Imported.cmake)

View File

@@ -0,0 +1,4 @@
cmake_policy(SET CMP0156 NEW)
include (CMP0156-Common-Imported.cmake)

View File

@@ -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()

View File

@@ -0,0 +1,5 @@
find_package_lib1()
add_library(lib2 STATIC ../lib2.c)
target_link_libraries(lib2 PUBLIC lib1::lib1)

View File

@@ -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 "$<$<AND:$<NOT:$<TARGET_POLICY:CMP0156>>,$<C_COMPILER_ID:AppleClang>,$<VERSION_GREATER_EQUAL:$<C_COMPILER_VERSION>,15.0>>:LINKER:-no_warn_duplicate_libraries>")
endif()