本文介绍了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

target默认不在all target中

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-name>才会执行:

以上打印了这个target的COMMAND信息,以及target build完成了。

ALL

在声明target的时候,可以加上ALL,这个target就会加入all target中,默认进行执行了。

add_custom_target(
    print-pwd
    ALL
    COMMAND "pwd"
)

DEPENDS

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),作用是一样的。

BYPRODUCTS

声明这个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"
)

执行结果:

执行make clean

WORKING_DIRECTORY

用于修改这个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后删除成功了。
设置为绝对路径也成功了。

来源:kendyChina

物联沃分享整理
物联沃-IOTWORD物联网 » CMake之add_custom_target

发表评论