diff options
author | Brad King <brad.king@kitware.com> | 2021-04-16 15:42:16 (GMT) |
---|---|---|
committer | Kitware Robot <kwrobot@kitware.com> | 2021-04-16 15:42:23 (GMT) |
commit | acace43852953b10eada5ee80dfb890d4e101b62 (patch) | |
tree | 2211f6b396ef077d7e4340d035754f521191a90e | |
parent | 09dee5f9baf836d27a437b0efc3b7fa73b3ecc10 (diff) | |
parent | d67cc4882d54a18abbd5d01365ce1fc72d702a0e (diff) | |
download | CMake-acace43852953b10eada5ee80dfb890d4e101b62.zip CMake-acace43852953b10eada5ee80dfb890d4e101b62.tar.gz CMake-acace43852953b10eada5ee80dfb890d4e101b62.tar.bz2 |
Merge topic 'Xcode-add_custom_command-DEPFILE'
d67cc4882d Xcode: Add support of DEPFILE for add_custom_command
Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !6006
-rw-r--r-- | Help/command/add_custom_command.rst | 30 | ||||
-rw-r--r-- | Help/release/dev/Xcode-add_custom_command-DEPFILE.rst | 5 | ||||
-rw-r--r-- | Source/cmCustomCommandGenerator.cxx | 30 | ||||
-rw-r--r-- | Source/cmCustomCommandGenerator.h | 13 | ||||
-rw-r--r-- | Source/cmGlobalXCodeGenerator.cxx | 33 | ||||
-rw-r--r-- | Source/cmGlobalXCodeGenerator.h | 13 | ||||
-rw-r--r-- | Source/cmTransformDepfile.cxx | 14 | ||||
-rw-r--r-- | Tests/RunCMake/BuildDepends/RunCMakeTest.cmake | 3 | ||||
-rw-r--r-- | Tests/RunCMake/CMakeLists.txt | 1 |
9 files changed, 115 insertions, 27 deletions
diff --git a/Help/command/add_custom_command.rst b/Help/command/add_custom_command.rst index b6ff0ea..c0ff81a 100644 --- a/Help/command/add_custom_command.rst +++ b/Help/command/add_custom_command.rst @@ -271,32 +271,42 @@ The options are: ``DEPFILE`` .. versionadded:: 3.7 - Specify a ``.d`` depfile for the :generator:`Ninja` generator and - :ref:`Makefile Generators`. The depfile may use "generator expressions" with - the syntax ``$<...>``. See the :manual:`generator-expressions(7) - <cmake-generator-expressions(7)>` manual for available expressions. - A ``.d`` file holds dependencies usually emitted by the custom - command itself. - Using ``DEPFILE`` with other generators than :generator:`Ninja` or - :ref:`Makefile Generators` is an error. + Specify a ``.d`` depfile for the :generator:`Ninja`, :generator:`Xcode` and + :ref:`Makefile <Makefile Generators>` generators. The depfile may use + "generator expressions" with the syntax ``$<...>``. See the + :manual:`generator-expressions(7) <cmake-generator-expressions(7)>` manual + for available expressions. A ``.d`` file holds dependencies usually emitted + by the custom command itself. + + Using ``DEPFILE`` with other generators than :generator:`Ninja`, + :generator:`Xcode` or :ref:`Makefile <Makefile Generators>` is an error. .. versionadded:: 3.20 Added the support of :ref:`Makefile Generators`. .. versionadded:: 3.21 - Added the support of :manual:`generator expressions <cmake-generator-expressions(7)>`. + Added the support of :generator:`Xcode` generator and + :manual:`generator expressions <cmake-generator-expressions(7)>`. If the ``DEPFILE`` argument is relative, it should be relative to :variable:`CMAKE_CURRENT_BINARY_DIR`, and any relative paths inside the ``DEPFILE`` should also be relative to :variable:`CMAKE_CURRENT_BINARY_DIR` (see policy :policy:`CMP0116`. This policy is always ``NEW`` for - :ref:`Makefile Generators`). + :ref:`Makefile <Makefile Generators>` and :generator:`Xcode` generators). .. note:: For :ref:`Makefile Generators`, this option cannot be specified at the same time as ``IMPLICIT_DEPENDS`` option. + .. note:: + + For the :generator:`Xcode` generator, this option requires that the + :ref:`Xcode Build System Selection` uses the ``buildsystem=12`` variant + or higher. This is the default when using Xcode 12 or above. + The :variable:`CMAKE_XCODE_BUILD_SYSTEM` variable indicates which variant + of the Xcode build system is used. + Examples: Generating Files ^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/Help/release/dev/Xcode-add_custom_command-DEPFILE.rst b/Help/release/dev/Xcode-add_custom_command-DEPFILE.rst new file mode 100644 index 0000000..4c4d48c --- /dev/null +++ b/Help/release/dev/Xcode-add_custom_command-DEPFILE.rst @@ -0,0 +1,5 @@ +Xcode-add_custom_command-DEPFILE +-------------------------------- + +* The :command:`add_custom_command` command gained ``DEPFILE`` support on + :generator:`Xcode` generator. diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx index 4705443..7659792 100644 --- a/Source/cmCustomCommandGenerator.cxx +++ b/Source/cmCustomCommandGenerator.cxx @@ -151,7 +151,9 @@ std::string EvaluateDepfile(std::string const& path, cmCustomCommandGenerator::cmCustomCommandGenerator( cmCustomCommand const& cc, std::string config, cmLocalGenerator* lg, - bool transformDepfile, cm::optional<std::string> crossConfig) + bool transformDepfile, cm::optional<std::string> crossConfig, + std::function<std::string(const std::string&, const std::string&)> + computeInternalDepfile) : CC(&cc) , OutputConfig(crossConfig ? *crossConfig : config) , CommandConfig(std::move(config)) @@ -159,7 +161,15 @@ cmCustomCommandGenerator::cmCustomCommandGenerator( , OldStyle(cc.GetEscapeOldStyle()) , MakeVars(cc.GetEscapeAllowMakeVars()) , EmulatorsWithArguments(cc.GetCommandLines().size()) + , ComputeInternalDepfile(std::move(computeInternalDepfile)) { + if (!this->ComputeInternalDepfile) { + this->ComputeInternalDepfile = + [this](const std::string& cfg, const std::string& file) -> std::string { + return this->GetInternalDepfileName(cfg, file); + }; + } + cmGeneratorExpression ge(cc.GetBacktrace()); const cmCustomCommandLines& cmdlines = this->CC->GetCommandLines(); @@ -413,13 +423,9 @@ std::string cmCustomCommandGenerator::GetFullDepfile() const return cmSystemTools::CollapseFullPath(depfile); } -std::string cmCustomCommandGenerator::GetInternalDepfile() const +std::string cmCustomCommandGenerator::GetInternalDepfileName( + const std::string& /*config*/, const std::string& depfile) { - std::string depfile = this->GetFullDepfile(); - if (depfile.empty()) { - return ""; - } - cmCryptoHash hash(cmCryptoHash::AlgoSHA256); std::string extension; switch (*this->LG->GetGlobalGenerator()->DepfileFormat()) { @@ -434,6 +440,16 @@ std::string cmCustomCommandGenerator::GetInternalDepfile() const hash.HashString(depfile), extension); } +std::string cmCustomCommandGenerator::GetInternalDepfile() const +{ + std::string depfile = this->GetFullDepfile(); + if (depfile.empty()) { + return ""; + } + + return this->ComputeInternalDepfile(this->OutputConfig, depfile); +} + const char* cmCustomCommandGenerator::GetComment() const { return this->CC->GetComment(); diff --git a/Source/cmCustomCommandGenerator.h b/Source/cmCustomCommandGenerator.h index 53e5573..e70909a 100644 --- a/Source/cmCustomCommandGenerator.h +++ b/Source/cmCustomCommandGenerator.h @@ -4,6 +4,7 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include <functional> #include <set> #include <string> #include <utility> @@ -19,6 +20,8 @@ class cmLocalGenerator; class cmCustomCommandGenerator { + std::string GetInternalDepfileName(const std::string&, const std::string&); + cmCustomCommand const* CC; std::string OutputConfig; std::string CommandConfig; @@ -32,15 +35,19 @@ class cmCustomCommandGenerator std::vector<std::string> Depends; std::string WorkingDirectory; std::set<BT<std::pair<std::string, bool>>> Utilities; + std::function<std::string(const std::string&, const std::string&)> + ComputeInternalDepfile; void FillEmulatorsWithArguments(); std::vector<std::string> GetCrossCompilingEmulator(unsigned int c) const; const char* GetArgv0Location(unsigned int c) const; public: - cmCustomCommandGenerator(cmCustomCommand const& cc, std::string config, - cmLocalGenerator* lg, bool transformDepfile = true, - cm::optional<std::string> crossConfig = {}); + cmCustomCommandGenerator( + cmCustomCommand const& cc, std::string config, cmLocalGenerator* lg, + bool transformDepfile = true, cm::optional<std::string> crossConfig = {}, + std::function<std::string(const std::string&, const std::string&)> + computeInternalDepfile = {}); cmCustomCommandGenerator(const cmCustomCommandGenerator&) = delete; cmCustomCommandGenerator(cmCustomCommandGenerator&&) = default; cmCustomCommandGenerator& operator=(const cmCustomCommandGenerator&) = diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 7dd1704..dc3d3f2 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -17,6 +17,7 @@ #include "cmsys/RegularExpression.hxx" +#include "cmCMakePath.h" #include "cmComputeLinkInformation.h" #include "cmCryptoHash.h" #include "cmCustomCommand.h" @@ -1864,9 +1865,20 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateRunScriptBuildPhase( std::set<std::string> allConfigInputs; std::set<std::string> allConfigOutputs; + cmXCodeObject* buildPhase = + this->CreateObject(cmXCodeObject::PBXShellScriptBuildPhase, + cmStrCat(gt->GetName(), ':', sf->GetFullPath())); + + auto depfilesDirectory = cmStrCat( + gt->GetLocalGenerator()->GetCurrentBinaryDirectory(), "/CMakeFiles/d/"); + auto depfilesPrefix = cmStrCat(depfilesDirectory, buildPhase->GetId(), "."); + std::string shellScript = "set -e\n"; for (std::string const& configName : this->CurrentConfigurationTypes) { - cmCustomCommandGenerator ccg(cc, configName, this->CurrentLocalGenerator); + cmCustomCommandGenerator ccg( + cc, configName, this->CurrentLocalGenerator, true, {}, + [&depfilesPrefix](const std::string& config, const std::string&) + -> std::string { return cmStrCat(depfilesPrefix, config, ".d"); }); std::vector<std::string> realDepends; realDepends.reserve(ccg.GetDepends().size()); for (auto const& d : ccg.GetDepends()) { @@ -1886,9 +1898,22 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateRunScriptBuildPhase( "\"; then :\n", this->ConstructScript(ccg), "fi\n"); } - cmXCodeObject* buildPhase = - this->CreateObject(cmXCodeObject::PBXShellScriptBuildPhase, - cmStrCat(gt->GetName(), ':', sf->GetFullPath())); + if (!cc.GetDepfile().empty()) { + buildPhase->AddAttribute( + "dependencyFile", + this->CreateString(cmStrCat(depfilesDirectory, buildPhase->GetId(), + ".$(CONFIGURATION).d"))); + // to avoid spurious errors during first build, create empty dependency + // files + cmSystemTools::MakeDirectory(depfilesDirectory); + for (std::string const& configName : this->CurrentConfigurationTypes) { + auto file = cmStrCat(depfilesPrefix, configName, ".d"); + if (!cmSystemTools::FileExists(file)) { + cmSystemTools::Touch(file, true); + } + } + } + buildPhase->AddAttribute("buildActionMask", this->CreateString("2147483647")); cmXCodeObject* buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST); diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h index 1ab56e2..2406472 100644 --- a/Source/cmGlobalXCodeGenerator.h +++ b/Source/cmGlobalXCodeGenerator.h @@ -14,6 +14,7 @@ #include <cm/string_view> #include "cmGlobalGenerator.h" +#include "cmTransformDepfile.h" #include "cmXCodeObject.h" class cmCustomCommand; @@ -111,6 +112,18 @@ public: bool ShouldStripResourcePath(cmMakefile*) const override; + /** + * Used to determine if this generator supports DEPFILE option. + */ + bool SupportsCustomCommandDepfile() const override + { + return this->XcodeBuildSystem >= BuildSystem::Twelve; + } + virtual cm::optional<cmDepfileFormat> DepfileFormat() const override + { + return cmDepfileFormat::GccDepfile; + } + bool SetSystemName(std::string const& s, cmMakefile* mf) override; bool SetGeneratorToolset(std::string const& ts, bool build, cmMakefile* mf) override; diff --git a/Source/cmTransformDepfile.cxx b/Source/cmTransformDepfile.cxx index 78aa4b2..b693582 100644 --- a/Source/cmTransformDepfile.cxx +++ b/Source/cmTransformDepfile.cxx @@ -2,6 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmTransformDepfile.h" +#include <functional> #include <string> #include <type_traits> #include <utility> @@ -13,6 +14,7 @@ #include "cmGccDepfileReader.h" #include "cmGccDepfileReaderTypes.h" +#include "cmGlobalGenerator.h" #include "cmLocalGenerator.h" #include "cmSystemTools.h" @@ -38,6 +40,14 @@ void WriteGccDepfile(cmsys::ofstream& fout, const cmLocalGenerator& lg, const cmGccDepfileContent& content) { const auto& binDir = lg.GetBinaryDirectory(); + std::function<std::string(const std::string&)> formatPath = + [&lg, &binDir](const std::string& path) -> std::string { + return lg.MaybeConvertToRelativePath(binDir, path); + }; + if (lg.GetGlobalGenerator()->GetName() == "Xcode") { + // full paths must be preserved for Xcode compliance + formatPath = [](const std::string& path) -> std::string { return path; }; + } for (auto const& dep : content) { bool first = true; @@ -46,12 +56,12 @@ void WriteGccDepfile(cmsys::ofstream& fout, const cmLocalGenerator& lg, fout << " \\\n "; } first = false; - WriteFilenameGcc(fout, lg.MaybeConvertToRelativePath(binDir, rule)); + WriteFilenameGcc(fout, formatPath(rule)); } fout << ':'; for (auto const& path : dep.paths) { fout << " \\\n "; - WriteFilenameGcc(fout, lg.MaybeConvertToRelativePath(binDir, path)); + WriteFilenameGcc(fout, formatPath(path)); } fout << '\n'; } diff --git a/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake b/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake index 6232634..a6e08da 100644 --- a/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake +++ b/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake @@ -155,7 +155,8 @@ if (RunCMake_GENERATOR MATCHES "Makefiles") run_cmake(CustomCommandDependencies-BadArgs) endif() -if(RunCMake_GENERATOR MATCHES "Make|Ninja") +if(RunCMake_GENERATOR MATCHES "Make|Ninja" OR + (RunCMake_GENERATOR STREQUAL "Xcode" AND CMAKE_XCODE_BUILD_SYSTEM GREATER_EQUAL "12")) unset(run_BuildDepends_skip_step_3) run_BuildDepends(CustomCommandDepfile) set(run_BuildDepends_skip_step_3 1) diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 5f23c05..be59a55 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -222,6 +222,7 @@ endif() add_RunCMake_test(BuildDepends -DMSVC_VERSION=${MSVC_VERSION} + -DCMAKE_XCODE_BUILD_SYSTEM=${CMAKE_XCODE_BUILD_SYSTEM} -DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID} -DCMake_TEST_BuildDepends_GNU_AS=${CMake_TEST_BuildDepends_GNU_AS} ) |