mirror of
https://github.com/Kitware/CMake.git
synced 2025-10-20 04:24:36 +08:00
Makefiles: Add support of DEPFILE for add_custom_command
Issue: #20286 Fixes: #21415
This commit is contained in:
@@ -201,6 +201,10 @@ The options are:
|
|||||||
Note that the ``IMPLICIT_DEPENDS`` option is currently supported
|
Note that the ``IMPLICIT_DEPENDS`` option is currently supported
|
||||||
only for Makefile generators and will be ignored by other generators.
|
only for Makefile generators and will be ignored by other generators.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
This option cannot be specified at the same time as ``DEPFILE`` option.
|
||||||
|
|
||||||
``JOB_POOL``
|
``JOB_POOL``
|
||||||
.. versionadded:: 3.15
|
.. versionadded:: 3.15
|
||||||
|
|
||||||
@@ -263,15 +267,26 @@ The options are:
|
|||||||
``DEPFILE``
|
``DEPFILE``
|
||||||
.. versionadded:: 3.7
|
.. versionadded:: 3.7
|
||||||
|
|
||||||
Specify a ``.d`` depfile for the :generator:`Ninja` generator.
|
Specify a ``.d`` depfile for the :generator:`Ninja` generator and
|
||||||
|
:ref:`Makefile Generators`.
|
||||||
A ``.d`` file holds dependencies usually emitted by the custom
|
A ``.d`` file holds dependencies usually emitted by the custom
|
||||||
command itself.
|
command itself.
|
||||||
Using ``DEPFILE`` with other generators than Ninja is an error.
|
Using ``DEPFILE`` with other generators than :generator:`Ninja` or
|
||||||
|
:ref:`Makefile Generators` is an error.
|
||||||
|
|
||||||
|
.. versionadded:: 3.20
|
||||||
|
Added the support of :ref:`Makefile Generators`.
|
||||||
|
|
||||||
If the ``DEPFILE`` argument is relative, it should be relative to
|
If the ``DEPFILE`` argument is relative, it should be relative to
|
||||||
:variable:`CMAKE_CURRENT_BINARY_DIR`, and any relative paths inside the
|
:variable:`CMAKE_CURRENT_BINARY_DIR`, and any relative paths inside the
|
||||||
``DEPFILE`` should also be relative to :variable:`CMAKE_CURRENT_BINARY_DIR`
|
``DEPFILE`` should also be relative to :variable:`CMAKE_CURRENT_BINARY_DIR`
|
||||||
(see policy :policy:`CMP0116`.)
|
(see policy :policy:`CMP0116`. This policy is always ``NEW`` for
|
||||||
|
:ref:`Makefile Generators`).
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
For :ref:`Makefile Generators`, this option cannot be specified at the
|
||||||
|
same time as ``IMPLICIT_DEPENDS`` option.
|
||||||
|
|
||||||
Examples: Generating Files
|
Examples: Generating Files
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
5
Help/release/dev/makefile-depfile.rst
Normal file
5
Help/release/dev/makefile-depfile.rst
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
makefile-depfile
|
||||||
|
----------------
|
||||||
|
|
||||||
|
* The :command:`add_custom_command` command gained ``DEPFILE`` support on
|
||||||
|
:ref:`Makefile Generators`.
|
@@ -296,6 +296,12 @@ bool cmAddCustomCommandCommand(std::vector<std::string> const& args,
|
|||||||
status.SetError("given APPEND option with no OUTPUT.");
|
status.SetError("given APPEND option with no OUTPUT.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (!implicit_depends.empty() && !depfile.empty() &&
|
||||||
|
mf.GetGlobalGenerator()->GetName() != "Ninja") {
|
||||||
|
// Makefiles generators does not support both at the same time
|
||||||
|
status.SetError("IMPLICIT_DEPENDS and DEPFILE can not both be specified.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Check for an append request.
|
// Check for an append request.
|
||||||
if (append) {
|
if (append) {
|
||||||
|
@@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
#include "cmFileTime.h"
|
#include "cmFileTime.h"
|
||||||
#include "cmGccDepfileReader.h"
|
#include "cmGccDepfileReader.h"
|
||||||
|
#include "cmGccDepfileReaderTypes.h"
|
||||||
#include "cmGlobalUnixMakefileGenerator3.h"
|
#include "cmGlobalUnixMakefileGenerator3.h"
|
||||||
#include "cmLocalUnixMakefileGenerator3.h"
|
#include "cmLocalUnixMakefileGenerator3.h"
|
||||||
#include "cmStringAlgorithms.h"
|
#include "cmStringAlgorithms.h"
|
||||||
@@ -86,7 +87,7 @@ bool cmDependsCompiler::CheckDependencies(
|
|||||||
if (!forceReadDeps) {
|
if (!forceReadDeps) {
|
||||||
depFileTime.Load(depFile);
|
depFileTime.Load(depFile);
|
||||||
}
|
}
|
||||||
if (forceReadDeps || depFileTime.Newer(internalDepFileTime)) {
|
if (forceReadDeps || depFileTime.Compare(internalDepFileTime) >= 0) {
|
||||||
status = false;
|
status = false;
|
||||||
if (this->Verbose) {
|
if (this->Verbose) {
|
||||||
cmSystemTools::Stdout(cmStrCat("Dependencies file \"", depFile,
|
cmSystemTools::Stdout(cmStrCat("Dependencies file \"", depFile,
|
||||||
@@ -95,59 +96,92 @@ bool cmDependsCompiler::CheckDependencies(
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> depends;
|
std::vector<std::string> depends;
|
||||||
if (format == "msvc"_s) {
|
if (format == "custom"_s) {
|
||||||
cmsys::ifstream fin(depFile.c_str());
|
std::string prefix;
|
||||||
if (!fin) {
|
if (this->LocalGenerator->GetCurrentBinaryDirectory() !=
|
||||||
continue;
|
this->LocalGenerator->GetBinaryDirectory()) {
|
||||||
|
prefix =
|
||||||
|
cmStrCat(this->LocalGenerator->MaybeConvertToRelativePath(
|
||||||
|
this->LocalGenerator->GetBinaryDirectory(),
|
||||||
|
this->LocalGenerator->GetCurrentBinaryDirectory()),
|
||||||
|
'/');
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string line;
|
auto deps = cmReadGccDepfile(depFile.c_str(), prefix);
|
||||||
if (!isValidPath) {
|
|
||||||
// insert source as first dependency
|
|
||||||
depends.push_back(source);
|
|
||||||
}
|
|
||||||
while (cmSystemTools::GetLineFromStream(fin, line)) {
|
|
||||||
depends.emplace_back(std::move(line));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
auto deps = cmReadGccDepfile(depFile.c_str());
|
|
||||||
if (!deps) {
|
if (!deps) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// dependencies generated by the compiler contains only one target
|
for (auto& entry : *deps) {
|
||||||
depends = std::move(deps->front().paths);
|
depends = std::move(entry.paths);
|
||||||
if (depends.empty()) {
|
if (isValidPath) {
|
||||||
// unexpectedly empty, ignore it and continue
|
cm::erase_if(depends, isValidPath);
|
||||||
|
}
|
||||||
|
// copy depends for each target, except first one, which can be
|
||||||
|
// moved
|
||||||
|
for (auto index = entry.rules.size() - 1; index > 0; --index) {
|
||||||
|
dependencies[entry.rules[index]] = depends;
|
||||||
|
}
|
||||||
|
dependencies[entry.rules.front()] = std::move(depends);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (format == "msvc"_s) {
|
||||||
|
cmsys::ifstream fin(depFile.c_str());
|
||||||
|
if (!fin) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string line;
|
||||||
|
if (!isValidPath) {
|
||||||
|
// insert source as first dependency
|
||||||
|
depends.push_back(source);
|
||||||
|
}
|
||||||
|
while (cmSystemTools::GetLineFromStream(fin, line)) {
|
||||||
|
depends.emplace_back(std::move(line));
|
||||||
|
}
|
||||||
|
} else if (format == "gcc"_s) {
|
||||||
|
auto deps = cmReadGccDepfile(depFile.c_str());
|
||||||
|
if (!deps) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// dependencies generated by the compiler contains only one target
|
||||||
|
depends = std::move(deps->front().paths);
|
||||||
|
if (depends.empty()) {
|
||||||
|
// unexpectedly empty, ignore it and continue
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// depending of the effective format of the dependencies file
|
||||||
|
// generated by the compiler, the target can be wrongly identified
|
||||||
|
// as a dependency so remove it from the list
|
||||||
|
if (depends.front() == target) {
|
||||||
|
depends.erase(depends.begin());
|
||||||
|
}
|
||||||
|
|
||||||
|
// ensure source file is the first dependency
|
||||||
|
if (depends.front() != source) {
|
||||||
|
cm::erase(depends, source);
|
||||||
|
if (!isValidPath) {
|
||||||
|
depends.insert(depends.begin(), source);
|
||||||
|
}
|
||||||
|
} else if (isValidPath) {
|
||||||
|
// remove first dependency because it must not be filtered out
|
||||||
|
depends.erase(depends.begin());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// unknown format, ignore it
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// depending of the effective format of the dependencies file generated
|
if (isValidPath) {
|
||||||
// by the compiler, the target can be wrongly identified as a
|
cm::erase_if(depends, isValidPath);
|
||||||
// dependency so remove it from the list
|
// insert source as first dependency
|
||||||
if (depends.front() == target) {
|
depends.insert(depends.begin(), source);
|
||||||
depends.erase(depends.begin());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ensure source file is the first dependency
|
dependencies[target] = std::move(depends);
|
||||||
if (depends.front() != source) {
|
|
||||||
cm::erase(depends, source);
|
|
||||||
if (!isValidPath) {
|
|
||||||
depends.insert(depends.begin(), source);
|
|
||||||
}
|
|
||||||
} else if (isValidPath) {
|
|
||||||
// remove first dependency because it must not be filtered out
|
|
||||||
depends.erase(depends.begin());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isValidPath) {
|
|
||||||
cm::erase_if(depends, isValidPath);
|
|
||||||
// insert source as first dependency
|
|
||||||
depends.insert(depends.begin(), source);
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies[target] = std::move(depends);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -168,6 +202,8 @@ void cmDependsCompiler::WriteDependencies(
|
|||||||
|
|
||||||
// external dependencies file
|
// external dependencies file
|
||||||
for (auto& node : makeDependencies) {
|
for (auto& node : makeDependencies) {
|
||||||
|
auto target = LocalGenerator->ConvertToMakefilePath(
|
||||||
|
this->LocalGenerator->MaybeConvertToRelativePath(binDir, node.first));
|
||||||
auto& deps = node.second;
|
auto& deps = node.second;
|
||||||
std::transform(
|
std::transform(
|
||||||
deps.cbegin(), deps.cend(), deps.begin(),
|
deps.cbegin(), deps.cend(), deps.begin(),
|
||||||
@@ -176,13 +212,16 @@ void cmDependsCompiler::WriteDependencies(
|
|||||||
this->LocalGenerator->MaybeConvertToRelativePath(binDir, dep));
|
this->LocalGenerator->MaybeConvertToRelativePath(binDir, dep));
|
||||||
});
|
});
|
||||||
|
|
||||||
makeDepends << this->LocalGenerator->ConvertToMakefilePath(node.first)
|
bool first_dep = true;
|
||||||
<< ": " << deps.front();
|
makeDepends << target << ": ";
|
||||||
// first dependency is the source, remove it because should not be declared
|
|
||||||
// as phony target
|
|
||||||
deps.erase(deps.begin());
|
|
||||||
for (const auto& dep : deps) {
|
for (const auto& dep : deps) {
|
||||||
makeDepends << ' ' << lineContinue << " " << dep;
|
if (first_dep) {
|
||||||
|
first_dep = false;
|
||||||
|
makeDepends << dep;
|
||||||
|
} else {
|
||||||
|
makeDepends << ' ' << lineContinue << " " << dep;
|
||||||
|
}
|
||||||
|
|
||||||
phonyTargets.emplace(dep.data(), dep.length());
|
phonyTargets.emplace(dep.data(), dep.length());
|
||||||
}
|
}
|
||||||
makeDepends << std::endl << std::endl;
|
makeDepends << std::endl << std::endl;
|
||||||
|
@@ -93,6 +93,12 @@ public:
|
|||||||
*/
|
*/
|
||||||
static bool SupportsPlatform() { return false; }
|
static bool SupportsPlatform() { return false; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utilized to determine if this generator
|
||||||
|
* supports DEPFILE option.
|
||||||
|
*/
|
||||||
|
bool SupportsCustomCommandDepfile() const override { return true; }
|
||||||
|
|
||||||
/** Get the documentation entry for this generator. */
|
/** Get the documentation entry for this generator. */
|
||||||
static void GetDocumentation(cmDocumentationEntry& entry);
|
static void GetDocumentation(cmDocumentationEntry& entry);
|
||||||
|
|
||||||
|
@@ -13,6 +13,7 @@
|
|||||||
#include <cm/string_view>
|
#include <cm/string_view>
|
||||||
#include <cm/vector>
|
#include <cm/vector>
|
||||||
#include <cmext/algorithm>
|
#include <cmext/algorithm>
|
||||||
|
#include <cmext/string_view>
|
||||||
|
|
||||||
#include "cmsys/FStream.hxx"
|
#include "cmsys/FStream.hxx"
|
||||||
#include "cmsys/Terminal.h"
|
#include "cmsys/Terminal.h"
|
||||||
@@ -1435,7 +1436,7 @@ bool cmLocalUnixMakefileGenerator3::UpdateDependencies(
|
|||||||
this->Makefile->GetSafeDefinition("CMAKE_DEPENDS_DEPENDENCY_FILES");
|
this->Makefile->GetSafeDefinition("CMAKE_DEPENDS_DEPENDENCY_FILES");
|
||||||
if (!depends.empty()) {
|
if (!depends.empty()) {
|
||||||
// dependencies are managed by compiler
|
// dependencies are managed by compiler
|
||||||
auto depFiles = cmExpandedList(depends);
|
auto depFiles = cmExpandedList(depends, true);
|
||||||
std::string const internalDepFile =
|
std::string const internalDepFile =
|
||||||
targetDir + "/compiler_depend.internal";
|
targetDir + "/compiler_depend.internal";
|
||||||
std::string const depFile = targetDir + "/compiler_depend.make";
|
std::string const depFile = targetDir + "/compiler_depend.make";
|
||||||
@@ -1998,18 +1999,32 @@ void cmLocalUnixMakefileGenerator3::WriteDependLanguageInfo(
|
|||||||
cmakefileStream << "\n# The set of dependency files which are needed:\n";
|
cmakefileStream << "\n# The set of dependency files which are needed:\n";
|
||||||
cmakefileStream << "set(CMAKE_DEPENDS_DEPENDENCY_FILES\n";
|
cmakefileStream << "set(CMAKE_DEPENDS_DEPENDENCY_FILES\n";
|
||||||
for (auto const& compilerLang : compilerLangs) {
|
for (auto const& compilerLang : compilerLangs) {
|
||||||
auto depFormat = this->Makefile->GetSafeDefinition(
|
|
||||||
cmStrCat("CMAKE_", compilerLang.first, "_DEPFILE_FORMAT"));
|
|
||||||
auto const& compilerPairs = compilerLang.second;
|
auto const& compilerPairs = compilerLang.second;
|
||||||
for (auto const& compilerPair : compilerPairs) {
|
if (compilerLang.first == "CUSTOM"_s) {
|
||||||
for (auto const& src : compilerPair.second) {
|
for (auto const& compilerPair : compilerPairs) {
|
||||||
cmakefileStream << " \"" << src << "\" \""
|
for (auto const& src : compilerPair.second) {
|
||||||
<< this->MaybeConvertToRelativePath(
|
cmakefileStream << R"( "" ")"
|
||||||
this->GetBinaryDirectory(), compilerPair.first)
|
<< this->MaybeConvertToRelativePath(
|
||||||
<< "\" \"" << depFormat << "\" \""
|
this->GetBinaryDirectory(), compilerPair.first)
|
||||||
<< this->MaybeConvertToRelativePath(
|
<< R"(" "custom" ")"
|
||||||
this->GetBinaryDirectory(), compilerPair.first)
|
<< this->MaybeConvertToRelativePath(
|
||||||
<< ".d\"\n";
|
this->GetBinaryDirectory(), src)
|
||||||
|
<< "\"\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
auto depFormat = this->Makefile->GetSafeDefinition(
|
||||||
|
cmStrCat("CMAKE_", compilerLang.first, "_DEPFILE_FORMAT"));
|
||||||
|
for (auto const& compilerPair : compilerPairs) {
|
||||||
|
for (auto const& src : compilerPair.second) {
|
||||||
|
cmakefileStream << " \"" << src << "\" \""
|
||||||
|
<< this->MaybeConvertToRelativePath(
|
||||||
|
this->GetBinaryDirectory(), compilerPair.first)
|
||||||
|
<< "\" \"" << depFormat << "\" \""
|
||||||
|
<< this->MaybeConvertToRelativePath(
|
||||||
|
this->GetBinaryDirectory(), compilerPair.first)
|
||||||
|
<< ".d\"\n";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1617,6 +1617,16 @@ void cmMakefileTargetGenerator::GenerateCustomRuleFile(
|
|||||||
std::vector<std::string> depends;
|
std::vector<std::string> depends;
|
||||||
this->LocalGenerator->AppendCustomDepend(depends, ccg);
|
this->LocalGenerator->AppendCustomDepend(depends, ccg);
|
||||||
|
|
||||||
|
if (!ccg.GetCC().GetDepfile().empty()) {
|
||||||
|
// Add dependency over timestamp file for dependencies management
|
||||||
|
auto dependTimestamp = cmSystemTools::ConvertToOutputPath(
|
||||||
|
this->LocalGenerator->MaybeConvertToRelativePath(
|
||||||
|
this->LocalGenerator->GetBinaryDirectory(),
|
||||||
|
cmStrCat(this->TargetBuildDirectoryFull, "/compiler_depend.ts")));
|
||||||
|
|
||||||
|
depends.push_back(dependTimestamp);
|
||||||
|
}
|
||||||
|
|
||||||
// Write the rule.
|
// Write the rule.
|
||||||
const std::vector<std::string>& outputs = ccg.GetOutputs();
|
const std::vector<std::string>& outputs = ccg.GetOutputs();
|
||||||
bool symbolic = this->WriteMakeRule(*this->BuildFileStream, nullptr, outputs,
|
bool symbolic = this->WriteMakeRule(*this->BuildFileStream, nullptr, outputs,
|
||||||
@@ -1653,6 +1663,15 @@ void cmMakefileTargetGenerator::GenerateCustomRuleFile(
|
|||||||
objFullPath, srcFullPath);
|
objFullPath, srcFullPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Setup implicit depend for depfile if any
|
||||||
|
if (!ccg.GetCC().GetDepfile().empty()) {
|
||||||
|
std::string objFullPath = cmSystemTools::CollapseFullPath(
|
||||||
|
outputs[0], this->LocalGenerator->GetCurrentBinaryDirectory());
|
||||||
|
this->LocalGenerator->AddImplicitDepends(
|
||||||
|
this->GeneratorTarget, "CUSTOM", objFullPath, ccg.GetFullDepfile(),
|
||||||
|
cmDependencyScannerKind::Compiler);
|
||||||
|
}
|
||||||
|
|
||||||
this->CustomCommandOutputs.insert(outputs.begin(), outputs.end());
|
this->CustomCommandOutputs.insert(outputs.begin(), outputs.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -15,6 +15,7 @@
|
|||||||
#include "cmLocalUnixMakefileGenerator3.h"
|
#include "cmLocalUnixMakefileGenerator3.h"
|
||||||
#include "cmMakefile.h"
|
#include "cmMakefile.h"
|
||||||
#include "cmOSXBundleGenerator.h"
|
#include "cmOSXBundleGenerator.h"
|
||||||
|
#include "cmStringAlgorithms.h"
|
||||||
#include "cmSystemTools.h"
|
#include "cmSystemTools.h"
|
||||||
|
|
||||||
cmMakefileUtilityTargetGenerator::cmMakefileUtilityTargetGenerator(
|
cmMakefileUtilityTargetGenerator::cmMakefileUtilityTargetGenerator(
|
||||||
@@ -36,10 +37,42 @@ void cmMakefileUtilityTargetGenerator::WriteRuleFiles()
|
|||||||
*this->BuildFileStream << "# Utility rule file for "
|
*this->BuildFileStream << "# Utility rule file for "
|
||||||
<< this->GeneratorTarget->GetName() << ".\n\n";
|
<< this->GeneratorTarget->GetName() << ".\n\n";
|
||||||
|
|
||||||
|
const char* root = (this->Makefile->IsOn("CMAKE_MAKE_INCLUDE_FROM_ROOT")
|
||||||
|
? "$(CMAKE_BINARY_DIR)/"
|
||||||
|
: "");
|
||||||
|
|
||||||
|
// Include the dependencies for the target.
|
||||||
|
std::string dependFile =
|
||||||
|
cmStrCat(this->TargetBuildDirectoryFull, "/compiler_depend.make");
|
||||||
|
*this->BuildFileStream
|
||||||
|
<< "# Include any custom commands dependencies for this target.\n"
|
||||||
|
<< this->GlobalGenerator->IncludeDirective << " " << root
|
||||||
|
<< cmSystemTools::ConvertToOutputPath(
|
||||||
|
this->LocalGenerator->MaybeConvertToRelativePath(
|
||||||
|
this->LocalGenerator->GetBinaryDirectory(), dependFile))
|
||||||
|
<< "\n\n";
|
||||||
|
if (!cmSystemTools::FileExists(dependFile)) {
|
||||||
|
// Write an empty dependency file.
|
||||||
|
cmGeneratedFileStream depFileStream(
|
||||||
|
dependFile, false, this->GlobalGenerator->GetMakefileEncoding());
|
||||||
|
depFileStream << "# Empty custom commands generated dependencies file for "
|
||||||
|
<< this->GeneratorTarget->GetName() << ".\n"
|
||||||
|
<< "# This may be replaced when dependencies are built.\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string dependTimestamp =
|
||||||
|
cmStrCat(this->TargetBuildDirectoryFull, "/compiler_depend.ts");
|
||||||
|
if (!cmSystemTools::FileExists(dependTimestamp)) {
|
||||||
|
// Write a dependency timestamp file.
|
||||||
|
cmGeneratedFileStream depFileStream(
|
||||||
|
dependTimestamp, false, this->GlobalGenerator->GetMakefileEncoding());
|
||||||
|
depFileStream << "# CMAKE generated file: DO NOT EDIT!\n"
|
||||||
|
<< "# Timestamp file for custom commands dependencies "
|
||||||
|
"management for "
|
||||||
|
<< this->GeneratorTarget->GetName() << ".\n";
|
||||||
|
}
|
||||||
|
|
||||||
if (!this->NoRuleMessages) {
|
if (!this->NoRuleMessages) {
|
||||||
const char* root = (this->Makefile->IsOn("CMAKE_MAKE_INCLUDE_FROM_ROOT")
|
|
||||||
? "$(CMAKE_BINARY_DIR)/"
|
|
||||||
: "");
|
|
||||||
// Include the progress variables for the target.
|
// Include the progress variables for the target.
|
||||||
*this->BuildFileStream
|
*this->BuildFileStream
|
||||||
<< "# Include the progress variables for this target.\n"
|
<< "# Include the progress variables for this target.\n"
|
||||||
|
@@ -1272,6 +1272,8 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args,
|
|||||||
cmStateSnapshot snapshot = cm.GetCurrentSnapshot();
|
cmStateSnapshot snapshot = cm.GetCurrentSnapshot();
|
||||||
snapshot.GetDirectory().SetCurrentBinary(startOutDir);
|
snapshot.GetDirectory().SetCurrentBinary(startOutDir);
|
||||||
snapshot.GetDirectory().SetCurrentSource(startDir);
|
snapshot.GetDirectory().SetCurrentSource(startDir);
|
||||||
|
snapshot.GetDirectory().SetRelativePathTopSource(homeDir.c_str());
|
||||||
|
snapshot.GetDirectory().SetRelativePathTopBinary(homeOutDir.c_str());
|
||||||
cmMakefile mf(cm.GetGlobalGenerator(), snapshot);
|
cmMakefile mf(cm.GetGlobalGenerator(), snapshot);
|
||||||
auto lgd = cm.GetGlobalGenerator()->CreateLocalGenerator(&mf);
|
auto lgd = cm.GetGlobalGenerator()->CreateLocalGenerator(&mf);
|
||||||
|
|
||||||
|
@@ -0,0 +1,4 @@
|
|||||||
|
CMake Error at CustomCommandDependencies-BadArgs.cmake:[0-9]+ \(add_custom_command\):
|
||||||
|
add_custom_command IMPLICIT_DEPENDS and DEPFILE can not both be specified.
|
||||||
|
Call Stack \(most recent call first\):
|
||||||
|
CMakeLists.txt:[0-9]+ \(include\)
|
@@ -0,0 +1,10 @@
|
|||||||
|
enable_language(C)
|
||||||
|
|
||||||
|
add_custom_command(OUTPUT main.c
|
||||||
|
DEPFILE main.c.d
|
||||||
|
IMPLICIT_DEPENDS C main.c.in
|
||||||
|
COMMAND "${CMAKE_COMMAND}" -DINFILE=main.c.in -DOUTFILE=main.c -DDEPFILE=main.c.d
|
||||||
|
-P "${CMAKE_CURRENT_SOURCE_DIR}/GenerateDepFile.cmake"
|
||||||
|
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
|
||||||
|
|
||||||
|
add_custom_target(mainc ALL DEPENDS main.c)
|
73
Tests/RunCMake/BuildDepends/CustomCommandDependencies.cmake
Normal file
73
Tests/RunCMake/BuildDepends/CustomCommandDependencies.cmake
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
enable_language(C)
|
||||||
|
|
||||||
|
add_custom_command(OUTPUT main.c
|
||||||
|
DEPFILE main.c.d
|
||||||
|
COMMAND "${CMAKE_COMMAND}" -DINFILE=main.c.in -DOUTFILE=main.c -DDEPFILE=main.c.d
|
||||||
|
-P "${CMAKE_CURRENT_SOURCE_DIR}/GenerateDepFile.cmake"
|
||||||
|
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
|
||||||
|
|
||||||
|
add_custom_target(mainc ALL DEPENDS main.c)
|
||||||
|
|
||||||
|
add_executable(main ${CMAKE_CURRENT_BINARY_DIR}/main.c)
|
||||||
|
|
||||||
|
file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/check-$<LOWER_CASE:$<CONFIG>>.cmake CONTENT "
|
||||||
|
cmake_minimum_required(VERSION 3.19)
|
||||||
|
set(check_pairs
|
||||||
|
\"$<TARGET_FILE:main>|${CMAKE_CURRENT_BINARY_DIR}/main.c.in\"
|
||||||
|
\"$<TARGET_FILE:main>|${CMAKE_CURRENT_BINARY_DIR}/main.c\"
|
||||||
|
)
|
||||||
|
set(check_exes
|
||||||
|
\"$<TARGET_FILE:main>\"
|
||||||
|
)
|
||||||
|
|
||||||
|
if (check_step EQUAL 2)
|
||||||
|
include(\"${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/Makefile.cmake\")
|
||||||
|
if (NOT CMAKE_DEPEND_INFO_FILES)
|
||||||
|
set(RunCMake_TEST_FAILED \"Variable CMAKE_DEPEND_INFO_FILES not found.\")
|
||||||
|
else()
|
||||||
|
foreach(DEPEND_INFO_FILE IN LISTS CMAKE_DEPEND_INFO_FILES)
|
||||||
|
include(\"${CMAKE_CURRENT_BINARY_DIR}/\${DEPEND_INFO_FILE}\")
|
||||||
|
if (NOT CMAKE_DEPENDS_DEPENDENCY_FILES)
|
||||||
|
set(RunCMake_TEST_FAILED \"Variable CMAKE_DEPENDS_DEPENDENCY_FILES not found.\")
|
||||||
|
else()
|
||||||
|
list(LENGTH CMAKE_DEPENDS_DEPENDENCY_FILES DEPENDENCY_FILES_SIZE)
|
||||||
|
math(EXPR STOP_INDEX \"\${DEPENDENCY_FILES_SIZE} - 1\")
|
||||||
|
foreach(INDEX RANGE 0 \${STOP_INDEX} 4)
|
||||||
|
math(EXPR OBJECT_INDEX \"\${INDEX} + 1\")
|
||||||
|
math(EXPR FORMAT_INDEX \"\${INDEX} + 2\")
|
||||||
|
math(EXPR DEP_INDEX \"\${INDEX} + 3\")
|
||||||
|
list(GET CMAKE_DEPENDS_DEPENDENCY_FILES \${OBJECT_INDEX} OBJECT_FILE)
|
||||||
|
list(GET CMAKE_DEPENDS_DEPENDENCY_FILES \${FORMAT_INDEX} DEP_FORMAT)
|
||||||
|
list(GET CMAKE_DEPENDS_DEPENDENCY_FILES \${DEP_INDEX} DEP_FILE)
|
||||||
|
if (NOT EXISTS \"${CMAKE_CURRENT_BINARY_DIR}/\${DEP_FILE}\")
|
||||||
|
set(RunCMake_TEST_FAILED \"File \${DEP_FILE} not found.\")
|
||||||
|
else()
|
||||||
|
cmake_path(APPEND TARGET_DEP_FILE \"${CMAKE_CURRENT_BINARY_DIR}\" \"\${DEPEND_INFO_FILE}\")
|
||||||
|
cmake_path(REPLACE_FILENAME TARGET_DEP_FILE \"compiler_depend.make\")
|
||||||
|
file(READ \"\${TARGET_DEP_FILE}\" DEPENDS_CONTENT)
|
||||||
|
if (WIN32)
|
||||||
|
string (REPLACE \"\\\\\" \"/\" DEPENDS_CONTENT \"\${DEPENDS_CONTENT}\")
|
||||||
|
string (TOLOWER \"\${DEPENDS_CONTENT}\" DEPENDS_CONTENT)
|
||||||
|
string (TOLOWER \"\${OBJECT_FILE}\" OBJECT_FILE)
|
||||||
|
else()
|
||||||
|
string(REPLACE \"\\\\ \" \" \" DEPENDS_CONTENT \"\${DEPENDS_CONTENT}\")
|
||||||
|
endif()
|
||||||
|
if(DEPEND_INFO_FILE MATCHES \"main\\\\.dir\")
|
||||||
|
if (DEP_FORMAT STREQUAL \"gcc\" AND NOT DEPENDS_CONTENT MATCHES \"\${OBJECT_FILE} *:.+main.c\")
|
||||||
|
set(RunCMake_TEST_FAILED \"Dependency file '\${TARGET_DEP_FILE}' badly generated:\\n\${DEPENDS_CONTENT}\")
|
||||||
|
endif()
|
||||||
|
if (DEP_FORMAT STREQUAL \"custom\" AND NOT DEPENDS_CONTENT MATCHES \"\${OBJECT_FILE} *:.+main.c.in\")
|
||||||
|
set(RunCMake_TEST_FAILED \"Dependency file '\${TARGET_DEP_FILE}' badly generated:\\n\${DEPENDS_CONTENT}\")
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
if (NOT DEPENDS_CONTENT MATCHES \"\${OBJECT_FILE} *:.+main.c.in\")
|
||||||
|
set(RunCMake_TEST_FAILED \"Dependency file '\${TARGET_DEP_FILE}' badly generated:\\n\${DEPENDS_CONTENT}\")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
")
|
@@ -0,0 +1,3 @@
|
|||||||
|
file(WRITE "${RunCMake_TEST_BINARY_DIR}/main.c.in" [[
|
||||||
|
int main(void) { return 1; }
|
||||||
|
]])
|
@@ -0,0 +1,3 @@
|
|||||||
|
file(WRITE "${RunCMake_TEST_BINARY_DIR}/main.c.in" [[
|
||||||
|
int main(void) { return 2; }
|
||||||
|
]])
|
6
Tests/RunCMake/BuildDepends/GenerateDepFile.cmake
Normal file
6
Tests/RunCMake/BuildDepends/GenerateDepFile.cmake
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
file(READ "${INFILE}" INCONTENT)
|
||||||
|
file(WRITE "${OUTFILE}" "${INCONTENT}")
|
||||||
|
|
||||||
|
string(REPLACE [[ ]] [[\ ]] OUTFILE "${OUTFILE}")
|
||||||
|
string(REPLACE [[ ]] [[\ ]] INFILE "${INFILE}")
|
||||||
|
file(WRITE "${DEPFILE}" "${OUTFILE}: ${INFILE}\n")
|
@@ -122,4 +122,9 @@ if ((RunCMake_GENERATOR STREQUAL "Unix Makefiles"
|
|||||||
AND MSVC_VERSION GREATER 1300
|
AND MSVC_VERSION GREATER 1300
|
||||||
AND CMAKE_C_COMPILER_ID STREQUAL "MSVC"))
|
AND CMAKE_C_COMPILER_ID STREQUAL "MSVC"))
|
||||||
run_BuildDepends(CompilerDependencies)
|
run_BuildDepends(CompilerDependencies)
|
||||||
|
run_BuildDepends(CustomCommandDependencies)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (RunCMake_GENERATOR MATCHES "Makefiles")
|
||||||
|
run_cmake(CustomCommandDependencies-BadArgs)
|
||||||
endif()
|
endif()
|
||||||
|
@@ -1,5 +0,0 @@
|
|||||||
^CMake Error at CustomCommandDepfile-ERROR.cmake:1 \(add_custom_command\):
|
|
||||||
add_custom_command Option DEPFILE not supported by [^
|
|
||||||
]+
|
|
||||||
Call Stack \(most recent call first\):
|
|
||||||
CMakeLists.txt:3 \(include\)$
|
|
@@ -1,8 +0,0 @@
|
|||||||
add_custom_command(
|
|
||||||
OUTPUT hello.copy.c
|
|
||||||
COMMAND "${CMAKE_COMMAND}" -E copy
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/hello.c"
|
|
||||||
hello.copy.c
|
|
||||||
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
|
|
||||||
DEPFILE "test.d"
|
|
||||||
)
|
|
@@ -39,7 +39,6 @@ function(run_VerboseBuild)
|
|||||||
endfunction()
|
endfunction()
|
||||||
run_VerboseBuild()
|
run_VerboseBuild()
|
||||||
|
|
||||||
run_cmake(CustomCommandDepfile-ERROR)
|
|
||||||
run_cmake(IncludeRegexSubdir)
|
run_cmake(IncludeRegexSubdir)
|
||||||
|
|
||||||
function(run_MakefileConflict)
|
function(run_MakefileConflict)
|
||||||
|
Reference in New Issue
Block a user