summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
authorGusts Kaksis <gusts.kaksis@sonarworks.com>2020-10-24 10:41:13 (GMT)
committerCraig Scott <craig.scott@crascit.com>2020-11-28 04:36:24 (GMT)
commit5651901c54ac74912110ba0d2395b25a96570326 (patch)
tree10df62d0144f44027e8bcecb7d34038d85a21706 /Source
parent70f11b9d3c5d2cfd81b2e33cc6c315cd9b2d1473 (diff)
downloadCMake-5651901c54ac74912110ba0d2395b25a96570326.zip
CMake-5651901c54ac74912110ba0d2395b25a96570326.tar.gz
CMake-5651901c54ac74912110ba0d2395b25a96570326.tar.bz2
Xcode: add support for embedding frameworks
This commit also prepares for embedding things other than frameworks. In the future, we may want to embed resources and other types supported by Xcode, so the target properties have been documented in a way that clearly signals the future intent.
Diffstat (limited to 'Source')
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx134
-rw-r--r--Source/cmGlobalXCodeGenerator.h3
-rw-r--r--Source/cmXCodeObject.h7
3 files changed, 143 insertions, 1 deletions
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index a881b74..78c7538 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -773,7 +773,9 @@ void cmGlobalXCodeGenerator::ClearXCodeObjects()
this->TargetGroup.clear();
this->FileRefs.clear();
this->ExternalLibRefs.clear();
+ this->EmbeddedLibRefs.clear();
this->FileRefToBuildFileMap.clear();
+ this->FileRefToEmbedBuildFileMap.clear();
this->CommandsVisited.clear();
}
@@ -1197,7 +1199,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeFileReferenceFromPath(
}
}
// Make a copy so that we can override it later
- std::string path = fullpath;
+ std::string path = cmSystemTools::CollapseFullPath(fullpath);
// Compute the extension without leading '.'.
std::string ext = cmSystemTools::GetFilenameLastExtension(path);
if (!ext.empty()) {
@@ -1793,6 +1795,10 @@ void cmGlobalXCodeGenerator::CreateCustomCommands(
if (frameworkBuildPhase) {
buildPhases->AddObject(frameworkBuildPhase);
}
+
+ // When this build phase is present, it must be last. More build phases may
+ // be added later for embedding things and they will insert themselves just
+ // before this last build phase.
if (postBuildPhase) {
buildPhases->AddObject(postBuildPhase);
}
@@ -3632,6 +3638,130 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
}
}
+void cmGlobalXCodeGenerator::AddEmbeddedFrameworks(cmXCodeObject* target)
+{
+ cmGeneratorTarget* gt = target->GetTarget();
+ if (!gt) {
+ cmSystemTools::Error("Error no target on xobject\n");
+ return;
+ }
+ if (!gt->IsInBuildSystem()) {
+ return;
+ }
+ bool isFrameworkTarget = gt->IsFrameworkOnApple();
+ bool isBundleTarget = gt->GetPropertyAsBool("MACOSX_BUNDLE");
+ bool isCFBundleTarget = gt->IsCFBundleOnApple();
+ if (!(isFrameworkTarget || isBundleTarget || isCFBundleTarget)) {
+ return;
+ }
+ cmProp files = gt->GetProperty("XCODE_EMBED_FRAMEWORKS");
+ if (!files) {
+ return;
+ }
+
+ // Create an "Embedded Frameworks" build phase
+ auto* copyFilesBuildPhase =
+ this->CreateObject(cmXCodeObject::PBXCopyFilesBuildPhase);
+ std::string copyFilesBuildPhaseName = "Embed Frameworks";
+ std::string destinationFrameworks = "10";
+ copyFilesBuildPhase->SetComment(copyFilesBuildPhaseName);
+ copyFilesBuildPhase->AddAttribute("buildActionMask",
+ this->CreateString("2147483647"));
+ copyFilesBuildPhase->AddAttribute("dstSubfolderSpec",
+ this->CreateString(destinationFrameworks));
+ copyFilesBuildPhase->AddAttribute(
+ "name", this->CreateString(copyFilesBuildPhaseName));
+ if (cmProp fwEmbedPath = gt->GetProperty("XCODE_EMBED_FRAMEWORKS_PATH")) {
+ copyFilesBuildPhase->AddAttribute("dstPath",
+ this->CreateString(*fwEmbedPath));
+ } else {
+ copyFilesBuildPhase->AddAttribute("dstPath", this->CreateString(""));
+ }
+ copyFilesBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
+ this->CreateString("0"));
+ cmXCodeObject* buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
+ // Collect all embedded frameworks and add them to build phase
+ std::vector<std::string> relFiles = cmExpandedList(*files);
+ for (std::string const& relFile : relFiles) {
+ cmXCodeObject* buildFile{ nullptr };
+ std::string filePath = relFile;
+ auto* genTarget = FindGeneratorTarget(relFile);
+ if (genTarget) {
+ // This is a target - get it's product path reference
+ auto* xcTarget = FindXCodeTarget(genTarget);
+ if (!xcTarget) {
+ cmSystemTools::Error("Can not find a target for " +
+ genTarget->GetName());
+ continue;
+ }
+ // Add the target output file as a build reference for other targets
+ // to link against
+ auto* fileRefObject = xcTarget->GetAttribute("productReference");
+ if (!fileRefObject) {
+ cmSystemTools::Error("Target " + genTarget->GetName() +
+ " is missing product reference");
+ continue;
+ }
+ auto it = FileRefToEmbedBuildFileMap.find(fileRefObject);
+ if (it == FileRefToEmbedBuildFileMap.end()) {
+ buildFile = this->CreateObject(cmXCodeObject::PBXBuildFile);
+ buildFile->AddAttribute("fileRef", fileRefObject);
+ FileRefToEmbedBuildFileMap[fileRefObject] = buildFile;
+ } else {
+ buildFile = it->second;
+ }
+ } else if (cmSystemTools::IsPathToFramework(relFile)) {
+ // This is a regular string path - create file reference
+ auto it = EmbeddedLibRefs.find(relFile);
+ if (it == EmbeddedLibRefs.end()) {
+ cmXCodeObject* fileRef =
+ this->CreateXCodeFileReferenceFromPath(relFile, gt, "", nullptr);
+ if (fileRef) {
+ buildFile = this->CreateObject(cmXCodeObject::PBXBuildFile);
+ buildFile->SetComment(fileRef->GetComment());
+ buildFile->AddAttribute("fileRef",
+ this->CreateObjectReference(fileRef));
+ }
+ if (!buildFile) {
+ cmSystemTools::Error("Can't create build file for " + relFile);
+ continue;
+ }
+ this->EmbeddedLibRefs.emplace(filePath, buildFile);
+ } else {
+ buildFile = it->second;
+ }
+ }
+ if (!buildFile) {
+ cmSystemTools::Error("Can't find a build file for " + relFile);
+ continue;
+ }
+ // Set build file configuration
+ cmXCodeObject* settings =
+ this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
+ cmXCodeObject* attrs = this->CreateObject(cmXCodeObject::OBJECT_LIST);
+ const auto& rmHeadersProp =
+ gt->GetSafeProperty("XCODE_EMBED_FRAMEWORKS_REMOVE_HEADERS_ON_COPY");
+ if (cmIsOn(rmHeadersProp)) {
+ attrs->AddObject(this->CreateString("RemoveHeadersOnCopy"));
+ }
+ const auto& codeSignProp =
+ gt->GetSafeProperty("XCODE_EMBED_FRAMEWORKS_CODE_SIGN_ON_COPY");
+ if (cmIsOn(codeSignProp)) {
+ attrs->AddObject(this->CreateString("CodeSignOnCopy"));
+ }
+ settings->AddAttributeIfNotEmpty("ATTRIBUTES", attrs);
+ buildFile->AddAttributeIfNotEmpty("settings", settings);
+ if (!buildFiles->HasObject(buildFile)) {
+ buildFiles->AddObject(buildFile);
+ }
+ }
+ copyFilesBuildPhase->AddAttribute("files", buildFiles);
+ auto* buildPhases = target->GetAttribute("buildPhases");
+ // Insert embed build phase right before the post-build command
+ buildPhases->InsertObject(buildPhases->GetObjectCount() - 1,
+ copyFilesBuildPhase);
+}
+
bool cmGlobalXCodeGenerator::CreateGroups(
std::vector<cmLocalGenerator*>& generators)
{
@@ -4010,7 +4140,9 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects(
// loop over all targets and add link and depend info
for (auto t : targets) {
this->AddDependAndLinkInformation(t);
+ this->AddEmbeddedFrameworks(t);
}
+
if (this->XcodeBuildSystem == BuildSystem::One) {
this->CreateXCodeDependHackMakefile(targets);
}
diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h
index ab5eeb2..3cc4efe 100644
--- a/Source/cmGlobalXCodeGenerator.h
+++ b/Source/cmGlobalXCodeGenerator.h
@@ -187,6 +187,7 @@ private:
const std::string& configName);
cmXCodeObject* CreateUtilityTarget(cmGeneratorTarget* gtgt);
void AddDependAndLinkInformation(cmXCodeObject* target);
+ void AddEmbeddedFrameworks(cmXCodeObject* target);
void AddPositionIndependentLinkAttribute(cmGeneratorTarget* target,
cmXCodeObject* buildSettings,
const std::string& configName);
@@ -324,8 +325,10 @@ private:
std::map<std::string, cmXCodeObject*> TargetGroup;
std::map<std::string, cmXCodeObject*> FileRefs;
std::map<std::string, cmXCodeObject*> ExternalLibRefs;
+ std::map<std::string, cmXCodeObject*> EmbeddedLibRefs;
std::map<cmGeneratorTarget const*, cmXCodeObject*> XCodeObjectMap;
std::map<cmXCodeObject*, cmXCodeObject*> FileRefToBuildFileMap;
+ std::map<cmXCodeObject*, cmXCodeObject*> FileRefToEmbedBuildFileMap;
std::vector<std::string> Architectures;
std::string ObjectDirArchDefault;
std::string ObjectDirArch;
diff --git a/Source/cmXCodeObject.h b/Source/cmXCodeObject.h
index 78d4727..ab7f99e 100644
--- a/Source/cmXCodeObject.h
+++ b/Source/cmXCodeObject.h
@@ -81,6 +81,13 @@ public:
void SetObject(cmXCodeObject* value) { this->Object = value; }
cmXCodeObject* GetObject() { return this->Object; }
void AddObject(cmXCodeObject* value) { this->List.push_back(value); }
+ size_t GetObjectCount() { return this->List.size(); }
+ void InsertObject(size_t position, cmXCodeObject* value)
+ {
+ if (position < GetObjectCount()) {
+ this->List.insert(this->List.begin() + position, value);
+ }
+ }
void PrependObject(cmXCodeObject* value)
{
this->List.insert(this->List.begin(), value);