查找 CMake 文件生成 add_custom_command 示例,其中需要 DEPENDS 选项

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

我想用一个简单的例子来说明文件生成add_custom_command(OUTPUT ...)DEPENDS选项,也就是说,如果我们注释DEPENDS部分,这个例子会给出不同的输出或者完全崩溃。

在下面的例子中(当前工作目录下有文件londongood.cpp),DEPENDS可有可无:

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)

我确实阅读了文档。我对构建系统知之甚少,无论是 Make 还是 CMake。第一句话Specify files on which the command depends.让我很困惑。我不明白一个命令如何依赖于其他文件,在我随意的例子中,命令行本身似乎可以定位所有内容。我想要一个 CMake 代码示例来展示命令如何依赖于其他文件,在 DEPENDS 的必要帮助下。

文档中的短语

Specify files on which the command depends.

更好理解为

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

可以猜到,命令cp london foo的输出文件内容只依赖于london,所以为[=14=指定选项DEPENDS london是合理的].

作为构建系统,CMake 使用 DEPENDS 中的信息来决定是否 运行 命令。如果:

  • OUTPUT 文件已在上一个 运行 上创建,并且
  • 自上次 运行 以来,DEPENDS 文件尚未更新,

那么命令就不会再是运行了。原因很简单:如果命令产生相同的文件,则不需要 运行 命令。


考虑到源(CMAKE_SOURCE_DIR)和构建(CMAKE_BINARY_DIR)目录分离,示例可以重写如下:

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.
)

第一次构建项目时,foo和可执行文件都会被构建。

第二次构建项目时(在 london 中没有更改)不会重建任何内容。

当更改london文件并再次构建项目时,foo将被重新构建(因为它依赖于london)。当 foo 被重建时,可执行文件也将被重建,因为它依赖于 foo.