diff options
Diffstat (limited to 'Source')
-rw-r--r-- | Source/cmComputeLinkInformation.cxx | 87 | ||||
-rw-r--r-- | Source/cmComputeLinkInformation.h | 5 | ||||
-rw-r--r-- | Source/cmGlobalGenerator.cxx | 13 | ||||
-rw-r--r-- | Source/cmGlobalGenerator.h | 7 | ||||
-rw-r--r-- | Source/cmGlobalXCodeGenerator.cxx | 46 |
5 files changed, 112 insertions, 46 deletions
diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx index 16f20036fc..cf8c9a14c7 100644 --- a/Source/cmComputeLinkInformation.cxx +++ b/Source/cmComputeLinkInformation.cxx @@ -10,6 +10,7 @@ #include <cm/memory> #include <cm/optional> #include <cmext/algorithm> +#include <cmext/string_view> #include "cmComputeLinkDepends.h" #include "cmGeneratorTarget.h" @@ -19,7 +20,6 @@ #include "cmMakefile.h" #include "cmMessageType.h" #include "cmOrderDirectories.h" -#include "cmOutputConverter.h" #include "cmPlaceholderExpander.h" #include "cmPolicies.h" #include "cmState.h" @@ -1045,12 +1045,14 @@ void cmComputeLinkInformation::AddItem(LinkEntry const& entry) } } else { // This is not a CMake target. Use the name given. - if (cmSystemTools::FileIsFullPath(item.Value)) { - if (cmSystemTools::IsPathToFramework(item.Value) && - this->Makefile->IsOn("APPLE")) { - // This is a framework. - this->AddFrameworkItem(entry); - } else if (cmSystemTools::FileIsDirectory(item.Value)) { + if (cmHasSuffix(entry.Feature, "FRAMEWORK"_s) || + (entry.Feature == DEFAULT && + cmSystemTools::IsPathToFramework(item.Value) && + this->Makefile->IsOn("APPLE"))) { + // This is a framework. + this->AddFrameworkItem(entry); + } else if (cmSystemTools::FileIsFullPath(item.Value)) { + if (cmSystemTools::FileIsDirectory(item.Value)) { // This is a directory. this->DropDirectoryItem(item); } else { @@ -1425,11 +1427,41 @@ void cmComputeLinkInformation::AddTargetItem(LinkEntry const& entry) this->OldLinkDirItems.push_back(item.Value); } - // Now add the full path to the library. - this->Items.emplace_back(item, ItemIsPath::Yes, target, - this->FindLibraryFeature(entry.Feature == DEFAULT - ? "__CMAKE_LINK_LIBRARY" - : entry.Feature)); + if (target->IsFrameworkOnApple() && this->GlobalGenerator->IsXcode() && + entry.Feature == DEFAULT) { + // ensure FRAMEWORK feature is loaded + this->AddLibraryFeature("FRAMEWORK"); + } + + if (cmHasSuffix(entry.Feature, "FRAMEWORK"_s) && + target->IsFrameworkOnApple() && !this->GlobalGenerator->IsXcode()) { + // Add the framework directory and the framework item itself + auto fwItems = this->GlobalGenerator->SplitFrameworkPath(item.Value, true); + if (!fwItems) { + this->CMakeInstance->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Could not parse framework path \"", item.Value, + "\" linked by target ", this->Target->GetName(), '.'), + item.Backtrace); + return; + } + if (!fwItems->first.empty()) { + // Add the directory portion to the framework search path. + this->AddFrameworkPath(fwItems->first); + } + this->Items.emplace_back(fwItems->second, ItemIsPath::Yes, target, + this->FindLibraryFeature(entry.Feature)); + } else { + // Now add the full path to the library. + this->Items.emplace_back( + item, ItemIsPath::Yes, target, + this->FindLibraryFeature( + entry.Feature == DEFAULT + ? (target->IsFrameworkOnApple() && this->GlobalGenerator->IsXcode() + ? "FRAMEWORK" + : "__CMAKE_LINK_LIBRARY") + : entry.Feature)); + } } void cmComputeLinkInformation::AddFullItem(LinkEntry const& entry) @@ -1680,7 +1712,8 @@ void cmComputeLinkInformation::AddFrameworkItem(LinkEntry const& entry) std::string const& item = entry.Item.Value; // Try to separate the framework name and path. - auto fwItems = this->GlobalGenerator->SplitFrameworkPath(item); + auto fwItems = + this->GlobalGenerator->SplitFrameworkPath(item, entry.Feature != DEFAULT); if (!fwItems) { std::ostringstream e; e << "Could not parse framework path \"" << item << "\" " @@ -1691,24 +1724,34 @@ void cmComputeLinkInformation::AddFrameworkItem(LinkEntry const& entry) std::string fw_path = std::move(fwItems->first); std::string fw = std::move(fwItems->second); - std::string full_fw = cmStrCat(fw_path, '/', fw, ".framework/", fw); + std::string full_fw = cmStrCat(fw, ".framework/", fw); - // Add the directory portion to the framework search path. - this->AddFrameworkPath(fw_path); + if (!fw_path.empty()) { + full_fw = cmStrCat(fw_path, '/', full_fw); + // Add the directory portion to the framework search path. + this->AddFrameworkPath(fw_path); + } // add runtime information this->AddLibraryRuntimeInfo(full_fw); + if (entry.Feature == DEFAULT) { + // ensure FRAMEWORK feature is loaded + this->AddLibraryFeature("FRAMEWORK"); + } + if (this->GlobalGenerator->IsXcode()) { // Add framework path - it will be handled by Xcode after it's added to // "Link Binary With Libraries" build phase - this->Items.emplace_back(item, ItemIsPath::Yes); + this->Items.emplace_back(item, ItemIsPath::Yes, nullptr, + this->FindLibraryFeature(entry.Feature == DEFAULT + ? "FRAMEWORK" + : entry.Feature)); } else { - // Add the item using the -framework option. - this->Items.emplace_back(std::string("-framework"), ItemIsPath::No); - cmOutputConverter converter(this->Makefile->GetStateSnapshot()); - fw = converter.EscapeForShell(fw); - this->Items.emplace_back(fw, ItemIsPath::No); + this->Items.emplace_back(fw, ItemIsPath::Yes, nullptr, + this->FindLibraryFeature(entry.Feature == DEFAULT + ? "FRAMEWORK" + : entry.Feature)); } } diff --git a/Source/cmComputeLinkInformation.h b/Source/cmComputeLinkInformation.h index ccb22bd647..4b7fb1aacc 100644 --- a/Source/cmComputeLinkInformation.h +++ b/Source/cmComputeLinkInformation.h @@ -63,6 +63,11 @@ public: cmGeneratorTarget const* Target = nullptr; bool HasFeature() const { return this->Feature != nullptr; } + const std::string& GetFeatureName() const + { + return HasFeature() ? this->Feature->Name + : cmComputeLinkDepends::LinkEntry::DEFAULT; + } BT<std::string> GetFormattedItem(std::string const& path) const { diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 79d637d644..baa54e58a0 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -2529,7 +2529,8 @@ bool cmGlobalGenerator::NameResolvesToFramework( // .tbd files also can be located in SDK frameworks (they are // placeholders for actual libraries shipped with the OS) cm::optional<std::pair<std::string, std::string>> -cmGlobalGenerator::SplitFrameworkPath(const std::string& path) const +cmGlobalGenerator::SplitFrameworkPath(const std::string& path, + bool extendedFormat) const { // Check for framework structure: // (/path/to/)?FwName.framework @@ -2550,6 +2551,16 @@ cmGlobalGenerator::SplitFrameworkPath(const std::string& path) const return std::pair<std::string, std::string>{ frameworkPath.match(2), name }; } + if (extendedFormat) { + // path format can be more flexible: (/path/to/)?fwName(.framework)? + auto fwDir = cmSystemTools::GetParentDirectory(path); + auto name = cmSystemTools::GetFilenameLastExtension(path) == ".framework" + ? cmSystemTools::GetFilenameWithoutExtension(path) + : cmSystemTools::GetFilenameName(path); + + return std::pair<std::string, std::string>{ fwDir, name }; + } + return cm::nullopt; } diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index 683968edf9..a4b2ae3e6d 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -368,9 +368,12 @@ public: that is a framework. */ bool NameResolvesToFramework(const std::string& libname) const; /** Split a framework path to the directory and name of the framework - * returns std::nullopt if the path does not match with framework format */ + * returns std::nullopt if the path does not match with framework format + * when extendedFormat is true, required format is relaxed (i.e. extension + * `.framework' is optional). Used when FRAMEWORK link feature is + * specified */ cm::optional<std::pair<std::string, std::string>> SplitFrameworkPath( - const std::string& path) const; + const std::string& path, bool extendedFormat = false) const; cmMakefile* FindMakefile(const std::string& start_dir) const; cmLocalGenerator* FindLocalGenerator(cmDirectoryId const& id) const; diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 7a8bbcdb84..b752c41b44 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -3519,13 +3519,14 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target) } else { linkDir = libItem->Value.Value; } - linkDir = this->GetLibraryOrFrameworkPath(linkDir); - bool isFramework = cmSystemTools::IsPathToFramework(linkDir); - linkDir = cmSystemTools::GetParentDirectory(linkDir); - if (isFramework) { - if (std::find(frameworkSearchPaths.begin(), frameworkSearchPaths.end(), - linkDir) == frameworkSearchPaths.end()) { - frameworkSearchPaths.push_back(linkDir); + if (cmHasSuffix(libItem->GetFeatureName(), "FRAMEWORK"_s)) { + auto fwItems = this->SplitFrameworkPath(linkDir, true); + if (fwItems && !fwItems->first.empty()) { + linkDir = std::move(fwItems->first); + if (std::find(frameworkSearchPaths.begin(), frameworkSearchPaths.end(), + linkDir) == frameworkSearchPaths.end()) { + frameworkSearchPaths.push_back(linkDir); + } } } else { if (std::find(linkSearchPaths.begin(), linkSearchPaths.end(), linkDir) == @@ -3533,7 +3534,7 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target) linkSearchPaths.push_back(linkDir); } } - // Add target dependency + if (libItem->Target && !libItem->Target->IsImported()) { for (auto const& configName : this->CurrentConfigurationTypes) { target->AddDependTarget(configName, libItem->Target->GetName()); @@ -3707,24 +3708,27 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target) if (cmSystemTools::FileIsFullPath(cleanPath)) { cleanPath = cmSystemTools::CollapseFullPath(cleanPath); } - const auto libPath = this->GetLibraryOrFrameworkPath(cleanPath); - if (cmSystemTools::StringEndsWith(libPath.c_str(), ".framework")) { - const auto fwName = - cmSystemTools::GetFilenameWithoutExtension(libPath); - const auto fwDir = cmSystemTools::GetParentDirectory(libPath); - if (emitted.insert(fwDir).second) { - // This is a search path we had not added before and it isn't an - // implicit search path, so we need it - libPaths.Add("-F " + this->XCodeEscapePath(fwDir)); + bool isFramework = + cmHasSuffix(libName.GetFeatureName(), "FRAMEWORK"_s); + if (isFramework) { + const auto fwItems = + this->SplitFrameworkPath(cleanPath, isFramework); + if (!fwItems->first.empty() && + emitted.insert(fwItems->first).second) { + // This is a search path we had not added before and it isn't + // an implicit search path, so we need it + libPaths.Add("-F " + this->XCodeEscapePath(fwItems->first)); } - libPaths.Add("-framework " + this->XCodeEscapePath(fwName)); + libPaths.Add( + libName.GetFormattedItem(this->XCodeEscapePath(fwItems->second)) + .Value); } else { libPaths.Add( libName.GetFormattedItem(this->XCodeEscapePath(cleanPath)) .Value); } if ((!libName.Target || libName.Target->IsImported()) && - IsLinkPhaseLibraryExtension(libPath)) { + (isFramework || IsLinkPhaseLibraryExtension(cleanPath))) { // Create file reference for embedding auto it = this->ExternalLibRefs.find(cleanPath); if (it == this->ExternalLibRefs.end()) { @@ -3892,8 +3896,8 @@ void cmGlobalXCodeGenerator::AddEmbeddedFrameworks(cmXCodeObject* target) { static const auto dstSubfolderSpec = "10"; - // Despite the name, by default Xcode uses "Embed Frameworks" build phase for - // both frameworks and dynamic libraries + // Despite the name, by default Xcode uses "Embed Frameworks" build phase + // for both frameworks and dynamic libraries this->AddEmbeddedObjects(target, "Embed Frameworks", "XCODE_EMBED_FRAMEWORKS", dstSubfolderSpec, NoActionOnCopyByDefault); |