From 40178f3c908795a993148553a04be25748942efc Mon Sep 17 00:00:00 2001 From: Marc Chevrier Date: Thu, 10 Feb 2022 19:16:18 +0100 Subject: cmGlobalGenerator: Add helper to split framework path cmComputeLinkInformation and cmGlobalXCodeGenerator now rely on this method to handle framework paths. --- Source/cmComputeLinkInformation.cxx | 11 ++++---- Source/cmComputeLinkInformation.h | 1 - Source/cmGlobalGenerator.cxx | 31 +++++++++++++++++++++ Source/cmGlobalGenerator.h | 4 +++ Source/cmGlobalXCodeGenerator.cxx | 54 +++++++++++-------------------------- Source/cmGlobalXCodeGenerator.h | 2 ++ 6 files changed, 58 insertions(+), 45 deletions(-) diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx index 15e9d60..16f2003 100644 --- a/Source/cmComputeLinkInformation.cxx +++ b/Source/cmComputeLinkInformation.cxx @@ -8,6 +8,7 @@ #include #include +#include #include #include "cmComputeLinkDepends.h" @@ -1679,7 +1680,8 @@ void cmComputeLinkInformation::AddFrameworkItem(LinkEntry const& entry) std::string const& item = entry.Item.Value; // Try to separate the framework name and path. - if (!this->SplitFramework.find(item)) { + auto fwItems = this->GlobalGenerator->SplitFrameworkPath(item); + if (!fwItems) { std::ostringstream e; e << "Could not parse framework path \"" << item << "\" " << "linked by target " << this->Target->GetName() << "."; @@ -1687,8 +1689,8 @@ void cmComputeLinkInformation::AddFrameworkItem(LinkEntry const& entry) return; } - std::string fw_path = this->SplitFramework.match(1); - std::string fw = this->SplitFramework.match(2); + 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); // Add the directory portion to the framework search path. @@ -1739,9 +1741,6 @@ void cmComputeLinkInformation::ComputeFrameworkInfo() this->FrameworkPathsEmitted.insert(implicitDirVec.begin(), implicitDirVec.end()); - - // Regular expression to extract a framework path and name. - this->SplitFramework.compile("(.*)/(.*)\\.framework$"); } void cmComputeLinkInformation::AddFrameworkPath(std::string const& p) diff --git a/Source/cmComputeLinkInformation.h b/Source/cmComputeLinkInformation.h index ce9f393..ccb22bd 100644 --- a/Source/cmComputeLinkInformation.h +++ b/Source/cmComputeLinkInformation.h @@ -205,7 +205,6 @@ private: void ComputeFrameworkInfo(); void AddFrameworkPath(std::string const& p); std::set FrameworkPathsEmitted; - cmsys::RegularExpression SplitFramework; // Linker search path computation. std::unique_ptr OrderLinkerSearchPath; diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 156ecce..79d637d 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -19,6 +19,7 @@ #include "cmsys/Directory.hxx" #include "cmsys/FStream.hxx" +#include "cmsys/RegularExpression.hxx" #if defined(_WIN32) && !defined(__CYGWIN__) # include @@ -2522,6 +2523,36 @@ bool cmGlobalGenerator::NameResolvesToFramework( return false; } +// If the file has no extension it's either a raw executable or might +// be a direct reference to a binary within a framework (bad practice!). +// This is where we change the path to point to the framework directory. +// .tbd files also can be located in SDK frameworks (they are +// placeholders for actual libraries shipped with the OS) +cm::optional> +cmGlobalGenerator::SplitFrameworkPath(const std::string& path) const +{ + // Check for framework structure: + // (/path/to/)?FwName.framework + // or (/path/to/)?FwName.framework/FwName(.tbd)? + // or (/path/to/)?FwName.framework/Versions/*/FwName(.tbd)? + static cmsys::RegularExpression frameworkPath( + "((.+)/)?(.+)\\.framework(/Versions/[^/]+)?(/(.+))?$"); + + auto ext = cmSystemTools::GetFilenameLastExtension(path); + if ((ext.empty() || ext == ".tbd" || ext == ".framework") && + frameworkPath.find(path)) { + auto name = frameworkPath.match(3); + auto libname = + cmSystemTools::GetFilenameWithoutExtension(frameworkPath.match(6)); + if (!libname.empty() && name != libname) { + return cm::nullopt; + } + return std::pair{ frameworkPath.match(2), name }; + } + + return cm::nullopt; +} + bool cmGlobalGenerator::CheckCMP0037(std::string const& targetName, std::string const& reason) const { diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index a43d4a6..683968e 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -367,6 +367,10 @@ public: /** Determine if a name resolves to a framework on disk or a built target 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 */ + cm::optional> SplitFrameworkPath( + const std::string& path) 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 489c7fb..7a8bbcd 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -1154,47 +1154,25 @@ std::string GetSourcecodeValueFromFileExtension( return sourcecode; } -// If the file has no extension it's either a raw executable or might -// be a direct reference to a binary within a framework (bad practice!). -// This is where we change the path to point to the framework directory. -// .tbd files also can be located in SDK frameworks (they are -// placeholders for actual libraries shipped with the OS) -std::string GetLibraryOrFrameworkPath(const std::string& path) +} // anonymous + +// Extracts the framework directory, if path matches the framework syntax +// otherwise returns the path untouched +std::string cmGlobalXCodeGenerator::GetLibraryOrFrameworkPath( + const std::string& path) const { - auto ext = cmSystemTools::GetFilenameLastExtension(path); - if (ext.empty() || ext == ".tbd") { - auto name = cmSystemTools::GetFilenameWithoutExtension(path); - // Check for iOS framework structure: - // FwName.framework/FwName (and also on macOS where FwName lib is a - // symlink) - auto parentDir = cmSystemTools::GetParentDirectory(path); - auto parentName = cmSystemTools::GetFilenameWithoutExtension(parentDir); - ext = cmSystemTools::GetFilenameLastExtension(parentDir); - if (ext == ".framework" && name == parentName) { - return parentDir; - } - // Check for macOS framework structure: - // FwName.framework/Versions/*/FwName - std::vector components; - cmSystemTools::SplitPath(path, components); - if (components.size() > 3 && - components[components.size() - 3] == "Versions") { - ext = cmSystemTools::GetFilenameLastExtension( - components[components.size() - 4]); - parentName = cmSystemTools::GetFilenameWithoutExtension( - components[components.size() - 4]); - if (ext == ".framework" && name == parentName) { - components.erase(components.begin() + components.size() - 3, - components.end()); - return cmSystemTools::JoinPath(components); - } + auto fwItems = this->SplitFrameworkPath(path); + if (fwItems) { + if (fwItems->first.empty()) { + return cmStrCat(fwItems->second, ".framework"); + } else { + return cmStrCat(fwItems->first, '/', fwItems->second, ".framework"); } } + return path; } -} // anonymous - cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeFileReferenceFromPath( const std::string& fullpath, cmGeneratorTarget* target, const std::string& lang, cmSourceFile* sf) @@ -1217,7 +1195,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeFileReferenceFromPath( ext = ext.substr(1); } if (fileType.empty()) { - path = GetLibraryOrFrameworkPath(path); + path = this->GetLibraryOrFrameworkPath(path); ext = cmSystemTools::GetFilenameLastExtension(path); if (!ext.empty()) { ext = ext.substr(1); @@ -3541,7 +3519,7 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target) } else { linkDir = libItem->Value.Value; } - linkDir = GetLibraryOrFrameworkPath(linkDir); + linkDir = this->GetLibraryOrFrameworkPath(linkDir); bool isFramework = cmSystemTools::IsPathToFramework(linkDir); linkDir = cmSystemTools::GetParentDirectory(linkDir); if (isFramework) { @@ -3729,7 +3707,7 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target) if (cmSystemTools::FileIsFullPath(cleanPath)) { cleanPath = cmSystemTools::CollapseFullPath(cleanPath); } - const auto libPath = GetLibraryOrFrameworkPath(cleanPath); + const auto libPath = this->GetLibraryOrFrameworkPath(cleanPath); if (cmSystemTools::StringEndsWith(libPath.c_str(), ".framework")) { const auto fwName = cmSystemTools::GetFilenameWithoutExtension(libPath); diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h index ff6ffe8..98cebef 100644 --- a/Source/cmGlobalXCodeGenerator.h +++ b/Source/cmGlobalXCodeGenerator.h @@ -330,6 +330,8 @@ private: { } + std::string GetLibraryOrFrameworkPath(const std::string& path) const; + std::string GetObjectsDirectory(const std::string& projName, const std::string& configName, const cmGeneratorTarget* t, -- cgit v0.12