Genex: add_custom_command: DEPFILE supports genex

This facility is very useful for 'Ninja Multi-Config' and required
as well for future support of DEPFILE in 'Xcode' and 'Visual Studio'
generators (#20286).
This commit is contained in:
Marc Chevrier 2021-04-09 19:09:52 +02:00
parent 43ecda68eb
commit 0c47b91fcc
11 changed files with 74 additions and 12 deletions

View File

@ -272,7 +272,9 @@ The options are:
.. versionadded:: 3.7
Specify a ``.d`` depfile for the :generator:`Ninja` generator and
:ref:`Makefile Generators`.
: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
@ -281,6 +283,9 @@ The options are:
.. versionadded:: 3.20
Added the support of :ref:`Makefile Generators`.
.. versionadded:: 3.21
Added the support of :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`

View File

@ -0,0 +1,5 @@
add_custom_command-DEPFILE-genex
--------------------------------
* The :command:`add_custom_command` command ``DEPFILE`` option learned to
support :manual:`generator expressions <cmake-generator-expressions(7)>`.

View File

@ -139,6 +139,14 @@ std::vector<std::string> EvaluateOutputs(std::vector<std::string> const& paths,
}
return outputs;
}
std::string EvaluateDepfile(std::string const& path,
cmGeneratorExpression const& ge,
cmLocalGenerator* lg, std::string const& config)
{
std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(path);
return cge->Evaluate(lg, config);
}
}
cmCustomCommandGenerator::cmCustomCommandGenerator(
@ -381,9 +389,20 @@ void cmCustomCommandGenerator::AppendArguments(unsigned int c,
}
}
std::string cmCustomCommandGenerator::GetDepfile() const
{
const auto& depfile = this->CC->GetDepfile();
if (depfile.empty()) {
return "";
}
cmGeneratorExpression ge(this->CC->GetBacktrace());
return EvaluateDepfile(depfile, ge, this->LG, this->OutputConfig);
}
std::string cmCustomCommandGenerator::GetFullDepfile() const
{
std::string depfile = this->CC->GetDepfile();
std::string depfile = this->GetDepfile();
if (depfile.empty()) {
return "";
}

View File

@ -57,6 +57,7 @@ public:
std::vector<std::string> const& GetDepends() const;
std::set<BT<std::pair<std::string, bool>>> const& GetUtilities() const;
bool HasOnlyEmptyCommandLines() const;
std::string GetDepfile() const;
std::string GetFullDepfile() const;
std::string GetInternalDepfile() const;

View File

@ -670,7 +670,7 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement(
cmCryptoHash hash(cmCryptoHash::AlgoSHA256);
customStep += hash.HashString(ninjaOutputs[0]).substr(0, 7);
std::string depfile = cc->GetDepfile();
std::string depfile = ccg.GetDepfile();
if (!depfile.empty()) {
switch (cc->GetCMP0116Status()) {
case cmPolicies::WARN:

View File

@ -3,15 +3,15 @@ enable_language(C)
add_custom_command(
OUTPUT topcc.c
DEPFILE topcc.c.d
COMMAND ${CMAKE_COMMAND} -DOUTFILE=${CMAKE_CURRENT_BINARY_DIR}/topcc.c -DINFILE=topccdep.txt -DDEPFILE=topcc.c.d -P "${CMAKE_CURRENT_LIST_DIR}/WriteDepfile.cmake"
DEPFILE topcc_$<CONFIG>.c.d
COMMAND ${CMAKE_COMMAND} -DOUTFILE=${CMAKE_CURRENT_BINARY_DIR}/topcc.c -DINFILE=topccdep.txt -DDEPFILE=topcc_$<CONFIG>.c.d -P "${CMAKE_CURRENT_LIST_DIR}/WriteDepfile.cmake"
)
add_custom_target(topcc ALL DEPENDS topcc.c)
add_custom_command(
OUTPUT topexe.c
DEPFILE ${CMAKE_CURRENT_BINARY_DIR}/topexe.c.d
COMMAND ${CMAKE_COMMAND} -DOUTFILE=topexe.c "-DINFILE=${CMAKE_CURRENT_BINARY_DIR}/topexedep.txt" -DDEPFILE=topexe.c.d -P "${CMAKE_CURRENT_LIST_DIR}/WriteDepfile.cmake"
DEPFILE ${CMAKE_CURRENT_BINARY_DIR}/topexe_$<CONFIG>.c.d
COMMAND ${CMAKE_COMMAND} -DOUTFILE=topexe.c "-DINFILE=${CMAKE_CURRENT_BINARY_DIR}/topexedep.txt" -DDEPFILE=topexe_$<CONFIG>.c.d -P "${CMAKE_CURRENT_LIST_DIR}/WriteDepfile.cmake"
)
add_executable(topexe "${CMAKE_CURRENT_BINARY_DIR}/topexe.c")

View File

@ -1,5 +1,10 @@
set(log "${RunCMake_BINARY_DIR}/CustomCommandDepfile-build/build.ninja")
file(READ "${log}" build_file)
set(RunCMake_TEST_FAILED)
if(NOT "${build_file}" MATCHES "depfile = test\\.d")
set(RunCMake_TEST_FAILED "Log file:\n ${log}\ndoes not have expected line: depfile = test.d")
list(APPEND RunCMake_TEST_FAILED "Log file:\n ${log}\ndoes not have expected line: depfile = test.d")
endif()
if(NOT "${build_file}" MATCHES "depfile = test_Debug\\.d")
list(APPEND RunCMake_TEST_FAILED "\nLog file:\n ${log}\ndoes not have expected line: depfile = test_Debug.d")
endif()

View File

@ -6,6 +6,17 @@ add_custom_command(
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
DEPFILE "test.d"
)
add_custom_target(copy ALL DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/hello.copy.c")
add_custom_command(
OUTPUT hello.copy2.c
COMMAND "${CMAKE_COMMAND}" -E copy
"${CMAKE_CURRENT_SOURCE_DIR}/hello.c"
hello.copy2.c
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
DEPFILE "test_$<CONFIG>.d"
)
add_custom_target(copy ALL DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/hello.copy.c"
"${CMAKE_CURRENT_BINARY_DIR}/hello.copy2.c")
include(CheckNoPrefixSubDir.cmake)

View File

@ -67,7 +67,7 @@ run_CMP0058(WARN-by)
run_CMP0058(NEW-no)
run_CMP0058(NEW-by)
run_cmake(CustomCommandDepfile)
run_cmake_with_options(CustomCommandDepfile -DCMAKE_BUILD_TYPE=Debug)
run_cmake(CustomCommandJobPool)
run_cmake(JobPoolUsesTerminal)

View File

@ -1,5 +1,10 @@
set(log "${RunCMake_BINARY_DIR}/CustomCommandDepfile-build/CMakeFiles/impl-Debug.ninja")
file(READ "${log}" build_file)
set(RunCMake_TEST_FAILED)
if(NOT "${build_file}" MATCHES "depfile = test\\.d")
set(RunCMake_TEST_FAILED "Log file:\n ${log}\ndoes not have expected line: depfile = test.d")
list(APPEND RunCMake_TEST_FAILED "Log file:\n ${log}\ndoes not have expected line: depfile = test.d")
endif()
if(NOT "${build_file}" MATCHES "depfile = test_Debug\\.d")
list(APPEND RunCMake_TEST_FAILED "\nLog file:\n ${log}\ndoes not have expected line: depfile = test_Debug.d")
endif()

View File

@ -6,4 +6,15 @@ add_custom_command(
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
DEPFILE "test.d"
)
add_custom_target(copy ALL DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/main.copy.c")
add_custom_command(
OUTPUT main.copy2.c
COMMAND "${CMAKE_COMMAND}" -E copy
"${CMAKE_CURRENT_SOURCE_DIR}/main.c"
main.copy2.c
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
DEPFILE "test_$<CONFIG>.d"
)
add_custom_target(copy ALL DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/main.copy.c"
"${CMAKE_CURRENT_BINARY_DIR}/main.copy2.c")