diff options
author | Brad King <brad.king@kitware.com> | 2020-09-14 19:02:47 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2020-09-18 17:02:14 (GMT) |
commit | 8d5f4c4db93959f77dc8fb185e4630df4ec26d98 (patch) | |
tree | d71f3fd9552500ecb52217bff53f4a7b37d6e18c | |
parent | 2db623f554d5522350214a7c5bacd5ec2dec1b34 (diff) | |
download | CMake-8d5f4c4db93959f77dc8fb185e4630df4ec26d98.zip CMake-8d5f4c4db93959f77dc8fb185e4630df4ec26d98.tar.gz CMake-8d5f4c4db93959f77dc8fb185e4630df4ec26d98.tar.bz2 |
Xcode: Switch to the "new build system" for Xcode 12 and above
Provide an option to switch back to the original build system via
`-T buildsystem=1`.
Fixes: #18088
26 files changed, 423 insertions, 31 deletions
diff --git a/Help/generator/Xcode.rst b/Help/generator/Xcode.rst index c0745dc..be03a22 100644 --- a/Help/generator/Xcode.rst +++ b/Help/generator/Xcode.rst @@ -30,3 +30,6 @@ Supported pairs are: ``buildsystem=<variant>`` Specify the buildsystem variant to use. See the :variable:`CMAKE_XCODE_BUILD_SYSTEM` variable for allowed values. + + For example, to select the original build system under Xcode 12, + run :manual:`cmake(1)` with the option ``-T buildsystem=1``. diff --git a/Help/release/dev/xcode-12-new-build-system.rst b/Help/release/dev/xcode-12-new-build-system.rst new file mode 100644 index 0000000..7a497b0 --- /dev/null +++ b/Help/release/dev/xcode-12-new-build-system.rst @@ -0,0 +1,7 @@ +xcode-12-new-build-system +------------------------- + +* The :generator:`Xcode` generator now uses the Xcode "new build system" + when generating for Xcode 12.0 or higher. + See the :variable:`CMAKE_XCODE_BUILD_SYSTEM` variable. + One may use ``-T buildsystem=1`` to switch to the legacy build system. diff --git a/Help/variable/CMAKE_XCODE_BUILD_SYSTEM.rst b/Help/variable/CMAKE_XCODE_BUILD_SYSTEM.rst index 8696bbf..587a5c9 100644 --- a/Help/variable/CMAKE_XCODE_BUILD_SYSTEM.rst +++ b/Help/variable/CMAKE_XCODE_BUILD_SYSTEM.rst @@ -10,7 +10,12 @@ mature enough for use by CMake. The possible values are: ``1`` The original Xcode build system. - This is the default. + This is the default when using Xcode 11.x or below. + +``12`` + The Xcode "new build system" introduced by Xcode 10. + It became mature enough for use by CMake in Xcode 12. + This is the default when using Xcode 12.x or above. The ``CMAKE_XCODE_BUILD_SYSTEM`` variable is informational and should not be modified by project code. See the :ref:`Xcode Build System Selection` diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index cceaea0..b2014e0 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -171,6 +171,11 @@ cmGlobalXCodeGenerator::cmGlobalXCodeGenerator( { this->VersionString = version_string; this->XcodeVersion = version_number; + if (this->XcodeVersion >= 120) { + this->XcodeBuildSystem = BuildSystem::Twelve; + } else { + this->XcodeBuildSystem = BuildSystem::One; + } this->RootObject = nullptr; this->MainGroupChildren = nullptr; @@ -287,6 +292,8 @@ cm::string_view cmXcodeBuildSystemString(cmGlobalXCodeGenerator::BuildSystem b) switch (b) { case cmGlobalXCodeGenerator::BuildSystem::One: return "1"_s; + case cmGlobalXCodeGenerator::BuildSystem::Twelve: + return "12"_s; } return {}; } @@ -371,6 +378,8 @@ bool cmGlobalXCodeGenerator::ProcessGeneratorToolsetField( if (key == "buildsystem") { if (value == "1"_s) { this->XcodeBuildSystem = BuildSystem::One; + } else if (value == "12"_s) { + this->XcodeBuildSystem = BuildSystem::Twelve; } else { /* clang-format off */ std::string const& e = cmStrCat( @@ -378,7 +387,21 @@ bool cmGlobalXCodeGenerator::ProcessGeneratorToolsetField( " ", this->GetName(), "\n" "toolset specification field\n" " buildsystem=", value, "\n" - "value is unkonwn. It must be '1'." + "value is unkonwn. It must be '1' or '12'." + ); + /* clang-format on */ + mf->IssueMessage(MessageType::FATAL_ERROR, e); + return false; + } + if (this->XcodeBuildSystem == BuildSystem::Twelve && + this->XcodeVersion < 120) { + /* clang-format off */ + std::string const& e = cmStrCat( + "Generator\n" + " ", this->GetName(), "\n" + "toolset specification field\n" + " buildsystem=", value, "\n" + "is not allowed with Xcode ", this->VersionString, '.' ); /* clang-format on */ mf->IssueMessage(MessageType::FATAL_ERROR, e); @@ -479,6 +502,9 @@ cmGlobalXCodeGenerator::GenerateBuildCommand( } } + if (this->XcodeBuildSystem >= BuildSystem::Twelve) { + makeCommand.Add("-parallelizeTargets"); + } makeCommand.Add("-configuration", (config.empty() ? "Debug" : config)); if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) { @@ -499,8 +525,15 @@ cmGlobalXCodeGenerator::GenerateBuildCommand( std::unique_ptr<cmLocalGenerator> cmGlobalXCodeGenerator::CreateLocalGenerator( cmMakefile* mf) { - return std::unique_ptr<cmLocalGenerator>( + std::unique_ptr<cmLocalGenerator> lg( cm::make_unique<cmLocalXCodeGenerator>(this, mf)); + if (this->XcodeBuildSystem >= BuildSystem::Twelve) { + // For this build system variant we generate custom commands as + // shell scripts directly rather than inside Makefiles. + // FIXME: Rename or refactor this option for clarity. + lg->SetLinkScriptShell(true); + } + return lg; } void cmGlobalXCodeGenerator::AddExtraIDETargets() @@ -1692,30 +1725,46 @@ void cmGlobalXCodeGenerator::CreateCustomCommands( cmXCodeObject* preLinkPhase = nullptr; cmXCodeObject* postBuildPhase = nullptr; - std::vector<cmSourceFile*> classes; - if (!gtgt->GetConfigCommonSourceFiles(classes)) { - return; - } - // add all the sources - std::vector<cmCustomCommand> commands; - auto& visited = this->CommandsVisited[gtgt]; - for (auto sourceFile : classes) { - if (sourceFile->GetCustomCommand() && visited.insert(sourceFile).second) { - commands.push_back(*sourceFile->GetCustomCommand()); + if (this->XcodeBuildSystem >= BuildSystem::Twelve) { + // create prebuild phase + preBuildPhase = + this->CreateRunScriptBuildPhase("CMake PreBuild Rules", prebuild); + // create prelink phase + preLinkPhase = + this->CreateRunScriptBuildPhase("CMake PreLink Rules", prelink); + // create postbuild phase + postBuildPhase = + this->CreateRunScriptBuildPhase("CMake PostBuild Rules", postbuild); + } else { + std::vector<cmSourceFile*> classes; + if (!gtgt->GetConfigCommonSourceFiles(classes)) { + return; + } + // add all the sources + std::vector<cmCustomCommand> commands; + auto& visited = this->CommandsVisited[gtgt]; + for (auto sourceFile : classes) { + if (sourceFile->GetCustomCommand() && + visited.insert(sourceFile).second) { + commands.push_back(*sourceFile->GetCustomCommand()); + if (this->XcodeBuildSystem >= BuildSystem::Twelve) { + this->CustomCommandRoots[sourceFile].insert(gtgt); + } + } } + // create custom commands phase + legacyCustomCommandsBuildPhase = this->CreateLegacyRunScriptBuildPhase( + "CMake Rules", "cmakeRulesBuildPhase", gtgt, commands); + // create prebuild phase + preBuildPhase = this->CreateLegacyRunScriptBuildPhase( + "CMake PreBuild Rules", "preBuildCommands", gtgt, prebuild); + // create prelink phase + preLinkPhase = this->CreateLegacyRunScriptBuildPhase( + "CMake PreLink Rules", "preLinkCommands", gtgt, prelink); + // create postbuild phase + postBuildPhase = this->CreateLegacyRunScriptBuildPhase( + "CMake PostBuild Rules", "postBuildPhase", gtgt, postbuild); } - // create custom commands phase - legacyCustomCommandsBuildPhase = this->CreateLegacyRunScriptBuildPhase( - "CMake Rules", "cmakeRulesBuildPhase", gtgt, commands); - // create prebuild phase - preBuildPhase = this->CreateLegacyRunScriptBuildPhase( - "CMake PreBuild Rules", "preBuildCommands", gtgt, prebuild); - // create prelink phase - preLinkPhase = this->CreateLegacyRunScriptBuildPhase( - "CMake PreLink Rules", "preLinkCommands", gtgt, prelink); - // create postbuild phase - postBuildPhase = this->CreateLegacyRunScriptBuildPhase( - "CMake PostBuild Rules", "postBuildPhase", gtgt, postbuild); // The order here is the order they will be built in. // The order "headers, resources, sources" mimics a native project generated @@ -1727,6 +1776,9 @@ void cmGlobalXCodeGenerator::CreateCustomCommands( if (legacyCustomCommandsBuildPhase) { buildPhases->AddObject(legacyCustomCommandsBuildPhase); } + if (this->XcodeBuildSystem >= BuildSystem::Twelve) { + this->CreateRunScriptBuildPhases(buildPhases, gtgt); + } if (headerBuildPhase) { buildPhases->AddObject(headerBuildPhase); } @@ -1750,6 +1802,199 @@ void cmGlobalXCodeGenerator::CreateCustomCommands( } } +void cmGlobalXCodeGenerator::CreateRunScriptBuildPhases( + cmXCodeObject* buildPhases, cmGeneratorTarget const* gt) +{ + std::vector<cmSourceFile*> sources; + if (!gt->GetConfigCommonSourceFiles(sources)) { + return; + } + auto& visited = this->CommandsVisited[gt]; + for (auto sf : sources) { + this->CreateRunScriptBuildPhases(buildPhases, sf, gt, visited); + } +} + +void cmGlobalXCodeGenerator::CreateRunScriptBuildPhases( + cmXCodeObject* buildPhases, cmSourceFile const* sf, + cmGeneratorTarget const* gt, std::set<cmSourceFile const*>& visited) +{ + cmCustomCommand const* cc = sf->GetCustomCommand(); + if (cc && visited.insert(sf).second) { + this->CustomCommandRoots[sf].insert(gt); + if (std::vector<cmSourceFile*> const* depends = gt->GetSourceDepends(sf)) { + for (cmSourceFile const* di : *depends) { + this->CreateRunScriptBuildPhases(buildPhases, di, gt, visited); + } + } + cmXCodeObject* buildPhase = this->CreateRunScriptBuildPhase(sf, gt, *cc); + buildPhases->AddObject(buildPhase); + } +} + +cmXCodeObject* cmGlobalXCodeGenerator::CreateRunScriptBuildPhase( + cmSourceFile const* sf, cmGeneratorTarget const* gt, + cmCustomCommand const& cc) +{ + std::set<std::string> allConfigInputs; + std::set<std::string> allConfigOutputs; + + std::string shellScript = "set -e\n"; + for (std::string const& configName : this->CurrentConfigurationTypes) { + cmCustomCommandGenerator ccg(cc, configName, this->CurrentLocalGenerator); + std::vector<std::string> realDepends; + realDepends.reserve(ccg.GetDepends().size()); + for (auto const& d : ccg.GetDepends()) { + std::string dep; + if (this->CurrentLocalGenerator->GetRealDependency(d, configName, dep)) { + realDepends.emplace_back(std::move(dep)); + } + } + + allConfigInputs.insert(realDepends.begin(), realDepends.end()); + allConfigOutputs.insert(ccg.GetByproducts().begin(), + ccg.GetByproducts().end()); + allConfigOutputs.insert(ccg.GetOutputs().begin(), ccg.GetOutputs().end()); + + shellScript = + cmStrCat(shellScript, R"(if test "$CONFIGURATION" = ")", configName, + "\"; then :\n", this->ConstructScript(ccg), "fi\n"); + } + + cmXCodeObject* buildPhase = + this->CreateObject(cmXCodeObject::PBXShellScriptBuildPhase); + buildPhase->AddAttribute("buildActionMask", + this->CreateString("2147483647")); + cmXCodeObject* buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST); + buildPhase->AddAttribute("files", buildFiles); + { + std::string name; + if (!allConfigOutputs.empty()) { + name = cmStrCat("Generate ", + this->RelativeToBinary(*allConfigOutputs.begin())); + } else { + name = sf->GetLocation().GetName(); + } + buildPhase->AddAttribute("name", this->CreateString(name)); + } + buildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", + this->CreateString("0")); + buildPhase->AddAttribute("shellPath", this->CreateString("/bin/sh")); + buildPhase->AddAttribute("shellScript", this->CreateString(shellScript)); + buildPhase->AddAttribute("showEnvVarsInLog", this->CreateString("0")); + + bool symbolic = false; + { + cmXCodeObject* inputPaths = this->CreateObject(cmXCodeObject::OBJECT_LIST); + for (std::string const& i : allConfigInputs) { + inputPaths->AddUniqueObject(this->CreateString(i)); + if (!symbolic) { + if (cmSourceFile* isf = + gt->GetLocalGenerator()->GetMakefile()->GetSource( + i, cmSourceFileLocationKind::Known)) { + symbolic = isf->GetPropertyAsBool("SYMBOLIC"); + } + } + } + buildPhase->AddAttribute("inputPaths", inputPaths); + } + { + cmXCodeObject* outputPaths = + this->CreateObject(cmXCodeObject::OBJECT_LIST); + for (std::string const& o : allConfigOutputs) { + outputPaths->AddUniqueObject(this->CreateString(o)); + if (!symbolic) { + if (cmSourceFile* osf = + gt->GetLocalGenerator()->GetMakefile()->GetSource( + o, cmSourceFileLocationKind::Known)) { + symbolic = osf->GetPropertyAsBool("SYMBOLIC"); + } + } + } + buildPhase->AddAttribute("outputPaths", outputPaths); + } + if (symbolic) { + buildPhase->AddAttribute("alwaysOutOfDate", this->CreateString("1")); + } + + return buildPhase; +} + +cmXCodeObject* cmGlobalXCodeGenerator::CreateRunScriptBuildPhase( + std::string const& name, std::vector<cmCustomCommand> const& commands) +{ + if (commands.empty()) { + return nullptr; + } + + std::set<std::string> allConfigOutputs; + + std::string shellScript = "set -e\n"; + for (std::string const& configName : this->CurrentConfigurationTypes) { + shellScript = cmStrCat(shellScript, R"(if test "$CONFIGURATION" = ")", + configName, "\"; then :\n"); + for (cmCustomCommand const& cc : commands) { + cmCustomCommandGenerator ccg(cc, configName, + this->CurrentLocalGenerator); + shellScript = cmStrCat(shellScript, this->ConstructScript(ccg)); + allConfigOutputs.insert(ccg.GetByproducts().begin(), + ccg.GetByproducts().end()); + } + shellScript = cmStrCat(shellScript, "fi\n"); + } + + cmXCodeObject* buildPhase = + this->CreateObject(cmXCodeObject::PBXShellScriptBuildPhase); + buildPhase->AddAttribute("buildActionMask", + this->CreateString("2147483647")); + cmXCodeObject* buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST); + buildPhase->AddAttribute("files", buildFiles); + buildPhase->AddAttribute("name", this->CreateString(name)); + buildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", + this->CreateString("0")); + buildPhase->AddAttribute("shellPath", this->CreateString("/bin/sh")); + buildPhase->AddAttribute("shellScript", this->CreateString(shellScript)); + buildPhase->AddAttribute("showEnvVarsInLog", this->CreateString("0")); + { + cmXCodeObject* outputPaths = + this->CreateObject(cmXCodeObject::OBJECT_LIST); + for (std::string const& o : allConfigOutputs) { + outputPaths->AddUniqueObject(this->CreateString(o)); + } + buildPhase->AddAttribute("outputPaths", outputPaths); + } + buildPhase->AddAttribute("alwaysOutOfDate", this->CreateString("1")); + + return buildPhase; +} + +std::string cmGlobalXCodeGenerator::ConstructScript( + cmCustomCommandGenerator const& ccg) +{ + std::string script; + cmLocalGenerator* lg = this->CurrentLocalGenerator; + std::string wd = ccg.GetWorkingDirectory(); + if (wd.empty()) { + wd = lg->GetCurrentBinaryDirectory(); + } + wd = lg->ConvertToOutputFormat(wd, cmOutputConverter::SHELL); + script = cmStrCat(script, " cd ", wd, "\n"); + for (unsigned int c = 0; c < ccg.GetNumberOfCommands(); ++c) { + std::string cmd = ccg.GetCommand(c); + if (cmd.empty()) { + continue; + } + cmSystemTools::ReplaceString(cmd, "/./", "/"); + cmd = lg->ConvertToOutputFormat(cmd, cmOutputConverter::SHELL); + ccg.AppendArguments(c, cmd); + cmSystemTools::ReplaceString(cmd, "$(CONFIGURATION)", "$CONFIGURATION"); + cmSystemTools::ReplaceString(cmd, "$(EFFECTIVE_PLATFORM_NAME)", + "$EFFECTIVE_PLATFORM_NAME"); + script = cmStrCat(script, " ", cmd, '\n'); + } + return script; +} + // This function removes each occurrence of the flag and returns the last one // (i.e., the dominant flag in GCC) std::string cmGlobalXCodeGenerator::ExtractFlag(const char* flag, @@ -3713,6 +3958,29 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects( if (!this->CreateXCodeTargets(generator, targets)) { return false; } + for (auto const& ccRoot : this->CustomCommandRoots) { + if (ccRoot.second.size() > 1) { + std::string e = "The custom command "; + std::vector<std::string> const& outputs = + ccRoot.first->GetCustomCommand()->GetOutputs(); + if (!outputs.empty()) { + e = cmStrCat(e, "generating\n ", outputs[0]); + } else { + e = cmStrCat(e, "driven by\n ", ccRoot.first->GetFullPath()); + } + e = cmStrCat(e, "\nis attached to multiple targets:"); + for (cmGeneratorTarget const* gt : ccRoot.second) { + e = cmStrCat(e, "\n ", gt->GetName()); + } + e = cmStrCat( + e, + "\nbut none of these is a common dependency of the other(s). " + "This is not allowed by the Xcode \"new build system\"."); + generator->IssueMessage(MessageType::FATAL_ERROR, e); + return false; + } + } + this->CustomCommandRoots.clear(); } // loop over all targets and add link and depend info for (auto t : targets) { @@ -4007,9 +4275,16 @@ void cmGlobalXCodeGenerator::OutputXCodeWorkspaceSettings( xout.StartElement("dict"); if (this->XcodeVersion >= 100) { xout.Element("key", "BuildSystemType"); - xout.Element("string", "Original"); - xout.Element("key", "DisableBuildSystemDeprecationWarning"); - xout.Element("true"); + switch (this->XcodeBuildSystem) { + case BuildSystem::One: + xout.Element("string", "Original"); + xout.Element("key", "DisableBuildSystemDeprecationWarning"); + xout.Element("true"); + break; + case BuildSystem::Twelve: + xout.Element("string", "Latest"); + break; + } } if (hasGeneratedSchemes) { xout.Element("key", diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h index bbf3ee9..fca9c27 100644 --- a/Source/cmGlobalXCodeGenerator.h +++ b/Source/cmGlobalXCodeGenerator.h @@ -15,6 +15,7 @@ #include "cmXCodeObject.h" class cmCustomCommand; +class cmCustomCommandGenerator; class cmGeneratorTarget; class cmGlobalGeneratorFactory; class cmLocalGenerator; @@ -116,6 +117,7 @@ public: enum class BuildSystem { One = 1, + Twelve = 12, }; protected: @@ -233,6 +235,18 @@ private: cmXCodeObject* CreateLegacyRunScriptBuildPhase( const char* name, const char* name2, cmGeneratorTarget* target, const std::vector<cmCustomCommand>&); + void CreateRunScriptBuildPhases(cmXCodeObject* buildPhases, + cmGeneratorTarget const* gt); + void CreateRunScriptBuildPhases(cmXCodeObject* buildPhases, + cmSourceFile const* sf, + cmGeneratorTarget const* gt, + std::set<cmSourceFile const*>& visited); + cmXCodeObject* CreateRunScriptBuildPhase(cmSourceFile const* sf, + cmGeneratorTarget const* gt, + cmCustomCommand const& cc); + cmXCodeObject* CreateRunScriptBuildPhase( + std::string const& name, std::vector<cmCustomCommand> const& commands); + std::string ConstructScript(cmCustomCommandGenerator const& ccg); void CreateReRunCMakeFile(cmLocalGenerator* root, std::vector<cmLocalGenerator*> const& gens); @@ -315,4 +329,6 @@ private: std::vector<std::string> EnabledLangs; std::map<cmGeneratorTarget const*, std::set<cmSourceFile const*>> CommandsVisited; + std::map<cmSourceFile const*, std::set<cmGeneratorTarget const*>> + CustomCommandRoots; }; diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetXcodeBuildSystem-stderr.txt b/Tests/RunCMake/GeneratorToolset/BadToolsetXcodeBuildSystem-stderr.txt index 9ef6b20..5e88e3b 100644 --- a/Tests/RunCMake/GeneratorToolset/BadToolsetXcodeBuildSystem-stderr.txt +++ b/Tests/RunCMake/GeneratorToolset/BadToolsetXcodeBuildSystem-stderr.txt @@ -7,4 +7,4 @@ CMake Error at CMakeLists.txt:[0-9]+ \(project\): buildsystem=bad - value is unkonwn. It must be '1'\.$ + value is unkonwn. It must be '1' or '12'\.$ diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetXcodeBuildSystem12-result.txt b/Tests/RunCMake/GeneratorToolset/BadToolsetXcodeBuildSystem12-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/BadToolsetXcodeBuildSystem12-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetXcodeBuildSystem12-stderr.txt b/Tests/RunCMake/GeneratorToolset/BadToolsetXcodeBuildSystem12-stderr.txt new file mode 100644 index 0000000..cdfae3e --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/BadToolsetXcodeBuildSystem12-stderr.txt @@ -0,0 +1,10 @@ +CMake Error at CMakeLists.txt:[0-9]+ \(project\): + Generator + + Xcode + + toolset specification field + + buildsystem=12 + + is not allowed with Xcode [0-9.]+\.$ diff --git a/Tests/RunCMake/GeneratorToolset/BadToolsetXcodeBuildSystem12.cmake b/Tests/RunCMake/GeneratorToolset/BadToolsetXcodeBuildSystem12.cmake new file mode 100644 index 0000000..2fc38e5 --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/BadToolsetXcodeBuildSystem12.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 af59019..5f12d79 100644 --- a/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake +++ b/Tests/RunCMake/GeneratorToolset/RunCMakeTest.cmake @@ -56,8 +56,19 @@ elseif("${RunCMake_GENERATOR}" STREQUAL "Xcode") run_cmake(BadToolsetHostArchXcode) set(RunCMake_GENERATOR_TOOLSET "buildsystem=bad") run_cmake(BadToolsetXcodeBuildSystem) - set(RunCMake_GENERATOR_TOOLSET "Test Toolset") - run_cmake(TestToolsetXcodeBuildSystemDefault1) + if(XCODE_VERSION VERSION_GREATER_EQUAL 12) + set(RunCMake_GENERATOR_TOOLSET "Test Toolset") + run_cmake(TestToolsetXcodeBuildSystemDefault12) + set(RunCMake_GENERATOR_TOOLSET "Test Toolset,buildsystem=1") + run_cmake(TestToolsetXcodeBuildSystem1) + set(RunCMake_GENERATOR_TOOLSET "Test Toolset,buildsystem=12") + run_cmake(TestToolsetXcodeBuildSystem12) + else() + set(RunCMake_GENERATOR_TOOLSET "Test Toolset") + run_cmake(TestToolsetXcodeBuildSystemDefault1) + set(RunCMake_GENERATOR_TOOLSET "buildsystem=12") + run_cmake(BadToolsetXcodeBuildSystem12) + endif() else() set(RunCMake_GENERATOR_TOOLSET "Bad Toolset") run_cmake(BadToolset) diff --git a/Tests/RunCMake/GeneratorToolset/TestToolsetXcodeBuildSystem1-result.txt b/Tests/RunCMake/GeneratorToolset/TestToolsetXcodeBuildSystem1-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/TestToolsetXcodeBuildSystem1-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GeneratorToolset/TestToolsetXcodeBuildSystem1-stderr.txt b/Tests/RunCMake/GeneratorToolset/TestToolsetXcodeBuildSystem1-stderr.txt new file mode 100644 index 0000000..817467b --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/TestToolsetXcodeBuildSystem1-stderr.txt @@ -0,0 +1,4 @@ +^CMake Error at TestToolsetXcodeBuildSystem1.cmake:[0-9]+ \(message\): + CMAKE_GENERATOR_TOOLSET is "Test Toolset,buildsystem=1" as expected. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/GeneratorToolset/TestToolsetXcodeBuildSystem1-stdout.txt b/Tests/RunCMake/GeneratorToolset/TestToolsetXcodeBuildSystem1-stdout.txt new file mode 100644 index 0000000..cba95ce --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/TestToolsetXcodeBuildSystem1-stdout.txt @@ -0,0 +1 @@ +CMAKE_XCODE_BUILD_SYSTEM='1' diff --git a/Tests/RunCMake/GeneratorToolset/TestToolsetXcodeBuildSystem1.cmake b/Tests/RunCMake/GeneratorToolset/TestToolsetXcodeBuildSystem1.cmake new file mode 100644 index 0000000..550a6a1 --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/TestToolsetXcodeBuildSystem1.cmake @@ -0,0 +1,8 @@ +message(STATUS "CMAKE_XCODE_BUILD_SYSTEM='${CMAKE_XCODE_BUILD_SYSTEM}'") +if(CMAKE_GENERATOR_TOOLSET STREQUAL "Test Toolset,buildsystem=1") + message(FATAL_ERROR "CMAKE_GENERATOR_TOOLSET is \"Test Toolset,buildsystem=1\" as expected.") +else() + message(FATAL_ERROR + "CMAKE_GENERATOR_TOOLSET is \"${CMAKE_GENERATOR_TOOLSET}\" " + "but should be \"Test Toolset,buildsystem=1\"!") +endif() diff --git a/Tests/RunCMake/GeneratorToolset/TestToolsetXcodeBuildSystem12-result.txt b/Tests/RunCMake/GeneratorToolset/TestToolsetXcodeBuildSystem12-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/TestToolsetXcodeBuildSystem12-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GeneratorToolset/TestToolsetXcodeBuildSystem12-stderr.txt b/Tests/RunCMake/GeneratorToolset/TestToolsetXcodeBuildSystem12-stderr.txt new file mode 100644 index 0000000..9352faf --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/TestToolsetXcodeBuildSystem12-stderr.txt @@ -0,0 +1,4 @@ +^CMake Error at TestToolsetXcodeBuildSystem12.cmake:[0-9]+ \(message\): + CMAKE_GENERATOR_TOOLSET is "Test Toolset,buildsystem=12" as expected. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/GeneratorToolset/TestToolsetXcodeBuildSystem12-stdout.txt b/Tests/RunCMake/GeneratorToolset/TestToolsetXcodeBuildSystem12-stdout.txt new file mode 100644 index 0000000..df49a31 --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/TestToolsetXcodeBuildSystem12-stdout.txt @@ -0,0 +1 @@ +CMAKE_XCODE_BUILD_SYSTEM='12' diff --git a/Tests/RunCMake/GeneratorToolset/TestToolsetXcodeBuildSystem12.cmake b/Tests/RunCMake/GeneratorToolset/TestToolsetXcodeBuildSystem12.cmake new file mode 100644 index 0000000..7e30e43 --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/TestToolsetXcodeBuildSystem12.cmake @@ -0,0 +1,8 @@ +message(STATUS "CMAKE_XCODE_BUILD_SYSTEM='${CMAKE_XCODE_BUILD_SYSTEM}'") +if(CMAKE_GENERATOR_TOOLSET STREQUAL "Test Toolset,buildsystem=12") + message(FATAL_ERROR "CMAKE_GENERATOR_TOOLSET is \"Test Toolset,buildsystem=12\" as expected.") +else() + message(FATAL_ERROR + "CMAKE_GENERATOR_TOOLSET is \"${CMAKE_GENERATOR_TOOLSET}\" " + "but should be \"Test Toolset,buildsystem=12\"!") +endif() diff --git a/Tests/RunCMake/GeneratorToolset/TestToolsetXcodeBuildSystemDefault12-result.txt b/Tests/RunCMake/GeneratorToolset/TestToolsetXcodeBuildSystemDefault12-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/TestToolsetXcodeBuildSystemDefault12-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/GeneratorToolset/TestToolsetXcodeBuildSystemDefault12-stderr.txt b/Tests/RunCMake/GeneratorToolset/TestToolsetXcodeBuildSystemDefault12-stderr.txt new file mode 100644 index 0000000..1d43537 --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/TestToolsetXcodeBuildSystemDefault12-stderr.txt @@ -0,0 +1,4 @@ +^CMake Error at TestToolsetXcodeBuildSystemDefault12.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/TestToolsetXcodeBuildSystemDefault12-stdout.txt b/Tests/RunCMake/GeneratorToolset/TestToolsetXcodeBuildSystemDefault12-stdout.txt new file mode 100644 index 0000000..df49a31 --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/TestToolsetXcodeBuildSystemDefault12-stdout.txt @@ -0,0 +1 @@ +CMAKE_XCODE_BUILD_SYSTEM='12' diff --git a/Tests/RunCMake/GeneratorToolset/TestToolsetXcodeBuildSystemDefault12.cmake b/Tests/RunCMake/GeneratorToolset/TestToolsetXcodeBuildSystemDefault12.cmake new file mode 100644 index 0000000..645bb19 --- /dev/null +++ b/Tests/RunCMake/GeneratorToolset/TestToolsetXcodeBuildSystemDefault12.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() diff --git a/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake b/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake index 70eaaeb..68de61c 100644 --- a/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake +++ b/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake @@ -10,6 +10,10 @@ run_cmake(XcodeAttributeGenex) run_cmake(XcodeAttributeGenexError) run_cmake(XcodeGenerateTopLevelProjectOnly) +if(XCODE_VERSION VERSION_GREATER_EQUAL 12) + run_cmake(XcodeDuplicateCustomCommand) +endif() + function(XcodeGenerateTopLevelProjectOnlyWithObjectLibrary) set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/XcodeGenerateTopLevelProjectOnlyWithObjectLibrary-build) run_cmake(XcodeGenerateTopLevelProjectOnlyWithObjectLibrary) diff --git a/Tests/RunCMake/XcodeProject/XcodeDuplicateCustomCommand-result.txt b/Tests/RunCMake/XcodeProject/XcodeDuplicateCustomCommand-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/XcodeProject/XcodeDuplicateCustomCommand-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/XcodeProject/XcodeDuplicateCustomCommand-stderr.txt b/Tests/RunCMake/XcodeProject/XcodeDuplicateCustomCommand-stderr.txt new file mode 100644 index 0000000..02af783 --- /dev/null +++ b/Tests/RunCMake/XcodeProject/XcodeDuplicateCustomCommand-stderr.txt @@ -0,0 +1,13 @@ +^CMake Error in CMakeLists.txt: + The custom command generating + + [^ +]*/Tests/RunCMake/XcodeProject/XcodeDuplicateCustomCommand-build/out.txt + + is attached to multiple targets: + + drive[0-9] + drive[0-9] + + but none of these is a common dependency of the other\(s\). This is not + allowed by the Xcode "new build system". diff --git a/Tests/RunCMake/XcodeProject/XcodeDuplicateCustomCommand.cmake b/Tests/RunCMake/XcodeProject/XcodeDuplicateCustomCommand.cmake new file mode 100644 index 0000000..3ef1312 --- /dev/null +++ b/Tests/RunCMake/XcodeProject/XcodeDuplicateCustomCommand.cmake @@ -0,0 +1,3 @@ +add_custom_command(OUTPUT out.txt COMMAND false) +add_custom_target(drive1 DEPENDS out.txt) +add_custom_target(drive2 DEPENDS out.txt) |