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                                    
======================================================================

-- 

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: 
http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more 
information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at 
http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake-developers

Reply via email to