mirror of
https://github.com/Kitware/CMake.git
synced 2026-02-06 07:09:49 -06:00
Merge topic 'xcode-target-order'
fb45559e09Xcode: Process targets in depth-first order during generation0bad9eba46Xcode: Refactor storage of ordered list of targetsd0de296e50Xcode: Factor target generation loop body into helper method30e27b4110Xcode: Compute global order index for targetse3469a5920Xcode: Remove loop over local generators that has no effect Acked-by: Kitware Robot <kwrobot@kitware.com> Merge-request: !2224
This commit is contained in:
@@ -386,12 +386,46 @@ void cmGlobalXCodeGenerator::AddExtraIDETargets()
|
||||
}
|
||||
}
|
||||
|
||||
void cmGlobalXCodeGenerator::ComputeTargetOrder()
|
||||
{
|
||||
size_t index = 0;
|
||||
auto const& lgens = this->GetLocalGenerators();
|
||||
for (cmLocalGenerator* lgen : lgens) {
|
||||
auto const& targets = lgen->GetGeneratorTargets();
|
||||
for (cmGeneratorTarget const* gt : targets) {
|
||||
this->ComputeTargetOrder(gt, index);
|
||||
}
|
||||
}
|
||||
assert(index == this->TargetOrderIndex.size());
|
||||
}
|
||||
|
||||
void cmGlobalXCodeGenerator::ComputeTargetOrder(cmGeneratorTarget const* gt,
|
||||
size_t& index)
|
||||
{
|
||||
std::map<cmGeneratorTarget const*, size_t>::value_type value(gt, 0);
|
||||
auto insertion = this->TargetOrderIndex.insert(value);
|
||||
if (!insertion.second) {
|
||||
return;
|
||||
}
|
||||
auto entry = insertion.first;
|
||||
|
||||
auto& deps = this->GetTargetDirectDepends(gt);
|
||||
for (auto& d : deps) {
|
||||
this->ComputeTargetOrder(d, index);
|
||||
}
|
||||
|
||||
entry->second = index++;
|
||||
}
|
||||
|
||||
void cmGlobalXCodeGenerator::Generate()
|
||||
{
|
||||
this->cmGlobalGenerator::Generate();
|
||||
if (cmSystemTools::GetErrorOccuredFlag()) {
|
||||
return;
|
||||
}
|
||||
|
||||
this->ComputeTargetOrder();
|
||||
|
||||
for (auto keyVal : this->ProjectMap) {
|
||||
cmLocalGenerator* root = keyVal.second[0];
|
||||
|
||||
@@ -1031,15 +1065,17 @@ struct cmSourceFilePathCompare
|
||||
|
||||
struct cmCompareTargets
|
||||
{
|
||||
bool operator()(std::string const& a, std::string const& b) const
|
||||
bool operator()(cmXCodeObject* l, cmXCodeObject* r) const
|
||||
{
|
||||
std::string const& a = l->GetTarget()->GetName();
|
||||
std::string const& b = r->GetTarget()->GetName();
|
||||
if (a == "ALL_BUILD") {
|
||||
return true;
|
||||
}
|
||||
if (b == "ALL_BUILD") {
|
||||
return false;
|
||||
}
|
||||
return strcmp(a.c_str(), b.c_str()) < 0;
|
||||
return a < b;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1047,274 +1083,279 @@ bool cmGlobalXCodeGenerator::CreateXCodeTargets(
|
||||
cmLocalGenerator* gen, std::vector<cmXCodeObject*>& targets)
|
||||
{
|
||||
this->SetCurrentLocalGenerator(gen);
|
||||
typedef std::map<std::string, cmGeneratorTarget*, cmCompareTargets>
|
||||
cmSortedTargets;
|
||||
cmSortedTargets sortedTargets;
|
||||
for (auto tgt : this->CurrentLocalGenerator->GetGeneratorTargets()) {
|
||||
sortedTargets[tgt->GetName()] = tgt;
|
||||
}
|
||||
for (auto& sortedTarget : sortedTargets) {
|
||||
cmGeneratorTarget* gtgt = sortedTarget.second;
|
||||
|
||||
std::string targetName = gtgt->GetName();
|
||||
|
||||
// make sure ALL_BUILD, INSTALL, etc are only done once
|
||||
if (this->SpecialTargetEmitted(targetName)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (gtgt->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (gtgt->GetType() == cmStateEnums::UTILITY ||
|
||||
gtgt->GetType() == cmStateEnums::GLOBAL_TARGET) {
|
||||
cmXCodeObject* t = this->CreateUtilityTarget(gtgt);
|
||||
if (!t) {
|
||||
return false;
|
||||
}
|
||||
targets.push_back(t);
|
||||
continue;
|
||||
}
|
||||
|
||||
// organize the sources
|
||||
std::vector<cmSourceFile*> classes;
|
||||
if (!gtgt->GetConfigCommonSourceFiles(classes)) {
|
||||
std::vector<cmGeneratorTarget*> gts =
|
||||
this->CurrentLocalGenerator->GetGeneratorTargets();
|
||||
std::sort(gts.begin(), gts.end(),
|
||||
[this](cmGeneratorTarget const* l, cmGeneratorTarget const* r) {
|
||||
return this->TargetOrderIndex[l] < this->TargetOrderIndex[r];
|
||||
});
|
||||
for (auto gtgt : gts) {
|
||||
if (!this->CreateXCodeTarget(gtgt, targets)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
std::sort(targets.begin(), targets.end(), cmCompareTargets());
|
||||
return true;
|
||||
}
|
||||
|
||||
// Add CMakeLists.txt file for user convenience.
|
||||
this->AddXCodeProjBuildRule(gtgt, classes);
|
||||
bool cmGlobalXCodeGenerator::CreateXCodeTarget(
|
||||
cmGeneratorTarget* gtgt, std::vector<cmXCodeObject*>& targets)
|
||||
{
|
||||
std::string targetName = gtgt->GetName();
|
||||
|
||||
std::sort(classes.begin(), classes.end(), cmSourceFilePathCompare());
|
||||
// make sure ALL_BUILD, INSTALL, etc are only done once
|
||||
if (this->SpecialTargetEmitted(targetName)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
gtgt->ComputeObjectMapping();
|
||||
if (gtgt->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<cmXCodeObject*> externalObjFiles;
|
||||
std::vector<cmXCodeObject*> headerFiles;
|
||||
std::vector<cmXCodeObject*> resourceFiles;
|
||||
std::vector<cmXCodeObject*> sourceFiles;
|
||||
for (auto sourceFile : classes) {
|
||||
cmXCodeObject* xsf = this->CreateXCodeSourceFile(
|
||||
this->CurrentLocalGenerator, sourceFile, gtgt);
|
||||
cmXCodeObject* fr = xsf->GetObject("fileRef");
|
||||
cmXCodeObject* filetype = fr->GetObject()->GetObject("explicitFileType");
|
||||
|
||||
cmGeneratorTarget::SourceFileFlags tsFlags =
|
||||
gtgt->GetTargetSourceFileFlags(sourceFile);
|
||||
|
||||
if (filetype && filetype->GetString() == "compiled.mach-o.objfile") {
|
||||
if (sourceFile->GetObjectLibrary().empty()) {
|
||||
externalObjFiles.push_back(xsf);
|
||||
}
|
||||
} else if (this->IsHeaderFile(sourceFile) ||
|
||||
(tsFlags.Type ==
|
||||
cmGeneratorTarget::SourceFileTypePrivateHeader) ||
|
||||
(tsFlags.Type ==
|
||||
cmGeneratorTarget::SourceFileTypePublicHeader)) {
|
||||
headerFiles.push_back(xsf);
|
||||
} else if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeResource) {
|
||||
resourceFiles.push_back(xsf);
|
||||
} else if (!sourceFile->GetPropertyAsBool("HEADER_FILE_ONLY")) {
|
||||
// Include this file in the build if it has a known language
|
||||
// and has not been listed as an ignored extension for this
|
||||
// generator.
|
||||
if (!this->CurrentLocalGenerator->GetSourceFileLanguage(*sourceFile)
|
||||
.empty() &&
|
||||
!this->IgnoreFile(sourceFile->GetExtension().c_str())) {
|
||||
sourceFiles.push_back(xsf);
|
||||
}
|
||||
}
|
||||
if (gtgt->GetType() == cmStateEnums::UTILITY ||
|
||||
gtgt->GetType() == cmStateEnums::GLOBAL_TARGET) {
|
||||
cmXCodeObject* t = this->CreateUtilityTarget(gtgt);
|
||||
if (!t) {
|
||||
return false;
|
||||
}
|
||||
targets.push_back(t);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this->XcodeVersion < 50) {
|
||||
// Add object library contents as external objects. (Equivalent to
|
||||
// the externalObjFiles above, except each one is not a cmSourceFile
|
||||
// within the target.)
|
||||
std::vector<cmSourceFile const*> objs;
|
||||
gtgt->GetExternalObjects(objs, "");
|
||||
for (auto sourceFile : objs) {
|
||||
if (sourceFile->GetObjectLibrary().empty()) {
|
||||
continue;
|
||||
}
|
||||
std::string const& obj = sourceFile->GetFullPath();
|
||||
cmXCodeObject* xsf =
|
||||
this->CreateXCodeSourceFileFromPath(obj, gtgt, "", nullptr);
|
||||
// organize the sources
|
||||
std::vector<cmSourceFile*> classes;
|
||||
if (!gtgt->GetConfigCommonSourceFiles(classes)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Add CMakeLists.txt file for user convenience.
|
||||
this->AddXCodeProjBuildRule(gtgt, classes);
|
||||
|
||||
std::sort(classes.begin(), classes.end(), cmSourceFilePathCompare());
|
||||
|
||||
gtgt->ComputeObjectMapping();
|
||||
|
||||
std::vector<cmXCodeObject*> externalObjFiles;
|
||||
std::vector<cmXCodeObject*> headerFiles;
|
||||
std::vector<cmXCodeObject*> resourceFiles;
|
||||
std::vector<cmXCodeObject*> sourceFiles;
|
||||
for (auto sourceFile : classes) {
|
||||
cmXCodeObject* xsf = this->CreateXCodeSourceFile(
|
||||
this->CurrentLocalGenerator, sourceFile, gtgt);
|
||||
cmXCodeObject* fr = xsf->GetObject("fileRef");
|
||||
cmXCodeObject* filetype = fr->GetObject()->GetObject("explicitFileType");
|
||||
|
||||
cmGeneratorTarget::SourceFileFlags tsFlags =
|
||||
gtgt->GetTargetSourceFileFlags(sourceFile);
|
||||
|
||||
if (filetype && filetype->GetString() == "compiled.mach-o.objfile") {
|
||||
if (sourceFile->GetObjectLibrary().empty()) {
|
||||
externalObjFiles.push_back(xsf);
|
||||
}
|
||||
}
|
||||
|
||||
// some build phases only apply to bundles and/or frameworks
|
||||
bool isFrameworkTarget = gtgt->IsFrameworkOnApple();
|
||||
bool isBundleTarget = gtgt->GetPropertyAsBool("MACOSX_BUNDLE");
|
||||
bool isCFBundleTarget = gtgt->IsCFBundleOnApple();
|
||||
|
||||
cmXCodeObject* buildFiles = nullptr;
|
||||
|
||||
// create source build phase
|
||||
cmXCodeObject* sourceBuildPhase = nullptr;
|
||||
if (!sourceFiles.empty()) {
|
||||
sourceBuildPhase =
|
||||
this->CreateObject(cmXCodeObject::PBXSourcesBuildPhase);
|
||||
sourceBuildPhase->SetComment("Sources");
|
||||
sourceBuildPhase->AddAttribute("buildActionMask",
|
||||
this->CreateString("2147483647"));
|
||||
buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
|
||||
for (auto& sourceFile : sourceFiles) {
|
||||
buildFiles->AddObject(sourceFile);
|
||||
}
|
||||
sourceBuildPhase->AddAttribute("files", buildFiles);
|
||||
sourceBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
|
||||
this->CreateString("0"));
|
||||
}
|
||||
|
||||
// create header build phase - only for framework targets
|
||||
cmXCodeObject* headerBuildPhase = nullptr;
|
||||
if (!headerFiles.empty() && isFrameworkTarget) {
|
||||
headerBuildPhase =
|
||||
this->CreateObject(cmXCodeObject::PBXHeadersBuildPhase);
|
||||
headerBuildPhase->SetComment("Headers");
|
||||
headerBuildPhase->AddAttribute("buildActionMask",
|
||||
this->CreateString("2147483647"));
|
||||
buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
|
||||
for (auto& headerFile : headerFiles) {
|
||||
buildFiles->AddObject(headerFile);
|
||||
}
|
||||
headerBuildPhase->AddAttribute("files", buildFiles);
|
||||
headerBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
|
||||
this->CreateString("0"));
|
||||
}
|
||||
|
||||
// create resource build phase - only for framework or bundle targets
|
||||
cmXCodeObject* resourceBuildPhase = nullptr;
|
||||
if (!resourceFiles.empty() &&
|
||||
(isFrameworkTarget || isBundleTarget || isCFBundleTarget)) {
|
||||
resourceBuildPhase =
|
||||
this->CreateObject(cmXCodeObject::PBXResourcesBuildPhase);
|
||||
resourceBuildPhase->SetComment("Resources");
|
||||
resourceBuildPhase->AddAttribute("buildActionMask",
|
||||
this->CreateString("2147483647"));
|
||||
buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
|
||||
for (auto& resourceFile : resourceFiles) {
|
||||
buildFiles->AddObject(resourceFile);
|
||||
}
|
||||
resourceBuildPhase->AddAttribute("files", buildFiles);
|
||||
resourceBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
|
||||
this->CreateString("0"));
|
||||
}
|
||||
|
||||
// create vector of "non-resource content file" build phases - only for
|
||||
// framework or bundle targets
|
||||
std::vector<cmXCodeObject*> contentBuildPhases;
|
||||
if (isFrameworkTarget || isBundleTarget || isCFBundleTarget) {
|
||||
typedef std::map<std::string, std::vector<cmSourceFile*>>
|
||||
mapOfVectorOfSourceFiles;
|
||||
mapOfVectorOfSourceFiles bundleFiles;
|
||||
for (auto sourceFile : classes) {
|
||||
cmGeneratorTarget::SourceFileFlags tsFlags =
|
||||
gtgt->GetTargetSourceFileFlags(sourceFile);
|
||||
if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeMacContent) {
|
||||
bundleFiles[tsFlags.MacFolder].push_back(sourceFile);
|
||||
}
|
||||
}
|
||||
for (auto keySources : bundleFiles) {
|
||||
cmXCodeObject* copyFilesBuildPhase =
|
||||
this->CreateObject(cmXCodeObject::PBXCopyFilesBuildPhase);
|
||||
copyFilesBuildPhase->SetComment("Copy files");
|
||||
copyFilesBuildPhase->AddAttribute("buildActionMask",
|
||||
this->CreateString("2147483647"));
|
||||
copyFilesBuildPhase->AddAttribute("dstSubfolderSpec",
|
||||
this->CreateString("6"));
|
||||
std::ostringstream ostr;
|
||||
if (gtgt->IsFrameworkOnApple()) {
|
||||
// dstPath in frameworks is relative to Versions/<version>
|
||||
ostr << keySources.first;
|
||||
} else if (keySources.first != "MacOS") {
|
||||
if (gtgt->Target->GetMakefile()->PlatformIsAppleEmbedded()) {
|
||||
ostr << keySources.first;
|
||||
} else {
|
||||
// dstPath in bundles is relative to Contents/MacOS
|
||||
ostr << "../" << keySources.first;
|
||||
}
|
||||
}
|
||||
copyFilesBuildPhase->AddAttribute("dstPath",
|
||||
this->CreateString(ostr.str()));
|
||||
copyFilesBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
|
||||
this->CreateString("0"));
|
||||
buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
|
||||
copyFilesBuildPhase->AddAttribute("files", buildFiles);
|
||||
for (auto sourceFile : keySources.second) {
|
||||
cmXCodeObject* xsf = this->CreateXCodeSourceFile(
|
||||
this->CurrentLocalGenerator, sourceFile, gtgt);
|
||||
buildFiles->AddObject(xsf);
|
||||
}
|
||||
contentBuildPhases.push_back(copyFilesBuildPhase);
|
||||
} else if (this->IsHeaderFile(sourceFile) ||
|
||||
(tsFlags.Type ==
|
||||
cmGeneratorTarget::SourceFileTypePrivateHeader) ||
|
||||
(tsFlags.Type ==
|
||||
cmGeneratorTarget::SourceFileTypePublicHeader)) {
|
||||
headerFiles.push_back(xsf);
|
||||
} else if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeResource) {
|
||||
resourceFiles.push_back(xsf);
|
||||
} else if (!sourceFile->GetPropertyAsBool("HEADER_FILE_ONLY")) {
|
||||
// Include this file in the build if it has a known language
|
||||
// and has not been listed as an ignored extension for this
|
||||
// generator.
|
||||
if (!this->CurrentLocalGenerator->GetSourceFileLanguage(*sourceFile)
|
||||
.empty() &&
|
||||
!this->IgnoreFile(sourceFile->GetExtension().c_str())) {
|
||||
sourceFiles.push_back(xsf);
|
||||
}
|
||||
}
|
||||
|
||||
// create vector of "resource content file" build phases - only for
|
||||
// framework or bundle targets
|
||||
if (isFrameworkTarget || isBundleTarget || isCFBundleTarget) {
|
||||
typedef std::map<std::string, std::vector<cmSourceFile*>>
|
||||
mapOfVectorOfSourceFiles;
|
||||
mapOfVectorOfSourceFiles bundleFiles;
|
||||
for (auto sourceFile : classes) {
|
||||
cmGeneratorTarget::SourceFileFlags tsFlags =
|
||||
gtgt->GetTargetSourceFileFlags(sourceFile);
|
||||
if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeDeepResource) {
|
||||
bundleFiles[tsFlags.MacFolder].push_back(sourceFile);
|
||||
}
|
||||
}
|
||||
for (auto keySources : bundleFiles) {
|
||||
cmXCodeObject* copyFilesBuildPhase =
|
||||
this->CreateObject(cmXCodeObject::PBXCopyFilesBuildPhase);
|
||||
copyFilesBuildPhase->SetComment("Copy files");
|
||||
copyFilesBuildPhase->AddAttribute("buildActionMask",
|
||||
this->CreateString("2147483647"));
|
||||
copyFilesBuildPhase->AddAttribute("dstSubfolderSpec",
|
||||
this->CreateString("7"));
|
||||
copyFilesBuildPhase->AddAttribute(
|
||||
"dstPath", this->CreateString(keySources.first));
|
||||
copyFilesBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
|
||||
this->CreateString("0"));
|
||||
buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
|
||||
copyFilesBuildPhase->AddAttribute("files", buildFiles);
|
||||
for (auto sourceFile : keySources.second) {
|
||||
cmXCodeObject* xsf = this->CreateXCodeSourceFile(
|
||||
this->CurrentLocalGenerator, sourceFile, gtgt);
|
||||
buildFiles->AddObject(xsf);
|
||||
}
|
||||
contentBuildPhases.push_back(copyFilesBuildPhase);
|
||||
}
|
||||
}
|
||||
|
||||
// create framework build phase
|
||||
cmXCodeObject* frameworkBuildPhase = nullptr;
|
||||
if (!externalObjFiles.empty()) {
|
||||
frameworkBuildPhase =
|
||||
this->CreateObject(cmXCodeObject::PBXFrameworksBuildPhase);
|
||||
frameworkBuildPhase->SetComment("Frameworks");
|
||||
frameworkBuildPhase->AddAttribute("buildActionMask",
|
||||
this->CreateString("2147483647"));
|
||||
buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
|
||||
frameworkBuildPhase->AddAttribute("files", buildFiles);
|
||||
for (auto& externalObjFile : externalObjFiles) {
|
||||
buildFiles->AddObject(externalObjFile);
|
||||
}
|
||||
frameworkBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
|
||||
this->CreateString("0"));
|
||||
}
|
||||
|
||||
// create list of build phases and create the Xcode target
|
||||
cmXCodeObject* buildPhases =
|
||||
this->CreateObject(cmXCodeObject::OBJECT_LIST);
|
||||
|
||||
this->CreateCustomCommands(buildPhases, sourceBuildPhase, headerBuildPhase,
|
||||
resourceBuildPhase, contentBuildPhases,
|
||||
frameworkBuildPhase, gtgt);
|
||||
|
||||
targets.push_back(this->CreateXCodeTarget(gtgt, buildPhases));
|
||||
}
|
||||
|
||||
if (this->XcodeVersion < 50) {
|
||||
// Add object library contents as external objects. (Equivalent to
|
||||
// the externalObjFiles above, except each one is not a cmSourceFile
|
||||
// within the target.)
|
||||
std::vector<cmSourceFile const*> objs;
|
||||
gtgt->GetExternalObjects(objs, "");
|
||||
for (auto sourceFile : objs) {
|
||||
if (sourceFile->GetObjectLibrary().empty()) {
|
||||
continue;
|
||||
}
|
||||
std::string const& obj = sourceFile->GetFullPath();
|
||||
cmXCodeObject* xsf =
|
||||
this->CreateXCodeSourceFileFromPath(obj, gtgt, "", nullptr);
|
||||
externalObjFiles.push_back(xsf);
|
||||
}
|
||||
}
|
||||
|
||||
// some build phases only apply to bundles and/or frameworks
|
||||
bool isFrameworkTarget = gtgt->IsFrameworkOnApple();
|
||||
bool isBundleTarget = gtgt->GetPropertyAsBool("MACOSX_BUNDLE");
|
||||
bool isCFBundleTarget = gtgt->IsCFBundleOnApple();
|
||||
|
||||
cmXCodeObject* buildFiles = nullptr;
|
||||
|
||||
// create source build phase
|
||||
cmXCodeObject* sourceBuildPhase = nullptr;
|
||||
if (!sourceFiles.empty()) {
|
||||
sourceBuildPhase = this->CreateObject(cmXCodeObject::PBXSourcesBuildPhase);
|
||||
sourceBuildPhase->SetComment("Sources");
|
||||
sourceBuildPhase->AddAttribute("buildActionMask",
|
||||
this->CreateString("2147483647"));
|
||||
buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
|
||||
for (auto& sourceFile : sourceFiles) {
|
||||
buildFiles->AddObject(sourceFile);
|
||||
}
|
||||
sourceBuildPhase->AddAttribute("files", buildFiles);
|
||||
sourceBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
|
||||
this->CreateString("0"));
|
||||
}
|
||||
|
||||
// create header build phase - only for framework targets
|
||||
cmXCodeObject* headerBuildPhase = nullptr;
|
||||
if (!headerFiles.empty() && isFrameworkTarget) {
|
||||
headerBuildPhase = this->CreateObject(cmXCodeObject::PBXHeadersBuildPhase);
|
||||
headerBuildPhase->SetComment("Headers");
|
||||
headerBuildPhase->AddAttribute("buildActionMask",
|
||||
this->CreateString("2147483647"));
|
||||
buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
|
||||
for (auto& headerFile : headerFiles) {
|
||||
buildFiles->AddObject(headerFile);
|
||||
}
|
||||
headerBuildPhase->AddAttribute("files", buildFiles);
|
||||
headerBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
|
||||
this->CreateString("0"));
|
||||
}
|
||||
|
||||
// create resource build phase - only for framework or bundle targets
|
||||
cmXCodeObject* resourceBuildPhase = nullptr;
|
||||
if (!resourceFiles.empty() &&
|
||||
(isFrameworkTarget || isBundleTarget || isCFBundleTarget)) {
|
||||
resourceBuildPhase =
|
||||
this->CreateObject(cmXCodeObject::PBXResourcesBuildPhase);
|
||||
resourceBuildPhase->SetComment("Resources");
|
||||
resourceBuildPhase->AddAttribute("buildActionMask",
|
||||
this->CreateString("2147483647"));
|
||||
buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
|
||||
for (auto& resourceFile : resourceFiles) {
|
||||
buildFiles->AddObject(resourceFile);
|
||||
}
|
||||
resourceBuildPhase->AddAttribute("files", buildFiles);
|
||||
resourceBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
|
||||
this->CreateString("0"));
|
||||
}
|
||||
|
||||
// create vector of "non-resource content file" build phases - only for
|
||||
// framework or bundle targets
|
||||
std::vector<cmXCodeObject*> contentBuildPhases;
|
||||
if (isFrameworkTarget || isBundleTarget || isCFBundleTarget) {
|
||||
typedef std::map<std::string, std::vector<cmSourceFile*>>
|
||||
mapOfVectorOfSourceFiles;
|
||||
mapOfVectorOfSourceFiles bundleFiles;
|
||||
for (auto sourceFile : classes) {
|
||||
cmGeneratorTarget::SourceFileFlags tsFlags =
|
||||
gtgt->GetTargetSourceFileFlags(sourceFile);
|
||||
if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeMacContent) {
|
||||
bundleFiles[tsFlags.MacFolder].push_back(sourceFile);
|
||||
}
|
||||
}
|
||||
for (auto keySources : bundleFiles) {
|
||||
cmXCodeObject* copyFilesBuildPhase =
|
||||
this->CreateObject(cmXCodeObject::PBXCopyFilesBuildPhase);
|
||||
copyFilesBuildPhase->SetComment("Copy files");
|
||||
copyFilesBuildPhase->AddAttribute("buildActionMask",
|
||||
this->CreateString("2147483647"));
|
||||
copyFilesBuildPhase->AddAttribute("dstSubfolderSpec",
|
||||
this->CreateString("6"));
|
||||
std::ostringstream ostr;
|
||||
if (gtgt->IsFrameworkOnApple()) {
|
||||
// dstPath in frameworks is relative to Versions/<version>
|
||||
ostr << keySources.first;
|
||||
} else if (keySources.first != "MacOS") {
|
||||
if (gtgt->Target->GetMakefile()->PlatformIsAppleEmbedded()) {
|
||||
ostr << keySources.first;
|
||||
} else {
|
||||
// dstPath in bundles is relative to Contents/MacOS
|
||||
ostr << "../" << keySources.first;
|
||||
}
|
||||
}
|
||||
copyFilesBuildPhase->AddAttribute("dstPath",
|
||||
this->CreateString(ostr.str()));
|
||||
copyFilesBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
|
||||
this->CreateString("0"));
|
||||
buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
|
||||
copyFilesBuildPhase->AddAttribute("files", buildFiles);
|
||||
for (auto sourceFile : keySources.second) {
|
||||
cmXCodeObject* xsf = this->CreateXCodeSourceFile(
|
||||
this->CurrentLocalGenerator, sourceFile, gtgt);
|
||||
buildFiles->AddObject(xsf);
|
||||
}
|
||||
contentBuildPhases.push_back(copyFilesBuildPhase);
|
||||
}
|
||||
}
|
||||
|
||||
// create vector of "resource content file" build phases - only for
|
||||
// framework or bundle targets
|
||||
if (isFrameworkTarget || isBundleTarget || isCFBundleTarget) {
|
||||
typedef std::map<std::string, std::vector<cmSourceFile*>>
|
||||
mapOfVectorOfSourceFiles;
|
||||
mapOfVectorOfSourceFiles bundleFiles;
|
||||
for (auto sourceFile : classes) {
|
||||
cmGeneratorTarget::SourceFileFlags tsFlags =
|
||||
gtgt->GetTargetSourceFileFlags(sourceFile);
|
||||
if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeDeepResource) {
|
||||
bundleFiles[tsFlags.MacFolder].push_back(sourceFile);
|
||||
}
|
||||
}
|
||||
for (auto keySources : bundleFiles) {
|
||||
cmXCodeObject* copyFilesBuildPhase =
|
||||
this->CreateObject(cmXCodeObject::PBXCopyFilesBuildPhase);
|
||||
copyFilesBuildPhase->SetComment("Copy files");
|
||||
copyFilesBuildPhase->AddAttribute("buildActionMask",
|
||||
this->CreateString("2147483647"));
|
||||
copyFilesBuildPhase->AddAttribute("dstSubfolderSpec",
|
||||
this->CreateString("7"));
|
||||
copyFilesBuildPhase->AddAttribute("dstPath",
|
||||
this->CreateString(keySources.first));
|
||||
copyFilesBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
|
||||
this->CreateString("0"));
|
||||
buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
|
||||
copyFilesBuildPhase->AddAttribute("files", buildFiles);
|
||||
for (auto sourceFile : keySources.second) {
|
||||
cmXCodeObject* xsf = this->CreateXCodeSourceFile(
|
||||
this->CurrentLocalGenerator, sourceFile, gtgt);
|
||||
buildFiles->AddObject(xsf);
|
||||
}
|
||||
contentBuildPhases.push_back(copyFilesBuildPhase);
|
||||
}
|
||||
}
|
||||
|
||||
// create framework build phase
|
||||
cmXCodeObject* frameworkBuildPhase = nullptr;
|
||||
if (!externalObjFiles.empty()) {
|
||||
frameworkBuildPhase =
|
||||
this->CreateObject(cmXCodeObject::PBXFrameworksBuildPhase);
|
||||
frameworkBuildPhase->SetComment("Frameworks");
|
||||
frameworkBuildPhase->AddAttribute("buildActionMask",
|
||||
this->CreateString("2147483647"));
|
||||
buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
|
||||
frameworkBuildPhase->AddAttribute("files", buildFiles);
|
||||
for (auto& externalObjFile : externalObjFiles) {
|
||||
buildFiles->AddObject(externalObjFile);
|
||||
}
|
||||
frameworkBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
|
||||
this->CreateString("0"));
|
||||
}
|
||||
|
||||
// create list of build phases and create the Xcode target
|
||||
cmXCodeObject* buildPhases = this->CreateObject(cmXCodeObject::OBJECT_LIST);
|
||||
|
||||
this->CreateCustomCommands(buildPhases, sourceBuildPhase, headerBuildPhase,
|
||||
resourceBuildPhase, contentBuildPhases,
|
||||
frameworkBuildPhase, gtgt);
|
||||
|
||||
targets.push_back(this->CreateXCodeTarget(gtgt, buildPhases));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -3319,13 +3360,6 @@ void cmGlobalXCodeGenerator::OutputXCodeProject(
|
||||
if (generators.empty()) {
|
||||
return;
|
||||
}
|
||||
// Skip local generators that are excluded from this project.
|
||||
for (auto generator : generators) {
|
||||
if (this->IsExcluded(root, generator)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!this->CreateXCodeObjects(root, generators)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -109,6 +109,8 @@ public:
|
||||
|
||||
protected:
|
||||
void AddExtraIDETargets() override;
|
||||
void ComputeTargetOrder();
|
||||
void ComputeTargetOrder(cmGeneratorTarget const* gt, size_t& index);
|
||||
void Generate() override;
|
||||
|
||||
private:
|
||||
@@ -204,6 +206,8 @@ private:
|
||||
void AddXCodeProjBuildRule(cmGeneratorTarget* target,
|
||||
std::vector<cmSourceFile*>& sources) const;
|
||||
bool CreateXCodeTargets(cmLocalGenerator* gen, std::vector<cmXCodeObject*>&);
|
||||
bool CreateXCodeTarget(cmGeneratorTarget* gtgt,
|
||||
std::vector<cmXCodeObject*>&);
|
||||
bool IsHeaderFile(cmSourceFile*);
|
||||
void AddDependTarget(cmXCodeObject* target, cmXCodeObject* dependTarget);
|
||||
void CreateXCodeDependHackTarget(std::vector<cmXCodeObject*>& targets);
|
||||
@@ -286,6 +290,7 @@ private:
|
||||
std::string ObjectDirArchDefault;
|
||||
std::string ObjectDirArch;
|
||||
std::string GeneratorToolset;
|
||||
std::map<cmGeneratorTarget const*, size_t> TargetOrderIndex;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user