我正在尝试使用add_custom_command在编译期间生成一个文件。该命令似乎从未被执行,因此我创建了这个测试文件。
cmake_minimum_required( VERSION 2.6 )
add_custom_command(
OUTPUT hello.txt
COMMAND touch hello.txt
DEPENDS hello.txt
)
我试着运行:
cmake .
make
而且hello.txt没有生成。我做错了什么?
我正在尝试使用add_custom_command在编译期间生成一个文件。该命令似乎从未被执行,因此我创建了这个测试文件。
cmake_minimum_required( VERSION 2.6 )
add_custom_command(
OUTPUT hello.txt
COMMAND touch hello.txt
DEPENDS hello.txt
)
cmake .
make
而且hello.txt没有生成。我做错了什么?
add_custom_target(run ALL ...
这个解决方案可以在构建单一目标时正常工作,但是当你有多个顶层目标(例如app和tests)时,它会失效。
我遇到了同样的问题,当我试图将一些测试数据文件打包成对象文件,以便我的单元测试不依赖于任何外部文件时。我使用add_custom_command
和一些额外的依赖关系魔法以及set_property
解决了这个问题。
add_custom_command(
OUTPUT testData.cpp
COMMAND reswrap
ARGS testData.src > testData.cpp
DEPENDS testData.src
)
set_property(SOURCE unit-tests.cpp APPEND PROPERTY OBJECT_DEPENDS testData.cpp)
add_executable(app main.cpp)
add_executable(tests unit-tests.cpp)
现在,testData.cpp将在编译unit-tests.cpp之前生成,并且每当testData.src更改时都会重新生成。如果你调用的命令非常慢,那么当你只构建app目标时,你不必等待该命令完成(因为只有测试可执行文件需要它),这是额外的好处。
虽然上面没有显示,但是小心使用${PROJECT_BINARY_DIR}、${PROJECT_SOURCE_DIR}和include_directories()
会使您的源代码树不再包含生成的文件。
add_dependencies
来实现,但是这有点棘手。你不能直接在add_custom_command
和其他东西之间添加依赖关系,你首先必须创建一个add_custom_target
(它是空的,只是提供一个你可以稍后命名的目标)。原因是add_dependencies
只能将目标作为参数,而不能将文件作为参数。请参阅此博客以了解更多信息:https://samthursfield.wordpress.com/2015/11/21/cmake-dependencies-between-targets-and-files-and-custom-commands/ - Elliott Slaughter现有两个答案的问题在于它们要么将依赖关系全局化(add_custom_target(name ALL ...)
),要么将其分配给特定的单个文件(set_property(...)
),如果您有许多需要该依赖项的文件,则会变得麻烦。相反,我们希望有一个目标,可以使它成为另一个目标的依赖项。
实现这一点的方法是使用add_custom_command
定义规则,然后使用add_custom_target
基于该规则定义新目标。然后,您可以通过add_dependencies
将该目标添加为另一个目标的依赖项。
# this defines the build rule for some_file
add_custom_command(
OUTPUT some_file
COMMAND ...
)
# create a target that includes some_file, this gives us a name that we can use later
add_custom_target(
some_target
DEPENDS some_file
)
# then let's suppose we're creating a library
add_library(some_library some_other_file.c)
# we can add the target as a dependency, and it will affect only this library
add_dependencies(some_library some_target)
这种方法的优点:
some_target
不是 ALL
的依赖项,这意味着仅在特定目标需要时才构建它。(而 add_custom_target(name ALL ...)
会无条件地为所有目标构建它。)some_target
是整个库的依赖项,所以将在该库中的所有文件之前构建它。这意味着如果库中有很多文件,我们不必在每个文件上都执行 set_property
。add_custom_command
中添加 DEPENDS
,则只有在其输入更改时才会重新构建它。(与使用 add_custom_target(name ALL ...)
的方法相比,该命令会在每次构建时运行,而不管它是否需要。)有关为什么会这样工作的更多信息,请参阅此博客文章:https://samthursfield.wordpress.com/2015/11/21/cmake-dependencies-between-targets-and-files-and-custom-commands/
添加以下内容:
add_custom_target(run ALL
DEPENDS hello.txt)
如果您熟悉makefile,那么这意味着:
all: run
run: hello.txt
add_custom_target
,建议改用Rian提倡的add_custom_command
。 - Anne van Rossumadd_custom_command()
调用中删除 DEPENDS,它会创建循环依赖。只有 add_custom_target()
应该在这里使用 DEPENDS 参数。当你修复这个问题时,它在我的 OS X 上可以工作(使用 CMake 3.8.0 进行测试)。 - Craig Scott这个问题很老了,但即使我按照建议的推荐去做,也不总是有效。
我正在使用Android Studio,并且需要调用cMake来构建C++库。它可以正常工作,直到我添加运行自定义脚本的代码(实际上,我现在尝试运行'touch',就像上面的例子一样)。
首先,
add_custom_command
完全不起作用。
我已经尝试过了
execute_process (
COMMAND touch hello.txt
)
它有时候工作,但不总是如此!
我尝试了清理项目,手动删除已创建的文件等方法,但效果一样。
尝试了cMake版本:
3.10.2
3.18.1
3.22.1
当它们工作时,它们会根据cMake版本产生不同的结果,可能是一个文件或几个文件。这并不重要,只要它们能够工作就好,但问题就在这里。
有人可以为这个谜团提供一些线索吗?
hello.txt
并依赖于hello.txt
! - Alexis Wilke