cmake构建后处理事件

使用add_custom_command()函数

参考官方文档:https://cmake.org/cmake/help/v3.20/command/add_custom_command.html#command:add_custom_command

之前使用Visual Studio 2010时记得有在项目配置里写后处理事件的脚本,经常遇到权限问题,那时以为是Visual Studio 2010 特别地执行后处理,但其实cmake的函数非常丰富,自带这些需求。windows平台的软件开发真得不堪回首。。。

add_custom_command()函数增加自定义的构建规则到生成的构建系统(我理解就是生成的Makefile,集成了构建系统的参数以及这里增加的自定义的构建规则)。

有两个主要的签名:

1、第一个签名用来增加一个生成输出(文件)的自定义命令

自定义命令可被用来生成源文件。例如:

add_custom_command(
  OUTPUT out.c
  COMMAND someTool -i ${CMAKE_CURRENT_SOURCE_DIR}/in.txt
                   -o out.c
  DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/in.txt
  VERBATIM)
add_library(myLib out.c)

这里增加了一个自定义命令,对生成的out.c执行somTool,然后编译生成的源文件为库的一部分。当in.txt发生改变时该生成规则将再次运行。

栗子,官网给出的Examples: Generation Files说自定义命令可被用来生成源文件。我最终尝试的结果是生成的源文件还必须参与构建目标则add_custom_command()才会被执行。

add_custom_command(
  OUTPUT cache.cpp  #Custom commands may be used to generate source files
  COMMAND cp ${CMAKE_CURRENT_SOURCE_DIR}/tiny_main.cpp cache.cpp
  DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/tiny_main.cpp
  VERBATIM
)
add_executable(cache cache.cpp)   #上面"生成的"输出文件OUTPUT必须作为源文件参与构建目标则add_custom_command()才会被执行
# message(STATUS "$<OUTPUT>file is: " cache.cpp)  #不作为源文件用途的其他使用都不会触发add_custom_command()被执行!

官网还介绍了cmake 3.20新增的特性:可以使用cmake的表达式来指定每个配置的输出。例如:

add_custom_command(
  OUTPUT "out-$<CONFIG>.c"
  COMMAND someTool -i ${CMAKE_CURRENT_SOURCE_DIR}/in.txt
                   -o "out-$<CONFIG>.c"
                   -c "$<CONFIG>"
  DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/in.txt
  VERBATIM)
add_library(myLib "out-$<CONFIG>.c")

这里<config>是构建配置,我尝试先message打印这个$<CONFIG>但没打印出什么东西,在cmake时也增加了比如--config、--verbose配置,这里d的$<config>配置不知道指的啥配置?

2、构建事件

第二个签名增加自定义的命令到构建目标,比如一个库或可执行程序。当要在构建目标之前或之后执行一些操作时很有用。此时该自定义命令成为所构建的目标的一部分并且只当目标本身被构建后才被执行。如果目标已经被构建过,则命令不会被执行。

add_custom_command(TARGET <target>
                   PRE_BUILD | PRE_LINK | POST_BUILD
                   COMMAND command1 [ARGS] [args1...]
                   [COMMAND command2 [ARGS] [args2...] ...]
                   [BYPRODUCTS [files...]]
                   [WORKING_DIRECTORY dir]
                   [COMMENT comment]
                   [VERBATIM] [USES_TERMINAL]
                   [COMMAND_EXPAND_LISTS])

这定义了一个与构建指定<target>相关的新的命令。<target>必须在当前目录被定义(指当前CMakeLists.txt表示的层级?);在其他目录中定义的targets可能不许指定。

命令何时发生取决于以下哪项被指定:

PRE_BUILD:在Visual Studio Generators,在target的其他规则被执行前执行。在其他生成器中,只在PRE_LINK命令之前执行;

PRE_LINK:在源文件们sources被编译之后但在链接二进制.o中间文件或执行静态库的librarian或archiver之前被执行(这是说在源文件被编译成xxx.o之后,但在链接其他.o文件或链接静态库.a或动态库.so之前)。

POST_BUILD:在target相关的所有其他规则(PRE_BUILD与PRE_LINK的规则)已被执行之后执行。

官网给出的第二个栗子:

add_library(myPlugin MODULE myPlugin.c)
add_custom_command(
  TARGET myPlugin POST_BUILD
  COMMAND someHasher -i "$<TARGET_FILE:myPlugin>"
                     --as-code "myPlugin-hash-$<CONFIG>.c"
  BYPRODUCTS "myPlugin-hash-$<CONFIG>.c"
  VERBATIM)
add_executable(myExe myExe.c "myPlugin-hash-$<CONFIG>.c")

将在链接完myPlugin后执行someHaser,比如生成包含有检查myPlugin的哈嘻的代码的一个.c文件,从而myExe可执行程序能在加载"myPlugin-hash-$<CONFIG>.c"之前验证它。这里自定义命令生成的副产品BYPRODUCTS被构建目标myExe所引用,从而构建时首先执行自定义命令。

另外比如经常需要的拷贝${PROJECT_BINARY_DIR}的targets到别处的后处理命令:

add_custom_command(
  TARGET Tutorial
  PRE_BUILD
  COMMAND echo "test POST_BUILD"
  COMMAND pwd   #就是执行cmake的目录,或者WORKING_DIRECTORY如果有的话
  COMMAND ls -l #由于是PRE_BUILD,此时目标Tutorial还没有生成
  # WORKING_DIRECTORY ${PROJECT_BINARY_DIR} #将在执行本条自定义命令时首先cd到WORKING_DIRECTORY
  COMMENT "comment: test POST_BUILD" #注释内容将在打印COMMAND输出之前首先输出
)
message(STATUS "$<CMAKE_CURRENT_SOURCE_DIR> in project: " ${CMAKE_CURRENT_SOURCE_DIR})  #/Users/haypin/cmake_tutorial/Step5
add_custom_command(TARGET Tutorial
  POST_BUILD  
  COMMAND cp ${PROJECT_BINARY_DIR}/Tutorial ${PROJECT_SOURCE_DIR}/Tutorial_bin
)

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值