mirror of
https://github.com/Kitware/CMake.git
synced 2026-01-11 08:20:18 -06:00
XCode: ensure LINK_LIBRARY genex is usable with XCODE_LINK_BUILD_PHASE_MODE
Fixes: #24176
This commit is contained in:
@@ -3581,27 +3581,36 @@ 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;
|
||||
} 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);
|
||||
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 {
|
||||
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) {
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
""
|
||||
|
||||
Reference in New Issue
Block a user