summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc Chevrier <marc.chevrier@gmail.com>2022-11-22 15:32:59 (GMT)
committerMarc Chevrier <marc.chevrier@gmail.com>2022-11-22 15:44:45 (GMT)
commit61075d2d7b0a77f53bc9a0d4c6644ab338f27886 (patch)
tree6d0130aaa0ee0f92877d4bd7895cfd67eeb92daa
parent3d1f91a245fec409b93c4f059ca50efcff9af578 (diff)
downloadCMake-61075d2d7b0a77f53bc9a0d4c6644ab338f27886.zip
CMake-61075d2d7b0a77f53bc9a0d4c6644ab338f27886.tar.gz
CMake-61075d2d7b0a77f53bc9a0d4c6644ab338f27886.tar.bz2
XCode: ensure LINK_LIBRARY genex is usable with XCODE_LINK_BUILD_PHASE_MODE
Fixes: #24176
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx74
-rw-r--r--Tests/RunCMake/XcodeProject/LinkBinariesBuildPhase.cmake62
-rw-r--r--Tests/RunCMake/XcodeProject/LinkBinariesBuildPhase_BUILT_ONLY-check.cmake9
-rw-r--r--Tests/RunCMake/XcodeProject/LinkBinariesBuildPhase_KNOWN_LOCATION-check.cmake9
-rw-r--r--Tests/RunCMake/XcodeProject/LinkBinariesBuildPhase_NONE-check.cmake2
5 files changed, 127 insertions, 29 deletions
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index 0658021..116e510 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -3581,28 +3581,37 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
libItem.IsPath == cmComputeLinkInformation::ItemIsPath::Yes &&
forceLinkPhase))) {
std::string libName;
- bool canUseLinkPhase = true;
- if (libItem.Target) {
- if (libItem.Target->GetType() == cmStateEnums::UNKNOWN_LIBRARY) {
- canUseLinkPhase = canUseLinkPhase && forceLinkPhase;
+ bool canUseLinkPhase = !libItem.HasFeature() ||
+ libItem.GetFeatureName() == "__CMAKE_LINK_FRAMEWORK"_s ||
+ libItem.GetFeatureName() == "FRAMEWORK"_s ||
+ libItem.GetFeatureName() == "WEAK_FRAMEWORK"_s ||
+ libItem.GetFeatureName() == "WEAK_LIBRARY"_s;
+ if (canUseLinkPhase) {
+ if (libItem.Target) {
+ if (libItem.Target->GetType() == cmStateEnums::UNKNOWN_LIBRARY) {
+ canUseLinkPhase = canUseLinkPhase && forceLinkPhase;
+ } else {
+ // If a library target uses custom build output directory Xcode
+ // won't pick it up so we have to resort back to linker flags,
+ // but that's OK as long as the custom output dir is absolute
+ // path.
+ for (auto const& libConfigName :
+ this->CurrentConfigurationTypes) {
+ canUseLinkPhase = canUseLinkPhase &&
+ libItem.Target->UsesDefaultOutputDir(
+ libConfigName, cmStateEnums::RuntimeBinaryArtifact);
+ }
+ }
+ libName = libItem.Target->GetName();
} else {
- // If a library target uses custom build output directory Xcode
- // won't pick it up so we have to resort back to linker flags, but
- // that's OK as long as the custom output dir is absolute path.
- for (auto const& libConfigName : this->CurrentConfigurationTypes) {
- canUseLinkPhase = canUseLinkPhase &&
- libItem.Target->UsesDefaultOutputDir(
- libConfigName, cmStateEnums::RuntimeBinaryArtifact);
+ libName = cmSystemTools::GetFilenameName(libItem.Value.Value);
+ // We don't want all the possible files here, just standard
+ // libraries
+ const auto libExt = cmSystemTools::GetFilenameExtension(libName);
+ if (!IsLinkPhaseLibraryExtension(libExt)) {
+ canUseLinkPhase = false;
}
}
- libName = libItem.Target->GetName();
- } else {
- libName = cmSystemTools::GetFilenameName(libItem.Value.Value);
- // We don't want all the possible files here, just standard libraries
- const auto libExt = cmSystemTools::GetFilenameExtension(libName);
- if (!IsLinkPhaseLibraryExtension(libExt)) {
- canUseLinkPhase = false;
- }
}
if (canUseLinkPhase) {
// Add unique configuration name to target-config map for later
@@ -3658,6 +3667,7 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
// separately.
std::vector<std::string> linkSearchPaths;
std::vector<std::string> frameworkSearchPaths;
+ std::set<std::pair<cmXCodeObject*, std::string>> linkBuildFileSet;
for (auto const& libItem : linkPhaseTargetVector) {
// Add target output directory as a library search path
std::string linkDir;
@@ -3760,8 +3770,30 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
cmSystemTools::Error("Missing files of PBXFrameworksBuildPhase");
continue;
}
- if (buildFile && !buildFiles->HasObject(buildFile)) {
- buildFiles->AddObject(buildFile);
+ if (buildFile) {
+ if (cmHasPrefix(libItem->GetFeatureName(), "WEAK_"_s)) {
+ auto key = std::make_pair(buildFile->GetAttribute("fileRef"),
+ libItem->GetFeatureName());
+ if (linkBuildFileSet.find(key) != linkBuildFileSet.end()) {
+ continue;
+ }
+ linkBuildFileSet.insert(key);
+
+ cmXCodeObject* buildObject =
+ this->CreateObject(cmXCodeObject::PBXBuildFile);
+ buildObject->AddAttribute("fileRef", key.first);
+ // Add settings, ATTRIBUTES, Weak flag
+ cmXCodeObject* settings =
+ this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
+ cmXCodeObject* attrs = this->CreateObject(cmXCodeObject::OBJECT_LIST);
+ attrs->AddObject(this->CreateString("Weak"));
+ settings->AddAttribute("ATTRIBUTES", attrs);
+ buildObject->AddAttribute("settings", settings);
+ buildFile = buildObject;
+ }
+ if (!buildFiles->HasObject(buildFile)) {
+ buildFiles->AddObject(buildFile);
+ }
}
}
diff --git a/Tests/RunCMake/XcodeProject/LinkBinariesBuildPhase.cmake b/Tests/RunCMake/XcodeProject/LinkBinariesBuildPhase.cmake
index 7abc58b..a9ea717 100644
--- a/Tests/RunCMake/XcodeProject/LinkBinariesBuildPhase.cmake
+++ b/Tests/RunCMake/XcodeProject/LinkBinariesBuildPhase.cmake
@@ -65,8 +65,12 @@ add_custom_target(prebuildDependencies ALL
COMMAND ${CMAKE_COMMAND} --build ${CMAKE_CURRENT_BINARY_DIR}/ExternalFrameworks/build --target staticFrameworkExt sharedFrameworkExt --config Debug
)
add_executable(app1 mainOuter.m)
+add_executable(app2 mainOuter.m)
+add_executable(app3 mainOuter.m)
add_library(static1 STATIC funcOuter.c)
add_library(shared1 SHARED funcOuter.c)
+add_library(shared3 SHARED funcOuter.c)
+add_library(shared4 SHARED funcOuter.c)
add_library(module1 MODULE funcOuter.c)
add_library(obj1 OBJECT funcOuter.c)
add_library(staticFramework1 STATIC funcOuter.c)
@@ -74,8 +78,12 @@ add_library(sharedFramework1 SHARED funcOuter.c)
set_target_properties(staticFramework1 PROPERTIES FRAMEWORK TRUE)
set_target_properties(sharedFramework1 PROPERTIES FRAMEWORK TRUE)
add_dependencies(app1 prebuildDependencies)
+add_dependencies(app2 prebuildDependencies)
+add_dependencies(app3 prebuildDependencies)
add_dependencies(static1 prebuildDependencies)
add_dependencies(shared1 prebuildDependencies)
+add_dependencies(shared3 prebuildDependencies)
+add_dependencies(shared4 prebuildDependencies)
add_dependencies(module1 prebuildDependencies)
add_dependencies(obj1 prebuildDependencies)
add_dependencies(staticFramework1 prebuildDependencies)
@@ -103,6 +111,14 @@ set(libresolv \"${libresolv}\")
set(CoreFoundation \"${CoreFoundation}\")
")
+macro(SET_LINK_LIBRARIES)
+ foreach(mainTarget IN LISTS mainTargets)
+ foreach(linkTo IN LISTS linkToThings)
+ target_link_libraries(${mainTarget} PRIVATE ${linkTo})
+ endforeach()
+ endforeach()
+endmacro()
+
set(mainTargets
app1
static1
@@ -125,8 +141,44 @@ set(linkToThings
"${CMAKE_CURRENT_BINARY_DIR}/ExternalFrameworks/build/Debug/staticFrameworkExt.framework"
)
-foreach(mainTarget IN LISTS mainTargets)
- foreach(linkTo IN LISTS linkToThings)
- target_link_libraries(${mainTarget} PRIVATE ${linkTo})
- endforeach()
-endforeach()
+set_link_libraries()
+
+set(mainTargets
+ app2
+ shared3
+)
+
+set(linkToThings
+ static2
+ "$<LINK_LIBRARY:WEAK_LIBRARY,shared2>"
+ obj2
+ staticFramework2
+ "$<LINK_LIBRARY:WEAK_FRAMEWORK,sharedFramework2>"
+ imported2
+ ${libresolv}
+ ${CoreFoundation}
+ "$<LINK_LIBRARY:WEAK_FRAMEWORK,${CMAKE_CURRENT_BINARY_DIR}/ExternalFrameworks/build/Debug/sharedFrameworkExt.framework>"
+ "${CMAKE_CURRENT_BINARY_DIR}/ExternalFrameworks/build/Debug/staticFrameworkExt.framework"
+)
+
+set_link_libraries()
+
+set(mainTargets
+ app3
+ shared4
+)
+
+set(linkToThings
+ static2
+ "$<LINK_LIBRARY:REEXPORT_LIBRARY,shared2>"
+ obj2
+ staticFramework2
+ "$<LINK_LIBRARY:REEXPORT_FRAMEWORK,sharedFramework2>"
+ imported2
+ ${libresolv}
+ ${CoreFoundation}
+ "$<LINK_LIBRARY:REEXPORT_FRAMEWORK,${CMAKE_CURRENT_BINARY_DIR}/ExternalFrameworks/build/Debug/sharedFrameworkExt.framework>"
+ "${CMAKE_CURRENT_BINARY_DIR}/ExternalFrameworks/build/Debug/staticFrameworkExt.framework"
+)
+
+set_link_libraries()
diff --git a/Tests/RunCMake/XcodeProject/LinkBinariesBuildPhase_BUILT_ONLY-check.cmake b/Tests/RunCMake/XcodeProject/LinkBinariesBuildPhase_BUILT_ONLY-check.cmake
index d07a25b..75edc5c 100644
--- a/Tests/RunCMake/XcodeProject/LinkBinariesBuildPhase_BUILT_ONLY-check.cmake
+++ b/Tests/RunCMake/XcodeProject/LinkBinariesBuildPhase_BUILT_ONLY-check.cmake
@@ -4,13 +4,20 @@ include(${RunCMake_TEST_BINARY_DIR}/foundLibs.cmake)
# obj2 --> Embeds func3.o in the link flags, but obj2 is part of the path
# ${libz} --> This is for imported2
-foreach(mainTarget IN ITEMS app1 shared1 module1 sharedFramework1)
+foreach(mainTarget IN ITEMS app1 app2 shared1 shared3 module1 sharedFramework1)
checkFlags(OTHER_LDFLAGS ${mainTarget}
"obj2;${libz};${libresolv};CoreFoundation;sharedFrameworkExt;staticFrameworkExt"
"static2;shared2;staticFramework2;sharedFramework2"
)
endforeach()
+foreach(mainTarget IN ITEMS app3 shared4)
+ checkFlags(OTHER_LDFLAGS ${mainTarget}
+ "obj2;${libz};${libresolv};CoreFoundation;sharedFrameworkExt;staticFrameworkExt;shared2;sharedFramework2"
+ "static2;staticFramework2"
+ )
+endforeach()
+
foreach(mainTarget IN ITEMS static1 staticFramework1)
checkFlags(OTHER_LIBTOOLFLAGS ${mainTarget}
"obj2"
diff --git a/Tests/RunCMake/XcodeProject/LinkBinariesBuildPhase_KNOWN_LOCATION-check.cmake b/Tests/RunCMake/XcodeProject/LinkBinariesBuildPhase_KNOWN_LOCATION-check.cmake
index e1484e7..1044f78 100644
--- a/Tests/RunCMake/XcodeProject/LinkBinariesBuildPhase_KNOWN_LOCATION-check.cmake
+++ b/Tests/RunCMake/XcodeProject/LinkBinariesBuildPhase_KNOWN_LOCATION-check.cmake
@@ -4,13 +4,20 @@ include(${RunCMake_TEST_BINARY_DIR}/foundLibs.cmake)
# obj2 --> Embeds func3.o in the link flags, but obj2 is part of the path
# ${libz} --> This is for imported2
-foreach(mainTarget IN ITEMS app1 shared1 module1 sharedFramework1)
+foreach(mainTarget IN ITEMS app1 app2 shared1 shared3 module1 sharedFramework1)
checkFlags(OTHER_LDFLAGS ${mainTarget}
"obj2"
"static2;shared2;staticFramework2;sharedFramework2;${libz};${libresolv};CoreFoundation;sharedFrameworkExt;staticFrameworkExt"
)
endforeach()
+foreach(mainTarget IN ITEMS app3 shared4)
+ checkFlags(OTHER_LDFLAGS ${mainTarget}
+ "obj2;shared2;sharedFramework2;sharedFrameworkExt"
+ "static2;staticFramework2;${libz};${libresolv};CoreFoundation;staticFrameworkExt"
+ )
+endforeach()
+
foreach(mainTarget IN ITEMS static1 staticFramework1)
checkFlags(OTHER_LIBTOOLFLAGS ${mainTarget}
"obj2"
diff --git a/Tests/RunCMake/XcodeProject/LinkBinariesBuildPhase_NONE-check.cmake b/Tests/RunCMake/XcodeProject/LinkBinariesBuildPhase_NONE-check.cmake
index 2601676..b67632b 100644
--- a/Tests/RunCMake/XcodeProject/LinkBinariesBuildPhase_NONE-check.cmake
+++ b/Tests/RunCMake/XcodeProject/LinkBinariesBuildPhase_NONE-check.cmake
@@ -4,7 +4,7 @@ include(${RunCMake_TEST_BINARY_DIR}/foundLibs.cmake)
# obj2 --> Embeds func3.o in the link flags, but obj2 is part of the path
# ${libz} --> This is for imported2
-foreach(mainTarget IN ITEMS app1 shared1 module1 sharedFramework1)
+foreach(mainTarget IN ITEMS app1 app2 app3 shared1 shared3 shared4 module1 sharedFramework1)
checkFlags(OTHER_LDFLAGS ${mainTarget}
"static2;shared2;staticFramework2;sharedFramework2;obj2;${libz};${libresolv};CoreFoundation;sharedFrameworkExt;staticFrameworkExt"
""