[cmake-developers] [CMake 0015858]: Rationalise documentation for DEPENDS fields of add_custom_command() and add_custom_target()
Mantis Bug Tracker
mantis at public.kitware.com
Tue Nov 24 13:21:57 EST 2015
The following issue has been SUBMITTED.
======================================================================
https://cmake.org/Bug/view.php?id=15858
======================================================================
Reported By: Sam Thursfield
Assigned To:
======================================================================
Project: CMake
Issue ID: 15858
Category: Documentation
Reproducibility: N/A
Severity: minor
Priority: normal
Status: new
======================================================================
Date Submitted: 2015-11-24 13:21 EST
Last Modified: 2015-11-24 13:21 EST
======================================================================
Summary: Rationalise documentation for DEPENDS fields of
add_custom_command() and add_custom_target()
Description:
Hi!
I've been finding that the way dependencies between files and targets
work in CMake is totally confusing. I think that the documentation makes
it a lot more confusing than it needs to be. I have some suggestions
which would hopefully improve things ...
Currently the documentation for the DEPENDS field of
add_custom_command() says this:
Specify files on which the command depends. If any dependency
is an OUTPUT of another custom command in the same directory
(CMakeLists.txt file) CMake automatically brings the other cus‐
tom command into the target in which this command is built. If
DEPENDS is not specified the command will run whenever the OUT‐
PUT is missing; if the command does not actually create the OUT‐
PUT then the rule will always run. If DEPENDS specifies any
target (created by the add_custom_target(), add_executable(), or
add_library() command) a target-level dependency is created to
make sure the target is built before any target using this cus‐
tom command. Additionally, if the target is an executable or
library a file-level dependency is created to cause the custom
command to re-run whenever the target is recompiled.
Arguments to DEPENDS may use generator expressions.
Currently the documentation for the DEPENDS field of add_custom_target()
says this:
Reference files and outputs of custom commands created with
add_custom_command() command calls in the same directory (CMake‐
Lists.txt file). They will be brought up to date when the tar‐
get is built.
Use the add_dependencies() command to add dependencies on other
targets.
Based on my testing, I would suggest changing the documentation for the
DEPENDS field of add_custom_command() to say this:
Specifies files and/or targets that this custom command depends on.
ONLY files generated by add_custom_command() calls IN THIS DIRECTORY
can be added as file dependencies. If you add a dependency on file
generated somewhere else, it will be silently ignored.
Targets from any directory can be listed here, which will cause
those targets to be built before this one. If a target listed here
is re-built, this rule will rerun as well, UNLESS the target is
created by add_custom_target(). In that case you will need to
manually list the file-level dependencies of that target here.
If no dependencies are specified, the command will run whenever the
OUTPUT is missing; if the command does not actually create the
OUTPUT then the rule will always run.
The add_dependencies() command cannot be used to make this custom
command depend on other targets or files -- it is only for
target->target dependencies.
Arguments to DEPENDS may use generator expressions.
I would suggest changing the documentation for the DEPENDS field of
add_custom_target() to say this:
Specifies files and/or targets that this custom target depends on.
ONLY files generated by add_custom_command() calls IN THIS DIRECTORY
can be added as file dependencies. If you add a dependency on file
generated somewhere else, it will be silently ignored.
Targets from any directory can be listed here, which will cause
those targets to be built before this rule runs.
The add_dependencies() command can also be used to make this target
depend on other targets (but cannot be used to make it depend on
other files).
Arguments to DEPENDS may use generator expressions.
Finally, I would suggest adding this somewhere prominent in the main
add_custom_command documentation:
Files generated by add_custom_command() are NOT targets, and do not
behave in the same way as targets created by add_executable(),
add_library() and add_custom_target(). They can only be referenced
in the directory where the add_custom_command() call runs. If you
need to depend on a generated file outside that directory, you must
wrap it in a target using add_custom_target(), and depend on the
target instead.
Another option would be to keep the text of the DEPENDS commands minimal,
and have a section in the `cmake-buildsystem` documentation describing
how files, targets and custom targets relate to each other.
I haven't done a patch yet, but if you like these improvements I can do it.
Steps to Reproduce:
There appear to be a couple inaccuracies in the current documentation,
which I tried to correct above in addition to making things clearer.
I've written some test cases which demonstrate where the documentation
and the reality don't match up. These have all been tested with the
"Unix Makefiles" generator.
It may be that they don't work under other generators, but in that case
CMake should be raising an error here rather than silently accepting the
incorrect rules.
# 1. Generator expressions work in DEPENDS of custom targets.
#
# Currently the documentation of add_custom_command() DEPENDS says that
# generator expressions may be used, but the documentation of
# add_custom_target() DEPENDS does not say that. But they seem to work
# fine there -- if you build this project, 'foo' is generated as
# expected.
cmake_minimum_required(VERSION 3.3)
add_custom_command(
OUTPUT foo
COMMAND cmake -E echo foo > foo
)
add_custom_target(
all-foo ALL
DEPENDS $<1:foo>
)
---
# 2. The add_custom_target DEPENDS field is not limited to depending on files.
#
# The documentation for the add_custom_target DEPENDS field implies that only
# files and outputs of custom commands can be passed, and that the
# add_dependencies() command must be used to create dependencies on other
# targets.
#
# This is clearly false: CMake doesn't raise an error in the following
# CMakeLists.txt when I pass targets 'generate-bar' and 'generate-baz' as
# DEPENDS of the 'generate-all' custom target, and those targets get built
# when I run 'make'.
#
cmake_minimum_required(VERSION 3.2)
add_custom_command(
OUTPUT foo
COMMAND sleep 1
COMMAND cmake -E echo 'foo' > foo
)
add_custom_target(generate-foo DEPENDS foo)
add_custom_command(
OUTPUT bar
COMMAND cmake -E copy foo bar
DEPENDS generate-foo
)
add_custom_target(generate-bar DEPENDS bar)
add_custom_command(
OUTPUT baz
COMMAND cmake -E copy foo baz
DEPENDS generate-foo
)
add_custom_target(generate-baz DEPENDS baz)
add_custom_target(
generate-all ALL
DEPENDS generate-bar generate-baz
)
Additional Information:
Related bugs:
- https://cmake.org/Bug/view.php?id=12311
======================================================================
Issue History
Date Modified Username Field Change
======================================================================
2015-11-24 13:21 Sam Thursfield New Issue
======================================================================
More information about the cmake-developers
mailing list