MantisBT - CMake | |||||
View Issue Details | |||||
ID | Project | Category | View Status | Date Submitted | Last Update |
0015858 | CMake | Documentation | public | 2015-11-24 13:21 | 2016-06-10 14:31 |
Reporter | Sam Thursfield | ||||
Assigned To | Kitware Robot | ||||
Priority | normal | Severity | minor | Reproducibility | N/A |
Status | closed | Resolution | moved | ||
Platform | OS | OS Version | |||
Product Version | |||||
Target Version | Fixed in Version | ||||
Summary | 0015858: 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 [^] | ||||
Tags | No tags attached. | ||||
Relationships | |||||
Attached Files | |||||
Issue History | |||||
Date Modified | Username | Field | Change | ||
2015-11-24 13:21 | Sam Thursfield | New Issue | |||
2015-11-25 04:45 | Bartosz | Note Added: 0039909 | |||
2016-06-10 14:29 | Kitware Robot | Note Added: 0042890 | |||
2016-06-10 14:29 | Kitware Robot | Status | new => resolved | ||
2016-06-10 14:29 | Kitware Robot | Resolution | open => moved | ||
2016-06-10 14:29 | Kitware Robot | Assigned To | => Kitware Robot | ||
2016-06-10 14:31 | Kitware Robot | Status | resolved => closed |
Notes | |||||
|
|||||
|
|
||||
|
|||||
|
|