mirror of
https://github.com/Kitware/CMake.git
synced 2026-02-18 13:10:17 -06:00
cmGlobalGenerator: Add helper to split framework path
cmComputeLinkInformation and cmGlobalXCodeGenerator now rely on this method to handle framework paths.
This commit is contained in:
@@ -8,6 +8,7 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include <cm/memory>
|
#include <cm/memory>
|
||||||
|
#include <cm/optional>
|
||||||
#include <cmext/algorithm>
|
#include <cmext/algorithm>
|
||||||
|
|
||||||
#include "cmComputeLinkDepends.h"
|
#include "cmComputeLinkDepends.h"
|
||||||
@@ -1679,7 +1680,8 @@ void cmComputeLinkInformation::AddFrameworkItem(LinkEntry const& entry)
|
|||||||
std::string const& item = entry.Item.Value;
|
std::string const& item = entry.Item.Value;
|
||||||
|
|
||||||
// Try to separate the framework name and path.
|
// Try to separate the framework name and path.
|
||||||
if (!this->SplitFramework.find(item)) {
|
auto fwItems = this->GlobalGenerator->SplitFrameworkPath(item);
|
||||||
|
if (!fwItems) {
|
||||||
std::ostringstream e;
|
std::ostringstream e;
|
||||||
e << "Could not parse framework path \"" << item << "\" "
|
e << "Could not parse framework path \"" << item << "\" "
|
||||||
<< "linked by target " << this->Target->GetName() << ".";
|
<< "linked by target " << this->Target->GetName() << ".";
|
||||||
@@ -1687,8 +1689,8 @@ void cmComputeLinkInformation::AddFrameworkItem(LinkEntry const& entry)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string fw_path = this->SplitFramework.match(1);
|
std::string fw_path = std::move(fwItems->first);
|
||||||
std::string fw = this->SplitFramework.match(2);
|
std::string fw = std::move(fwItems->second);
|
||||||
std::string full_fw = cmStrCat(fw_path, '/', fw, ".framework/", fw);
|
std::string full_fw = cmStrCat(fw_path, '/', fw, ".framework/", fw);
|
||||||
|
|
||||||
// Add the directory portion to the framework search path.
|
// Add the directory portion to the framework search path.
|
||||||
@@ -1739,9 +1741,6 @@ void cmComputeLinkInformation::ComputeFrameworkInfo()
|
|||||||
|
|
||||||
this->FrameworkPathsEmitted.insert(implicitDirVec.begin(),
|
this->FrameworkPathsEmitted.insert(implicitDirVec.begin(),
|
||||||
implicitDirVec.end());
|
implicitDirVec.end());
|
||||||
|
|
||||||
// Regular expression to extract a framework path and name.
|
|
||||||
this->SplitFramework.compile("(.*)/(.*)\\.framework$");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void cmComputeLinkInformation::AddFrameworkPath(std::string const& p)
|
void cmComputeLinkInformation::AddFrameworkPath(std::string const& p)
|
||||||
|
|||||||
@@ -205,7 +205,6 @@ private:
|
|||||||
void ComputeFrameworkInfo();
|
void ComputeFrameworkInfo();
|
||||||
void AddFrameworkPath(std::string const& p);
|
void AddFrameworkPath(std::string const& p);
|
||||||
std::set<std::string> FrameworkPathsEmitted;
|
std::set<std::string> FrameworkPathsEmitted;
|
||||||
cmsys::RegularExpression SplitFramework;
|
|
||||||
|
|
||||||
// Linker search path computation.
|
// Linker search path computation.
|
||||||
std::unique_ptr<cmOrderDirectories> OrderLinkerSearchPath;
|
std::unique_ptr<cmOrderDirectories> OrderLinkerSearchPath;
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
#include "cmsys/Directory.hxx"
|
#include "cmsys/Directory.hxx"
|
||||||
#include "cmsys/FStream.hxx"
|
#include "cmsys/FStream.hxx"
|
||||||
|
#include "cmsys/RegularExpression.hxx"
|
||||||
|
|
||||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||||
# include <windows.h>
|
# include <windows.h>
|
||||||
@@ -2522,6 +2523,36 @@ bool cmGlobalGenerator::NameResolvesToFramework(
|
|||||||
return false;
|
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<std::pair<std::string, std::string>>
|
||||||
|
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<std::string, std::string>{ frameworkPath.match(2), name };
|
||||||
|
}
|
||||||
|
|
||||||
|
return cm::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
bool cmGlobalGenerator::CheckCMP0037(std::string const& targetName,
|
bool cmGlobalGenerator::CheckCMP0037(std::string const& targetName,
|
||||||
std::string const& reason) const
|
std::string const& reason) const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -367,6 +367,10 @@ public:
|
|||||||
/** Determine if a name resolves to a framework on disk or a built target
|
/** Determine if a name resolves to a framework on disk or a built target
|
||||||
that is a framework. */
|
that is a framework. */
|
||||||
bool NameResolvesToFramework(const std::string& libname) const;
|
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<std::pair<std::string, std::string>> SplitFrameworkPath(
|
||||||
|
const std::string& path) const;
|
||||||
|
|
||||||
cmMakefile* FindMakefile(const std::string& start_dir) const;
|
cmMakefile* FindMakefile(const std::string& start_dir) const;
|
||||||
cmLocalGenerator* FindLocalGenerator(cmDirectoryId const& id) const;
|
cmLocalGenerator* FindLocalGenerator(cmDirectoryId const& id) const;
|
||||||
|
|||||||
@@ -1154,47 +1154,25 @@ std::string GetSourcecodeValueFromFileExtension(
|
|||||||
return sourcecode;
|
return sourcecode;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the file has no extension it's either a raw executable or might
|
} // anonymous
|
||||||
// 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.
|
// Extracts the framework directory, if path matches the framework syntax
|
||||||
// .tbd files also can be located in SDK frameworks (they are
|
// otherwise returns the path untouched
|
||||||
// placeholders for actual libraries shipped with the OS)
|
std::string cmGlobalXCodeGenerator::GetLibraryOrFrameworkPath(
|
||||||
std::string GetLibraryOrFrameworkPath(const std::string& path)
|
const std::string& path) const
|
||||||
{
|
{
|
||||||
auto ext = cmSystemTools::GetFilenameLastExtension(path);
|
auto fwItems = this->SplitFrameworkPath(path);
|
||||||
if (ext.empty() || ext == ".tbd") {
|
if (fwItems) {
|
||||||
auto name = cmSystemTools::GetFilenameWithoutExtension(path);
|
if (fwItems->first.empty()) {
|
||||||
// Check for iOS framework structure:
|
return cmStrCat(fwItems->second, ".framework");
|
||||||
// FwName.framework/FwName (and also on macOS where FwName lib is a
|
} else {
|
||||||
// symlink)
|
return cmStrCat(fwItems->first, '/', fwItems->second, ".framework");
|
||||||
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<std::string> 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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // anonymous
|
|
||||||
|
|
||||||
cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeFileReferenceFromPath(
|
cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeFileReferenceFromPath(
|
||||||
const std::string& fullpath, cmGeneratorTarget* target,
|
const std::string& fullpath, cmGeneratorTarget* target,
|
||||||
const std::string& lang, cmSourceFile* sf)
|
const std::string& lang, cmSourceFile* sf)
|
||||||
@@ -1217,7 +1195,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeFileReferenceFromPath(
|
|||||||
ext = ext.substr(1);
|
ext = ext.substr(1);
|
||||||
}
|
}
|
||||||
if (fileType.empty()) {
|
if (fileType.empty()) {
|
||||||
path = GetLibraryOrFrameworkPath(path);
|
path = this->GetLibraryOrFrameworkPath(path);
|
||||||
ext = cmSystemTools::GetFilenameLastExtension(path);
|
ext = cmSystemTools::GetFilenameLastExtension(path);
|
||||||
if (!ext.empty()) {
|
if (!ext.empty()) {
|
||||||
ext = ext.substr(1);
|
ext = ext.substr(1);
|
||||||
@@ -3541,7 +3519,7 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
|
|||||||
} else {
|
} else {
|
||||||
linkDir = libItem->Value.Value;
|
linkDir = libItem->Value.Value;
|
||||||
}
|
}
|
||||||
linkDir = GetLibraryOrFrameworkPath(linkDir);
|
linkDir = this->GetLibraryOrFrameworkPath(linkDir);
|
||||||
bool isFramework = cmSystemTools::IsPathToFramework(linkDir);
|
bool isFramework = cmSystemTools::IsPathToFramework(linkDir);
|
||||||
linkDir = cmSystemTools::GetParentDirectory(linkDir);
|
linkDir = cmSystemTools::GetParentDirectory(linkDir);
|
||||||
if (isFramework) {
|
if (isFramework) {
|
||||||
@@ -3729,7 +3707,7 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
|
|||||||
if (cmSystemTools::FileIsFullPath(cleanPath)) {
|
if (cmSystemTools::FileIsFullPath(cleanPath)) {
|
||||||
cleanPath = cmSystemTools::CollapseFullPath(cleanPath);
|
cleanPath = cmSystemTools::CollapseFullPath(cleanPath);
|
||||||
}
|
}
|
||||||
const auto libPath = GetLibraryOrFrameworkPath(cleanPath);
|
const auto libPath = this->GetLibraryOrFrameworkPath(cleanPath);
|
||||||
if (cmSystemTools::StringEndsWith(libPath.c_str(), ".framework")) {
|
if (cmSystemTools::StringEndsWith(libPath.c_str(), ".framework")) {
|
||||||
const auto fwName =
|
const auto fwName =
|
||||||
cmSystemTools::GetFilenameWithoutExtension(libPath);
|
cmSystemTools::GetFilenameWithoutExtension(libPath);
|
||||||
|
|||||||
@@ -330,6 +330,8 @@ private:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string GetLibraryOrFrameworkPath(const std::string& path) const;
|
||||||
|
|
||||||
std::string GetObjectsDirectory(const std::string& projName,
|
std::string GetObjectsDirectory(const std::string& projName,
|
||||||
const std::string& configName,
|
const std::string& configName,
|
||||||
const cmGeneratorTarget* t,
|
const cmGeneratorTarget* t,
|
||||||
|
|||||||
Reference in New Issue
Block a user