summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2020-09-14 11:52:31 -0400
committerBrad King <brad.king@kitware.com>2020-09-18 12:49:17 -0400
commit2db623f554d5522350214a7c5bacd5ec2dec1b34 (patch)
tree27da28d96274f726e195d216199fd949005a0930 /Source
parent3ab18c870dc00499f33a40a193e95cc4e1df54ba (diff)
downloadcmake-2db623f554d5522350214a7c5bacd5ec2dec1b34.tar.gz
Xcode: Add option to specify build system variant
Extend the `-T <toolset>` option to support a `buildsystem=` field with the Xcode generator. Add a `CMAKE_XCODE_BUILD_SYSTEM` variable to inform project code about the selected build system variant.
Diffstat (limited to 'Source')
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx115
-rw-r--r--Source/cmGlobalXCodeGenerator.h11
2 files changed, 114 insertions, 12 deletions
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index be4f9ad5b9..cceaea0f84 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -8,6 +8,7 @@
#include <cstring>
#include <iomanip>
#include <sstream>
+#include <unordered_set>
#include <utility>
#include <cm/memory>
@@ -280,32 +281,122 @@ bool cmGlobalXCodeGenerator::SetSystemName(std::string const& s,
return this->cmGlobalGenerator::SetSystemName(s, mf);
}
+namespace {
+cm::string_view cmXcodeBuildSystemString(cmGlobalXCodeGenerator::BuildSystem b)
+{
+ switch (b) {
+ case cmGlobalXCodeGenerator::BuildSystem::One:
+ return "1"_s;
+ }
+ return {};
+}
+}
+
bool cmGlobalXCodeGenerator::SetGeneratorToolset(std::string const& ts,
bool build, cmMakefile* mf)
{
- if (ts.find_first_of(",=") != std::string::npos) {
- std::ostringstream e;
- /* clang-format off */
- e <<
- "Generator\n"
- " " << this->GetName() << "\n"
- "does not recognize the toolset\n"
- " " << ts << "\n"
- "that was specified.";
- /* clang-format on */
- mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ if (!this->ParseGeneratorToolset(ts, mf)) {
return false;
}
- this->GeneratorToolset = ts;
if (build) {
return true;
}
if (!this->GeneratorToolset.empty()) {
mf->AddDefinition("CMAKE_XCODE_PLATFORM_TOOLSET", this->GeneratorToolset);
}
+ mf->AddDefinition("CMAKE_XCODE_BUILD_SYSTEM",
+ cmXcodeBuildSystemString(this->XcodeBuildSystem));
return true;
}
+bool cmGlobalXCodeGenerator::ParseGeneratorToolset(std::string const& ts,
+ cmMakefile* mf)
+{
+ std::vector<std::string> const fields = cmTokenize(ts, ",");
+ auto fi = fields.cbegin();
+ if (fi == fields.cend()) {
+ return true;
+ }
+
+ // The first field may be the Xcode GCC_VERSION.
+ if (fi->find('=') == fi->npos) {
+ this->GeneratorToolset = *fi;
+ ++fi;
+ }
+
+ std::unordered_set<std::string> handled;
+
+ // The rest of the fields must be key=value pairs.
+ for (; fi != fields.cend(); ++fi) {
+ std::string::size_type pos = fi->find('=');
+ if (pos == fi->npos) {
+ /* clang-format off */
+ std::string const& e = cmStrCat(
+ "Generator\n"
+ " ", this->GetName(), "\n"
+ "given toolset specification\n"
+ " ", ts, "\n"
+ "that contains a field after the first ',' with no '='."
+ );
+ /* clang-format on */
+ mf->IssueMessage(MessageType::FATAL_ERROR, e);
+ return false;
+ }
+ std::string const key = fi->substr(0, pos);
+ std::string const value = fi->substr(pos + 1);
+ if (!handled.insert(key).second) {
+ /* clang-format off */
+ std::string const& e = cmStrCat(
+ "Generator\n"
+ " ", this->GetName(), "\n"
+ "given toolset specification\n"
+ " ", ts, "\n"
+ "that contains duplicate field key '", key, "'."
+ );
+ /* clang-format on */
+ mf->IssueMessage(MessageType::FATAL_ERROR, e);
+ return false;
+ }
+ if (!this->ProcessGeneratorToolsetField(key, value, mf)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool cmGlobalXCodeGenerator::ProcessGeneratorToolsetField(
+ std::string const& key, std::string const& value, cmMakefile* mf)
+{
+ if (key == "buildsystem") {
+ if (value == "1"_s) {
+ this->XcodeBuildSystem = BuildSystem::One;
+ } else {
+ /* clang-format off */
+ std::string const& e = cmStrCat(
+ "Generator\n"
+ " ", this->GetName(), "\n"
+ "toolset specification field\n"
+ " buildsystem=", value, "\n"
+ "value is unkonwn. It must be '1'."
+ );
+ /* clang-format on */
+ mf->IssueMessage(MessageType::FATAL_ERROR, e);
+ return false;
+ }
+ return true;
+ }
+ /* clang-format off */
+ std::string const& e = cmStrCat(
+ "Generator\n"
+ " ", this->GetName(), "\n"
+ "given toolset specification that contains invalid field '", key, "'."
+ );
+ /* clang-format on */
+ mf->IssueMessage(MessageType::FATAL_ERROR, e);
+ return false;
+}
+
void cmGlobalXCodeGenerator::EnableLanguage(
std::vector<std::string> const& lang, cmMakefile* mf, bool optional)
{
diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h
index 4e686822ba..bbf3ee915c 100644
--- a/Source/cmGlobalXCodeGenerator.h
+++ b/Source/cmGlobalXCodeGenerator.h
@@ -113,11 +113,20 @@ public:
cmMakefile* mf) override;
void AppendFlag(std::string& flags, std::string const& flag) const;
+ enum class BuildSystem
+ {
+ One = 1,
+ };
+
protected:
void AddExtraIDETargets() override;
void Generate() override;
private:
+ bool ParseGeneratorToolset(std::string const& ts, cmMakefile* mf);
+ bool ProcessGeneratorToolsetField(std::string const& key,
+ std::string const& value, cmMakefile* mf);
+
cmXCodeObject* CreateOrGetPBXGroup(cmGeneratorTarget* gtgt,
cmSourceGroup* sg);
cmXCodeObject* CreatePBXGroup(cmXCodeObject* parent,
@@ -254,6 +263,8 @@ protected:
std::vector<std::unique_ptr<cmXCodeObject>> XCodeObjects;
cmXCodeObject* RootObject;
+ BuildSystem XcodeBuildSystem = BuildSystem::One;
+
private:
std::string const& GetXcodeBuildCommand();
std::string FindXcodeBuildCommand();