summaryrefslogtreecommitdiff
path: root/Source/cmGlobalXCodeGenerator.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'Source/cmGlobalXCodeGenerator.cxx')
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx2122
1 files changed, 1124 insertions, 998 deletions
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index 903796123..3002b2a68 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -2,15 +2,21 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGlobalXCodeGenerator.h"
-#include "cmsys/RegularExpression.hxx"
-#include <assert.h>
+#include <cassert>
+#include <cstdio>
+#include <cstring>
#include <iomanip>
#include <sstream>
-#include <stdio.h>
-#include <string.h>
+#include <cm/memory>
+
+#include "cmsys/RegularExpression.hxx"
+
+#include "cmAlgorithms.h"
#include "cmComputeLinkInformation.h"
+#include "cmCustomCommand.h"
#include "cmCustomCommandGenerator.h"
+#include "cmCustomCommandLines.h"
#include "cmDocumentationEntry.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
@@ -19,6 +25,7 @@
#include "cmLocalGenerator.h"
#include "cmLocalXCodeGenerator.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmOutputConverter.h"
#include "cmSourceFile.h"
#include "cmSourceGroup.h"
@@ -29,13 +36,17 @@
#include "cmXCode21Object.h"
#include "cmXCodeObject.h"
#include "cmXCodeScheme.h"
-#include "cm_auto_ptr.hxx"
#include "cmake.h"
struct cmLinkImplementation;
-#if defined(CMAKE_BUILD_WITH_CMAKE)
-#include "cmXMLParser.h"
+#if !defined(CMAKE_BOOTSTRAP) && defined(__APPLE__)
+# define HAVE_APPLICATION_SERVICES
+# include <ApplicationServices/ApplicationServices.h>
+#endif
+
+#if !defined(CMAKE_BOOTSTRAP)
+# include "cmXMLParser.h"
// parse the xml file storing the installed version of Xcode on
// the machine
@@ -46,8 +57,11 @@ public:
: Version("1.5")
{
}
- void StartElement(const std::string&, const char**) { this->Data = ""; }
- void EndElement(const std::string& name)
+ void StartElement(const std::string&, const char**) override
+ {
+ this->Data = "";
+ }
+ void EndElement(const std::string& name) override
{
if (name == "key") {
this->Key = this->Data;
@@ -57,7 +71,7 @@ public:
}
}
}
- void CharacterDataHandler(const char* data, int length)
+ void CharacterDataHandler(const char* data, int length) override
{
this->Data.append(data, length);
}
@@ -79,7 +93,7 @@ class cmGlobalXCodeGenerator::BuildObjectListOrString
public:
BuildObjectListOrString(cmGlobalXCodeGenerator* gen, bool buildObjectList)
: Generator(gen)
- , Group(0)
+ , Group(nullptr)
, Empty(true)
{
if (buildObjectList) {
@@ -107,9 +121,8 @@ public:
{
if (this->Group) {
return this->Group;
- } else {
- return this->Generator->CreateString(this->String);
}
+ return this->Generator->CreateString(this->String);
}
};
@@ -117,20 +130,34 @@ class cmGlobalXCodeGenerator::Factory : public cmGlobalGeneratorFactory
{
public:
cmGlobalGenerator* CreateGlobalGenerator(const std::string& name,
- cmake* cm) const CM_OVERRIDE;
+ cmake* cm) const override;
- void GetDocumentation(cmDocumentationEntry& entry) const CM_OVERRIDE
+ void GetDocumentation(cmDocumentationEntry& entry) const override
{
cmGlobalXCodeGenerator::GetDocumentation(entry);
}
- void GetGenerators(std::vector<std::string>& names) const CM_OVERRIDE
+ std::vector<std::string> GetGeneratorNames() const override
{
+ std::vector<std::string> names;
names.push_back(cmGlobalXCodeGenerator::GetActualName());
+ return names;
}
- bool SupportsToolset() const CM_OVERRIDE { return true; }
- bool SupportsPlatform() const CM_OVERRIDE { return false; }
+ std::vector<std::string> GetGeneratorNamesWithPlatform() const override
+ {
+ return std::vector<std::string>();
+ }
+
+ bool SupportsToolset() const override { return true; }
+ bool SupportsPlatform() const override { return false; }
+
+ std::vector<std::string> GetKnownPlatforms() const override
+ {
+ return std::vector<std::string>();
+ }
+
+ std::string GetDefaultPlatformName() const override { return std::string(); }
};
cmGlobalXCodeGenerator::cmGlobalXCodeGenerator(
@@ -140,10 +167,10 @@ cmGlobalXCodeGenerator::cmGlobalXCodeGenerator(
this->VersionString = version_string;
this->XcodeVersion = version_number;
- this->RootObject = 0;
- this->MainGroupChildren = 0;
- this->CurrentMakefile = 0;
- this->CurrentLocalGenerator = 0;
+ this->RootObject = nullptr;
+ this->MainGroupChildren = nullptr;
+ this->CurrentMakefile = nullptr;
+ this->CurrentLocalGenerator = nullptr;
this->XcodeBuildCommandInitialized = false;
this->ObjectDirArchDefault = "$(CURRENT_ARCH)";
@@ -160,21 +187,25 @@ cmGlobalGeneratorFactory* cmGlobalXCodeGenerator::NewFactory()
cmGlobalGenerator* cmGlobalXCodeGenerator::Factory::CreateGlobalGenerator(
const std::string& name, cmake* cm) const
{
- if (name != GetActualName())
- return 0;
-#if defined(CMAKE_BUILD_WITH_CMAKE)
+ if (name != GetActualName()) {
+ return nullptr;
+ }
+#if !defined(CMAKE_BOOTSTRAP)
cmXcodeVersionParser parser;
std::string versionFile;
{
std::string out;
- std::string::size_type pos;
- if (cmSystemTools::RunSingleCommand("xcode-select --print-path", &out, 0,
- 0, 0, cmSystemTools::OUTPUT_NONE) &&
- (pos = out.find(".app/"), pos != std::string::npos)) {
- versionFile = out.substr(0, pos + 5) + "Contents/version.plist";
+ bool commandResult = cmSystemTools::RunSingleCommand(
+ "xcode-select --print-path", &out, nullptr, nullptr, nullptr,
+ cmSystemTools::OUTPUT_NONE);
+ if (commandResult) {
+ std::string::size_type pos = out.find(".app/");
+ if (pos != std::string::npos) {
+ versionFile = out.substr(0, pos + 5) + "Contents/version.plist";
+ }
}
}
- if (!versionFile.empty() && cmSystemTools::FileExists(versionFile.c_str())) {
+ if (!versionFile.empty() && cmSystemTools::FileExists(versionFile)) {
parser.ParseFile(versionFile.c_str());
} else if (cmSystemTools::FileExists(
"/Applications/Xcode.app/Contents/version.plist")) {
@@ -190,14 +221,14 @@ cmGlobalGenerator* cmGlobalXCodeGenerator::Factory::CreateGlobalGenerator(
sscanf(version_string.c_str(), "%u.%u", &v[0], &v[1]);
unsigned int version_number = 10 * v[0] + v[1];
- if (version_number < 30) {
- cm->IssueMessage(cmake::FATAL_ERROR,
+ if (version_number < 50) {
+ cm->IssueMessage(MessageType::FATAL_ERROR,
"Xcode " + version_string + " not supported.");
- return CM_NULLPTR;
+ return nullptr;
}
- CM_AUTO_PTR<cmGlobalXCodeGenerator> gg(
- new cmGlobalXCodeGenerator(cm, version_string, version_number));
+ auto gg = cm::make_unique<cmGlobalXCodeGenerator>(cm, version_string,
+ version_number);
return gg.release();
#else
std::cerr << "CMake should be built with cmake to use Xcode, "
@@ -211,9 +242,8 @@ bool cmGlobalXCodeGenerator::FindMakeProgram(cmMakefile* mf)
// The Xcode generator knows how to lookup its build tool
// directly instead of needing a helper module to do it, so we
// do not actually need to put CMAKE_MAKE_PROGRAM into the cache.
- if (cmSystemTools::IsOff(mf->GetDefinition("CMAKE_MAKE_PROGRAM"))) {
- mf->AddDefinition("CMAKE_MAKE_PROGRAM",
- this->GetXcodeBuildCommand().c_str());
+ if (cmIsOff(mf->GetDefinition("CMAKE_MAKE_PROGRAM"))) {
+ mf->AddDefinition("CMAKE_MAKE_PROGRAM", this->GetXcodeBuildCommand());
}
return true;
}
@@ -229,16 +259,11 @@ std::string const& cmGlobalXCodeGenerator::GetXcodeBuildCommand()
std::string cmGlobalXCodeGenerator::FindXcodeBuildCommand()
{
- if (this->XcodeVersion >= 40) {
- std::string makeProgram = cmSystemTools::FindProgram("xcodebuild");
- if (makeProgram.empty()) {
- makeProgram = "xcodebuild";
- }
- return makeProgram;
- } else {
- // Use cmakexbuild wrapper to suppress environment dump from output.
- return cmSystemTools::GetCMakeCommand() + "xbuild";
+ std::string makeProgram = cmSystemTools::FindProgram("xcodebuild");
+ if (makeProgram.empty()) {
+ makeProgram = "xcodebuild";
}
+ return makeProgram;
}
bool cmGlobalXCodeGenerator::SetGeneratorToolset(std::string const& ts,
@@ -254,13 +279,12 @@ bool cmGlobalXCodeGenerator::SetGeneratorToolset(std::string const& ts,
" " << ts << "\n"
"that was specified.";
/* clang-format on */
- mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+ mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
return false;
}
this->GeneratorToolset = ts;
if (!this->GeneratorToolset.empty()) {
- mf->AddDefinition("CMAKE_XCODE_PLATFORM_TOOLSET",
- this->GeneratorToolset.c_str());
+ mf->AddDefinition("CMAKE_XCODE_PLATFORM_TOOLSET", this->GeneratorToolset);
}
return true;
}
@@ -269,7 +293,7 @@ void cmGlobalXCodeGenerator::EnableLanguage(
std::vector<std::string> const& lang, cmMakefile* mf, bool optional)
{
mf->AddDefinition("XCODE", "1");
- mf->AddDefinition("XCODE_VERSION", this->VersionString.c_str());
+ mf->AddDefinition("XCODE_VERSION", this->VersionString);
if (!mf->GetDefinition("CMAKE_CONFIGURATION_TYPES")) {
mf->AddCacheDefinition(
"CMAKE_CONFIGURATION_TYPES", "Debug;Release;MinSizeRel;RelWithDebInfo",
@@ -283,46 +307,87 @@ void cmGlobalXCodeGenerator::EnableLanguage(
this->ComputeArchitectures(mf);
}
-void cmGlobalXCodeGenerator::GenerateBuildCommand(
- std::vector<std::string>& makeCommand, const std::string& makeProgram,
- const std::string& projectName, const std::string& /*projectDir*/,
- const std::string& targetName, const std::string& config, bool /*fast*/,
- bool /*verbose*/, std::vector<std::string> const& makeOptions)
+bool cmGlobalXCodeGenerator::Open(const std::string& bindir,
+ const std::string& projectName, bool dryRun)
+{
+ bool ret = false;
+
+#ifdef HAVE_APPLICATION_SERVICES
+ std::string url = bindir + "/" + projectName + ".xcodeproj";
+
+ if (dryRun) {
+ return cmSystemTools::FileExists(url, false);
+ }
+
+ CFStringRef cfStr = CFStringCreateWithCString(
+ kCFAllocatorDefault, url.c_str(), kCFStringEncodingUTF8);
+ if (cfStr) {
+ CFURLRef cfUrl = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, cfStr,
+ kCFURLPOSIXPathStyle, true);
+ if (cfUrl) {
+ OSStatus err = LSOpenCFURLRef(cfUrl, nullptr);
+ ret = err == noErr;
+ CFRelease(cfUrl);
+ }
+ CFRelease(cfStr);
+ }
+#endif
+
+ return ret;
+}
+
+std::vector<cmGlobalGenerator::GeneratedMakeCommand>
+cmGlobalXCodeGenerator::GenerateBuildCommand(
+ const std::string& makeProgram, const std::string& projectName,
+ const std::string& /*projectDir*/,
+ std::vector<std::string> const& targetNames, const std::string& config,
+ bool /*fast*/, int jobs, bool /*verbose*/,
+ std::vector<std::string> const& makeOptions)
{
+ GeneratedMakeCommand makeCommand;
// now build the test
- makeCommand.push_back(
+ makeCommand.Add(
this->SelectMakeProgram(makeProgram, this->GetXcodeBuildCommand()));
- makeCommand.push_back("-project");
- std::string projectArg = projectName;
- projectArg += ".xcode";
- projectArg += "proj";
- makeCommand.push_back(projectArg);
-
- bool clean = false;
- std::string realTarget = targetName;
- if (realTarget == "clean") {
- clean = true;
- realTarget = "ALL_BUILD";
+ if (!projectName.empty()) {
+ makeCommand.Add("-project");
+ std::string projectArg = cmStrCat(projectName, ".xcodeproj");
+ makeCommand.Add(projectArg);
}
- if (clean) {
- makeCommand.push_back("clean");
+ if (cmContains(targetNames, "clean")) {
+ makeCommand.Add("clean");
+ makeCommand.Add("-target", "ALL_BUILD");
} else {
- makeCommand.push_back("build");
+ makeCommand.Add("build");
+ if (targetNames.empty() ||
+ ((targetNames.size() == 1) && targetNames.front().empty())) {
+ makeCommand.Add("-target", "ALL_BUILD");
+ } else {
+ for (const auto& tname : targetNames) {
+ if (!tname.empty()) {
+ makeCommand.Add("-target", tname);
+ }
+ }
+ }
}
- makeCommand.push_back("-target");
- if (!realTarget.empty()) {
- makeCommand.push_back(realTarget);
- } else {
- makeCommand.push_back("ALL_BUILD");
+
+ makeCommand.Add("-configuration", (config.empty() ? "Debug" : config));
+
+ if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) {
+ makeCommand.Add("-jobs");
+ if (jobs != cmake::DEFAULT_BUILD_PARALLEL_LEVEL) {
+ makeCommand.Add(std::to_string(jobs));
+ }
}
- makeCommand.push_back("-configuration");
- makeCommand.push_back(!config.empty() ? config : "Debug");
- makeCommand.insert(makeCommand.end(), makeOptions.begin(),
- makeOptions.end());
+
+ if (this->XcodeVersion >= 70) {
+ makeCommand.Add("-hideShellScriptEnvironment");
+ }
+ makeCommand.Add(makeOptions.begin(), makeOptions.end());
+ return { std::move(makeCommand) };
}
-///! Create a local generator appropriate to this Global Generator
+//! Create a local generator appropriate to this Global Generator
cmLocalGenerator* cmGlobalXCodeGenerator::CreateLocalGenerator(cmMakefile* mf)
{
return new cmLocalXCodeGenerator(this, mf);
@@ -330,15 +395,45 @@ cmLocalGenerator* cmGlobalXCodeGenerator::CreateLocalGenerator(cmMakefile* mf)
void cmGlobalXCodeGenerator::AddExtraIDETargets()
{
- std::map<std::string, std::vector<cmLocalGenerator*> >::iterator it;
// make sure extra targets are added before calling
// the parent generate which will call trace depends
- for (it = this->ProjectMap.begin(); it != this->ProjectMap.end(); ++it) {
- cmLocalGenerator* root = it->second[0];
+ for (auto keyVal : this->ProjectMap) {
+ cmLocalGenerator* root = keyVal.second[0];
this->SetGenerationRoot(root);
// add ALL_BUILD, INSTALL, etc
- this->AddExtraTargets(root, it->second);
+ this->AddExtraTargets(root, keyVal.second);
+ }
+}
+
+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()
@@ -347,12 +442,25 @@ void cmGlobalXCodeGenerator::Generate()
if (cmSystemTools::GetErrorOccuredFlag()) {
return;
}
- std::map<std::string, std::vector<cmLocalGenerator*> >::iterator it;
- for (it = this->ProjectMap.begin(); it != this->ProjectMap.end(); ++it) {
- cmLocalGenerator* root = it->second[0];
+
+ this->ComputeTargetOrder();
+
+ for (auto keyVal : this->ProjectMap) {
+ cmLocalGenerator* root = keyVal.second[0];
+
+ bool generateTopLevelProjectOnly =
+ root->GetMakefile()->IsOn("CMAKE_XCODE_GENERATE_TOP_LEVEL_PROJECT_ONLY");
+
+ if (generateTopLevelProjectOnly) {
+ cmStateSnapshot snp = root->GetStateSnapshot();
+ if (snp.GetBuildsystemDirectoryParent().IsValid()) {
+ continue;
+ }
+ }
+
this->SetGenerationRoot(root);
// now create the project
- this->OutputXCodeProject(root, it->second);
+ this->OutputXCodeProject(root, keyVal.second);
}
}
@@ -367,9 +475,9 @@ void cmGlobalXCodeGenerator::SetGenerationRoot(cmLocalGenerator* root)
this->CurrentLocalGenerator->GetCurrentBinaryDirectory(),
this->ProjectOutputDirectoryComponents);
- this->CurrentXCodeHackMakefile = root->GetCurrentBinaryDirectory();
- this->CurrentXCodeHackMakefile += "/CMakeScripts";
- cmSystemTools::MakeDirectory(this->CurrentXCodeHackMakefile.c_str());
+ this->CurrentXCodeHackMakefile =
+ cmStrCat(root->GetCurrentBinaryDirectory(), "/CMakeScripts");
+ cmSystemTools::MakeDirectory(this->CurrentXCodeHackMakefile);
this->CurrentXCodeHackMakefile += "/XCODE_DEPEND_HELPER.make";
}
@@ -378,54 +486,52 @@ std::string cmGlobalXCodeGenerator::PostBuildMakeTarget(
{
std::string target = tName;
std::replace(target.begin(), target.end(), ' ', '_');
- std::string out = "PostBuild." + target;
- out += "." + configName;
+ std::string out = cmStrCat("PostBuild.", target, '.', configName);
return out;
}
#define CMAKE_CHECK_BUILD_SYSTEM_TARGET "ZERO_CHECK"
+#define OBJECT_LIBRARY_ARTIFACT_DIR std::string()
void cmGlobalXCodeGenerator::AddExtraTargets(
cmLocalGenerator* root, std::vector<cmLocalGenerator*>& gens)
{
cmMakefile* mf = root->GetMakefile();
- // Add ALL_BUILD
- const char* no_working_directory = 0;
+ const char* no_working_directory = nullptr;
+ std::vector<std::string> no_byproducts;
std::vector<std::string> no_depends;
- cmTarget* allbuild =
- mf->AddUtilityCommand("ALL_BUILD", true, no_depends, no_working_directory,
- "echo", "Build all projects");
+
+ // Add ALL_BUILD
+ cmTarget* allbuild = mf->AddUtilityCommand(
+ "ALL_BUILD", cmCommandOrigin::Generator, true, no_working_directory,
+ no_byproducts, no_depends,
+ cmMakeSingleCommandLine({ "echo", "Build all projects" }));
cmGeneratorTarget* allBuildGt = new cmGeneratorTarget(allbuild, root);
root->AddGeneratorTarget(allBuildGt);
- // Refer to the main build configuration file for easy editing.
- std::string listfile = root->GetCurrentSourceDirectory();
- listfile += "/";
- listfile += "CMakeLists.txt";
- allBuildGt->AddSource(listfile);
-
// Add XCODE depend helper
std::string dir = root->GetCurrentBinaryDirectory();
- cmCustomCommandLine makeHelper;
- makeHelper.push_back("make");
- makeHelper.push_back("-C");
- makeHelper.push_back(dir);
- makeHelper.push_back("-f");
- makeHelper.push_back(this->CurrentXCodeHackMakefile);
- makeHelper.push_back(""); // placeholder, see below
+ cmCustomCommandLines commandLines = cmMakeSingleCommandLine(
+ { "make", "-C", dir, "-f", this->CurrentXCodeHackMakefile,
+ "OBJDIR=$(OBJDIR)", /* placeholder, see below */ "" });
// Add ZERO_CHECK
- bool regenerate = !mf->IsOn("CMAKE_SUPPRESS_REGENERATION");
- if (regenerate) {
+ bool regenerate = !this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION");
+ bool generateTopLevelProjectOnly =
+ mf->IsOn("CMAKE_XCODE_GENERATE_TOP_LEVEL_PROJECT_ONLY");
+ bool isTopLevel =
+ !root->GetStateSnapshot().GetBuildsystemDirectoryParent().IsValid();
+ if (regenerate && (isTopLevel || !generateTopLevelProjectOnly)) {
this->CreateReRunCMakeFile(root, gens);
std::string file =
- this->ConvertToRelativeForMake(this->CurrentReRunCMakeMakefile.c_str());
+ this->ConvertToRelativeForMake(this->CurrentReRunCMakeMakefile);
cmSystemTools::ReplaceString(file, "\\ ", " ");
- cmTarget* check =
- mf->AddUtilityCommand(CMAKE_CHECK_BUILD_SYSTEM_TARGET, true, no_depends,
- no_working_directory, "make", "-f", file.c_str());
+ cmTarget* check = mf->AddUtilityCommand(
+ CMAKE_CHECK_BUILD_SYSTEM_TARGET, cmCommandOrigin::Generator, true,
+ no_working_directory, no_byproducts, no_depends,
+ cmMakeSingleCommandLine({ "make", "-f", file }));
cmGeneratorTarget* checkGt = new cmGeneratorTarget(check, root);
root->AddGeneratorTarget(checkGt);
@@ -433,25 +539,14 @@ void cmGlobalXCodeGenerator::AddExtraTargets(
// now make the allbuild depend on all the non-utility targets
// in the project
- for (std::vector<cmLocalGenerator*>::iterator i = gens.begin();
- i != gens.end(); ++i) {
- cmLocalGenerator* lg = *i;
- if (this->IsExcluded(root, *i)) {
- continue;
- }
-
- std::vector<cmGeneratorTarget*> tgts = lg->GetGeneratorTargets();
- for (std::vector<cmGeneratorTarget*>::iterator l = tgts.begin();
- l != tgts.end(); l++) {
- cmGeneratorTarget* target = *l;
-
+ for (auto& gen : gens) {
+ for (auto target : gen->GetGeneratorTargets()) {
if (target->GetType() == cmStateEnums::GLOBAL_TARGET) {
continue;
}
- std::string targetName = target->GetName();
-
- if (regenerate && (targetName != CMAKE_CHECK_BUILD_SYSTEM_TARGET)) {
+ if (regenerate &&
+ (target->GetName() != CMAKE_CHECK_BUILD_SYSTEM_TARGET)) {
target->Target->AddUtility(CMAKE_CHECK_BUILD_SYSTEM_TARGET);
}
@@ -459,33 +554,19 @@ void cmGlobalXCodeGenerator::AddExtraTargets(
// run the depend check makefile as a post build rule
// this will make sure that when the next target is built
// things are up-to-date
- if (target->GetType() == cmStateEnums::OBJECT_LIBRARY ||
- (this->XcodeVersion < 50 &&
- (target->GetType() == cmStateEnums::EXECUTABLE ||
- target->GetType() == cmStateEnums::STATIC_LIBRARY ||
- target->GetType() == cmStateEnums::SHARED_LIBRARY ||
- target->GetType() == cmStateEnums::MODULE_LIBRARY))) {
- makeHelper[makeHelper.size() - 1] = // fill placeholder
+ if (target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
+ commandLines.front().back() = // fill placeholder
this->PostBuildMakeTarget(target->GetName(), "$(CONFIGURATION)");
- cmCustomCommandLines commandLines;
- commandLines.push_back(makeHelper);
- std::vector<std::string> no_byproducts;
- lg->GetMakefile()->AddCustomCommandToTarget(
+ gen->GetMakefile()->AddCustomCommandToTarget(
target->GetName(), no_byproducts, no_depends, commandLines,
- cmTarget::POST_BUILD, "Depend check for xcode", dir.c_str(), true,
- false, "", false, cmMakefile::AcceptObjectLibraryCommands);
+ cmCustomCommandType::POST_BUILD, "Depend check for xcode",
+ dir.c_str(), true, false, "", "", false,
+ cmObjectLibraryCommands::Accept);
}
- if (target->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
- !target->GetPropertyAsBool("EXCLUDE_FROM_ALL")) {
+ if (!this->IsExcluded(gens[0], target)) {
allbuild->AddUtility(target->GetName());
}
-
- // Refer to the build configuration file for easy editing.
- listfile = lg->GetCurrentSourceDirectory();
- listfile += "/";
- listfile += "CMakeLists.txt";
- target->AddSource(listfile);
}
}
}
@@ -494,47 +575,60 @@ void cmGlobalXCodeGenerator::CreateReRunCMakeFile(
cmLocalGenerator* root, std::vector<cmLocalGenerator*> const& gens)
{
std::vector<std::string> lfiles;
- for (std::vector<cmLocalGenerator*>::const_iterator gi = gens.begin();
- gi != gens.end(); ++gi) {
- std::vector<std::string> const& lf = (*gi)->GetMakefile()->GetListFiles();
- lfiles.insert(lfiles.end(), lf.begin(), lf.end());
+ for (auto gen : gens) {
+ cmAppend(lfiles, gen->GetMakefile()->GetListFiles());
}
// sort the array
- std::sort(lfiles.begin(), lfiles.end(), std::less<std::string>());
- std::vector<std::string>::iterator new_end =
- std::unique(lfiles.begin(), lfiles.end());
- lfiles.erase(new_end, lfiles.end());
- this->CurrentReRunCMakeMakefile = root->GetCurrentBinaryDirectory();
- this->CurrentReRunCMakeMakefile += "/CMakeScripts";
- cmSystemTools::MakeDirectory(this->CurrentReRunCMakeMakefile.c_str());
+ std::sort(lfiles.begin(), lfiles.end());
+ lfiles.erase(std::unique(lfiles.begin(), lfiles.end()), lfiles.end());
+
+ cmake* cm = this->GetCMakeInstance();
+ if (cm->DoWriteGlobVerifyTarget()) {
+ lfiles.emplace_back(cm->GetGlobVerifyStamp());
+ }
+
+ this->CurrentReRunCMakeMakefile =
+ cmStrCat(root->GetCurrentBinaryDirectory(), "/CMakeScripts");
+ cmSystemTools::MakeDirectory(this->CurrentReRunCMakeMakefile);
this->CurrentReRunCMakeMakefile += "/ReRunCMake.make";
- cmGeneratedFileStream makefileStream(
- this->CurrentReRunCMakeMakefile.c_str());
+ cmGeneratedFileStream makefileStream(this->CurrentReRunCMakeMakefile);
makefileStream.SetCopyIfDifferent(true);
makefileStream << "# Generated by CMake, DO NOT EDIT\n\n";
+ makefileStream << "TARGETS:= \n";
makefileStream << "empty:= \n";
makefileStream << "space:= $(empty) $(empty)\n";
makefileStream << "spaceplus:= $(empty)\\ $(empty)\n\n";
- for (std::vector<std::string>::const_iterator i = lfiles.begin();
- i != lfiles.end(); ++i) {
+ for (const auto& lfile : lfiles) {
makefileStream << "TARGETS += $(subst $(space),$(spaceplus),$(wildcard "
- << this->ConvertToRelativeForMake(i->c_str()) << "))\n";
+ << this->ConvertToRelativeForMake(lfile) << "))\n";
}
+ makefileStream << "\n";
- std::string checkCache = root->GetBinaryDirectory();
- checkCache += "/";
- checkCache += cmake::GetCMakeFilesDirectoryPostSlash();
- checkCache += "cmake.check_cache";
+ std::string checkCache =
+ cmStrCat(root->GetBinaryDirectory(), "/CMakeFiles/cmake.check_cache");
- makefileStream << "\n"
- << this->ConvertToRelativeForMake(checkCache.c_str())
+ if (cm->DoWriteGlobVerifyTarget()) {
+ makefileStream << ".NOTPARALLEL:\n\n";
+ makefileStream << ".PHONY: all VERIFY_GLOBS\n\n";
+ makefileStream << "all: VERIFY_GLOBS "
+ << this->ConvertToRelativeForMake(checkCache) << "\n\n";
+ makefileStream << "VERIFY_GLOBS:\n";
+ makefileStream << "\t"
+ << this->ConvertToRelativeForMake(
+ cmSystemTools::GetCMakeCommand())
+ << " -P "
+ << this->ConvertToRelativeForMake(cm->GetGlobVerifyScript())
+ << "\n\n";
+ }
+
+ makefileStream << this->ConvertToRelativeForMake(checkCache)
<< ": $(TARGETS)\n";
makefileStream << "\t"
<< this->ConvertToRelativeForMake(
- cmSystemTools::GetCMakeCommand().c_str())
+ cmSystemTools::GetCMakeCommand())
<< " -H"
<< this->ConvertToRelativeForMake(root->GetSourceDirectory())
<< " -B"
@@ -556,8 +650,8 @@ void cmGlobalXCodeGenerator::SortXCodeObjects()
void cmGlobalXCodeGenerator::ClearXCodeObjects()
{
this->TargetDoneSet.clear();
- for (unsigned int i = 0; i < this->XCodeObjects.size(); ++i) {
- delete this->XCodeObjects[i];
+ for (auto& obj : this->XCodeObjects) {
+ delete obj;
}
this->XCodeObjects.clear();
this->XCodeObjectIDs.clear();
@@ -571,7 +665,7 @@ void cmGlobalXCodeGenerator::ClearXCodeObjects()
void cmGlobalXCodeGenerator::addObject(cmXCodeObject* obj)
{
if (obj->GetType() == cmXCodeObject::OBJECT) {
- std::string id = obj->GetId();
+ const std::string& id = obj->GetId();
// If this is a duplicate id, it's an error:
//
@@ -649,9 +743,58 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFileFromPath(
return buildFile;
}
+class XCodeGeneratorExpressionInterpreter
+ : public cmGeneratorExpressionInterpreter
+{
+public:
+ XCodeGeneratorExpressionInterpreter(cmSourceFile* sourceFile,
+ cmLocalGenerator* localGenerator,
+ cmGeneratorTarget* headTarget,
+ const std::string& lang)
+ : cmGeneratorExpressionInterpreter(
+ localGenerator, "NO-PER-CONFIG-SUPPORT-IN-XCODE", headTarget, lang)
+ , SourceFile(sourceFile)
+ {
+ }
+
+ XCodeGeneratorExpressionInterpreter(
+ XCodeGeneratorExpressionInterpreter const&) = delete;
+ XCodeGeneratorExpressionInterpreter& operator=(
+ XCodeGeneratorExpressionInterpreter const&) = delete;
+
+ using cmGeneratorExpressionInterpreter::Evaluate;
+
+ const std::string& Evaluate(const char* expression,
+ const std::string& property)
+ {
+ const std::string& processed =
+ this->cmGeneratorExpressionInterpreter::Evaluate(expression, property);
+ if (this->CompiledGeneratorExpression->GetHadContextSensitiveCondition()) {
+ std::ostringstream e;
+ /* clang-format off */
+ e <<
+ "Xcode does not support per-config per-source " << property << ":\n"
+ " " << expression << "\n"
+ "specified for source:\n"
+ " " << this->SourceFile->ResolveFullPath() << "\n";
+ /* clang-format on */
+ this->LocalGenerator->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ }
+
+ return processed;
+ }
+
+private:
+ cmSourceFile* SourceFile = nullptr;
+};
+
cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile(
cmLocalGenerator* lg, cmSourceFile* sf, cmGeneratorTarget* gtgt)
{
+ std::string lang = this->CurrentLocalGenerator->GetSourceFileLanguage(*sf);
+
+ XCodeGeneratorExpressionInterpreter genexInterpreter(sf, lg, gtgt, lang);
+
// Add flags from target and source file properties.
std::string flags;
const char* srcfmt = sf->GetProperty("Fortran_FORMAT");
@@ -665,29 +808,30 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile(
default:
break;
}
- if (const char* cflags = sf->GetProperty("COMPILE_FLAGS")) {
- cmGeneratorExpression ge;
- std::string configName = "NO-PER-CONFIG-SUPPORT-IN-XCODE";
- CM_AUTO_PTR<cmCompiledGeneratorExpression> compiledExpr = ge.Parse(cflags);
- const char* processed = compiledExpr->Evaluate(lg, configName);
- if (compiledExpr->GetHadContextSensitiveCondition()) {
- std::ostringstream e;
- /* clang-format off */
- e <<
- "Xcode does not support per-config per-source COMPILE_FLAGS:\n"
- " " << cflags << "\n"
- "specified for source:\n"
- " " << sf->GetFullPath() << "\n";
- /* clang-format on */
- lg->IssueMessage(cmake::FATAL_ERROR, e.str());
- }
- lg->AppendFlags(flags, processed);
+ const std::string COMPILE_FLAGS("COMPILE_FLAGS");
+ if (const char* cflags = sf->GetProperty(COMPILE_FLAGS)) {
+ lg->AppendFlags(flags, genexInterpreter.Evaluate(cflags, COMPILE_FLAGS));
+ }
+ const std::string COMPILE_OPTIONS("COMPILE_OPTIONS");
+ if (const char* coptions = sf->GetProperty(COMPILE_OPTIONS)) {
+ lg->AppendCompileOptions(
+ flags, genexInterpreter.Evaluate(coptions, COMPILE_OPTIONS));
}
// Add per-source definitions.
BuildObjectListOrString flagsBuild(this, false);
- this->AppendDefines(flagsBuild, sf->GetProperty("COMPILE_DEFINITIONS"),
- true);
+ const std::string COMPILE_DEFINITIONS("COMPILE_DEFINITIONS");
+ if (const char* compile_defs = sf->GetProperty(COMPILE_DEFINITIONS)) {
+ this->AppendDefines(
+ flagsBuild,
+ genexInterpreter.Evaluate(compile_defs, COMPILE_DEFINITIONS).c_str(),
+ true);
+ }
+
+ if (sf->GetPropertyAsBool("SKIP_PRECOMPILE_HEADERS")) {
+ this->AppendDefines(flagsBuild, "CMAKE_SKIP_PRECOMPILE_HEADERS", true);
+ }
+
if (!flagsBuild.IsEmpty()) {
if (!flags.empty()) {
flags += ' ';
@@ -695,10 +839,18 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile(
flags += flagsBuild.GetString();
}
- std::string lang = this->CurrentLocalGenerator->GetSourceFileLanguage(*sf);
+ // Add per-source include directories.
+ std::vector<std::string> includes;
+ const std::string INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES");
+ if (const char* cincludes = sf->GetProperty(INCLUDE_DIRECTORIES)) {
+ lg->AppendIncludeDirectories(
+ includes, genexInterpreter.Evaluate(cincludes, INCLUDE_DIRECTORIES),
+ *sf);
+ }
+ lg->AppendFlags(flags, lg->GetIncludeFlags(includes, gtgt, lang, true));
cmXCodeObject* buildFile =
- this->CreateXCodeSourceFileFromPath(sf->GetFullPath(), gtgt, lang, sf);
+ this->CreateXCodeSourceFileFromPath(sf->ResolveFullPath(), gtgt, lang, sf);
cmXCodeObject* settings = this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
settings->AddAttributeIfNotEmpty("COMPILER_FLAGS",
@@ -724,13 +876,11 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile(
const char* extraFileAttributes = sf->GetProperty("XCODE_FILE_ATTRIBUTES");
if (extraFileAttributes) {
// Expand the list of attributes.
- std::vector<std::string> attributes;
- cmSystemTools::ExpandListArgument(extraFileAttributes, attributes);
+ std::vector<std::string> attributes = cmExpandedList(extraFileAttributes);
// Store the attributes.
- for (std::vector<std::string>::const_iterator ai = attributes.begin();
- ai != attributes.end(); ++ai) {
- attrs->AddObject(this->CreateString(*ai));
+ for (const auto& attribute : attributes) {
+ attrs->AddObject(this->CreateString(attribute));
}
}
@@ -740,6 +890,19 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile(
return buildFile;
}
+void cmGlobalXCodeGenerator::AddXCodeProjBuildRule(
+ cmGeneratorTarget* target, std::vector<cmSourceFile*>& sources) const
+{
+ std::string listfile =
+ cmStrCat(target->GetLocalGenerator()->GetCurrentSourceDirectory(),
+ "/CMakeLists.txt");
+ cmSourceFile* srcCMakeLists = target->Makefile->GetOrCreateSource(
+ listfile, false, cmSourceFileLocationKind::Known);
+ if (!cmContains(sources, srcCMakeLists)) {
+ sources.push_back(srcCMakeLists);
+ }
+}
+
std::string GetSourcecodeValueFromFileExtension(const std::string& _ext,
const std::string& lang,
bool& keepLastKnownFileType)
@@ -779,6 +942,10 @@ std::string GetSourcecodeValueFromFileExtension(const std::string& _ext,
sourcecode += ".cpp.cpp";
} else if (lang == "C") {
sourcecode += ".c.c";
+ } else if (lang == "OBJCXX") {
+ sourcecode += ".cpp.objcpp";
+ } else if (lang == "OBJC") {
+ sourcecode += ".c.objc";
} else if (lang == "Fortran") {
sourcecode += ".fortran.f90";
} else if (lang == "ASM") {
@@ -852,11 +1019,10 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeFileReferenceFromPath(
this->CreateString(fileType));
// Store the file path relative to the top of the source tree.
- std::string path = this->RelativeToSource(fullpath.c_str());
+ std::string path = this->RelativeToSource(fullpath);
std::string name = cmSystemTools::GetFilenameName(path);
const char* sourceTree =
- (cmSystemTools::FileIsFullPath(path.c_str()) ? "<absolute>"
- : "SOURCE_ROOT");
+ cmSystemTools::FileIsFullPath(path) ? "<absolute>" : "SOURCE_ROOT";
fileRef->AddAttribute("name", this->CreateString(name));
fileRef->AddAttribute("path", this->CreateString(path));
fileRef->AddAttribute("sourceTree", this->CreateString(sourceTree));
@@ -868,7 +1034,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeFileReference(
{
std::string lang = this->CurrentLocalGenerator->GetSourceFileLanguage(*sf);
- return this->CreateXCodeFileReferenceFromPath(sf->GetFullPath(), target,
+ return this->CreateXCodeFileReferenceFromPath(sf->ResolveFullPath(), target,
lang, sf);
}
@@ -895,7 +1061,7 @@ void cmGlobalXCodeGenerator::SetCurrentLocalGenerator(cmLocalGenerator* gen)
this->CurrentConfigurationTypes.clear();
this->CurrentMakefile->GetConfigurations(this->CurrentConfigurationTypes);
if (this->CurrentConfigurationTypes.empty()) {
- this->CurrentConfigurationTypes.push_back("");
+ this->CurrentConfigurationTypes.emplace_back();
}
}
@@ -903,21 +1069,23 @@ struct cmSourceFilePathCompare
{
bool operator()(cmSourceFile* l, cmSourceFile* r)
{
- return l->GetFullPath() < r->GetFullPath();
+ return l->ResolveFullPath() < r->ResolveFullPath();
}
};
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;
}
};
@@ -925,298 +1093,282 @@ bool cmGlobalXCodeGenerator::CreateXCodeTargets(
cmLocalGenerator* gen, std::vector<cmXCodeObject*>& targets)
{
this->SetCurrentLocalGenerator(gen);
- std::vector<cmGeneratorTarget*> tgts =
+ std::vector<cmGeneratorTarget*> gts =
this->CurrentLocalGenerator->GetGeneratorTargets();
- typedef std::map<std::string, cmGeneratorTarget*, cmCompareTargets>
- cmSortedTargets;
- cmSortedTargets sortedTargets;
- for (std::vector<cmGeneratorTarget*>::iterator l = tgts.begin();
- l != tgts.end(); l++) {
- sortedTargets[(*l)->GetName()] = *l;
+ 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;
+ }
}
- for (cmSortedTargets::iterator l = sortedTargets.begin();
- l != sortedTargets.end(); l++) {
- cmGeneratorTarget* gtgt = l->second;
-
- std::string targetName = gtgt->GetName();
+ std::sort(targets.begin(), targets.end(), cmCompareTargets());
+ return true;
+}
- // make sure ALL_BUILD, INSTALL, etc are only done once
- if (this->SpecialTargetEmitted(targetName)) {
- continue;
- }
+bool cmGlobalXCodeGenerator::CreateXCodeTarget(
+ cmGeneratorTarget* gtgt, std::vector<cmXCodeObject*>& targets)
+{
+ std::string targetName = gtgt->GetName();
- if (gtgt->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
- continue;
- }
+ // make sure ALL_BUILD, INSTALL, etc are only done once
+ if (this->SpecialTargetEmitted(targetName)) {
+ return true;
+ }
- if (gtgt->GetType() == cmStateEnums::UTILITY ||
- gtgt->GetType() == cmStateEnums::GLOBAL_TARGET) {
- cmXCodeObject* t = this->CreateUtilityTarget(gtgt);
- if (!t) {
- return false;
- }
- targets.push_back(t);
- continue;
- }
+ if (gtgt->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ return true;
+ }
- // organize the sources
- std::vector<cmSourceFile*> classes;
- if (!gtgt->GetConfigCommonSourceFiles(classes)) {
+ if (gtgt->GetType() == cmStateEnums::UTILITY ||
+ gtgt->GetType() == cmStateEnums::GLOBAL_TARGET) {
+ cmXCodeObject* t = this->CreateUtilityTarget(gtgt);
+ if (!t) {
return false;
}
- std::sort(classes.begin(), classes.end(), cmSourceFilePathCompare());
+ targets.push_back(t);
+ return true;
+ }
- gtgt->ComputeObjectMapping();
+ // organize the sources
+ std::vector<cmSourceFile*> classes;
+ if (!gtgt->GetConfigCommonSourceFiles(classes)) {
+ return false;
+ }
- std::vector<cmXCodeObject*> externalObjFiles;
- std::vector<cmXCodeObject*> headerFiles;
- std::vector<cmXCodeObject*> resourceFiles;
- std::vector<cmXCodeObject*> sourceFiles;
- for (std::vector<cmSourceFile*>::const_iterator i = classes.begin();
- i != classes.end(); ++i) {
- cmXCodeObject* xsf =
- this->CreateXCodeSourceFile(this->CurrentLocalGenerator, *i, gtgt);
- cmXCodeObject* fr = xsf->GetObject("fileRef");
- cmXCodeObject* filetype = fr->GetObject()->GetObject("explicitFileType");
+ // Add CMakeLists.txt file for user convenience.
+ this->AddXCodeProjBuildRule(gtgt, classes);
- cmGeneratorTarget::SourceFileFlags tsFlags =
- gtgt->GetTargetSourceFileFlags(*i);
+ // Add the Info.plist we are about to generate for an App Bundle.
+ if (gtgt->GetPropertyAsBool("MACOSX_BUNDLE")) {
+ std::string plist = this->ComputeInfoPListLocation(gtgt);
+ cmSourceFile* sf = gtgt->Makefile->GetOrCreateSource(
+ plist, true, cmSourceFileLocationKind::Known);
+ classes.push_back(sf);
+ }
- if (filetype && filetype->GetString() == "compiled.mach-o.objfile") {
- if ((*i)->GetObjectLibrary().empty()) {
- externalObjFiles.push_back(xsf);
- }
- } else if (this->IsHeaderFile(*i) ||
- (tsFlags.Type ==
- cmGeneratorTarget::SourceFileTypePrivateHeader) ||
- (tsFlags.Type ==
- cmGeneratorTarget::SourceFileTypePublicHeader)) {
- headerFiles.push_back(xsf);
- } else if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeResource) {
- resourceFiles.push_back(xsf);
- } else if (!(*i)->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(**i).empty() &&
- !this->IgnoreFile((*i)->GetExtension().c_str())) {
- sourceFiles.push_back(xsf);
- }
- }
- }
+ std::sort(classes.begin(), classes.end(), cmSourceFilePathCompare());
- 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 (std::vector<cmSourceFile const*>::const_iterator oi = objs.begin();
- oi != objs.end(); ++oi) {
- if ((*oi)->GetObjectLibrary().empty()) {
- continue;
- }
- std::string const& obj = (*oi)->GetFullPath();
- cmXCodeObject* xsf =
- this->CreateXCodeSourceFileFromPath(obj, gtgt, "", 0);
- externalObjFiles.push_back(xsf);
- }
- }
+ gtgt->ComputeObjectMapping();
- // some build phases only apply to bundles and/or frameworks
- bool isFrameworkTarget = gtgt->IsFrameworkOnApple();
- bool isBundleTarget = gtgt->GetPropertyAsBool("MACOSX_BUNDLE");
- bool isCFBundleTarget = gtgt->IsCFBundleOnApple();
+ 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");
- cmXCodeObject* buildFiles = 0;
+ cmGeneratorTarget::SourceFileFlags tsFlags =
+ gtgt->GetTargetSourceFileFlags(sourceFile);
- // create source build phase
- cmXCodeObject* sourceBuildPhase = 0;
- if (!sourceFiles.empty()) {
- sourceBuildPhase =
- this->CreateObject(cmXCodeObject::PBXSourcesBuildPhase);
- sourceBuildPhase->SetComment("Sources");
- sourceBuildPhase->AddAttribute("buildActionMask",
- this->CreateString("2147483647"));
- buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
- for (std::vector<cmXCodeObject*>::iterator i = sourceFiles.begin();
- i != sourceFiles.end(); ++i) {
- buildFiles->AddObject(*i);
+ 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") &&
+ !gtgt->IsSourceFilePartOfUnityBatch(
+ sourceFile->ResolveFullPath())) {
+ // 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);
}
- sourceBuildPhase->AddAttribute("files", buildFiles);
- sourceBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
- this->CreateString("0"));
}
+ }
- // create header build phase - only for framework targets
- cmXCodeObject* headerBuildPhase = 0;
- if (!headerFiles.empty() && isFrameworkTarget) {
- headerBuildPhase =
- this->CreateObject(cmXCodeObject::PBXHeadersBuildPhase);
- headerBuildPhase->SetComment("Headers");
- headerBuildPhase->AddAttribute("buildActionMask",
+ // 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 (std::vector<cmXCodeObject*>::iterator i = headerFiles.begin();
- i != headerFiles.end(); ++i) {
- buildFiles->AddObject(*i);
- }
- headerBuildPhase->AddAttribute("files", buildFiles);
- headerBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
- this->CreateString("0"));
+ buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
+ for (auto& resourceFile : resourceFiles) {
+ buildFiles->AddObject(resourceFile);
}
+ resourceBuildPhase->AddAttribute("files", buildFiles);
+ resourceBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
+ this->CreateString("0"));
+ }
- // create resource build phase - only for framework or bundle targets
- cmXCodeObject* resourceBuildPhase = 0;
- 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 (std::vector<cmXCodeObject*>::iterator i = resourceFiles.begin();
- i != resourceFiles.end(); ++i) {
- buildFiles->AddObject(*i);
+ // create vector of "non-resource content file" build phases - only for
+ // framework or bundle targets
+ std::vector<cmXCodeObject*> contentBuildPhases;
+ if (isFrameworkTarget || isBundleTarget || isCFBundleTarget) {
+ using mapOfVectorOfSourceFiles =
+ std::map<std::string, std::vector<cmSourceFile*>>;
+ mapOfVectorOfSourceFiles bundleFiles;
+ for (auto sourceFile : classes) {
+ cmGeneratorTarget::SourceFileFlags tsFlags =
+ gtgt->GetTargetSourceFileFlags(sourceFile);
+ if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeMacContent) {
+ bundleFiles[tsFlags.MacFolder].push_back(sourceFile);
}
- 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 (std::vector<cmSourceFile*>::const_iterator i = classes.begin();
- i != classes.end(); ++i) {
- cmGeneratorTarget::SourceFileFlags tsFlags =
- gtgt->GetTargetSourceFileFlags(*i);
- if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeMacContent) {
- bundleFiles[tsFlags.MacFolder].push_back(*i);
+ }
+ for (auto const& 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;
}
}
- mapOfVectorOfSourceFiles::iterator mit;
- for (mit = bundleFiles.begin(); mit != bundleFiles.end(); ++mit) {
- 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 << mit->first;
- } else if (mit->first != "MacOS") {
- if (gtgt->Target->GetMakefile()->PlatformIsAppleIos()) {
- ostr << mit->first;
- } else {
- // dstPath in bundles is relative to Contents/MacOS
- ostr << "../" << mit->first;
- }
- }
- copyFilesBuildPhase->AddAttribute("dstPath",
- this->CreateString(ostr.str()));
- copyFilesBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
- this->CreateString("0"));
- buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
- copyFilesBuildPhase->AddAttribute("files", buildFiles);
- std::vector<cmSourceFile*>::iterator sfIt;
- for (sfIt = mit->second.begin(); sfIt != mit->second.end(); ++sfIt) {
- cmXCodeObject* xsf = this->CreateXCodeSourceFile(
- this->CurrentLocalGenerator, *sfIt, gtgt);
- buildFiles->AddObject(xsf);
- }
- contentBuildPhases.push_back(copyFilesBuildPhase);
+ 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 (std::vector<cmSourceFile*>::const_iterator i = classes.begin();
- i != classes.end(); ++i) {
- cmGeneratorTarget::SourceFileFlags tsFlags =
- gtgt->GetTargetSourceFileFlags(*i);
- if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeDeepResource) {
- bundleFiles[tsFlags.MacFolder].push_back(*i);
- }
- }
- mapOfVectorOfSourceFiles::iterator mit;
- for (mit = bundleFiles.begin(); mit != bundleFiles.end(); ++mit) {
- 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(mit->first));
- copyFilesBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
- this->CreateString("0"));
- buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
- copyFilesBuildPhase->AddAttribute("files", buildFiles);
- std::vector<cmSourceFile*>::iterator sfIt;
- for (sfIt = mit->second.begin(); sfIt != mit->second.end(); ++sfIt) {
- cmXCodeObject* xsf = this->CreateXCodeSourceFile(
- this->CurrentLocalGenerator, *sfIt, 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) {
+ using mapOfVectorOfSourceFiles =
+ std::map<std::string, std::vector<cmSourceFile*>>;
+ mapOfVectorOfSourceFiles bundleFiles;
+ for (auto sourceFile : classes) {
+ cmGeneratorTarget::SourceFileFlags tsFlags =
+ gtgt->GetTargetSourceFileFlags(sourceFile);
+ if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeDeepResource) {
+ bundleFiles[tsFlags.MacFolder].push_back(sourceFile);
}
}
-
- // create framework build phase
- cmXCodeObject* frameworkBuildPhase = 0;
- if (!externalObjFiles.empty()) {
- frameworkBuildPhase =
- this->CreateObject(cmXCodeObject::PBXFrameworksBuildPhase);
- frameworkBuildPhase->SetComment("Frameworks");
- frameworkBuildPhase->AddAttribute("buildActionMask",
+ for (auto const& 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);
- frameworkBuildPhase->AddAttribute("files", buildFiles);
- for (std::vector<cmXCodeObject*>::iterator i = externalObjFiles.begin();
- i != externalObjFiles.end(); ++i) {
- buildFiles->AddObject(*i);
+ copyFilesBuildPhase->AddAttribute("files", buildFiles);
+ for (auto sourceFile : keySources.second) {
+ cmXCodeObject* xsf = this->CreateXCodeSourceFile(
+ this->CurrentLocalGenerator, sourceFile, gtgt);
+ buildFiles->AddObject(xsf);
}
- frameworkBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
- this->CreateString("0"));
+ contentBuildPhases.push_back(copyFilesBuildPhase);
}
+ }
- // create list of build phases and create the Xcode target
- cmXCodeObject* buildPhases =
- this->CreateObject(cmXCodeObject::OBJECT_LIST);
+ // 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"));
+ }
- this->CreateCustomCommands(buildPhases, sourceBuildPhase, headerBuildPhase,
- resourceBuildPhase, contentBuildPhases,
- frameworkBuildPhase, gtgt);
+ // create list of build phases and create the Xcode target
+ cmXCodeObject* buildPhases = this->CreateObject(cmXCodeObject::OBJECT_LIST);
- targets.push_back(this->CreateXCodeTarget(gtgt, buildPhases));
- }
+ this->CreateCustomCommands(buildPhases, sourceBuildPhase, headerBuildPhase,
+ resourceBuildPhase, contentBuildPhases,
+ frameworkBuildPhase, gtgt);
+
+ targets.push_back(this->CreateXCodeTarget(gtgt, buildPhases));
return true;
}
void cmGlobalXCodeGenerator::ForceLinkerLanguages()
{
- for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i) {
- std::vector<cmGeneratorTarget*> tgts =
- this->LocalGenerators[i]->GetGeneratorTargets();
+ for (auto localGenerator : this->LocalGenerators) {
// All targets depend on the build-system check target.
- for (std::vector<cmGeneratorTarget*>::const_iterator ti = tgts.begin();
- ti != tgts.end(); ++ti) {
+ for (auto tgt : localGenerator->GetGeneratorTargets()) {
// This makes sure all targets link using the proper language.
- this->ForceLinkerLanguage(*ti);
+ this->ForceLinkerLanguage(tgt);
}
}
}
@@ -1236,10 +1388,9 @@ void cmGlobalXCodeGenerator::ForceLinkerLanguage(cmGeneratorTarget* gtgt)
}
// If the language is compiled as a source trust Xcode to link with it.
- cmLinkImplementation const* impl = gtgt->GetLinkImplementation("NOCONFIG");
- for (std::vector<std::string>::const_iterator li = impl->Languages.begin();
- li != impl->Languages.end(); ++li) {
- if (*li == llang) {
+ for (auto const& Language :
+ gtgt->GetLinkImplementation("NOCONFIG")->Languages) {
+ if (Language == llang) {
return;
}
}
@@ -1248,15 +1399,11 @@ void cmGlobalXCodeGenerator::ForceLinkerLanguage(cmGeneratorTarget* gtgt)
// linker language. This should convince Xcode to choose the proper
// language.
cmMakefile* mf = gtgt->Target->GetMakefile();
- std::string fname = gtgt->GetLocalGenerator()->GetCurrentBinaryDirectory();
- fname += cmake::GetCMakeFilesDirectory();
- fname += "/";
- fname += gtgt->GetName();
- fname += "-CMakeForceLinker";
- fname += ".";
- fname += cmSystemTools::LowerCase(llang);
+ std::string fname = cmStrCat(
+ gtgt->GetLocalGenerator()->GetCurrentBinaryDirectory(), "/CMakeFiles/",
+ gtgt->GetName(), "-CMakeForceLinker.", cmSystemTools::LowerCase(llang));
{
- cmGeneratedFileStream fout(fname.c_str());
+ cmGeneratedFileStream fout(fname);
fout << "\n";
}
if (cmSourceFile* sf = mf->GetOrCreateSource(fname)) {
@@ -1267,18 +1414,16 @@ void cmGlobalXCodeGenerator::ForceLinkerLanguage(cmGeneratorTarget* gtgt)
bool cmGlobalXCodeGenerator::IsHeaderFile(cmSourceFile* sf)
{
- const std::vector<std::string>& hdrExts =
- this->CMakeInstance->GetHeaderExtensions();
- return (std::find(hdrExts.begin(), hdrExts.end(), sf->GetExtension()) !=
- hdrExts.end());
+ return cmContains(this->CMakeInstance->GetHeaderExtensions(),
+ sf->GetExtension());
}
cmXCodeObject* cmGlobalXCodeGenerator::CreateBuildPhase(
const char* name, const char* name2, cmGeneratorTarget* target,
const std::vector<cmCustomCommand>& commands)
{
- if (commands.size() == 0 && strcmp(name, "CMake ReRun") != 0) {
- return 0;
+ if (commands.empty() && strcmp(name, "CMake ReRun") != 0) {
+ return nullptr;
}
cmXCodeObject* buildPhase =
this->CreateObject(cmXCodeObject::PBXShellScriptBuildPhase);
@@ -1297,7 +1442,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateBuildPhase(
void cmGlobalXCodeGenerator::CreateCustomCommands(
cmXCodeObject* buildPhases, cmXCodeObject* sourceBuildPhase,
cmXCodeObject* headerBuildPhase, cmXCodeObject* resourceBuildPhase,
- std::vector<cmXCodeObject*> contentBuildPhases,
+ std::vector<cmXCodeObject*> const& contentBuildPhases,
cmXCodeObject* frameworkBuildPhase, cmGeneratorTarget* gtgt)
{
std::vector<cmCustomCommand> const& prebuild = gtgt->GetPreBuildCommands();
@@ -1306,23 +1451,14 @@ void cmGlobalXCodeGenerator::CreateCustomCommands(
if (gtgt->GetType() == cmStateEnums::SHARED_LIBRARY &&
!gtgt->IsFrameworkOnApple()) {
- cmCustomCommandLines cmd;
- cmd.resize(1);
- cmd[0].push_back(cmSystemTools::GetCMakeCommand());
- cmd[0].push_back("-E");
- cmd[0].push_back("cmake_symlink_library");
- std::string str_file = "$<TARGET_FILE:";
- str_file += gtgt->GetName();
- str_file += ">";
- std::string str_so_file = "$<TARGET_SONAME_FILE:";
- str_so_file += gtgt->GetName();
- str_so_file += ">";
- std::string str_link_file = "$<TARGET_LINKER_FILE:";
- str_link_file += gtgt->GetName();
- str_link_file += ">";
- cmd[0].push_back(str_file);
- cmd[0].push_back(str_so_file);
- cmd[0].push_back(str_link_file);
+ std::string str_file = cmStrCat("$<TARGET_FILE:", gtgt->GetName(), '>');
+ std::string str_so_file =
+ cmStrCat("$<TARGET_SONAME_FILE:", gtgt->GetName(), '>');
+ std::string str_link_file =
+ cmStrCat("$<TARGET_LINKER_FILE:", gtgt->GetName(), '>');
+ cmCustomCommandLines cmd = cmMakeSingleCommandLine(
+ { cmSystemTools::GetCMakeCommand(), "-E", "cmake_symlink_library",
+ str_file, str_so_file, str_link_file });
cmCustomCommand command(this->CurrentMakefile, std::vector<std::string>(),
std::vector<std::string>(),
@@ -1338,10 +1474,9 @@ void cmGlobalXCodeGenerator::CreateCustomCommands(
}
// add all the sources
std::vector<cmCustomCommand> commands;
- for (std::vector<cmSourceFile*>::const_iterator i = classes.begin();
- i != classes.end(); ++i) {
- if ((*i)->GetCustomCommand()) {
- commands.push_back(*(*i)->GetCustomCommand());
+ for (auto sourceFile : classes) {
+ if (sourceFile->GetCustomCommand()) {
+ commands.push_back(*sourceFile->GetCustomCommand());
}
}
// create prebuild phase
@@ -1373,10 +1508,8 @@ void cmGlobalXCodeGenerator::CreateCustomCommands(
if (resourceBuildPhase) {
buildPhases->AddObject(resourceBuildPhase);
}
- std::vector<cmXCodeObject*>::iterator cit;
- for (cit = contentBuildPhases.begin(); cit != contentBuildPhases.end();
- ++cit) {
- buildPhases->AddObject(*cit);
+ for (auto obj : contentBuildPhases) {
+ buildPhases->AddObject(obj);
}
if (sourceBuildPhase) {
buildPhases->AddObject(sourceBuildPhase);
@@ -1438,7 +1571,7 @@ std::string cmGlobalXCodeGenerator::ExtractFlagRegex(const char* exp,
std::string::size_type offset = 0;
- while (regex.find(flags.c_str() + offset)) {
+ while (regex.find(&flags[offset])) {
const std::string::size_type startPos = offset + regex.start(matchIndex);
const std::string::size_type endPos = offset + regex.end(matchIndex);
const std::string::size_type size = endPos - startPos;
@@ -1465,7 +1598,7 @@ void cmGlobalXCodeGenerator::FilterConfigurationAttribute(
return;
}
- std::string::size_type endVariant = attribute.find("]", beginVariant + 9);
+ std::string::size_type endVariant = attribute.find(']', beginVariant + 9);
if (endVariant == std::string::npos) {
// There is no terminating bracket.
return;
@@ -1489,32 +1622,23 @@ void cmGlobalXCodeGenerator::AddCommandsToBuildPhase(
cmXCodeObject* buildphase, cmGeneratorTarget* target,
std::vector<cmCustomCommand> const& commands, const char* name)
{
- std::string dir = this->CurrentLocalGenerator->GetCurrentBinaryDirectory();
- dir += "/CMakeScripts";
- cmSystemTools::MakeDirectory(dir.c_str());
- std::string makefile = dir;
- makefile += "/";
- makefile += target->GetName();
- makefile += "_";
- makefile += name;
- makefile += ".make";
-
- for (std::vector<std::string>::const_iterator currentConfig =
- this->CurrentConfigurationTypes.begin();
- currentConfig != this->CurrentConfigurationTypes.end();
- currentConfig++) {
+ std::string dir = cmStrCat(
+ this->CurrentLocalGenerator->GetCurrentBinaryDirectory(), "/CMakeScripts");
+ cmSystemTools::MakeDirectory(dir);
+ std::string makefile =
+ cmStrCat(dir, '/', target->GetName(), '_', name, ".make");
+
+ for (const auto& currentConfig : this->CurrentConfigurationTypes) {
this->CreateCustomRulesMakefile(makefile.c_str(), target, commands,
- *currentConfig);
+ currentConfig);
}
std::string cdir = this->CurrentLocalGenerator->GetCurrentBinaryDirectory();
- cdir = this->ConvertToRelativeForMake(cdir.c_str());
- std::string makecmd = "make -C ";
- makecmd += cdir;
- makecmd += " -f ";
- makecmd +=
- this->ConvertToRelativeForMake((makefile + "$CONFIGURATION").c_str());
- makecmd += " all";
+ cdir = this->ConvertToRelativeForMake(cdir);
+ std::string makecmd =
+ cmStrCat("make -C ", cdir, " -f ",
+ this->ConvertToRelativeForMake((makefile + "$CONFIGURATION")),
+ " OBJDIR=$(basename \"$OBJECT_FILE_DIR_normal\") all");
buildphase->AddAttribute("shellScript", this->CreateString(makecmd));
buildphase->AddAttribute("showEnvVarsInLog", this->CreateString("0"));
}
@@ -1523,9 +1647,8 @@ void cmGlobalXCodeGenerator::CreateCustomRulesMakefile(
const char* makefileBasename, cmGeneratorTarget* target,
std::vector<cmCustomCommand> const& commands, const std::string& configName)
{
- std::string makefileName = makefileBasename;
- makefileName += configName;
- cmGeneratedFileStream makefileStream(makefileName.c_str());
+ std::string makefileName = cmStrCat(makefileBasename, configName);
+ cmGeneratedFileStream makefileStream(makefileName);
if (!makefileStream) {
return;
}
@@ -1541,38 +1664,35 @@ void cmGlobalXCodeGenerator::CreateCustomRulesMakefile(
makefileStream << "all: ";
std::map<const cmCustomCommand*, std::string> tname;
int count = 0;
- for (std::vector<cmCustomCommand>::const_iterator i = commands.begin();
- i != commands.end(); ++i) {
- cmCustomCommandGenerator ccg(*i, configName, this->CurrentLocalGenerator);
+ for (auto const& command : commands) {
+ cmCustomCommandGenerator ccg(command, configName,
+ this->CurrentLocalGenerator);
if (ccg.GetNumberOfCommands() > 0) {
const std::vector<std::string>& outputs = ccg.GetOutputs();
if (!outputs.empty()) {
- for (std::vector<std::string>::const_iterator o = outputs.begin();
- o != outputs.end(); ++o) {
- makefileStream << "\\\n\t"
- << this->ConvertToRelativeForMake(o->c_str());
+ for (auto const& output : outputs) {
+ makefileStream << "\\\n\t" << this->ConvertToRelativeForMake(output);
}
} else {
std::ostringstream str;
str << "_buildpart_" << count++;
- tname[&ccg.GetCC()] = std::string(target->GetName()) + str.str();
+ tname[&ccg.GetCC()] = target->GetName() + str.str();
makefileStream << "\\\n\t" << tname[&ccg.GetCC()];
}
}
}
makefileStream << "\n\n";
- for (std::vector<cmCustomCommand>::const_iterator i = commands.begin();
- i != commands.end(); ++i) {
- cmCustomCommandGenerator ccg(*i, configName, this->CurrentLocalGenerator);
+ for (auto const& command : commands) {
+ cmCustomCommandGenerator ccg(command, configName,
+ this->CurrentLocalGenerator);
if (ccg.GetNumberOfCommands() > 0) {
makefileStream << "\n";
const std::vector<std::string>& outputs = ccg.GetOutputs();
if (!outputs.empty()) {
// There is at least one output, start the rule for it
const char* sep = "";
- for (std::vector<std::string>::const_iterator oi = outputs.begin();
- oi != outputs.end(); ++oi) {
- makefileStream << sep << this->ConvertToRelativeForMake(oi->c_str());
+ for (auto const& output : outputs) {
+ makefileStream << sep << this->ConvertToRelativeForMake(output);
sep = " ";
}
makefileStream << ": ";
@@ -1580,22 +1700,20 @@ void cmGlobalXCodeGenerator::CreateCustomRulesMakefile(
// There are no outputs. Use the generated force rule name.
makefileStream << tname[&ccg.GetCC()] << ": ";
}
- for (std::vector<std::string>::const_iterator d =
- ccg.GetDepends().begin();
- d != ccg.GetDepends().end(); ++d) {
+ for (auto const& d : ccg.GetDepends()) {
std::string dep;
- if (this->CurrentLocalGenerator->GetRealDependency(*d, configName,
+ if (this->CurrentLocalGenerator->GetRealDependency(d, configName,
dep)) {
- makefileStream << "\\\n"
- << this->ConvertToRelativeForMake(dep.c_str());
+ makefileStream << "\\\n" << this->ConvertToRelativeForMake(dep);
}
}
makefileStream << "\n";
if (const char* comment = ccg.GetComment()) {
- std::string echo_cmd = "echo ";
- echo_cmd += (this->CurrentLocalGenerator->EscapeForShell(
- comment, ccg.GetCC().GetEscapeAllowMakeVars()));
+ std::string echo_cmd =
+ cmStrCat("echo ",
+ (this->CurrentLocalGenerator->EscapeForShell(
+ comment, ccg.GetCC().GetEscapeAllowMakeVars())));
makefileStream << "\t" << echo_cmd << "\n";
}
@@ -1604,12 +1722,12 @@ void cmGlobalXCodeGenerator::CreateCustomRulesMakefile(
// Build the command line in a single string.
std::string cmd2 = ccg.GetCommand(c);
cmSystemTools::ReplaceString(cmd2, "/./", "/");
- cmd2 = this->ConvertToRelativeForMake(cmd2.c_str());
+ cmd2 = this->ConvertToRelativeForMake(cmd2);
std::string cmd;
std::string wd = ccg.GetWorkingDirectory();
if (!wd.empty()) {
cmd += "cd ";
- cmd += this->ConvertToRelativeForMake(wd.c_str());
+ cmd += this->ConvertToRelativeForMake(wd);
cmd += " && ";
}
cmd += cmd2;
@@ -1620,6 +1738,25 @@ void cmGlobalXCodeGenerator::CreateCustomRulesMakefile(
}
}
+void cmGlobalXCodeGenerator::AddPositionIndependentLinkAttribute(
+ cmGeneratorTarget* target, cmXCodeObject* buildSettings,
+ const std::string& configName)
+{
+ // For now, only EXECUTABLE is concerned
+ if (target->GetType() != cmStateEnums::EXECUTABLE) {
+ return;
+ }
+
+ const char* PICValue = target->GetLinkPIEProperty(configName);
+ if (PICValue == nullptr) {
+ // POSITION_INDEPENDENT_CODE is not set
+ return;
+ }
+
+ buildSettings->AddAttribute(
+ "LD_NO_PIE", this->CreateString(cmIsOn(PICValue) ? "NO" : "YES"));
+}
+
void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
cmXCodeObject* buildSettings,
const std::string& configName)
@@ -1639,15 +1776,17 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
std::set<std::string> languages;
gtgt->GetLanguages(languages, configName);
std::map<std::string, std::string> cflags;
- for (std::set<std::string>::iterator li = languages.begin();
- li != languages.end(); ++li) {
- std::string const& lang = *li;
+ for (auto const& lang : languages) {
std::string& flags = cflags[lang];
// Add language-specific flags.
this->CurrentLocalGenerator->AddLanguageFlags(flags, gtgt, lang,
configName);
+ if (gtgt->IsIPOEnabled(lang, configName)) {
+ this->CurrentLocalGenerator->AppendFeatureOptions(flags, lang, "IPO");
+ }
+
// Add shared-library flags if needed.
this->CurrentLocalGenerator->AddCMP0018Flags(flags, gtgt, lang,
configName);
@@ -1661,10 +1800,11 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
std::string llang = gtgt->GetLinkerLanguage(configName);
if (binary && llang.empty()) {
cmSystemTools::Error(
- "CMake can not determine linker language for target: ",
- gtgt->GetName().c_str());
+ "CMake can not determine linker language for target: " +
+ gtgt->GetName());
return;
}
+ std::string const& langForPreprocessor = llang;
if (gtgt->IsIPOEnabled(llang, configName)) {
const char* ltoValue =
@@ -1672,6 +1812,9 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
buildSettings->AddAttribute("LLVM_LTO", this->CreateString(ltoValue));
}
+ // Handle PIE linker configuration
+ this->AddPositionIndependentLinkAttribute(gtgt, buildSettings, configName);
+
// Add define flags
this->CurrentLocalGenerator->AppendFlags(
defFlags, this->CurrentMakefile->GetDefineFlags());
@@ -1680,12 +1823,15 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
BuildObjectListOrString ppDefs(this, true);
this->AppendDefines(
ppDefs, "CMAKE_INTDIR=\"$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)\"");
- if (const char* exportMacro = gtgt->GetExportMacro()) {
+ if (const std::string* exportMacro = gtgt->GetExportMacro()) {
// Add the export symbol definition for shared library objects.
- this->AppendDefines(ppDefs, exportMacro);
+ this->AppendDefines(ppDefs, exportMacro->c_str());
}
std::vector<std::string> targetDefines;
- gtgt->GetCompileDefinitions(targetDefines, configName, "C");
+ if (!langForPreprocessor.empty()) {
+ gtgt->GetCompileDefinitions(targetDefines, configName,
+ langForPreprocessor);
+ }
this->AppendDefines(ppDefs, targetDefines);
buildSettings->AddAttribute("GCC_PREPROCESSOR_DEFINITIONS",
ppDefs.CreateList());
@@ -1707,7 +1853,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
if (gtgt->GetType() == cmStateEnums::OBJECT_LIBRARY ||
gtgt->GetType() == cmStateEnums::STATIC_LIBRARY) {
this->CurrentLocalGenerator->GetStaticLibraryFlags(
- extraLinkOptions, cmSystemTools::UpperCase(configName), gtgt);
+ extraLinkOptions, cmSystemTools::UpperCase(configName), llang, gtgt);
} else {
const char* targetLinkFlags = gtgt->GetProperty("LINK_FLAGS");
if (targetLinkFlags) {
@@ -1715,12 +1861,16 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
targetLinkFlags);
}
if (!configName.empty()) {
- std::string linkFlagsVar = "LINK_FLAGS_";
- linkFlagsVar += cmSystemTools::UpperCase(configName);
+ std::string linkFlagsVar =
+ cmStrCat("LINK_FLAGS_", cmSystemTools::UpperCase(configName));
if (const char* linkFlags = gtgt->GetProperty(linkFlagsVar)) {
this->CurrentLocalGenerator->AppendFlags(extraLinkOptions, linkFlags);
}
}
+ std::vector<std::string> opts;
+ gtgt->GetLinkOptions(opts, configName, llang);
+ // LINK_OPTIONS are escaped.
+ this->CurrentLocalGenerator->AppendCompileOptions(extraLinkOptions, opts);
}
// Set target-specific architectures.
@@ -1737,9 +1887,8 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
} else {
cmXCodeObject* archObjects =
this->CreateObject(cmXCodeObject::OBJECT_LIST);
- for (std::vector<std::string>::iterator i = archs.begin();
- i != archs.end(); i++) {
- archObjects->AddObject(this->CreateString(*i));
+ for (auto& arch : archs) {
+ archObjects->AddObject(this->CreateString(arch));
}
buildSettings->AddAttribute("ARCHS", archObjects);
}
@@ -1754,8 +1903,8 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
const char* version = gtgt->GetProperty("VERSION");
const char* soversion = gtgt->GetProperty("SOVERSION");
if (!gtgt->HasSOName(configName) || gtgt->IsFrameworkOnApple()) {
- version = 0;
- soversion = 0;
+ version = nullptr;
+ soversion = nullptr;
}
if (version && !soversion) {
soversion = version;
@@ -1799,8 +1948,8 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
pnbase = gtgt->GetName();
pnsuffix = ".a";
- std::string pncdir =
- this->GetObjectsNormalDirectory(this->CurrentProject, configName, gtgt);
+ std::string pncdir = this->GetObjectsDirectory(
+ this->CurrentProject, configName, gtgt, OBJECT_LIBRARY_ARTIFACT_DIR);
buildSettings->AddAttribute("CONFIGURATION_BUILD_DIR",
this->CreateString(pncdir));
}
@@ -1827,7 +1976,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
// so let it replace the framework name. This avoids creating
// a per-configuration Info.plist file.
this->CurrentLocalGenerator->GenerateFrameworkInfoPList(
- gtgt, "$(EXECUTABLE_NAME)", plist.c_str());
+ gtgt, "$(EXECUTABLE_NAME)", plist);
buildSettings->AddAttribute("INFOPLIST_FILE",
this->CreateString(plist));
buildSettings->AddAttribute("MACH_O_TYPE",
@@ -1868,7 +2017,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
// a per-configuration Info.plist file. The cfbundle plist
// is very similar to the application bundle plist
this->CurrentLocalGenerator->GenerateAppleInfoPList(
- gtgt, "$(EXECUTABLE_NAME)", plist.c_str());
+ gtgt, "$(EXECUTABLE_NAME)", plist);
buildSettings->AddAttribute("INFOPLIST_FILE",
this->CreateString(plist));
} else {
@@ -1902,7 +2051,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
// so let it replace the framework name. This avoids creating
// a per-configuration Info.plist file.
this->CurrentLocalGenerator->GenerateFrameworkInfoPList(
- gtgt, "$(EXECUTABLE_NAME)", plist.c_str());
+ gtgt, "$(EXECUTABLE_NAME)", plist);
buildSettings->AddAttribute("INFOPLIST_FILE",
this->CreateString(plist));
} else {
@@ -1940,7 +2089,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
// so let it replace the executable name. This avoids creating
// a per-configuration Info.plist file.
this->CurrentLocalGenerator->GenerateAppleInfoPList(
- gtgt, "$(EXECUTABLE_NAME)", plist.c_str());
+ gtgt, "$(EXECUTABLE_NAME)", plist);
buildSettings->AddAttribute("INFOPLIST_FILE",
this->CreateString(plist));
}
@@ -1948,9 +2097,6 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
default:
break;
}
- if (this->XcodeVersion < 40) {
- buildSettings->AddAttribute("PREBINDING", this->CreateString("NO"));
- }
BuildObjectListOrString dirs(this, true);
BuildObjectListOrString fdirs(this, true);
@@ -1959,30 +2105,32 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
const bool emitSystemIncludes = this->XcodeVersion >= 83;
std::vector<std::string> includes;
- this->CurrentLocalGenerator->GetIncludeDirectories(includes, gtgt, "C",
- configName);
+ if (!langForPreprocessor.empty()) {
+ this->CurrentLocalGenerator->GetIncludeDirectories(
+ includes, gtgt, langForPreprocessor, configName);
+ }
std::set<std::string> emitted;
emitted.insert("/System/Library/Frameworks");
- for (std::vector<std::string>::iterator i = includes.begin();
- i != includes.end(); ++i) {
- if (this->NameResolvesToFramework(*i)) {
- std::string frameworkDir = *i;
- frameworkDir += "/../";
+ for (auto& include : includes) {
+ if (this->NameResolvesToFramework(include)) {
+ std::string frameworkDir = cmStrCat(include, "/../");
frameworkDir = cmSystemTools::CollapseFullPath(frameworkDir);
if (emitted.insert(frameworkDir).second) {
std::string incpath = this->XCodeEscapePath(frameworkDir);
if (emitSystemIncludes &&
- gtgt->IsSystemIncludeDirectory(frameworkDir, configName)) {
+ gtgt->IsSystemIncludeDirectory(frameworkDir, configName,
+ langForPreprocessor)) {
sysfdirs.Add(incpath);
} else {
fdirs.Add(incpath);
}
}
} else {
- std::string incpath = this->XCodeEscapePath(*i);
+ std::string incpath = this->XCodeEscapePath(include);
if (emitSystemIncludes &&
- gtgt->IsSystemIncludeDirectory(*i, configName)) {
+ gtgt->IsSystemIncludeDirectory(include, configName,
+ langForPreprocessor)) {
sysdirs.Add(incpath);
} else {
dirs.Add(incpath);
@@ -1991,13 +2139,12 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
}
// Add framework search paths needed for linking.
if (cmComputeLinkInformation* cli = gtgt->GetLinkInformation(configName)) {
- std::vector<std::string> const& fwDirs = cli->GetFrameworkPaths();
- for (std::vector<std::string>::const_iterator fdi = fwDirs.begin();
- fdi != fwDirs.end(); ++fdi) {
- if (emitted.insert(*fdi).second) {
- std::string incpath = this->XCodeEscapePath(*fdi);
+ for (auto const& fwDir : cli->GetFrameworkPaths()) {
+ if (emitted.insert(fwDir).second) {
+ std::string incpath = this->XCodeEscapePath(fwDir);
if (emitSystemIncludes &&
- gtgt->IsSystemIncludeDirectory(*fdi, configName)) {
+ gtgt->IsSystemIncludeDirectory(fwDir, configName,
+ langForPreprocessor)) {
sysfdirs.Add(incpath);
} else {
fdirs.Add(incpath);
@@ -2025,27 +2172,25 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
// system include directory awareness. We need to also keep on setting
// HEADER_SEARCH_PATHS to work around a missing compile options flag for
// GNU assembly files (#16449)
- for (std::set<std::string>::iterator li = languages.begin();
- li != languages.end(); ++li) {
+ for (auto const& language : languages) {
std::string includeFlags = this->CurrentLocalGenerator->GetIncludeFlags(
- includes, gtgt, *li, true, false, configName);
+ includes, gtgt, language, true, false, configName);
if (!includeFlags.empty()) {
- cflags[*li] += " " + includeFlags;
+ cflags[language] += " " + includeFlags;
}
}
}
bool same_gflags = true;
std::map<std::string, std::string> gflags;
- std::string const* last_gflag = 0;
+ std::string const* last_gflag = nullptr;
std::string optLevel = "0";
// Minimal map of flags to build settings.
- for (std::set<std::string>::iterator li = languages.begin();
- li != languages.end(); ++li) {
- std::string& flags = cflags[*li];
- std::string& gflag = gflags[*li];
+ for (auto const& language : languages) {
+ std::string& flags = cflags[language];
+ std::string& gflag = gflags[language];
std::string oflag =
this->ExtractFlagRegex("(^| )(-Ofast|-Os|-O[0-9]*)( |$)", 2, flags);
if (oflag.size() == 2) {
@@ -2070,16 +2215,34 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
if (!same_gflags) {
// We can't set the Xcode flag differently depending on the language,
// so put them back in this case.
- for (std::set<std::string>::iterator li = languages.begin();
- li != languages.end(); ++li) {
- cflags[*li] += " ";
- cflags[*li] += gflags[*li];
+ for (auto const& language : languages) {
+ cflags[language] += " ";
+ cflags[language] += gflags[language];
}
debugStr = "NO";
} else if (last_gflag && (last_gflag->empty() || *last_gflag == "-g0")) {
debugStr = "NO";
}
+ // extract C++ stdlib
+ for (auto const& language : languages) {
+ if (language != "CXX" && language != "OBJCXX") {
+ continue;
+ }
+ std::string& flags = cflags[language];
+
+ auto stdlib =
+ this->ExtractFlagRegex("(^| )(-stdlib=[^ ]+)( |$)", 2, flags);
+ if (stdlib.size() > 8) {
+ const auto cxxLibrary = stdlib.substr(8);
+ if (language == "CXX" ||
+ !buildSettings->GetObject("CLANG_CXX_LIBRARY")) {
+ buildSettings->AddAttribute("CLANG_CXX_LIBRARY",
+ this->CreateString(cxxLibrary));
+ }
+ }
+ }
+
buildSettings->AddAttribute("COMBINE_HIDPI_IMAGES",
this->CreateString("YES"));
buildSettings->AddAttribute("GCC_GENERATE_DEBUGGING_SYMBOLS",
@@ -2090,25 +2253,30 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
this->CreateString("NO"));
buildSettings->AddAttribute("GCC_INLINES_ARE_PRIVATE_EXTERN",
this->CreateString("NO"));
- for (std::set<std::string>::iterator li = languages.begin();
- li != languages.end(); ++li) {
- std::string flags = cflags[*li] + " " + defFlags;
- if (*li == "CXX") {
- buildSettings->AddAttribute("OTHER_CPLUSPLUSFLAGS",
- this->CreateString(flags));
- } else if (*li == "Fortran") {
+
+ for (auto const& language : languages) {
+ std::string flags = cflags[language] + " " + defFlags;
+ if (language == "CXX" || language == "OBJCXX") {
+ if (language == "CXX" ||
+ !buildSettings->GetObject("OTHER_CPLUSPLUSFLAGS")) {
+ buildSettings->AddAttribute("OTHER_CPLUSPLUSFLAGS",
+ this->CreateString(flags));
+ }
+ } else if (language == "Fortran") {
buildSettings->AddAttribute("IFORT_OTHER_FLAGS",
this->CreateString(flags));
- } else if (*li == "C") {
- buildSettings->AddAttribute("OTHER_CFLAGS", this->CreateString(flags));
- } else if (*li == "Swift") {
+ } else if (language == "C" || language == "OBJC") {
+ if (language == "C" || !buildSettings->GetObject("OTHER_CFLAGS")) {
+ buildSettings->AddAttribute("OTHER_CFLAGS", this->CreateString(flags));
+ }
+ } else if (language == "Swift") {
buildSettings->AddAttribute("OTHER_SWIFT_FLAGS",
this->CreateString(flags));
}
}
// Add Fortran source format attribute if property is set.
- const char* format = 0;
+ const char* format = nullptr;
const char* tgtfmt = gtgt->GetProperty("Fortran_FORMAT");
switch (cmOutputConverter::GetFortranFormat(tgtfmt)) {
case cmOutputConverter::FortranFormatFixed:
@@ -2162,9 +2330,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
// runpath dirs needs to be unique to prevent corruption
std::set<std::string> unique_dirs;
- for (std::vector<std::string>::const_iterator i = runtimeDirs.begin();
- i != runtimeDirs.end(); ++i) {
- std::string runpath = *i;
+ for (auto runpath : runtimeDirs) {
runpath = this->ExpandCFGIntDir(runpath, configName);
if (unique_dirs.find(runpath) == unique_dirs.end()) {
@@ -2221,20 +2387,26 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
buildSettings->AddAttribute("DYLIB_COMPATIBILITY_VERSION",
this->CreateString(vso.str()));
}
+
+ // Precompile Headers
+ std::string pchHeader = gtgt->GetPchHeader(configName, llang);
+ if (!pchHeader.empty()) {
+ buildSettings->AddAttribute("GCC_PREFIX_HEADER",
+ this->CreateString(pchHeader));
+ buildSettings->AddAttribute("GCC_PRECOMPILE_PREFIX_HEADER",
+ this->CreateString("YES"));
+ }
+
// put this last so it can override existing settings
// Convert "XCODE_ATTRIBUTE_*" properties directly.
{
- std::vector<std::string> const& props = gtgt->GetPropertyKeys();
- for (std::vector<std::string>::const_iterator i = props.begin();
- i != props.end(); ++i) {
- if (i->find("XCODE_ATTRIBUTE_") == 0) {
- std::string attribute = i->substr(16);
+ for (auto const& prop : gtgt->GetPropertyKeys()) {
+ if (prop.find("XCODE_ATTRIBUTE_") == 0) {
+ std::string attribute = prop.substr(16);
this->FilterConfigurationAttribute(configName, attribute);
if (!attribute.empty()) {
- cmGeneratorExpression ge;
- std::string processed =
- ge.Parse(gtgt->GetProperty(*i))
- ->Evaluate(this->CurrentLocalGenerator, configName);
+ std::string processed = cmGeneratorExpression::Evaluate(
+ gtgt->GetProperty(prop), this->CurrentLocalGenerator, configName);
buildSettings->AddAttribute(attribute,
this->CreateString(processed));
}
@@ -2268,8 +2440,8 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateUtilityTarget(
target->SetComment(gtgt->GetName());
cmXCodeObject* buildPhases = this->CreateObject(cmXCodeObject::OBJECT_LIST);
std::vector<cmXCodeObject*> emptyContentVector;
- this->CreateCustomCommands(buildPhases, 0, 0, 0, emptyContentVector, 0,
- gtgt);
+ this->CreateCustomCommands(buildPhases, nullptr, nullptr, nullptr,
+ emptyContentVector, nullptr, gtgt);
target->AddAttribute("buildPhases", buildPhases);
this->AddConfigurations(target, gtgt);
cmXCodeObject* dependencies = this->CreateObject(cmXCodeObject::OBJECT_LIST);
@@ -2280,16 +2452,19 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateUtilityTarget(
this->XCodeObjectMap[gtgt] = target;
// Add source files without build rules for editing convenience.
- if (gtgt->GetType() == cmStateEnums::UTILITY) {
+ if (gtgt->GetType() == cmStateEnums::UTILITY &&
+ gtgt->GetName() != CMAKE_CHECK_BUILD_SYSTEM_TARGET) {
std::vector<cmSourceFile*> sources;
if (!gtgt->GetConfigCommonSourceFiles(sources)) {
- return 0;
+ return nullptr;
}
- for (std::vector<cmSourceFile*>::const_iterator i = sources.begin();
- i != sources.end(); ++i) {
- if (!(*i)->GetPropertyAsBool("GENERATED")) {
- this->CreateXCodeFileReference(*i, gtgt);
+ // Add CMakeLists.txt file for user convenience.
+ this->AddXCodeProjBuildRule(gtgt, sources);
+
+ for (auto sourceFile : sources) {
+ if (!sourceFile->GetIsGenerated()) {
+ this->CreateXCodeFileReference(sourceFile, gtgt);
}
}
}
@@ -2302,34 +2477,28 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateUtilityTarget(
std::string cmGlobalXCodeGenerator::AddConfigurations(cmXCodeObject* target,
cmGeneratorTarget* gtgt)
{
- std::string configTypes =
- this->CurrentMakefile->GetRequiredDefinition("CMAKE_CONFIGURATION_TYPES");
- std::vector<std::string> configVectorIn;
- std::vector<std::string> configVector;
- configVectorIn.push_back(configTypes);
- cmSystemTools::ExpandList(configVectorIn, configVector);
+ std::vector<std::string> const configVector = cmExpandedList(
+ this->CurrentMakefile->GetRequiredDefinition("CMAKE_CONFIGURATION_TYPES"));
cmXCodeObject* configlist =
this->CreateObject(cmXCodeObject::XCConfigurationList);
cmXCodeObject* buildConfigurations =
this->CreateObject(cmXCodeObject::OBJECT_LIST);
configlist->AddAttribute("buildConfigurations", buildConfigurations);
- std::string comment = "Build configuration list for ";
- comment += cmXCodeObject::PBXTypeNames[target->GetIsA()];
- comment += " \"";
- comment += gtgt->GetName();
- comment += "\"";
+ std::string comment = cmStrCat("Build configuration list for ",
+ cmXCodeObject::PBXTypeNames[target->GetIsA()],
+ " \"", gtgt->GetName(), '"');
configlist->SetComment(comment);
target->AddAttribute("buildConfigurationList",
this->CreateObjectReference(configlist));
- for (unsigned int i = 0; i < configVector.size(); ++i) {
+ for (auto const& i : configVector) {
cmXCodeObject* config =
this->CreateObject(cmXCodeObject::XCBuildConfiguration);
buildConfigurations->AddObject(config);
cmXCodeObject* buildSettings =
this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
- this->CreateBuildSettings(gtgt, buildSettings, configVector[i]);
- config->AddAttribute("name", this->CreateString(configVector[i]));
- config->SetComment(configVector[i]);
+ this->CreateBuildSettings(gtgt, buildSettings, i);
+ config->AddAttribute("name", this->CreateString(i));
+ config->SetComment(i);
config->AddAttribute("buildSettings", buildSettings);
}
if (!configVector.empty()) {
@@ -2349,9 +2518,8 @@ const char* cmGlobalXCodeGenerator::GetTargetLinkFlagsVar(
(target->GetType() == cmStateEnums::STATIC_LIBRARY ||
target->GetType() == cmStateEnums::OBJECT_LIBRARY)) {
return "OTHER_LIBTOOLFLAGS";
- } else {
- return "OTHER_LDFLAGS";
}
+ return "OTHER_LDFLAGS";
}
const char* cmGlobalXCodeGenerator::GetTargetFileType(
@@ -2368,12 +2536,13 @@ const char* cmGlobalXCodeGenerator::GetTargetFileType(
return (target->GetPropertyAsBool("FRAMEWORK") ? "wrapper.framework"
: "archive.ar");
case cmStateEnums::MODULE_LIBRARY:
- if (target->IsXCTestOnApple())
+ if (target->IsXCTestOnApple()) {
return "wrapper.cfbundle";
- else if (target->IsCFBundleOnApple())
+ }
+ if (target->IsCFBundleOnApple()) {
return "wrapper.plug-in";
- else
- return "compiled.mach-o.executable";
+ }
+ return "compiled.mach-o.executable";
case cmStateEnums::SHARED_LIBRARY:
return (target->GetPropertyAsBool("FRAMEWORK")
? "wrapper.framework"
@@ -2383,7 +2552,7 @@ const char* cmGlobalXCodeGenerator::GetTargetFileType(
default:
break;
}
- return 0;
+ return nullptr;
}
const char* cmGlobalXCodeGenerator::GetTargetProductType(
@@ -2401,12 +2570,13 @@ const char* cmGlobalXCodeGenerator::GetTargetProductType(
? "com.apple.product-type.framework"
: "com.apple.product-type.library.static");
case cmStateEnums::MODULE_LIBRARY:
- if (target->IsXCTestOnApple())
+ if (target->IsXCTestOnApple()) {
return "com.apple.product-type.bundle.unit-test";
- else if (target->IsCFBundleOnApple())
+ } else if (target->IsCFBundleOnApple()) {
return "com.apple.product-type.bundle";
- else
+ } else {
return "com.apple.product-type.tool";
+ }
case cmStateEnums::SHARED_LIBRARY:
return (target->GetPropertyAsBool("FRAMEWORK")
? "com.apple.product-type.framework"
@@ -2418,14 +2588,14 @@ const char* cmGlobalXCodeGenerator::GetTargetProductType(
default:
break;
}
- return 0;
+ return nullptr;
}
cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeTarget(
cmGeneratorTarget* gtgt, cmXCodeObject* buildPhases)
{
if (gtgt->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
- return 0;
+ return nullptr;
}
cmXCodeObject* target = this->CreateObject(cmXCodeObject::PBXNativeTarget);
target->AddAttribute("buildPhases", buildPhases);
@@ -2444,9 +2614,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeTarget(
}
std::string fullName;
if (gtgt->GetType() == cmStateEnums::OBJECT_LIBRARY) {
- fullName = "lib";
- fullName += gtgt->GetName();
- fullName += ".a";
+ fullName = cmStrCat("lib", gtgt->GetName(), ".a");
} else {
fullName = gtgt->GetFullName(defConfig);
}
@@ -2469,13 +2637,12 @@ cmXCodeObject* cmGlobalXCodeGenerator::FindXCodeTarget(
cmGeneratorTarget const* t)
{
if (!t) {
- return 0;
+ return nullptr;
}
- std::map<cmGeneratorTarget const*, cmXCodeObject*>::const_iterator const i =
- this->XCodeObjectMap.find(t);
+ auto const i = this->XCodeObjectMap.find(t);
if (i == this->XCodeObjectMap.end()) {
- return 0;
+ return nullptr;
}
return i->second;
}
@@ -2483,8 +2650,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::FindXCodeTarget(
std::string cmGlobalXCodeGenerator::GetOrCreateId(const std::string& name,
const std::string& id)
{
- std::string guidStoreName = name;
- guidStoreName += "_GUID_CMAKE";
+ std::string guidStoreName = cmStrCat(name, "_GUID_CMAKE");
const char* storedGUID =
this->CMakeInstance->GetCacheDefinition(guidStoreName);
@@ -2539,9 +2705,7 @@ void cmGlobalXCodeGenerator::AppendOrAddBuildSetting(cmXCodeObject* settings,
if (!attr) {
settings->AddAttribute(attribute, this->CreateString(value));
} else {
- std::string oldValue = attr->GetString();
- oldValue += " ";
- oldValue += value;
+ std::string oldValue = cmStrCat(attr->GetString(), ' ', value);
attr->SetString(oldValue);
}
}
@@ -2557,18 +2721,10 @@ void cmGlobalXCodeGenerator::AppendBuildSettingAttribute(
target->GetObject("buildConfigurationList")->GetObject();
cmXCodeObject* buildConfigs =
configurationList->GetObject("buildConfigurations");
- std::vector<cmXCodeObject*> list = buildConfigs->GetObjectList();
- // each configuration and the target itself has a buildSettings in it
- // list.push_back(target);
- for (std::vector<cmXCodeObject*>::iterator i = list.begin(); i != list.end();
- ++i) {
- if (!configName.empty()) {
- if ((*i)->GetObject("name")->GetString() == configName) {
- cmXCodeObject* settings = (*i)->GetObject("buildSettings");
- this->AppendOrAddBuildSetting(settings, attribute, value);
- }
- } else {
- cmXCodeObject* settings = (*i)->GetObject("buildSettings");
+ for (auto obj : buildConfigs->GetObjectList()) {
+ if (configName.empty() ||
+ obj->GetObject("name")->GetString() == configName) {
+ cmXCodeObject* settings = obj->GetObject("buildSettings");
this->AppendOrAddBuildSetting(settings, attribute, value);
}
}
@@ -2586,35 +2742,27 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
}
// Add dependencies on other CMake targets.
- TargetDependSet const& deps = this->GetTargetDirectDepends(gt);
- for (TargetDependSet::const_iterator i = deps.begin(); i != deps.end();
- ++i) {
- if (cmXCodeObject* dptarget = this->FindXCodeTarget(*i)) {
+ for (const auto& dep : this->GetTargetDirectDepends(gt)) {
+ if (cmXCodeObject* dptarget = this->FindXCodeTarget(dep)) {
this->AddDependTarget(target, dptarget);
}
}
// Loop over configuration types and set per-configuration info.
- for (std::vector<std::string>::iterator i =
- this->CurrentConfigurationTypes.begin();
- i != this->CurrentConfigurationTypes.end(); ++i) {
- // Get the current configuration name.
- std::string configName = *i;
-
- if (this->XcodeVersion >= 50) {
+ for (auto const& configName : this->CurrentConfigurationTypes) {
+ {
// Add object library contents as link flags.
std::string linkObjs;
const char* sep = "";
std::vector<cmSourceFile const*> objs;
gt->GetExternalObjects(objs, configName);
- for (std::vector<cmSourceFile const*>::const_iterator oi = objs.begin();
- oi != objs.end(); ++oi) {
- if ((*oi)->GetObjectLibrary().empty()) {
+ for (auto sourceFile : objs) {
+ if (sourceFile->GetObjectLibrary().empty()) {
continue;
}
linkObjs += sep;
sep = " ";
- linkObjs += this->XCodeEscapePath((*oi)->GetFullPath());
+ linkObjs += this->XCodeEscapePath(sourceFile->GetFullPath());
}
this->AppendBuildSettingAttribute(
target, this->GetTargetLinkFlagsVar(gt), linkObjs.c_str(), configName);
@@ -2634,28 +2782,22 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
cmComputeLinkInformation& cli = *pcli;
// Add dependencies directly on library files.
- {
- std::vector<std::string> const& libDeps = cli.GetDepends();
- for (std::vector<std::string>::const_iterator j = libDeps.begin();
- j != libDeps.end(); ++j) {
- target->AddDependLibrary(configName, *j);
- }
+ for (auto const& libDep : cli.GetDepends()) {
+ target->AddDependLibrary(configName, libDep);
}
// add the library search paths
{
- std::vector<std::string> const& libDirs = cli.GetDirectories();
std::string linkDirs;
- for (std::vector<std::string>::const_iterator libDir = libDirs.begin();
- libDir != libDirs.end(); ++libDir) {
- if (libDir->size() && *libDir != "/usr/lib") {
+ for (auto const& libDir : cli.GetDirectories()) {
+ if (!libDir.empty() && libDir != "/usr/lib") {
// Now add the same one but append
// $(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) to it:
linkDirs += " ";
linkDirs += this->XCodeEscapePath(
- *libDir + "/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)");
+ libDir + "/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)");
linkDirs += " ";
- linkDirs += this->XCodeEscapePath(*libDir);
+ linkDirs += this->XCodeEscapePath(libDir);
}
}
this->AppendBuildSettingAttribute(target, "LIBRARY_SEARCH_PATHS",
@@ -2666,20 +2808,18 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
{
std::string linkLibs;
const char* sep = "";
- typedef cmComputeLinkInformation::ItemVector ItemVector;
- ItemVector const& libNames = cli.GetItems();
- for (ItemVector::const_iterator li = libNames.begin();
- li != libNames.end(); ++li) {
+ for (auto const& libName : cli.GetItems()) {
linkLibs += sep;
sep = " ";
- if (li->IsPath) {
- linkLibs += this->XCodeEscapePath(li->Value);
- } else if (!li->Target ||
- li->Target->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
- linkLibs += li->Value;
+ if (libName.IsPath) {
+ linkLibs += this->XCodeEscapePath(libName.Value);
+ } else if (!libName.Target ||
+ libName.Target->GetType() !=
+ cmStateEnums::INTERFACE_LIBRARY) {
+ linkLibs += libName.Value;
}
- if (li->Target && !li->Target->IsImported()) {
- target->AddDependTarget(configName, li->Target->GetName());
+ if (libName.Target && !libName.Target->IsImported()) {
+ target->AddDependTarget(configName, libName.Target->GetName());
}
}
this->AppendBuildSettingAttribute(
@@ -2691,17 +2831,12 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
bool cmGlobalXCodeGenerator::CreateGroups(
std::vector<cmLocalGenerator*>& generators)
{
- for (std::vector<cmLocalGenerator*>::iterator i = generators.begin();
- i != generators.end(); ++i) {
- cmMakefile* mf = (*i)->GetMakefile();
+ for (auto& generator : generators) {
+ cmMakefile* mf = generator->GetMakefile();
std::vector<cmSourceGroup> sourceGroups = mf->GetSourceGroups();
- std::vector<cmGeneratorTarget*> tgts = (*i)->GetGeneratorTargets();
- for (std::vector<cmGeneratorTarget*>::iterator l = tgts.begin();
- l != tgts.end(); l++) {
- cmGeneratorTarget* gtgt = *l;
-
+ for (auto gtgt : generator->GetGeneratorTargets()) {
// Same skipping logic here as in CreateXCodeTargets so that we do not
- // end up with (empty anyhow) ALL_BUILD and XCODE_DEPEND_HELPER source
+ // end up with (empty anyhow) ZERO_CHECK, install, or test source
// groups:
//
if (gtgt->GetType() == cmStateEnums::GLOBAL_TARGET) {
@@ -2710,34 +2845,44 @@ bool cmGlobalXCodeGenerator::CreateGroups(
if (gtgt->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
continue;
}
-
- // add the soon to be generated Info.plist file as a source for a
- // MACOSX_BUNDLE file
- if (gtgt->GetPropertyAsBool("MACOSX_BUNDLE")) {
- std::string plist = this->ComputeInfoPListLocation(gtgt);
- mf->GetOrCreateSource(plist, true);
- gtgt->AddSource(plist);
+ if (gtgt->GetName() == CMAKE_CHECK_BUILD_SYSTEM_TARGET) {
+ continue;
}
- std::vector<cmGeneratorTarget::AllConfigSource> const& sources =
- gtgt->GetAllConfigSources();
+ auto addSourceToGroup = [this, mf, gtgt,
+ &sourceGroups](std::string const& source) {
+ cmSourceGroup* sourceGroup = mf->FindSourceGroup(source, sourceGroups);
+ cmXCodeObject* pbxgroup = this->CreateOrGetPBXGroup(gtgt, sourceGroup);
+ std::string key = GetGroupMapKeyFromPath(gtgt, source);
+ this->GroupMap[key] = pbxgroup;
+ };
// Put cmSourceFile instances in proper groups:
- for (std::vector<cmGeneratorTarget::AllConfigSource>::const_iterator si =
- sources.begin();
- si != sources.end(); ++si) {
- cmSourceFile const* sf = si->Source;
- if (this->XcodeVersion >= 50 && !sf->GetObjectLibrary().empty()) {
+ for (auto const& si : gtgt->GetAllConfigSources()) {
+ cmSourceFile const* sf = si.Source;
+ if (!sf->GetObjectLibrary().empty()) {
// Object library files go on the link line instead.
continue;
}
- // Add the file to the list of sources.
- std::string const& source = sf->GetFullPath();
- cmSourceGroup* sourceGroup =
- mf->FindSourceGroup(source.c_str(), sourceGroups);
- cmXCodeObject* pbxgroup = this->CreateOrGetPBXGroup(gtgt, sourceGroup);
- std::string key = GetGroupMapKeyFromPath(gtgt, source);
- this->GroupMap[key] = pbxgroup;
+ addSourceToGroup(sf->GetFullPath());
+ }
+
+ // Add CMakeLists.txt file for user convenience.
+ {
+ std::string listfile =
+ cmStrCat(gtgt->GetLocalGenerator()->GetCurrentSourceDirectory(),
+ "/CMakeLists.txt");
+ cmSourceFile* sf = gtgt->Makefile->GetOrCreateSource(
+ listfile, false, cmSourceFileLocationKind::Known);
+ addSourceToGroup(sf->ResolveFullPath());
+ }
+
+ // Add the Info.plist we are about to generate for an App Bundle.
+ if (gtgt->GetPropertyAsBool("MACOSX_BUNDLE")) {
+ std::string plist = this->ComputeInfoPListLocation(gtgt);
+ cmSourceFile* sf = gtgt->Makefile->GetOrCreateSource(
+ plist, true, cmSourceFileLocationKind::Known);
+ addSourceToGroup(sf->ResolveFullPath());
}
}
}
@@ -2745,19 +2890,21 @@ bool cmGlobalXCodeGenerator::CreateGroups(
}
cmXCodeObject* cmGlobalXCodeGenerator::CreatePBXGroup(cmXCodeObject* parent,
- std::string name)
+ const std::string& name)
{
- cmXCodeObject* parentChildren = NULL;
- if (parent)
+ cmXCodeObject* parentChildren = nullptr;
+ if (parent) {
parentChildren = parent->GetObject("children");
+ }
cmXCodeObject* group = this->CreateObject(cmXCodeObject::PBXGroup);
cmXCodeObject* groupChildren =
this->CreateObject(cmXCodeObject::OBJECT_LIST);
group->AddAttribute("name", this->CreateString(name));
group->AddAttribute("children", groupChildren);
group->AddAttribute("sourceTree", this->CreateString("<group>"));
- if (parentChildren)
+ if (parentChildren) {
parentChildren->AddObject(group);
+ }
return group;
}
@@ -2768,25 +2915,21 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateOrGetPBXGroup(
std::string target;
const std::string targetFolder = gtgt->GetEffectiveFolderName();
if (!targetFolder.empty()) {
- target = targetFolder;
- target += "/";
+ target = cmStrCat(targetFolder, '/');
}
target += gtgt->GetName();
- s = target + "/";
- s += sg->GetFullName();
- std::map<std::string, cmXCodeObject*>::iterator it =
- this->GroupNameMap.find(s);
+ s = cmStrCat(target, '/', sg->GetFullName());
+ auto it = this->GroupNameMap.find(s);
if (it != this->GroupNameMap.end()) {
return it->second;
}
it = this->TargetGroup.find(target);
- cmXCodeObject* tgroup = 0;
+ cmXCodeObject* tgroup = nullptr;
if (it != this->TargetGroup.end()) {
tgroup = it->second;
} else {
- std::vector<std::string> tgt_folders =
- cmSystemTools::tokenize(target, "/");
+ std::vector<std::string> tgt_folders = cmTokenize(target, "/");
std::string curr_tgt_folder;
for (std::vector<std::string>::size_type i = 0; i < tgt_folders.size();
i++) {
@@ -2811,30 +2954,26 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateOrGetPBXGroup(
// If it's the default source group (empty name) then put the source file
// directly in the tgroup...
//
- if (std::string(sg->GetFullName()) == "") {
+ if (sg->GetFullName().empty()) {
this->GroupNameMap[s] = tgroup;
return tgroup;
}
// It's a recursive folder structure, let's find the real parent group
- if (std::string(sg->GetFullName()) != std::string(sg->GetName())) {
- std::vector<std::string> folders =
- cmSystemTools::tokenize(sg->GetFullName(), "\\");
- std::string curr_folder = target;
- curr_folder += "/";
- for (std::vector<std::string>::size_type i = 0; i < folders.size(); i++) {
- curr_folder += folders[i];
- std::map<std::string, cmXCodeObject*>::iterator i_folder =
- this->GroupNameMap.find(curr_folder);
+ if (sg->GetFullName() != sg->GetName()) {
+ std::string curr_folder = cmStrCat(target, '/');
+ for (auto const& folder : cmTokenize(sg->GetFullName(), "\\")) {
+ curr_folder += folder;
+ auto const i_folder = this->GroupNameMap.find(curr_folder);
// Create new folder
if (i_folder == this->GroupNameMap.end()) {
- cmXCodeObject* group = this->CreatePBXGroup(tgroup, folders[i]);
+ cmXCodeObject* group = this->CreatePBXGroup(tgroup, folder);
this->GroupNameMap[curr_folder] = group;
tgroup = group;
} else {
tgroup = i_folder->second;
}
- curr_folder = curr_folder + "\\";
+ curr_folder += "\\";
}
return tgroup;
}
@@ -2847,15 +2986,16 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects(
cmLocalGenerator* root, std::vector<cmLocalGenerator*>& generators)
{
this->ClearXCodeObjects();
- this->RootObject = 0;
- this->MainGroupChildren = 0;
+ this->RootObject = nullptr;
+ this->MainGroupChildren = nullptr;
cmXCodeObject* group = this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
group->AddAttribute("COPY_PHASE_STRIP", this->CreateString("NO"));
cmXCodeObject* listObjs = this->CreateObject(cmXCodeObject::OBJECT_LIST);
- for (unsigned int i = 0; i < this->CurrentConfigurationTypes.size(); ++i) {
+ for (const std::string& CurrentConfigurationType :
+ this->CurrentConfigurationTypes) {
cmXCodeObject* buildStyle =
this->CreateObject(cmXCodeObject::PBXBuildStyle);
- const char* name = this->CurrentConfigurationTypes[i].c_str();
+ const std::string& name = CurrentConfigurationType;
buildStyle->AddAttribute("name", this->CreateString(name));
buildStyle->SetComment(name);
cmXCodeObject* sgroup = this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
@@ -2885,10 +3025,9 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects(
this->RootObject = this->CreateObject(cmXCodeObject::PBXProject);
this->RootObject->SetComment("Project object");
- std::string project_id = "PROJECT_";
- project_id += root->GetProjectName();
+ std::string project_id = cmStrCat("PROJECT_", root->GetProjectName());
this->RootObject->SetId(
- this->GetOrCreateId(project_id.c_str(), this->RootObject->GetId()));
+ this->GetOrCreateId(project_id, this->RootObject->GetId()));
group = this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
this->RootObject->AddAttribute("mainGroup",
@@ -2904,15 +3043,8 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects(
v << std::setfill('0') << std::setw(4) << XcodeVersion * 10;
group->AddAttribute("LastUpgradeCheck", this->CreateString(v.str()));
this->RootObject->AddAttribute("attributes", group);
- if (this->XcodeVersion >= 32)
- this->RootObject->AddAttribute("compatibilityVersion",
- this->CreateString("Xcode 3.2"));
- else if (this->XcodeVersion >= 31)
- this->RootObject->AddAttribute("compatibilityVersion",
- this->CreateString("Xcode 3.1"));
- else
- this->RootObject->AddAttribute("compatibilityVersion",
- this->CreateString("Xcode 3.0"));
+ this->RootObject->AddAttribute("compatibilityVersion",
+ this->CreateString("Xcode 3.2"));
// Point Xcode at the top of the source tree.
{
std::string pdir =
@@ -2924,12 +3056,11 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects(
this->CreateObject(cmXCodeObject::XCConfigurationList);
cmXCodeObject* buildConfigurations =
this->CreateObject(cmXCodeObject::OBJECT_LIST);
- typedef std::vector<std::pair<std::string, cmXCodeObject*> > Configs;
+ using Configs = std::vector<std::pair<std::string, cmXCodeObject*>>;
Configs configs;
- const char* defaultConfigName = "Debug";
- for (unsigned int i = 0; i < this->CurrentConfigurationTypes.size(); ++i) {
- const char* name = this->CurrentConfigurationTypes[i].c_str();
- if (0 == i) {
+ std::string defaultConfigName;
+ for (const auto& name : this->CurrentConfigurationTypes) {
+ if (defaultConfigName.empty()) {
defaultConfigName = name;
}
cmXCodeObject* config =
@@ -2937,15 +3068,16 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects(
config->AddAttribute("name", this->CreateString(name));
configs.push_back(std::make_pair(name, config));
}
- for (Configs::iterator c = configs.begin(); c != configs.end(); ++c) {
- buildConfigurations->AddObject(c->second);
+ if (defaultConfigName.empty()) {
+ defaultConfigName = "Debug";
+ }
+ for (auto& config : configs) {
+ buildConfigurations->AddObject(config.second);
}
configlist->AddAttribute("buildConfigurations", buildConfigurations);
- std::string comment = "Build configuration list for PBXProject";
- comment += " \"";
- comment += this->CurrentProject;
- comment += "\"";
+ std::string comment = cmStrCat("Build configuration list for PBXProject \"",
+ this->CurrentProject, '"');
configlist->SetComment(comment);
configlist->AddAttribute("defaultConfigurationIsVisible",
this->CreateString("0"));
@@ -2971,7 +3103,7 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects(
buildSettings->AddAttribute("ARCHS", this->CreateString(archs));
}
if (deploymentTarget && *deploymentTarget) {
- buildSettings->AddAttribute("MACOSX_DEPLOYMENT_TARGET",
+ buildSettings->AddAttribute(GetDeploymentPlatform(root->GetMakefile()),
this->CreateString(deploymentTarget));
}
if (!this->GeneratorToolset.empty()) {
@@ -2983,6 +3115,8 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects(
if (const char* vers = this->CurrentMakefile->GetDefinition(
"CMAKE_Swift_LANGUAGE_VERSION")) {
swiftVersion = vers;
+ } else if (this->XcodeVersion >= 102) {
+ swiftVersion = "4.0";
} else if (this->XcodeVersion >= 83) {
swiftVersion = "3.0";
} else {
@@ -2992,57 +3126,48 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects(
this->CreateString(swiftVersion));
}
- std::string symroot = root->GetCurrentBinaryDirectory();
- symroot += "/build";
+ std::string symroot = cmStrCat(root->GetCurrentBinaryDirectory(), "/build");
buildSettings->AddAttribute("SYMROOT", this->CreateString(symroot));
- for (Configs::iterator i = configs.begin(); i != configs.end(); ++i) {
+ for (auto& config : configs) {
cmXCodeObject* buildSettingsForCfg = this->CreateFlatClone(buildSettings);
// Put this last so it can override existing settings
// Convert "CMAKE_XCODE_ATTRIBUTE_*" variables directly.
- std::vector<std::string> vars = this->CurrentMakefile->GetDefinitions();
- for (std::vector<std::string>::const_iterator d = vars.begin();
- d != vars.end(); ++d) {
- if (d->find("CMAKE_XCODE_ATTRIBUTE_") == 0) {
- std::string attribute = d->substr(22);
- this->FilterConfigurationAttribute(i->first, attribute);
+ for (const auto& var : this->CurrentMakefile->GetDefinitions()) {
+ if (var.find("CMAKE_XCODE_ATTRIBUTE_") == 0) {
+ std::string attribute = var.substr(22);
+ this->FilterConfigurationAttribute(config.first, attribute);
if (!attribute.empty()) {
- cmGeneratorExpression ge;
- std::string processed =
- ge.Parse(this->CurrentMakefile->GetDefinition(*d))
- ->Evaluate(this->CurrentLocalGenerator, i->first);
+ std::string processed = cmGeneratorExpression::Evaluate(
+ this->CurrentMakefile->GetDefinition(var),
+ this->CurrentLocalGenerator, config.first);
buildSettingsForCfg->AddAttribute(attribute,
this->CreateString(processed));
}
}
}
// store per-config buildSettings into configuration object
- i->second->AddAttribute("buildSettings", buildSettingsForCfg);
+ config.second->AddAttribute("buildSettings", buildSettingsForCfg);
}
this->RootObject->AddAttribute("buildConfigurationList",
this->CreateObjectReference(configlist));
std::vector<cmXCodeObject*> targets;
- for (std::vector<cmLocalGenerator*>::iterator i = generators.begin();
- i != generators.end(); ++i) {
- if (!this->CreateXCodeTargets(*i, targets)) {
+ for (auto& generator : generators) {
+ if (!this->CreateXCodeTargets(generator, targets)) {
return false;
}
}
// loop over all targets and add link and depend info
- for (std::vector<cmXCodeObject*>::iterator i = targets.begin();
- i != targets.end(); ++i) {
- cmXCodeObject* t = *i;
+ for (auto t : targets) {
this->AddDependAndLinkInformation(t);
}
this->CreateXCodeDependHackTarget(targets);
// now add all targets to the root object
cmXCodeObject* allTargets = this->CreateObject(cmXCodeObject::OBJECT_LIST);
- for (std::vector<cmXCodeObject*>::iterator i = targets.begin();
- i != targets.end(); ++i) {
- cmXCodeObject* t = *i;
+ for (auto t : targets) {
allTargets->AddObject(t);
cmXCodeObject* productRef = t->GetObject("productReference");
if (productRef) {
@@ -3053,19 +3178,13 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects(
return true;
}
-std::string cmGlobalXCodeGenerator::GetObjectsNormalDirectory(
+std::string cmGlobalXCodeGenerator::GetObjectsDirectory(
const std::string& projName, const std::string& configName,
- const cmGeneratorTarget* t) const
+ const cmGeneratorTarget* t, const std::string& variant) const
{
- std::string dir = t->GetLocalGenerator()->GetCurrentBinaryDirectory();
- dir += "/";
- dir += projName;
- dir += ".build/";
- dir += configName;
- dir += "/";
- dir += t->GetName();
- dir += ".build/Objects-normal/";
-
+ std::string dir = cmStrCat(
+ t->GetLocalGenerator()->GetCurrentBinaryDirectory(), '/', projName,
+ ".build/", configName, '/', t->GetName(), ".build/", variant);
return dir;
}
@@ -3075,15 +3194,19 @@ void cmGlobalXCodeGenerator::ComputeArchitectures(cmMakefile* mf)
const char* osxArch = mf->GetDefinition("CMAKE_OSX_ARCHITECTURES");
const char* sysroot = mf->GetDefinition("CMAKE_OSX_SYSROOT");
if (osxArch && sysroot) {
- cmSystemTools::ExpandListArgument(std::string(osxArch),
- this->Architectures);
+ cmExpandList(std::string(osxArch), this->Architectures);
}
if (this->Architectures.empty()) {
// With no ARCHS we use ONLY_ACTIVE_ARCH.
// Look up the arch that Xcode chooses in this case.
- if (const char* arch = mf->GetDefinition("CMAKE_XCODE_CURRENT_ARCH")) {
+ if (const char* arch = mf->GetDefinition("CMAKE_XCODE_ARCHS")) {
this->ObjectDirArchDefault = arch;
+ // We expect only one arch but choose the first just in case.
+ std::string::size_type pos = this->ObjectDirArchDefault.find(';');
+ if (pos != std::string::npos) {
+ this->ObjectDirArchDefault = this->ObjectDirArchDefault.substr(0, pos);
+ }
}
}
@@ -3104,10 +3227,9 @@ void cmGlobalXCodeGenerator::ComputeObjectDirArch(cmMakefile* mf)
void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget(
std::vector<cmXCodeObject*>& targets)
{
- cmGeneratedFileStream makefileStream(this->CurrentXCodeHackMakefile.c_str());
+ cmGeneratedFileStream makefileStream(this->CurrentXCodeHackMakefile);
if (!makefileStream) {
- cmSystemTools::Error("Could not create",
- this->CurrentXCodeHackMakefile.c_str());
+ cmSystemTools::Error("Could not create " + this->CurrentXCodeHackMakefile);
return;
}
makefileStream.SetCopyIfDifferent(true);
@@ -3131,13 +3253,8 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget(
"# link. This forces Xcode to relink the targets from scratch. It\n"
"# does not seem to check these dependencies itself.\n";
/* clang-format on */
- for (std::vector<std::string>::const_iterator ct =
- this->CurrentConfigurationTypes.begin();
- ct != this->CurrentConfigurationTypes.end(); ++ct) {
- std::string configName = *ct;
- for (std::vector<cmXCodeObject*>::iterator i = targets.begin();
- i != targets.end(); ++i) {
- cmXCodeObject* target = *i;
+ for (const auto& configName : this->CurrentConfigurationTypes) {
+ for (auto target : targets) {
cmGeneratorTarget* gt = target->GetTarget();
if (gt->GetType() == cmStateEnums::EXECUTABLE ||
@@ -3146,7 +3263,7 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget(
gt->GetType() == cmStateEnums::SHARED_LIBRARY ||
gt->GetType() == cmStateEnums::MODULE_LIBRARY) {
// Declare an entry point for the target post-build phase.
- makefileStream << this->PostBuildMakeTarget(gt->GetName(), *ct)
+ makefileStream << this->PostBuildMakeTarget(gt->GetName(), configName)
<< ":\n";
}
@@ -3155,26 +3272,22 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget(
gt->GetType() == cmStateEnums::SHARED_LIBRARY ||
gt->GetType() == cmStateEnums::MODULE_LIBRARY) {
std::string tfull = gt->GetFullPath(configName);
- std::string trel = this->ConvertToRelativeForMake(tfull.c_str());
+ std::string trel = this->ConvertToRelativeForMake(tfull);
// Add this target to the post-build phases of its dependencies.
- std::map<std::string, cmXCodeObject::StringVec>::const_iterator y =
- target->GetDependTargets().find(*ct);
+ auto const y = target->GetDependTargets().find(configName);
if (y != target->GetDependTargets().end()) {
- std::vector<std::string> const& deptgts = y->second;
- for (std::vector<std::string>::const_iterator d = deptgts.begin();
- d != deptgts.end(); ++d) {
- makefileStream << this->PostBuildMakeTarget(*d, *ct) << ": "
- << trel << "\n";
+ for (auto const& deptgt : y->second) {
+ makefileStream << this->PostBuildMakeTarget(deptgt, configName)
+ << ": " << trel << "\n";
}
}
std::vector<cmGeneratorTarget*> objlibs;
gt->GetObjectLibrariesCMP0026(objlibs);
- for (std::vector<cmGeneratorTarget*>::const_iterator it =
- objlibs.begin();
- it != objlibs.end(); ++it) {
- makefileStream << this->PostBuildMakeTarget((*it)->GetName(), *ct)
+ for (auto objLib : objlibs) {
+ makefileStream << this->PostBuildMakeTarget(objLib->GetName(),
+ configName)
<< ": " << trel << "\n";
}
@@ -3182,30 +3295,24 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget(
makefileStream << trel << ":";
// List dependencies if any exist.
- std::map<std::string, cmXCodeObject::StringVec>::const_iterator x =
- target->GetDependLibraries().find(*ct);
+ auto const x = target->GetDependLibraries().find(configName);
if (x != target->GetDependLibraries().end()) {
- std::vector<std::string> const& deplibs = x->second;
- for (std::vector<std::string>::const_iterator d = deplibs.begin();
- d != deplibs.end(); ++d) {
- std::string file = this->ConvertToRelativeForMake(d->c_str());
+ for (auto const& deplib : x->second) {
+ std::string file = this->ConvertToRelativeForMake(deplib);
makefileStream << "\\\n\t" << file;
dummyRules.insert(file);
}
}
- for (std::vector<cmGeneratorTarget*>::const_iterator it =
- objlibs.begin();
- it != objlibs.end(); ++it) {
+ for (auto objLib : objlibs) {
- const std::string objLibName = (*it)->GetName();
- std::string d = this->GetObjectsNormalDirectory(this->CurrentProject,
- configName, *it);
- d += "lib";
- d += objLibName;
- d += ".a";
+ const std::string objLibName = objLib->GetName();
+ std::string d = cmStrCat(
+ this->GetObjectsDirectory(this->CurrentProject, configName, objLib,
+ OBJECT_LIBRARY_ARTIFACT_DIR),
+ "lib", objLibName, ".a");
- std::string dependency = this->ConvertToRelativeForMake(d.c_str());
+ std::string dependency = this->ConvertToRelativeForMake(d);
makefileStream << "\\\n\t" << dependency;
dummyRules.insert(dependency);
}
@@ -3213,23 +3320,17 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget(
// Write the action to remove the target if it is out of date.
makefileStream << "\n";
makefileStream << "\t/bin/rm -f "
- << this->ConvertToRelativeForMake(tfull.c_str())
- << "\n";
+ << this->ConvertToRelativeForMake(tfull) << "\n";
// if building for more than one architecture
- // then remove those exectuables as well
+ // then remove those executables as well
if (this->Architectures.size() > 1) {
- std::string universal = this->GetObjectsNormalDirectory(
- this->CurrentProject, configName, gt);
- for (std::vector<std::string>::iterator arch =
- this->Architectures.begin();
- arch != this->Architectures.end(); ++arch) {
- std::string universalFile = universal;
- universalFile += *arch;
- universalFile += "/";
- universalFile += gt->GetFullName(configName);
+ std::string universal = this->GetObjectsDirectory(
+ this->CurrentProject, configName, gt, "$(OBJDIR)/");
+ for (const auto& architecture : this->Architectures) {
+ std::string universalFile = cmStrCat(universal, architecture, '/',
+ gt->GetFullName(configName));
makefileStream << "\t/bin/rm -f "
- << this->ConvertToRelativeForMake(
- universalFile.c_str())
+ << this->ConvertToRelativeForMake(universalFile)
<< "\n";
}
}
@@ -3241,51 +3342,33 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget(
makefileStream << "\n\n"
<< "# For each target create a dummy rule"
<< "so the target does not have to exist\n";
- for (std::set<std::string>::const_iterator it = dummyRules.begin();
- it != dummyRules.end(); ++it) {
- makefileStream << *it << ":\n";
+ for (auto const& dummyRule : dummyRules) {
+ makefileStream << dummyRule << ":\n";
}
}
void cmGlobalXCodeGenerator::OutputXCodeProject(
cmLocalGenerator* root, std::vector<cmLocalGenerator*>& generators)
{
- if (generators.size() == 0) {
+ if (generators.empty()) {
return;
}
- // Skip local generators that are excluded from this project.
- for (std::vector<cmLocalGenerator*>::iterator g = generators.begin();
- g != generators.end(); ++g) {
- if (this->IsExcluded(root, *g)) {
- continue;
- }
- }
-
if (!this->CreateXCodeObjects(root, generators)) {
return;
}
- std::string xcodeDir = root->GetCurrentBinaryDirectory();
- xcodeDir += "/";
- xcodeDir += root->GetProjectName();
- xcodeDir += ".xcodeproj";
- cmSystemTools::MakeDirectory(xcodeDir.c_str());
+ std::string xcodeDir = cmStrCat(root->GetCurrentBinaryDirectory(), '/',
+ root->GetProjectName(), ".xcodeproj");
+ cmSystemTools::MakeDirectory(xcodeDir);
std::string xcodeProjFile = xcodeDir + "/project.pbxproj";
- cmGeneratedFileStream fout(xcodeProjFile.c_str());
+ cmGeneratedFileStream fout(xcodeProjFile);
fout.SetCopyIfDifferent(true);
if (!fout) {
return;
}
this->WriteXCodePBXProj(fout, root, generators);
- // Since the lowest available Xcode version for testing was 7.0,
- // I'm setting this as a limit then
- if (this->XcodeVersion >= 70) {
- if (root->GetMakefile()->GetCMakeInstance()->GetIsInTryCompile() ||
- root->GetMakefile()->IsOn("CMAKE_XCODE_GENERATE_SCHEME")) {
- this->OutputXCodeSharedSchemes(xcodeDir);
- this->OutputXCodeWorkspaceSettings(xcodeDir);
- }
- }
+ bool hasGeneratedSchemes = this->OutputXCodeSharedSchemes(xcodeDir, root);
+ this->OutputXCodeWorkspaceSettings(xcodeDir, hasGeneratedSchemes);
this->ClearXCodeObjects();
@@ -3295,35 +3378,67 @@ void cmGlobalXCodeGenerator::OutputXCodeProject(
root->GetBinaryDirectory());
}
-void cmGlobalXCodeGenerator::OutputXCodeSharedSchemes(
- const std::string& xcProjDir)
+bool cmGlobalXCodeGenerator::OutputXCodeSharedSchemes(
+ const std::string& xcProjDir, cmLocalGenerator* root)
{
- for (std::vector<cmXCodeObject*>::const_iterator i =
- this->XCodeObjects.begin();
- i != this->XCodeObjects.end(); ++i) {
- cmXCodeObject* obj = *i;
- if (obj->GetType() == cmXCodeObject::OBJECT &&
- (obj->GetIsA() == cmXCodeObject::PBXNativeTarget ||
- obj->GetIsA() == cmXCodeObject::PBXAggregateTarget)) {
- cmXCodeScheme schm(obj, this->CurrentConfigurationTypes,
- this->XcodeVersion);
- schm.WriteXCodeSharedScheme(xcProjDir,
- this->RelativeToSource(xcProjDir.c_str()));
+ // collect all tests for the targets
+ std::map<std::string, cmXCodeScheme::TestObjects> testables;
+
+ for (auto obj : this->XCodeObjects) {
+ if (obj->GetType() != cmXCodeObject::OBJECT ||
+ obj->GetIsA() != cmXCodeObject::PBXNativeTarget) {
+ continue;
+ }
+
+ if (!obj->GetTarget()->IsXCTestOnApple()) {
+ continue;
+ }
+
+ const char* testee = obj->GetTarget()->GetProperty("XCTEST_TESTEE");
+ if (!testee) {
+ continue;
+ }
+
+ testables[testee].push_back(obj);
+ }
+
+ // generate scheme
+ bool ret = false;
+
+ // Since the lowest available Xcode version for testing was 6.4,
+ // I'm setting this as a limit then
+ if (this->XcodeVersion >= 64) {
+ for (auto obj : this->XCodeObjects) {
+ if (obj->GetType() == cmXCodeObject::OBJECT &&
+ (obj->GetIsA() == cmXCodeObject::PBXNativeTarget ||
+ obj->GetIsA() == cmXCodeObject::PBXAggregateTarget) &&
+ (root->GetMakefile()->GetCMakeInstance()->GetIsInTryCompile() ||
+ obj->GetTarget()->GetPropertyAsBool("XCODE_GENERATE_SCHEME"))) {
+ const std::string& targetName = obj->GetTarget()->GetName();
+ cmXCodeScheme schm(obj, testables[targetName],
+ this->CurrentConfigurationTypes,
+ this->XcodeVersion);
+ schm.WriteXCodeSharedScheme(xcProjDir,
+ this->RelativeToSource(xcProjDir));
+ ret = true;
+ }
}
}
+
+ return ret;
}
void cmGlobalXCodeGenerator::OutputXCodeWorkspaceSettings(
- const std::string& xcProjDir)
+ const std::string& xcProjDir, bool hasGeneratedSchemes)
{
- std::string xcodeSharedDataDir = xcProjDir;
- xcodeSharedDataDir += "/project.xcworkspace/xcshareddata";
+ std::string xcodeSharedDataDir =
+ cmStrCat(xcProjDir, "/project.xcworkspace/xcshareddata");
cmSystemTools::MakeDirectory(xcodeSharedDataDir);
- std::string workspaceSettingsFile = xcodeSharedDataDir;
- workspaceSettingsFile += "/WorkspaceSettings.xcsettings";
+ std::string workspaceSettingsFile =
+ cmStrCat(xcodeSharedDataDir, "/WorkspaceSettings.xcsettings");
- cmGeneratedFileStream fout(workspaceSettingsFile.c_str());
+ cmGeneratedFileStream fout(workspaceSettingsFile);
fout.SetCopyIfDifferent(true);
if (!fout) {
return;
@@ -3336,8 +3451,15 @@ void cmGlobalXCodeGenerator::OutputXCodeWorkspaceSettings(
xout.StartElement("plist");
xout.Attribute("version", "1.0");
xout.StartElement("dict");
- xout.Element("key", "IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded");
- xout.Element("false");
+ if (this->XcodeVersion >= 100) {
+ xout.Element("key", "BuildSystemType");
+ xout.Element("string", "Original");
+ }
+ if (hasGeneratedSchemes) {
+ xout.Element("key",
+ "IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded");
+ xout.Element("false");
+ }
xout.EndElement(); // dict
xout.EndElement(); // plist
xout.EndDocument();
@@ -3358,12 +3480,7 @@ void cmGlobalXCodeGenerator::WriteXCodePBXProj(std::ostream& fout,
cmXCodeObject::Indent(1, fout);
fout << "};\n";
cmXCodeObject::Indent(1, fout);
- if (this->XcodeVersion >= 32)
- fout << "objectVersion = 46;\n";
- else if (this->XcodeVersion >= 31)
- fout << "objectVersion = 45;\n";
- else
- fout << "objectVersion = 44;\n";
+ fout << "objectVersion = 46;\n";
cmXCode21Object::PrintList(this->XCodeObjects, fout);
cmXCodeObject::Indent(1, fout);
fout << "rootObject = " << this->RootObject->GetId()
@@ -3402,31 +3519,30 @@ void cmGlobalXCodeGenerator::GetDocumentation(cmDocumentationEntry& entry)
entry.Brief = "Generate Xcode project files.";
}
-std::string cmGlobalXCodeGenerator::ConvertToRelativeForMake(const char* p)
+std::string cmGlobalXCodeGenerator::ConvertToRelativeForMake(
+ std::string const& p)
{
return cmSystemTools::ConvertToOutputPath(p);
}
-std::string cmGlobalXCodeGenerator::RelativeToSource(const char* p)
+std::string cmGlobalXCodeGenerator::RelativeToSource(const std::string& p)
{
// We force conversion because Xcode breakpoints do not work unless
// they are in a file named relative to the source tree.
- return cmOutputConverter::ForceToRelativePath(
+ return cmSystemTools::ForceToRelativePath(
cmSystemTools::JoinPath(this->ProjectSourceDirectoryComponents), p);
}
-std::string cmGlobalXCodeGenerator::RelativeToBinary(const char* p)
+std::string cmGlobalXCodeGenerator::RelativeToBinary(const std::string& p)
{
- return this->CurrentLocalGenerator->ConvertToRelativePath(
+ return this->CurrentLocalGenerator->MaybeConvertToRelativePath(
cmSystemTools::JoinPath(this->ProjectOutputDirectoryComponents), p);
}
std::string cmGlobalXCodeGenerator::XCodeEscapePath(const std::string& p)
{
if (p.find(' ') != std::string::npos) {
- std::string t = "\"";
- t += p;
- t += "\"";
+ std::string t = cmStrCat('"', p, '"');
return t;
}
return p;
@@ -3448,9 +3564,7 @@ std::string cmGlobalXCodeGenerator::LookupFlags(
const std::string& varNameSuffix, const std::string& default_flags)
{
if (!varNameLang.empty()) {
- std::string varName = varNamePrefix;
- varName += varNameLang;
- varName += varNameSuffix;
+ std::string varName = cmStrCat(varNamePrefix, varNameLang, varNameSuffix);
if (const char* varValue = this->CurrentMakefile->GetDefinition(varName)) {
if (*varValue) {
return varValue;
@@ -3470,8 +3584,7 @@ void cmGlobalXCodeGenerator::AppendDefines(BuildObjectListOrString& defs,
}
// Expand the list of definitions.
- std::vector<std::string> defines;
- cmSystemTools::ExpandListArgument(defines_list, defines);
+ std::vector<std::string> defines = cmExpandedList(defines_list);
// Store the definitions in the string.
this->AppendDefines(defs, defines, dflag);
@@ -3483,11 +3596,9 @@ void cmGlobalXCodeGenerator::AppendDefines(
{
// GCC_PREPROCESSOR_DEFINITIONS is a space-separated list of definitions.
std::string def;
- for (std::vector<std::string>::const_iterator di = defines.begin();
- di != defines.end(); ++di) {
+ for (auto const& define : defines) {
// Start with -D if requested.
- def = dflag ? "-D" : "";
- def += *di;
+ def = cmStrCat(dflag ? "-D" : "", define);
// Append the flag with needed escapes.
std::string tmp;
@@ -3497,7 +3608,7 @@ void cmGlobalXCodeGenerator::AppendDefines(
}
void cmGlobalXCodeGenerator::AppendFlag(std::string& flags,
- std::string const& flag)
+ std::string const& flag) const
{
// Short-circuit for an empty flag.
if (flag.empty()) {
@@ -3529,17 +3640,13 @@ void cmGlobalXCodeGenerator::AppendFlag(std::string& flags,
}
// Flag value with escaped quotes and backslashes.
- for (const char* c = flag.c_str(); *c; ++c) {
- if (*c == '\'') {
- if (this->XcodeVersion >= 40) {
- flags += "'\\''";
- } else {
- flags += "\\'";
- }
- } else if (*c == '\\') {
+ for (auto c : flag) {
+ if (c == '\'') {
+ flags += "'\\''";
+ } else if (c == '\\') {
flags += "\\\\";
} else {
- flags += *c;
+ flags += c;
}
}
@@ -3552,11 +3659,9 @@ void cmGlobalXCodeGenerator::AppendFlag(std::string& flags,
std::string cmGlobalXCodeGenerator::ComputeInfoPListLocation(
cmGeneratorTarget* target)
{
- std::string plist = target->GetLocalGenerator()->GetCurrentBinaryDirectory();
- plist += cmake::GetCMakeFilesDirectory();
- plist += "/";
- plist += target->GetName();
- plist += ".dir/Info.plist";
+ std::string plist =
+ cmStrCat(target->GetLocalGenerator()->GetCurrentBinaryDirectory(),
+ "/CMakeFiles/", target->GetName(), ".dir/Info.plist");
return plist;
}
@@ -3572,7 +3677,7 @@ bool cmGlobalXCodeGenerator::HasKnownObjectFileLocation(
std::string* reason) const
{
if (this->ObjectDirArch.find('$') != std::string::npos) {
- if (reason != CM_NULLPTR) {
+ if (reason != nullptr) {
*reason = " under Xcode with multiple architectures";
}
return false;
@@ -3587,10 +3692,10 @@ bool cmGlobalXCodeGenerator::UseEffectivePlatformName(cmMakefile* mf) const
"XCODE_EMIT_EFFECTIVE_PLATFORM_NAME");
if (!epnValue) {
- return mf->PlatformIsAppleIos();
+ return mf->PlatformIsAppleEmbedded();
}
- return cmSystemTools::IsOn(epnValue);
+ return cmIsOn(epnValue);
}
bool cmGlobalXCodeGenerator::ShouldStripResourcePath(cmMakefile*) const
@@ -3604,8 +3709,29 @@ void cmGlobalXCodeGenerator::ComputeTargetObjectDirectory(
{
std::string configName = this->GetCMakeCFGIntDir();
std::string dir =
- this->GetObjectsNormalDirectory("$(PROJECT_NAME)", configName, gt);
- dir += this->ObjectDirArch;
- dir += "/";
+ cmStrCat(this->GetObjectsDirectory("$(PROJECT_NAME)", configName, gt,
+ "$(OBJECT_FILE_DIR_normal:base)/"),
+ this->ObjectDirArch, '/');
gt->ObjectDirectory = dir;
}
+
+std::string cmGlobalXCodeGenerator::GetDeploymentPlatform(const cmMakefile* mf)
+{
+ switch (mf->GetAppleSDKType()) {
+ case cmMakefile::AppleSDK::AppleTVOS:
+ case cmMakefile::AppleSDK::AppleTVSimulator:
+ return "TVOS_DEPLOYMENT_TARGET";
+
+ case cmMakefile::AppleSDK::IPhoneOS:
+ case cmMakefile::AppleSDK::IPhoneSimulator:
+ return "IPHONEOS_DEPLOYMENT_TARGET";
+
+ case cmMakefile::AppleSDK::WatchOS:
+ case cmMakefile::AppleSDK::WatchSimulator:
+ return "WATCHOS_DEPLOYMENT_TARGET";
+
+ case cmMakefile::AppleSDK::MacOS:
+ default:
+ return "MACOSX_DEPLOYMENT_TARGET";
+ }
+}