add_custom_command: Add DEPENDS_EXPLICIT_ONLY option for Ninja
Add option `DEPENDS_EXPLICIT_ONLY` to `add_custom_command` to indicate that implicit dependencies coming from users of the output are not needed, and only consider dependencies explicitly specified in the custom command. Fixes: #17097
This commit is contained in:
parent
48c69eeafe
commit
082ccd7530
@ -25,7 +25,8 @@ The first signature is for adding a custom command to produce an output:
|
|||||||
[DEPFILE depfile]
|
[DEPFILE depfile]
|
||||||
[JOB_POOL job_pool]
|
[JOB_POOL job_pool]
|
||||||
[VERBATIM] [APPEND] [USES_TERMINAL]
|
[VERBATIM] [APPEND] [USES_TERMINAL]
|
||||||
[COMMAND_EXPAND_LISTS])
|
[COMMAND_EXPAND_LISTS]
|
||||||
|
[DEPENDS_EXPLICIT_ONLY])
|
||||||
|
|
||||||
This defines a command to generate specified ``OUTPUT`` file(s).
|
This defines a command to generate specified ``OUTPUT`` file(s).
|
||||||
A target created in the same directory (``CMakeLists.txt`` file)
|
A target created in the same directory (``CMakeLists.txt`` file)
|
||||||
@ -357,6 +358,21 @@ The options are:
|
|||||||
:ref:`Makefile Generators`, :ref:`Visual Studio Generators`,
|
:ref:`Makefile Generators`, :ref:`Visual Studio Generators`,
|
||||||
and the :generator:`Xcode` generator.
|
and the :generator:`Xcode` generator.
|
||||||
|
|
||||||
|
``DEPENDS_EXPLICIT_ONLY``
|
||||||
|
|
||||||
|
.. versionadded:: 3.27
|
||||||
|
|
||||||
|
Indicate that the command's ``DEPENDS`` argument represents all files
|
||||||
|
required by the command and implicit dependencies are not required.
|
||||||
|
|
||||||
|
Without this option, if any target uses the output of the custom command,
|
||||||
|
CMake will consider that target's dependencies as implicit dependencies for
|
||||||
|
the custom command in case this custom command requires files implicitly
|
||||||
|
created by those targets.
|
||||||
|
|
||||||
|
Only the :ref:`Ninja Generators` actually use this information to remove
|
||||||
|
unnecessary implicit dependencies.
|
||||||
|
|
||||||
Examples: Generating Files
|
Examples: Generating Files
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
7
Help/release/dev/ninja-custom-command-depends.rst
Normal file
7
Help/release/dev/ninja-custom-command-depends.rst
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
ninja-custom-command-depends
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
* The :command:`add_custom_command` command gained a new
|
||||||
|
``DEPENDS_EXPLICIT_ONLY`` option to tell the :ref:`Ninja Generators`
|
||||||
|
not to add any dependencies implied by the target to which it is
|
||||||
|
attached.
|
@ -49,6 +49,7 @@ bool cmAddCustomCommandCommand(std::vector<std::string> const& args,
|
|||||||
bool append = false;
|
bool append = false;
|
||||||
bool uses_terminal = false;
|
bool uses_terminal = false;
|
||||||
bool command_expand_lists = false;
|
bool command_expand_lists = false;
|
||||||
|
bool depends_explicit_only = false;
|
||||||
std::string implicit_depends_lang;
|
std::string implicit_depends_lang;
|
||||||
cmImplicitDependsList implicit_depends;
|
cmImplicitDependsList implicit_depends;
|
||||||
|
|
||||||
@ -104,6 +105,7 @@ bool cmAddCustomCommandCommand(std::vector<std::string> const& args,
|
|||||||
MAKE_STATIC_KEYWORD(USES_TERMINAL);
|
MAKE_STATIC_KEYWORD(USES_TERMINAL);
|
||||||
MAKE_STATIC_KEYWORD(VERBATIM);
|
MAKE_STATIC_KEYWORD(VERBATIM);
|
||||||
MAKE_STATIC_KEYWORD(WORKING_DIRECTORY);
|
MAKE_STATIC_KEYWORD(WORKING_DIRECTORY);
|
||||||
|
MAKE_STATIC_KEYWORD(DEPENDS_EXPLICIT_ONLY);
|
||||||
#undef MAKE_STATIC_KEYWORD
|
#undef MAKE_STATIC_KEYWORD
|
||||||
static std::unordered_set<std::string> const keywords{
|
static std::unordered_set<std::string> const keywords{
|
||||||
keyAPPEND,
|
keyAPPEND,
|
||||||
@ -126,7 +128,8 @@ bool cmAddCustomCommandCommand(std::vector<std::string> const& args,
|
|||||||
keyTARGET,
|
keyTARGET,
|
||||||
keyUSES_TERMINAL,
|
keyUSES_TERMINAL,
|
||||||
keyVERBATIM,
|
keyVERBATIM,
|
||||||
keyWORKING_DIRECTORY
|
keyWORKING_DIRECTORY,
|
||||||
|
keyDEPENDS_EXPLICIT_ONLY
|
||||||
};
|
};
|
||||||
|
|
||||||
for (std::string const& copy : args) {
|
for (std::string const& copy : args) {
|
||||||
@ -155,6 +158,8 @@ bool cmAddCustomCommandCommand(std::vector<std::string> const& args,
|
|||||||
uses_terminal = true;
|
uses_terminal = true;
|
||||||
} else if (copy == keyCOMMAND_EXPAND_LISTS) {
|
} else if (copy == keyCOMMAND_EXPAND_LISTS) {
|
||||||
command_expand_lists = true;
|
command_expand_lists = true;
|
||||||
|
} else if (copy == keyDEPENDS_EXPLICIT_ONLY) {
|
||||||
|
depends_explicit_only = true;
|
||||||
} else if (copy == keyTARGET) {
|
} else if (copy == keyTARGET) {
|
||||||
doing = doing_target;
|
doing = doing_target;
|
||||||
} else if (copy == keyARGS) {
|
} else if (copy == keyARGS) {
|
||||||
@ -329,6 +334,7 @@ bool cmAddCustomCommandCommand(std::vector<std::string> const& args,
|
|||||||
cc->SetDepfile(depfile);
|
cc->SetDepfile(depfile);
|
||||||
cc->SetJobPool(job_pool);
|
cc->SetJobPool(job_pool);
|
||||||
cc->SetCommandExpandLists(command_expand_lists);
|
cc->SetCommandExpandLists(command_expand_lists);
|
||||||
|
cc->SetDependsExplicitOnly(depends_explicit_only);
|
||||||
if (source.empty() && output.empty()) {
|
if (source.empty() && output.empty()) {
|
||||||
// Source is empty, use the target.
|
// Source is empty, use the target.
|
||||||
mf.AddCustomCommandToTarget(target, cctype, std::move(cc));
|
mf.AddCustomCommandToTarget(target, cctype, std::move(cc));
|
||||||
|
@ -164,6 +164,16 @@ void cmCustomCommand::SetCommandExpandLists(bool b)
|
|||||||
this->CommandExpandLists = b;
|
this->CommandExpandLists = b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool cmCustomCommand::GetDependsExplicitOnly() const
|
||||||
|
{
|
||||||
|
return this->DependsExplicitOnly;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cmCustomCommand::SetDependsExplicitOnly(bool b)
|
||||||
|
{
|
||||||
|
this->DependsExplicitOnly = b;
|
||||||
|
}
|
||||||
|
|
||||||
const std::string& cmCustomCommand::GetDepfile() const
|
const std::string& cmCustomCommand::GetDepfile() const
|
||||||
{
|
{
|
||||||
return this->Depfile;
|
return this->Depfile;
|
||||||
|
@ -102,6 +102,11 @@ public:
|
|||||||
bool GetCommandExpandLists() const;
|
bool GetCommandExpandLists() const;
|
||||||
void SetCommandExpandLists(bool b);
|
void SetCommandExpandLists(bool b);
|
||||||
|
|
||||||
|
/** Set/Get whether to use additional dependencies coming from
|
||||||
|
users of OUTPUT of the custom command. */
|
||||||
|
bool GetDependsExplicitOnly() const;
|
||||||
|
void SetDependsExplicitOnly(bool b);
|
||||||
|
|
||||||
/** Set/Get the depfile (used by the Ninja generator) */
|
/** Set/Get the depfile (used by the Ninja generator) */
|
||||||
const std::string& GetDepfile() const;
|
const std::string& GetDepfile() const;
|
||||||
void SetDepfile(const std::string& depfile);
|
void SetDepfile(const std::string& depfile);
|
||||||
@ -141,6 +146,7 @@ private:
|
|||||||
bool CommandExpandLists = false;
|
bool CommandExpandLists = false;
|
||||||
bool StdPipesUTF8 = false;
|
bool StdPipesUTF8 = false;
|
||||||
bool HasMainDependency_ = false;
|
bool HasMainDependency_ = false;
|
||||||
|
bool DependsExplicitOnly = false;
|
||||||
|
|
||||||
// Policies are NEW for synthesized custom commands, and set by cmMakefile for
|
// Policies are NEW for synthesized custom commands, and set by cmMakefile for
|
||||||
// user-created custom commands.
|
// user-created custom commands.
|
||||||
|
@ -586,6 +586,7 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement(
|
|||||||
|
|
||||||
cmNinjaDeps orderOnlyDeps;
|
cmNinjaDeps orderOnlyDeps;
|
||||||
|
|
||||||
|
if (!cc->GetDependsExplicitOnly()) {
|
||||||
// A custom command may appear on multiple targets. However, some build
|
// A custom command may appear on multiple targets. However, some build
|
||||||
// systems exist where the target dependencies on some of the targets are
|
// systems exist where the target dependencies on some of the targets are
|
||||||
// overspecified, leading to a dependency cycle. If we assume all target
|
// overspecified, leading to a dependency cycle. If we assume all target
|
||||||
@ -613,6 +614,7 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement(
|
|||||||
std::back_inserter(depsIntersection));
|
std::back_inserter(depsIntersection));
|
||||||
orderOnlyDeps = depsIntersection;
|
orderOnlyDeps = depsIntersection;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const std::vector<std::string>& outputs = ccg.GetOutputs();
|
const std::vector<std::string>& outputs = ccg.GetOutputs();
|
||||||
const std::vector<std::string>& byproducts = ccg.GetByproducts();
|
const std::vector<std::string>& byproducts = ccg.GetByproducts();
|
||||||
|
18
Tests/RunCMake/Ninja/CustomCommandExplicitDepends.cmake
Normal file
18
Tests/RunCMake/Ninja/CustomCommandExplicitDepends.cmake
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.26)
|
||||||
|
project(CustomCommandExplicitDepends C)
|
||||||
|
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/command.h"
|
||||||
|
COMMAND "${CMAKE_COMMAND}" -E touch
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/command.h"
|
||||||
|
COMMENT "Creating command.h"
|
||||||
|
DEPENDS_EXPLICIT_ONLY
|
||||||
|
)
|
||||||
|
|
||||||
|
add_library(dep STATIC dep.c)
|
||||||
|
|
||||||
|
add_library(top STATIC
|
||||||
|
top.c
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/command.h"
|
||||||
|
)
|
||||||
|
target_link_libraries(top PRIVATE dep)
|
@ -190,6 +190,18 @@ function (run_LooseObjectDepends)
|
|||||||
endfunction ()
|
endfunction ()
|
||||||
run_LooseObjectDepends()
|
run_LooseObjectDepends()
|
||||||
|
|
||||||
|
function (run_CustomCommandExplictDepends)
|
||||||
|
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/CustomCommandExplicitDepends-build)
|
||||||
|
run_cmake(CustomCommandExplicitDepends)
|
||||||
|
run_ninja("${RunCMake_TEST_BINARY_DIR}" "command.h")
|
||||||
|
if (EXISTS "${RunCMake_TEST_BINARY_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}dep${CMAKE_STATIC_LIBRARY_SUFFIX}")
|
||||||
|
message(FATAL_ERROR
|
||||||
|
"The `dep` library was created when requesting an custom command to be "
|
||||||
|
"generated; this should no longer be necessary when passing DEPENDS_EXPLICIT_ONLY keyword.")
|
||||||
|
endif ()
|
||||||
|
endfunction ()
|
||||||
|
run_CustomCommandExplictDepends()
|
||||||
|
|
||||||
function (run_AssumedSources)
|
function (run_AssumedSources)
|
||||||
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/AssumedSources-build)
|
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/AssumedSources-build)
|
||||||
run_cmake(AssumedSources)
|
run_cmake(AssumedSources)
|
||||||
|
Loading…
Reference in New Issue
Block a user