Search code examples
cmakecmake-custom-command

Find a CMake file-generating add_custom_command example in which DEPENDS option is necessary


I want a simple example to illustrate the DEPENDS option of file generating add_custom_command(OUTPUT ...), that is, if we comment the DEPENDS part, the example will give different output or totally crash.

In the following example (there are files london and good.cpp in the current working directory), DEPENDS is dispensable:

cmake_minimum_required(VERSION 3.10)
project(Tutorial VERSION 1.0)

add_custom_command(OUTPUT foo
COMMAND cp london foo
#DEPENDS london
COMMENT "I'm testing the new method.")

add_executable(cake good.cpp foo)

I did read the documentation. I have little knowledge about building system, neither Make nor CMake. The first sentence Specify files on which the command depends. confuses me. I don't understand how a command depends on other files, in my casual example, the command line itself seems to locate everything. I want a CMake code example to show how command depends on other files, with the necessary help of DEPENDS.


Solution

  • The phrase in documentation

    Specify files on which the command depends.

    is better understandable as

    Specify files on which content of the command's output file(s) depends.

    As one could guess, a content of the output file of the command cp london foo depends only from london, so it is reasonable to specify option DEPENDS london for add_custom_command.

    As a build system, CMake uses information in DEPENDS for decide, whether to run the command or not. If:

    • OUTPUT file has already been created on previous run, and
    • since previous run the DEPENDS file has not been updated,

    then the command won't be run again. The reasoning is simple: no needs to run the command if it results with the same file(s).


    Taking into account source (CMAKE_SOURCE_DIR) and build (CMAKE_BINARY_DIR) directories separation, the example could be rewritten as follows:

    cmake_minimum_required(VERSION 3.10)
    project(Tutorial VERSION 1.0)
    
    add_custom_command(
      OUTPUT foo # relative path denotes a file in the build directory
      COMMAND cp ${CMAKE_SOURCE_DIR}/london foo # The command will be run from the build directory,
        # so need to use absolute path for the file in the source directory
      DEPENDS london # relative path is resolved in the source directory,
        # assuming that corresponded file is already existed
      WORKING_DIRECTORY ${CMAKE_BINARY_DIR} # specifies a directory from which run the COMMAND
        # build directory is used by default, so the option can be omitted
      COMMENT "I'm testing the new method."
    )
    
    add_executable(cake
      good.cpp # relative path is resolved in the source directory,
        # assuming that corresponded file is already existed
      foo # because given file is absent in the source directory,
        # the path is resolved relative to the build directory.
    )
    

    When build the project the first time, both foo and executable will be built.

    When build the project the second time (without changing in london) nothing will be rebuilt.

    When change london file and build the project again, foo will be re-built (because it depends on london). As foo is rebuilt, the executable will be rebuilt too, because it depends on foo.