parent
498b916cdd
commit
d67cc4882d
@ -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
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
5
Help/release/dev/Xcode-add_custom_command-DEPFILE.rst
Normal file
5
Help/release/dev/Xcode-add_custom_command-DEPFILE.rst
Normal file
@ -0,0 +1,5 @@
|
||||
Xcode-add_custom_command-DEPFILE
|
||||
--------------------------------
|
||||
|
||||
* The :command:`add_custom_command` command gained ``DEPFILE`` support on
|
||||
:generator:`Xcode` generator.
|
@ -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();
|
||||
|
@ -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&) =
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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';
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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}
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user