summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2020-10-14 15:49:45 (GMT)
committerKitware Robot <kwrobot@kitware.com>2020-10-14 15:49:51 (GMT)
commitc5559597177eabd5620766e9dbc6f02a3b827ddb (patch)
tree8a5a7c2cef60393de936f7fbed63b99bb0139c3a /Source
parent609f2a14063c2bd7be416ac363257e616dce6ff2 (diff)
parent146e1e6ba14d964bf120635aca953cc76e5b2282 (diff)
downloadCMake-c5559597177eabd5620766e9dbc6f02a3b827ddb.zip
CMake-c5559597177eabd5620766e9dbc6f02a3b827ddb.tar.gz
CMake-c5559597177eabd5620766e9dbc6f02a3b827ddb.tar.bz2
Merge topic 'ninja-depfile-transformation'
146e1e6ba1 Ninja: Transform DEPFILEs with policy CMP0116 596439b1bb cmCustomCommandGenerator: Add option to transform depfile b2c14bc774 cmake -E: Add cmake_transform_depfile internal command 946adadd40 cmGccDepfileReader: Rework helper code Acked-by: Kitware Robot <kwrobot@kitware.com> Merge-request: !5325
Diffstat (limited to 'Source')
-rw-r--r--Source/CMakeLists.txt2
-rw-r--r--Source/LexerParser/cmGccDepfileLexer.cxx2
-rw-r--r--Source/LexerParser/cmGccDepfileLexer.in.l2
-rw-r--r--Source/cmCustomCommandGenerator.cxx73
-rw-r--r--Source/cmCustomCommandGenerator.h4
-rw-r--r--Source/cmGccDepfileLexerHelper.cxx33
-rw-r--r--Source/cmGccDepfileLexerHelper.h3
-rw-r--r--Source/cmGccDepfileReader.cxx9
-rw-r--r--Source/cmGccDepfileReader.h4
-rw-r--r--Source/cmGlobalGenerator.h6
-rw-r--r--Source/cmGlobalNinjaGenerator.h5
-rw-r--r--Source/cmLocalNinjaGenerator.cxx45
-rw-r--r--Source/cmPolicies.h5
-rw-r--r--Source/cmQtAutoMocUic.cxx8
-rw-r--r--Source/cmTransformDepfile.cxx114
-rw-r--r--Source/cmTransformDepfile.h14
-rw-r--r--Source/cmcmd.cxx18
17 files changed, 318 insertions, 29 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 1e16e17..2946022 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -439,6 +439,8 @@ set(SRCS
cmTest.h
cmTestGenerator.cxx
cmTestGenerator.h
+ cmTransformDepfile.cxx
+ cmTransformDepfile.h
cmUuid.cxx
cmUVHandlePtr.cxx
cmUVHandlePtr.h
diff --git a/Source/LexerParser/cmGccDepfileLexer.cxx b/Source/LexerParser/cmGccDepfileLexer.cxx
index a98969d..3630f4e 100644
--- a/Source/LexerParser/cmGccDepfileLexer.cxx
+++ b/Source/LexerParser/cmGccDepfileLexer.cxx
@@ -994,7 +994,7 @@ case 5:
YY_RULE_SETUP
{
// A line continuation ends the current file name.
- yyextra->newDependency();
+ yyextra->newRuleOrDependency();
}
YY_BREAK
case 6:
diff --git a/Source/LexerParser/cmGccDepfileLexer.in.l b/Source/LexerParser/cmGccDepfileLexer.in.l
index 08f8577..c83cb75 100644
--- a/Source/LexerParser/cmGccDepfileLexer.in.l
+++ b/Source/LexerParser/cmGccDepfileLexer.in.l
@@ -42,7 +42,7 @@ NEWLINE \r?\n
}
{WSPACE}*\\{NEWLINE} {
// A line continuation ends the current file name.
- yyextra->newDependency();
+ yyextra->newRuleOrDependency();
}
{NEWLINE} {
// A newline ends the current file name and the current rule.
diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx
index 60504ba..d8307f6 100644
--- a/Source/cmCustomCommandGenerator.cxx
+++ b/Source/cmCustomCommandGenerator.cxx
@@ -6,18 +6,22 @@
#include <memory>
#include <utility>
+#include <cm/optional>
#include <cmext/algorithm>
+#include "cmCryptoHash.h"
#include "cmCustomCommand.h"
#include "cmCustomCommandLines.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
+#include "cmGlobalGenerator.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmProperty.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmTransformDepfile.h"
namespace {
void AppendPaths(const std::vector<std::string>& inputs,
@@ -42,7 +46,8 @@ void AppendPaths(const std::vector<std::string>& inputs,
cmCustomCommandGenerator::cmCustomCommandGenerator(cmCustomCommand const& cc,
std::string config,
- cmLocalGenerator* lg)
+ cmLocalGenerator* lg,
+ bool transformDepfile)
: CC(cc)
, Config(std::move(config))
, LG(lg)
@@ -75,6 +80,36 @@ cmCustomCommandGenerator::cmCustomCommandGenerator(cmCustomCommand const& cc,
this->CommandLines.push_back(std::move(argv));
}
+ if (transformDepfile && !this->CommandLines.empty() &&
+ !cc.GetDepfile().empty() &&
+ this->LG->GetGlobalGenerator()->DepfileFormat()) {
+ cmCustomCommandLine argv;
+ argv.push_back(cmSystemTools::GetCMakeCommand());
+ argv.emplace_back("-E");
+ argv.emplace_back("cmake_transform_depfile");
+ switch (*this->LG->GetGlobalGenerator()->DepfileFormat()) {
+ case cmDepfileFormat::GccDepfile:
+ argv.emplace_back("gccdepfile");
+ break;
+ case cmDepfileFormat::VsTlog:
+ argv.emplace_back("vstlog");
+ break;
+ }
+ if (this->LG->GetCurrentBinaryDirectory() ==
+ this->LG->GetBinaryDirectory()) {
+ argv.emplace_back("./");
+ } else {
+ argv.push_back(cmStrCat(this->LG->MaybeConvertToRelativePath(
+ this->LG->GetBinaryDirectory(),
+ this->LG->GetCurrentBinaryDirectory()),
+ '/'));
+ }
+ argv.push_back(this->GetFullDepfile());
+ argv.push_back(this->GetInternalDepfile());
+
+ this->CommandLines.push_back(std::move(argv));
+ }
+
AppendPaths(cc.GetByproducts(), ge, this->LG, this->Config,
this->Byproducts);
AppendPaths(cc.GetDepends(), ge, this->LG, this->Config, this->Depends);
@@ -97,7 +132,7 @@ cmCustomCommandGenerator::cmCustomCommandGenerator(cmCustomCommand const& cc,
unsigned int cmCustomCommandGenerator::GetNumberOfCommands() const
{
- return static_cast<unsigned int>(this->CC.GetCommandLines().size());
+ return static_cast<unsigned int>(this->CommandLines.size());
}
void cmCustomCommandGenerator::FillEmulatorsWithArguments()
@@ -234,6 +269,40 @@ void cmCustomCommandGenerator::AppendArguments(unsigned int c,
}
}
+std::string cmCustomCommandGenerator::GetFullDepfile() const
+{
+ std::string depfile = this->CC.GetDepfile();
+ if (depfile.empty()) {
+ return "";
+ }
+
+ if (!cmSystemTools::FileIsFullPath(depfile)) {
+ depfile = cmStrCat(this->LG->GetCurrentBinaryDirectory(), '/', depfile);
+ }
+ return cmSystemTools::CollapseFullPath(depfile);
+}
+
+std::string cmCustomCommandGenerator::GetInternalDepfile() const
+{
+ std::string depfile = this->GetFullDepfile();
+ if (depfile.empty()) {
+ return "";
+ }
+
+ cmCryptoHash hash(cmCryptoHash::AlgoSHA256);
+ std::string extension;
+ switch (*this->LG->GetGlobalGenerator()->DepfileFormat()) {
+ case cmDepfileFormat::GccDepfile:
+ extension = ".d";
+ break;
+ case cmDepfileFormat::VsTlog:
+ extension = ".tlog";
+ break;
+ }
+ return cmStrCat(this->LG->GetBinaryDirectory(), "/CMakeFiles/d/",
+ hash.HashString(depfile), extension);
+}
+
const char* cmCustomCommandGenerator::GetComment() const
{
return this->CC.GetComment();
diff --git a/Source/cmCustomCommandGenerator.h b/Source/cmCustomCommandGenerator.h
index 412eba8..8b5259d 100644
--- a/Source/cmCustomCommandGenerator.h
+++ b/Source/cmCustomCommandGenerator.h
@@ -31,7 +31,7 @@ class cmCustomCommandGenerator
public:
cmCustomCommandGenerator(cmCustomCommand const& cc, std::string config,
- cmLocalGenerator* lg);
+ cmLocalGenerator* lg, bool transformDepfile = true);
cmCustomCommandGenerator(const cmCustomCommandGenerator&) = delete;
cmCustomCommandGenerator& operator=(const cmCustomCommandGenerator&) =
delete;
@@ -45,4 +45,6 @@ public:
std::vector<std::string> const& GetByproducts() const;
std::vector<std::string> const& GetDepends() const;
bool HasOnlyEmptyCommandLines() const;
+ std::string GetFullDepfile() const;
+ std::string GetInternalDepfile() const;
};
diff --git a/Source/cmGccDepfileLexerHelper.cxx b/Source/cmGccDepfileLexerHelper.cxx
index 957896f..c782bcd 100644
--- a/Source/cmGccDepfileLexerHelper.cxx
+++ b/Source/cmGccDepfileLexerHelper.cxx
@@ -27,23 +27,30 @@ bool cmGccDepfileLexerHelper::readFile(const char* filePath)
if (!file) {
return false;
}
- newEntry();
+ this->newEntry();
yyscan_t scanner;
cmGccDepfile_yylex_init(&scanner);
cmGccDepfile_yyset_extra(this, scanner);
cmGccDepfile_yyrestart(file, scanner);
cmGccDepfile_yylex(scanner);
cmGccDepfile_yylex_destroy(scanner);
- sanitizeContent();
+ this->sanitizeContent();
fclose(file);
- return true;
+ return this->HelperState != State::Failed;
}
void cmGccDepfileLexerHelper::newEntry()
{
+ if (this->HelperState == State::Rule && !this->Content.empty()) {
+ if (!this->Content.back().rules.empty() &&
+ !this->Content.back().rules.back().empty()) {
+ this->HelperState = State::Failed;
+ }
+ return;
+ }
this->HelperState = State::Rule;
this->Content.emplace_back();
- newRule();
+ this->newRule();
}
void cmGccDepfileLexerHelper::newRule()
@@ -56,20 +63,22 @@ void cmGccDepfileLexerHelper::newRule()
void cmGccDepfileLexerHelper::newDependency()
{
- // printf("NEW DEP\n");
+ if (this->HelperState == State::Failed) {
+ return;
+ }
this->HelperState = State::Dependency;
- if (this->Content.back().paths.empty() ||
- !this->Content.back().paths.back().empty()) {
- this->Content.back().paths.emplace_back();
+ auto& entry = this->Content.back();
+ if (entry.paths.empty() || !entry.paths.back().empty()) {
+ entry.paths.emplace_back();
}
}
void cmGccDepfileLexerHelper::newRuleOrDependency()
{
if (this->HelperState == State::Rule) {
- newRule();
- } else {
- newDependency();
+ this->newRule();
+ } else if (this->HelperState == State::Dependency) {
+ this->newDependency();
}
}
@@ -93,6 +102,8 @@ void cmGccDepfileLexerHelper::addToCurrentPath(const char* s)
}
dst = &dep->paths.back();
} break;
+ case State::Failed:
+ return;
}
dst->append(s);
}
diff --git a/Source/cmGccDepfileLexerHelper.h b/Source/cmGccDepfileLexerHelper.h
index 07ca61d..91132f5 100644
--- a/Source/cmGccDepfileLexerHelper.h
+++ b/Source/cmGccDepfileLexerHelper.h
@@ -29,7 +29,8 @@ private:
enum class State
{
Rule,
- Dependency
+ Dependency,
+ Failed,
};
State HelperState = State::Rule;
};
diff --git a/Source/cmGccDepfileReader.cxx b/Source/cmGccDepfileReader.cxx
index 9d70ede..eb3511a 100644
--- a/Source/cmGccDepfileReader.cxx
+++ b/Source/cmGccDepfileReader.cxx
@@ -5,14 +5,15 @@
#include <type_traits>
#include <utility>
+#include <cm/optional>
+
#include "cmGccDepfileLexerHelper.h"
-cmGccDepfileContent cmReadGccDepfile(const char* filePath)
+cm::optional<cmGccDepfileContent> cmReadGccDepfile(const char* filePath)
{
- cmGccDepfileContent result;
cmGccDepfileLexerHelper helper;
if (helper.readFile(filePath)) {
- result = std::move(helper).extractContent();
+ return cm::make_optional(std::move(helper).extractContent());
}
- return result;
+ return cm::nullopt;
}
diff --git a/Source/cmGccDepfileReader.h b/Source/cmGccDepfileReader.h
index 395dd77..59ed7fd 100644
--- a/Source/cmGccDepfileReader.h
+++ b/Source/cmGccDepfileReader.h
@@ -2,6 +2,8 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#pragma once
+#include <cm/optional>
+
#include "cmGccDepfileReaderTypes.h"
-cmGccDepfileContent cmReadGccDepfile(const char* filePath);
+cm::optional<cmGccDepfileContent> cmReadGccDepfile(const char* filePath);
diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h
index b532a43..de5eba7 100644
--- a/Source/cmGlobalGenerator.h
+++ b/Source/cmGlobalGenerator.h
@@ -14,6 +14,7 @@
#include <utility>
#include <vector>
+#include <cm/optional>
#include <cmext/algorithm>
#include "cm_codecvt.hxx"
@@ -26,6 +27,7 @@
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTargetDepend.h"
+#include "cmTransformDepfile.h"
#if !defined(CMAKE_BOOTSTRAP)
# include <cm3p/json/value.h>
@@ -452,6 +454,10 @@ public:
virtual bool ShouldStripResourcePath(cmMakefile*) const;
virtual bool SupportsCustomCommandDepfile() const { return false; }
+ virtual cm::optional<cmDepfileFormat> DepfileFormat() const
+ {
+ return cm::nullopt;
+ }
std::string GetSharedLibFlagsForLanguage(std::string const& lang) const;
diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h
index f6e7633..8d6ebdc 100644
--- a/Source/cmGlobalNinjaGenerator.h
+++ b/Source/cmGlobalNinjaGenerator.h
@@ -24,6 +24,7 @@
#include "cmNinjaTypes.h"
#include "cmPolicies.h"
#include "cmStringAlgorithms.h"
+#include "cmTransformDepfile.h"
class cmCustomCommand;
class cmGeneratorTarget;
@@ -210,6 +211,10 @@ public:
const char* GetCleanTargetName() const override { return "clean"; }
bool SupportsCustomCommandDepfile() const override { return true; }
+ cm::optional<cmDepfileFormat> DepfileFormat() const override
+ {
+ return cmDepfileFormat::GccDepfile;
+ }
virtual cmGeneratedFileStream* GetImplFileStream(
const std::string& /*config*/) const
diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx
index ad782ee..ce85320 100644
--- a/Source/cmLocalNinjaGenerator.cxx
+++ b/Source/cmLocalNinjaGenerator.cxx
@@ -22,7 +22,9 @@
#include "cmGlobalNinjaGenerator.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmNinjaTargetGenerator.h"
+#include "cmPolicies.h"
#include "cmProperty.h"
#include "cmRulePlaceholderExpander.h"
#include "cmSourceFile.h"
@@ -573,7 +575,20 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement(
return;
}
- cmCustomCommandGenerator ccg(*cc, config, this);
+ bool transformDepfile = false;
+ auto cmp0116 = this->GetPolicyStatus(cmPolicies::CMP0116);
+ switch (cmp0116) {
+ case cmPolicies::OLD:
+ case cmPolicies::WARN:
+ break;
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::NEW:
+ transformDepfile = true;
+ break;
+ }
+
+ cmCustomCommandGenerator ccg(*cc, config, this, transformDepfile);
const std::vector<std::string>& outputs = ccg.GetOutputs();
const std::vector<std::string>& byproducts = ccg.GetByproducts();
@@ -623,10 +638,36 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement(
cmCryptoHash hash(cmCryptoHash::AlgoSHA256);
customStep += hash.HashString(ninjaOutputs[0]).substr(0, 7);
+ std::string depfile = cc->GetDepfile();
+ if (!depfile.empty()) {
+ switch (cmp0116) {
+ case cmPolicies::WARN:
+ if (this->GetCurrentBinaryDirectory() !=
+ this->GetBinaryDirectory() ||
+ this->Makefile->PolicyOptionalWarningEnabled(
+ "CMAKE_POLICY_WARNING_CMP0116")) {
+ this->GetCMakeInstance()->IssueMessage(
+ MessageType::AUTHOR_WARNING,
+ cmPolicies::GetPolicyWarning(cmPolicies::CMP0116),
+ cc->GetBacktrace());
+ }
+ CM_FALLTHROUGH;
+ case cmPolicies::OLD:
+ break;
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::NEW:
+ cmSystemTools::MakeDirectory(
+ cmStrCat(this->GetBinaryDirectory(), "/CMakeFiles/d"));
+ depfile = ccg.GetInternalDepfile();
+ break;
+ }
+ }
+
gg->WriteCustomCommandBuild(
this->BuildCommandLine(cmdLines, customStep),
this->ConstructComment(ccg), "Custom command for " + ninjaOutputs[0],
- cc->GetDepfile(), cc->GetJobPool(), cc->GetUsesTerminal(),
+ depfile, cc->GetJobPool(), cc->GetUsesTerminal(),
/*restat*/ !symbolic || !byproducts.empty(), ninjaOutputs, config,
ninjaDeps, orderOnlyDeps);
}
diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h
index f9f7d0e..99bac98 100644
--- a/Source/cmPolicies.h
+++ b/Source/cmPolicies.h
@@ -342,7 +342,10 @@ class cmMakefile;
"ExternalProject step targets fully adopt their steps.", 3, 19, 0, \
cmPolicies::WARN) \
SELECT(POLICY, CMP0115, "Source file extensions must be explicit.", 3, 20, \
- 0, cmPolicies::WARN)
+ 0, cmPolicies::WARN) \
+ SELECT(POLICY, CMP0116, \
+ "Ninja generators transform DEPFILEs from add_custom_command().", 3, \
+ 20, 0, cmPolicies::WARN)
#define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
#define CM_FOR_EACH_POLICY_ID(POLICY) \
diff --git a/Source/cmQtAutoMocUic.cxx b/Source/cmQtAutoMocUic.cxx
index 9cb172b..b27bb88 100644
--- a/Source/cmQtAutoMocUic.cxx
+++ b/Source/cmQtAutoMocUic.cxx
@@ -15,6 +15,7 @@
#include <vector>
#include <cm/memory>
+#include <cm/optional>
#include <cm/string_view>
#include <cmext/algorithm>
@@ -26,7 +27,6 @@
#include "cmCryptoHash.h"
#include "cmFileTime.h"
#include "cmGccDepfileReader.h"
-#include "cmGccDepfileReaderTypes.h"
#include "cmGeneratedFileStream.h"
#include "cmQtAutoGen.h"
#include "cmQtAutoGenerator.h"
@@ -2841,14 +2841,14 @@ bool cmQtAutoMocUicT::CreateDirectories()
std::vector<std::string> cmQtAutoMocUicT::dependenciesFromDepFile(
const char* filePath)
{
- cmGccDepfileContent content = cmReadGccDepfile(filePath);
- if (content.empty()) {
+ auto const content = cmReadGccDepfile(filePath);
+ if (!content || content->empty()) {
return {};
}
// Moc outputs a depfile with exactly one rule.
// Discard the rule and return the dependencies.
- return content.front().paths;
+ return content->front().paths;
}
void cmQtAutoMocUicT::Abort(bool error)
diff --git a/Source/cmTransformDepfile.cxx b/Source/cmTransformDepfile.cxx
new file mode 100644
index 0000000..e1f8753
--- /dev/null
+++ b/Source/cmTransformDepfile.cxx
@@ -0,0 +1,114 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmTransformDepfile.h"
+
+#include <string>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+#include <cm/optional>
+
+#include "cmsys/FStream.hxx"
+
+#include "cmGccDepfileReader.h"
+#include "cmGccDepfileReaderTypes.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+
+namespace {
+void WriteFilenameGcc(cmsys::ofstream& fout, const std::string& filename)
+{
+ for (auto c : filename) {
+ switch (c) {
+ case ' ':
+ fout << "\\ ";
+ break;
+ case '\\':
+ fout << "\\\\";
+ break;
+ default:
+ fout << c;
+ break;
+ }
+ }
+}
+
+void WriteGccDepfile(cmsys::ofstream& fout, const cmGccDepfileContent& content)
+{
+ for (auto const& dep : content) {
+ bool first = true;
+ for (auto const& rule : dep.rules) {
+ if (!first) {
+ fout << " \\\n ";
+ }
+ first = false;
+ WriteFilenameGcc(fout, rule);
+ }
+ fout << ':';
+ for (auto const& path : dep.paths) {
+ fout << " \\\n " << path;
+ }
+ fout << '\n';
+ }
+}
+
+void WriteVsTlog(cmsys::ofstream& fout, const cmGccDepfileContent& content)
+{
+ for (auto const& dep : content) {
+ fout << '^';
+ bool first = true;
+ for (auto const& rule : dep.rules) {
+ if (!first) {
+ fout << '|';
+ }
+ first = false;
+ fout << cmSystemTools::ConvertToOutputPath(rule);
+ }
+ fout << "\r\n";
+ for (auto const& path : dep.paths) {
+ fout << cmSystemTools::ConvertToOutputPath(path) << "\r\n";
+ }
+ }
+}
+}
+
+bool cmTransformDepfile(cmDepfileFormat format, const std::string& prefix,
+ const std::string& infile, const std::string& outfile)
+{
+ cmGccDepfileContent content;
+ if (cmSystemTools::FileExists(infile)) {
+ auto result = cmReadGccDepfile(infile.c_str());
+ if (!result) {
+ return false;
+ }
+ content = *std::move(result);
+ }
+
+ for (auto& dep : content) {
+ for (auto& rule : dep.rules) {
+ if (!cmSystemTools::FileIsFullPath(rule)) {
+ rule = cmStrCat(prefix, rule);
+ }
+ }
+ for (auto& path : dep.paths) {
+ if (!cmSystemTools::FileIsFullPath(path)) {
+ path = cmStrCat(prefix, path);
+ }
+ }
+ }
+
+ cmsys::ofstream fout(outfile.c_str());
+ if (!fout) {
+ return false;
+ }
+ switch (format) {
+ case cmDepfileFormat::GccDepfile:
+ WriteGccDepfile(fout, content);
+ break;
+ case cmDepfileFormat::VsTlog:
+ WriteVsTlog(fout, content);
+ break;
+ }
+ return true;
+}
diff --git a/Source/cmTransformDepfile.h b/Source/cmTransformDepfile.h
new file mode 100644
index 0000000..792c1aa
--- /dev/null
+++ b/Source/cmTransformDepfile.h
@@ -0,0 +1,14 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+#include <string>
+
+enum class cmDepfileFormat
+{
+ GccDepfile,
+ VsTlog,
+};
+
+bool cmTransformDepfile(cmDepfileFormat format, const std::string& prefix,
+ const std::string& infile, const std::string& outfile);
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index 15d2fd1..0bdc6fa 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -19,6 +19,7 @@
#include "cmStateSnapshot.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmTransformDepfile.h"
#include "cmUVProcessChain.h"
#include "cmUtils.hxx"
#include "cmVersion.h"
@@ -1426,6 +1427,23 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args)
return cmcmd::WindowsCEEnvironment("9.0", args[2]);
}
#endif
+
+ // Internal depfile transformation
+ if (args[1] == "cmake_transform_depfile" && args.size() == 6) {
+ auto format = cmDepfileFormat::GccDepfile;
+ if (args[2] == "gccdepfile") {
+ format = cmDepfileFormat::GccDepfile;
+ } else if (args[2] == "vstlog") {
+ format = cmDepfileFormat::VsTlog;
+ } else {
+ return 1;
+ }
+ std::string prefix = args[3];
+ if (prefix == "./") {
+ prefix.clear();
+ }
+ return cmTransformDepfile(format, prefix, args[4], args[5]) ? 0 : 1;
+ }
}
::CMakeCommandUsage(args[0].c_str());