From 7d1924613858ec15d7d628306ea0e3156a1a6ddd Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Mon, 6 Nov 2023 12:40:13 -0500 Subject: Xcode: Fix linking against .xcframework from static libraries Issue: #21752 --- Source/cmGlobalXCodeGenerator.cxx | 93 +++++++++++++++++----- .../XcFramework/create-executable-target.cmake | 3 + Tests/RunCMake/XcFramework/create-executable.cmake | 3 + .../XcFramework/myconsuminglib/myconsuminglib.c | 6 ++ 4 files changed, 84 insertions(+), 21 deletions(-) create mode 100644 Tests/RunCMake/XcFramework/myconsuminglib/myconsuminglib.c diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 5076e6c..cce45a3 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -3854,18 +3854,84 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target) configName); } - // Skip link information for object libraries. - if (gt->GetType() == cmStateEnums::OBJECT_LIBRARY || - gt->GetType() == cmStateEnums::STATIC_LIBRARY) { - continue; - } - // Compute the link library and directory information. cmComputeLinkInformation* cli = gt->GetLinkInformation(configName); if (!cli) { continue; } + // add .xcframework include paths + { + // Keep track of framework search paths we've already added or that are + // part of the set of implicit search paths. We don't want to repeat + // them and we also need to avoid hard-coding any SDK-specific paths. + // This is essential for getting device-and-simulator builds to work, + // otherwise we end up hard-coding a path to the wrong SDK for + // SDK-provided frameworks that are added by their full path. + std::set emitted(cli->GetFrameworkPathsEmitted()); + BuildObjectListOrString includePaths(this, true); + BuildObjectListOrString fwSearchPaths(this, true); + for (auto const& libItem : configItemMap[configName]) { + auto const& libName = *libItem; + if (libName.IsPath == cmComputeLinkInformation::ItemIsPath::Yes) { + auto cleanPath = libName.Value.Value; + if (cmSystemTools::FileIsFullPath(cleanPath)) { + cleanPath = cmSystemTools::CollapseFullPath(cleanPath); + } + bool isXcFramework = + cmHasSuffix(libName.GetFeatureName(), "XCFRAMEWORK"_s); + if (isXcFramework) { + auto plist = cmParseXcFrameworkPlist( + cleanPath, *this->Makefiles.front(), libName.Value.Backtrace); + if (!plist) { + return; + } + if (auto const* library = plist->SelectSuitableLibrary( + *this->Makefiles.front(), libName.Value.Backtrace)) { + auto libraryPath = + cmStrCat(cleanPath, '/', library->LibraryIdentifier, '/', + library->LibraryPath); + if (auto const fwDescriptor = this->SplitFrameworkPath( + libraryPath, + cmGlobalGenerator::FrameworkFormat::Relaxed)) { + if (!fwDescriptor->Directory.empty() && + emitted.insert(fwDescriptor->Directory).second) { + // This is a search path we had not added before and it + // isn't an implicit search path, so we need it + fwSearchPaths.Add( + this->XCodeEscapePath(fwDescriptor->Directory)); + } + } else { + if (!library->HeadersPath.empty()) { + includePaths.Add(this->XCodeEscapePath( + cmStrCat(cleanPath, '/', library->LibraryIdentifier, '/', + library->HeadersPath))); + } + } + } else { + return; + } + } + } + } + if (!includePaths.IsEmpty()) { + this->AppendBuildSettingAttribute(target, "HEADER_SEARCH_PATHS", + includePaths.CreateList(), + configName); + } + if (!fwSearchPaths.IsEmpty()) { + this->AppendBuildSettingAttribute(target, "FRAMEWORK_SEARCH_PATHS", + fwSearchPaths.CreateList(), + configName); + } + } + + // Skip link information for object libraries. + if (gt->GetType() == cmStateEnums::OBJECT_LIBRARY || + gt->GetType() == cmStateEnums::STATIC_LIBRARY) { + continue; + } + // Add dependencies directly on library files. for (auto const& libDep : cli->GetDepends()) { target->AddDependLibrary(configName, libDep); @@ -3972,13 +4038,6 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target) if (auto const fwDescriptor = this->SplitFrameworkPath( libraryPath, cmGlobalGenerator::FrameworkFormat::Relaxed)) { - if (!fwDescriptor->Directory.empty() && - emitted.insert(fwDescriptor->Directory).second) { - // This is a search path we had not added before and it - // isn't an implicit search path, so we need it - fwSearchPaths.Add( - this->XCodeEscapePath(fwDescriptor->Directory)); - } libPaths.Add(cmStrCat( "-framework ", this->XCodeEscapePath(fwDescriptor->GetLinkName()))); @@ -3986,14 +4045,6 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target) libPaths.Add( libName.GetFormattedItem(this->XCodeEscapePath(libraryPath)) .Value); - if (!library->HeadersPath.empty()) { - this->AppendBuildSettingAttribute( - target, "HEADER_SEARCH_PATHS", - this->CreateString(this->XCodeEscapePath( - cmStrCat(cleanPath, '/', library->LibraryIdentifier, '/', - library->HeadersPath))), - configName); - } } } else { return; diff --git a/Tests/RunCMake/XcFramework/create-executable-target.cmake b/Tests/RunCMake/XcFramework/create-executable-target.cmake index 0cc356c..1bc091f 100644 --- a/Tests/RunCMake/XcFramework/create-executable-target.cmake +++ b/Tests/RunCMake/XcFramework/create-executable-target.cmake @@ -19,3 +19,6 @@ set_property(TARGET mylib PROPERTY IMPORTED_LOCATION ${MYLIB_LIBRARY}) add_executable(myexe myexe/myexe.c) target_link_libraries(myexe PRIVATE mylib) + +add_library(myconsuminglib STATIC myconsuminglib/myconsuminglib.c) +target_link_libraries(myconsuminglib PRIVATE mylib) diff --git a/Tests/RunCMake/XcFramework/create-executable.cmake b/Tests/RunCMake/XcFramework/create-executable.cmake index 6706b9f..eaad890 100644 --- a/Tests/RunCMake/XcFramework/create-executable.cmake +++ b/Tests/RunCMake/XcFramework/create-executable.cmake @@ -16,3 +16,6 @@ endif() add_executable(myexe myexe/myexe.c) target_link_libraries(myexe PRIVATE ${MYLIB_LIBRARY}) + +add_library(myconsuminglib STATIC myconsuminglib/myconsuminglib.c) +target_link_libraries(myconsuminglib PRIVATE ${MYLIB_LIBRARY}) diff --git a/Tests/RunCMake/XcFramework/myconsuminglib/myconsuminglib.c b/Tests/RunCMake/XcFramework/myconsuminglib/myconsuminglib.c new file mode 100644 index 0000000..83c0789 --- /dev/null +++ b/Tests/RunCMake/XcFramework/myconsuminglib/myconsuminglib.c @@ -0,0 +1,6 @@ +#include + +void myconsuminglib(void) +{ + mylib(); +} -- cgit v0.12