summaryrefslogtreecommitdiff
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
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.
-rw-r--r--Help/generator/Xcode.rst23
-rw-r--r--Help/manual/cmake-variables.7.rst1
-rw-r--r--Help/variable/CMAKE_XCODE_BUILD_SYSTEM.rst17
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx115
-rw-r--r--Source/cmGlobalXCodeGenerator.h11
-rw-r--r--Tests/RunCMake/CMakeLists.txt3
-rw-r--r--Tests/RunCMake/GeneratorToolset/BadToolsetHostArchXcode-stderr.txt6
-rw-r--r--Tests/RunCMake/GeneratorToolset/BadToolsetXcodeBuildSystem-result.txt1
-rw-r--r--Tests/RunCMake/GeneratorToolset/BadToolsetXcodeBuildSystem-stderr.txt10
-rw-r--r--Tests/RunCMake/GeneratorToolset/BadToolsetXcodeBuildSystem.cmake1
-rw-r--r--Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake4
-rw-r--r--Tests/RunCMake/GeneratorToolset/TestToolsetXcodeBuildSystemDefault1-result.txt1
-rw-r--r--Tests/RunCMake/GeneratorToolset/TestToolsetXcodeBuildSystemDefault1-stderr.txt4
-rw-r--r--Tests/RunCMake/GeneratorToolset/TestToolsetXcodeBuildSystemDefault1-stdout.txt1
-rw-r--r--Tests/RunCMake/GeneratorToolset/TestToolsetXcodeBuildSystemDefault1.cmake8
15 files changed, 187 insertions, 19 deletions
diff --git a/Help/generator/Xcode.rst b/Help/generator/Xcode.rst
index d893ac504f..c0745dca2a 100644
--- a/Help/generator/Xcode.rst
+++ b/Help/generator/Xcode.rst
@@ -5,9 +5,28 @@ Generate Xcode project files.
This supports Xcode 5.0 and above.
-Toolset Selection
-^^^^^^^^^^^^^^^^^
+.. _`Xcode Build System Selection`:
+
+Toolset and Build System Selection
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
By default Xcode is allowed to select its own default toolchain.
The :variable:`CMAKE_GENERATOR_TOOLSET` option may be set, perhaps
via the :manual:`cmake(1)` ``-T`` option, to specify another toolset.
+
+This generator supports toolset specification using one of these forms:
+
+* ``toolset``
+* ``toolset[,key=value]*``
+* ``key=value[,key=value]*``
+
+The ``toolset`` specifies the toolset name. The selected toolset name
+is provided in the :variable:`CMAKE_XCODE_PLATFORM_TOOLSET` variable.
+
+The ``key=value`` pairs form a comma-separated list of options to
+specify generator-specific details of the toolset selection.
+Supported pairs are:
+
+``buildsystem=<variant>``
+ Specify the buildsystem variant to use.
+ See the :variable:`CMAKE_XCODE_BUILD_SYSTEM` variable for allowed values.
diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst
index b5bc7b1af2..17d0882536 100644
--- a/Help/manual/cmake-variables.7.rst
+++ b/Help/manual/cmake-variables.7.rst
@@ -125,6 +125,7 @@ Variables that Provide Information
/variable/CMAKE_VS_PLATFORM_TOOLSET_VERSION
/variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION
/variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION_MAXIMUM
+ /variable/CMAKE_XCODE_BUILD_SYSTEM
/variable/CMAKE_XCODE_PLATFORM_TOOLSET
/variable/PROJECT-NAME_BINARY_DIR
/variable/PROJECT-NAME_DESCRIPTION
diff --git a/Help/variable/CMAKE_XCODE_BUILD_SYSTEM.rst b/Help/variable/CMAKE_XCODE_BUILD_SYSTEM.rst
new file mode 100644
index 0000000000..8696bbf5c8
--- /dev/null
+++ b/Help/variable/CMAKE_XCODE_BUILD_SYSTEM.rst
@@ -0,0 +1,17 @@
+CMAKE_XCODE_BUILD_SYSTEM
+------------------------
+
+Xcode build system selection.
+
+The :generator:`Xcode` generator defines this variable to indicate which
+variant of the Xcode build system will be used. The value is the
+version of Xcode in which the corresponding build system first became
+mature enough for use by CMake. The possible values are:
+
+``1``
+ The original Xcode build system.
+ This is the default.
+
+The ``CMAKE_XCODE_BUILD_SYSTEM`` variable is informational and should not
+be modified by project code. See the :ref:`Xcode Build System Selection`
+documentation section to select the Xcode build system.
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();
diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index e5869612bd..39455b7bd8 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -238,6 +238,9 @@ add_RunCMake_test(GenEx-GENEX_EVAL)
add_RunCMake_test(GeneratorExpression)
add_RunCMake_test(GeneratorInstance)
add_RunCMake_test(GeneratorPlatform)
+if(XCODE_VERSION)
+ set(GeneratorToolset_ARGS -DXCODE_VERSION=${XCODE_VERSION})
+endif()
add_RunCMake_test(GeneratorToolset)
add_RunCMake_test(GetPrerequisites)
add_RunCMake_test(GNUInstallDirs -DSYSTEM_NAME=${CMAKE_SYSTEM_NAME})
diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchXcode-stderr.txt b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchXcode-stderr.txt
index 5737e953e8..a86bd020ea 100644
--- a/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchXcode-stderr.txt
+++ b/Tests/RunCMake/GeneratorToolset/BadToolsetHostArchXcode-stderr.txt
@@ -3,8 +3,4 @@ CMake Error at CMakeLists.txt:[0-9]+ \(project\):
.*
- does not recognize the toolset
-
- Test Toolset,host=x6[45]
-
- that was specified\.$
+ given toolset specification that contains invalid field 'host'\.$
diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetXcodeBuildSystem-result.txt b/Tests/RunCMake/GeneratorToolset/BadToolsetXcodeBuildSystem-result.txt
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/Tests/RunCMake/GeneratorToolset/BadToolsetXcodeBuildSystem-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetXcodeBuildSystem-stderr.txt b/Tests/RunCMake/GeneratorToolset/BadToolsetXcodeBuildSystem-stderr.txt
new file mode 100644
index 0000000000..9ef6b20128
--- /dev/null
+++ b/Tests/RunCMake/GeneratorToolset/BadToolsetXcodeBuildSystem-stderr.txt
@@ -0,0 +1,10 @@
+CMake Error at CMakeLists.txt:[0-9]+ \(project\):
+ Generator
+
+ Xcode
+
+ toolset specification field
+
+ buildsystem=bad
+
+ value is unkonwn. It must be '1'\.$
diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetXcodeBuildSystem.cmake b/Tests/RunCMake/GeneratorToolset/BadToolsetXcodeBuildSystem.cmake
new file mode 100644
index 0000000000..2fc38e5c59
--- /dev/null
+++ b/Tests/RunCMake/GeneratorToolset/BadToolsetXcodeBuildSystem.cmake
@@ -0,0 +1 @@
+message(FATAL_ERROR "This should not be reached!")
diff --git a/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake b/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake
index bb22841543..af59019be3 100644
--- a/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake
+++ b/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake
@@ -54,6 +54,10 @@ elseif("${RunCMake_GENERATOR}" STREQUAL "Xcode")
run_cmake(TestToolset)
set(RunCMake_GENERATOR_TOOLSET "Test Toolset,host=x64")
run_cmake(BadToolsetHostArchXcode)
+ set(RunCMake_GENERATOR_TOOLSET "buildsystem=bad")
+ run_cmake(BadToolsetXcodeBuildSystem)
+ set(RunCMake_GENERATOR_TOOLSET "Test Toolset")
+ run_cmake(TestToolsetXcodeBuildSystemDefault1)
else()
set(RunCMake_GENERATOR_TOOLSET "Bad Toolset")
run_cmake(BadToolset)
diff --git a/Tests/RunCMake/GeneratorToolset/TestToolsetXcodeBuildSystemDefault1-result.txt b/Tests/RunCMake/GeneratorToolset/TestToolsetXcodeBuildSystemDefault1-result.txt
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/Tests/RunCMake/GeneratorToolset/TestToolsetXcodeBuildSystemDefault1-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/GeneratorToolset/TestToolsetXcodeBuildSystemDefault1-stderr.txt b/Tests/RunCMake/GeneratorToolset/TestToolsetXcodeBuildSystemDefault1-stderr.txt
new file mode 100644
index 0000000000..0adbd0c8ca
--- /dev/null
+++ b/Tests/RunCMake/GeneratorToolset/TestToolsetXcodeBuildSystemDefault1-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at TestToolsetXcodeBuildSystemDefault1.cmake:[0-9]+ \(message\):
+ CMAKE_GENERATOR_TOOLSET is "Test Toolset" as expected.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/GeneratorToolset/TestToolsetXcodeBuildSystemDefault1-stdout.txt b/Tests/RunCMake/GeneratorToolset/TestToolsetXcodeBuildSystemDefault1-stdout.txt
new file mode 100644
index 0000000000..cba95ce6c4
--- /dev/null
+++ b/Tests/RunCMake/GeneratorToolset/TestToolsetXcodeBuildSystemDefault1-stdout.txt
@@ -0,0 +1 @@
+CMAKE_XCODE_BUILD_SYSTEM='1'
diff --git a/Tests/RunCMake/GeneratorToolset/TestToolsetXcodeBuildSystemDefault1.cmake b/Tests/RunCMake/GeneratorToolset/TestToolsetXcodeBuildSystemDefault1.cmake
new file mode 100644
index 0000000000..645bb19a06
--- /dev/null
+++ b/Tests/RunCMake/GeneratorToolset/TestToolsetXcodeBuildSystemDefault1.cmake
@@ -0,0 +1,8 @@
+message(STATUS "CMAKE_XCODE_BUILD_SYSTEM='${CMAKE_XCODE_BUILD_SYSTEM}'")
+if(CMAKE_GENERATOR_TOOLSET STREQUAL "Test Toolset")
+ message(FATAL_ERROR "CMAKE_GENERATOR_TOOLSET is \"Test Toolset\" as expected.")
+else()
+ message(FATAL_ERROR
+ "CMAKE_GENERATOR_TOOLSET is \"${CMAKE_GENERATOR_TOOLSET}\" "
+ "but should be \"Test Toolset\"!")
+endif()