本文介绍了CMake中的add_custom_target
命令。使用的CMake版本是3.22.1。
CMake中一切都是基于target的,如add_library
会产生一个library的target,add_executable
会产生一个exe的target…
本文的add_custom_target
会根据命令的参数生成一个target,这个target相对的可以更定制化一点。
官方文档:https://cmake.org/cmake/help/v3.22/command/add_custom_target.html?highlight=add_custom
all target的意思是,在cmake
之后,make
会生成和执行all target内所有的target。
例如add_executable
默认就会生成在all target中。但如果在add_exe
命令中加入EXCLUDE_FROM_ALL,才会从all target中移除,即make
不会默认生成。
而add_custom_target
的target则是默认不在all target中。
如下面案例,定义了一个print-pwd的target,这个target执行pwd
命令。
add_custom_target(
print-pwd
COMMAND "pwd"
)
在make
之后,是没有任何反应的,这证明了此target不是all target内:
对于这种target,需要make
才会执行:
以上打印了这个target的COMMAND信息,以及target build完成了。
在声明target的时候,可以加上ALL,这个target就会加入all target中,默认进行执行了。
add_custom_target(
print-pwd
ALL
COMMAND "pwd"
)
target之间可以有依赖关系,A依赖B(A depends on B),意味着A的build,需要基于B 已经build完成。
要实现A依赖B,则要在定义A的时候,加上DEPENDS B。具体如下案例:
add_custom_target(
print-pwd
COMMAND "pwd"
)
add_custom_target(
depend-print-pwd
COMMAND "echo" "depend pwd"
DEPENDS print-pwd
)
定义了两个target,后者依赖前者,并且后者会打印"depend pwd"。
这里要注意一点,COMMAND中的命令和参数是分开的,如第二个target的COMMAND "echo" "depend pwd"
,而不能COMMAND "echo 'depend pwd'"
。
同样的,在make
之后是没有反应的。在make depend-print-pwd
后:
能发现会先build print-pwd,再build depend-print-pwd。
这里也可以把命令内的DEPENDS改为:add_dependencies(depend-print-pwd print-pwd)
,作用是一样的。
声明这个target在执行时随之生成的文件。
BYPRODUCTS需要和COMMAND配合使用,如果漏了COMMAND则会报错:
add_custom_target(
byproduct
BYPRODUCTS "aaa.txt"
)
BYPRODUCTS不会校验文件是否生成了,即使没有生成文件,也不会报错:
add_custom_target(
byproduct
COMMAND "echo" "aaa"
BYPRODUCTS "aaa.txt"
)
执行cmake .. ; make byproduct
:
make clean
会清理掉BYPRODUCTS指定的文件:
add_custom_target(
byproduct
COMMAND "touch" "aaa.txt"
COMMAND "touch" "bbb.txt"
BYPRODUCTS "aaa.txt"
)
用于修改这个target执行COMMAND时所在的路径,支持绝对路径和相对路径。
默认是在编译路径下所在的子目录。
add_custom_target(
work-dir
COMMAND "pwd"
)
这个CMakeLists.txt是在源文件的src下的:
因此执行后打印的pwd
就是在build内相应的子目录下:
对WORKING_DIRECTORY使用绝对路径:
add_custom_target(
work-dir
COMMAND "pwd"
WORKING_DIRECTORY "/root/cmake_learning/src/test-add-custom-target/build/src2"
)
执行mkdir src2 ; cmake .. ; make work-dir
。
那么执行时的路径就在配置的绝对路径下:
同样的,使用相对路径:
add_custom_target(
work-dir
COMMAND "pwd"
WORKING_DIRECTORY "../src2"
)
执行命令,也是一样的效果。
那么在修改的执行路径后,BYPRODUCTS还有没有效果呢?
add_custom_target(
work-dir
COMMAND "pwd"
COMMAND "touch" "aaa.txt"
WORKING_DIRECTORY "../src2"
BYPRODUCTS "aaa.txt"
)
可以看到文件生成成功了:
但是用了make clean
之后,文件却没有被删除。
这是因为WORKING_DIRECTORY的功能实际上是在执行每个COMMAND的命令前,先cd
到指定路径,在执行相应命令。
这是在调试过程中偶然发现的:
因此估计是BYPRODUCTS定位不到生成的文件,导致make clean
失败。
对BYPRODUCTS设置为相对路径的文件:
add_custom_target(
work-dir
COMMAND "pwd"
COMMAND "touch" "aaa.txt"
WORKING_DIRECTORY "../src2"
BYPRODUCTS "../src2/aaa.txt"
)
make clean
后删除成功了。
设置为绝对路径也成功了。