如果你要
- 在cmake中创建一些目标,做
clean
、copy
等操作 - 在cmake某些对象编译之后,再做某些操作(延迟执行)
就可以使用add_custom_command
或add_custom_target
自定义目标add_custom_target
add_custom_target
的用处:增加一个没有输出的目标,使得它总是被构建
add_custom_target(Name [ALL] [command1 [args1...]]
[COMMAND command2 [args2...] ...]
[DEPENDS depend depend depend ... ]
[BYPRODUCTS [files...]]
[WORKING_DIRECTORY dir]
[COMMENT comment]
[JOB_POOL job_pool]
[VERBATIM] [USES_TERMINAL]
[COMMAND_EXPAND_LISTS]
[SOURCES src1 [src2...]])
这个命令参数有点多,其实不需要全部了解
例:拷贝文件与拷贝文件夹
cmake_minimum_required(VERSION 3.0)
project(test)
# 添加一个名为CopyTask的自定义目标
## 注:但这个目标没有输出(动态库、静态库、可执行文件)
add_custom_target(CopyTask
#第一个命令
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/config ${CMAKE_CURRENT_SOURCE_DIR}/etc
#第二个命令
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/log.txt ${CMAKE_CURRENT_SOURCE_DIR}/etc
#如果还有命令,可以继续添加
)
${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/config ${CMAKE_CURRENT_SOURCE_DIR}/etc
${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/log.txt ${CMAKE_CURRENT_SOURCE_DIR}/etc
这两条命令,都是调用cmake.exe
进行操作的,一个是拷贝文件夹,一个是拷贝文件
${CMAKE_COMMAND}
的值是D:/software/CMake/bin/cmake.exe
cmake.exe -E
是Cmake的命令模式,具体可以运行cmake --help
、cmake -E
查看帮助文档
自定义命令add_custom_command
用途:将自定义构建规则添加到生成的构建系统
自定义命令有两种使用场景:生成文件、构建事件
生成文件
第一种是输出模式,即OUTPUT
。用在生成文件的场景中,即添加一个定制命令来生成文件。
add_custom_command(OUTPUT output1 [output2 ...]
COMMAND command1 [ARGS] [args1...]``
[COMMAND command2 [ARGS] [args2...] ...]
[MAIN_DEPENDENCY depend]
[DEPENDS [depends...]]
[BYPRODUCTS [files...]]
[IMPLICIT_DEPENDS <lang1> depend1
[<lang2> depend2] ...]
[WORKING_DIRECTORY dir]
[COMMENT comment]
[DEPFILE depfile]
[JOB_POOL job_pool]
[VERBATIM] [APPEND] [USES_TERMINAL]
[COMMAND_EXPAND_LISTS])
参数简述:
OUTPUT
:指定命令预期产生的输出文件。如果输出文件的名称是相对路径,即相对于当前的构建的源目录路径;COMMAND
:指定要在构建时执行的命令行;DEPENDS
:指定命令所依赖的文件;COMMENT
:在构建时执行命令之前显示给定消息;WORKING_DIRECTORY
:使用给定的当前工作目录执行命令。如果它是相对路径,它将相对于对应于当前源目录的构建树目录;DEPFILE
:为生成器指定一个.d depfile .d文件保存通常由自定义命令本身发出的依赖关系;MAIN_DEPENDENCY
:指定命令的主要输入源文件;BYPRODUCTS
:指定命令预期产生的文件。
例:拷贝文件与拷贝文件夹
cmake_minimum_required(VERSION 3.0)
project(test)
# 添加一个名字为COPY_RES的自定义命令
# 模式为output
add_custom_command(OUTPUT COPY_RES
# 第一条命令:拷贝目录
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/config ${CMAKE_CURRENT_SOURCE_DIR}/etc
# 第二条命令:拷贝文件
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/log.txt ${CMAKE_CURRENT_SOURCE_DIR}/etc
)
# 添加一个名字为CopyTask的自定义目标
add_custom_target(CopyTask ALL DEPENDS COPY_RES)
### 该目标依赖于COPY_RES,COPY_RES是上面添加的自定义命令
构建事件
另一种是构建事件:为某个Target添加一个定制命令,这个命令会在某个时间触发
触发的时间点有三种选项:
参数 | 含义 |
---|---|
PRE_BUILD |
在target build之前触发这个命令(即生成前事件) |
PRE_LINK |
在编译源代码之后,链接二进制文件(或库文件)之前触发命令 |
POST_BUILD |
在Target所有规则均运行后触发命令(即生成后事件) |
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])
- TARGET:指定命令运行的目标;
- COMMAND:指定要在构建时执行的命令行;
- COMMENT:在构建时执行命令之前显示给定消息;
- WORKING_DIRECTORY:使用给定的当前工作目录执行命令。如果它是相对路径,它将相对于对应于当前源目录的构建树目录;
- BYPRODUCTS:指定命令预期产生的文件。
例:拷贝文件与拷贝文件夹
cmake_minimum_required(VERSION 3.0)
project(test)
# 添加一个名字为CopyTask的目标
add_custom_target(CopyTask)
# 注意:add_custom_command需要写在add_custom_target之后,否则将cmake不通过
# 添加一个自定义命令
add_custom_command(TARGET CopyTask
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/config ${CMAKE_CURRENT_SOURCE_DIR}/etc
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/log.txt ${CMAKE_CURRENT_SOURCE_DIR}/etc
)
execute_process
其他例子
生成后构建C#工程
set(csc csc.exe)
# 添加一个自定义命令
ADD_CUSTOM_COMMAND(TARGET #模式为“构建事件”
cxx_module_name POST_BUILD #cxx_module_name目标生成后进行触发
COMMAND #具体命令
#第一条命令
${csc}
#该命令的参数
-t:library -platform:x64 "${csharp_depends_libs}"
-out:${CSHARP_LIBRARY_OUTPUT_PATH}\\${project_name}.dll
-langversion:default
-doc:${CSHARP_LIBRARY_OUTPUT_PATH}\\${project_name}.xml
${csharp_srcs} #.cs文件列表
)
综合示例:生成dotnet工程
https://github.com/Mizux/cmake-swig.git
#寻找dotnet的执行文件,需要安装dotnet
# Find dotnet cli
find_program(DOTNET_EXECUTABLE NAMES dotnet)
if(NOT DOTNET_EXECUTABLE)
message(FATAL_ERROR "Check for dotnet Program: not found")
else()
message(STATUS "Found dotnet Program: ${DOTNET_EXECUTABLE}")
endif()
###接下来是一组lib或者可执行程序。这里选取Mizux.Foo.runtime.<RID>, Mizux.Foo和Mizux.FooApp分析
############################
## .Net Runtime Package ##
############################
message(STATUS ".Net runtime project: ${DOTNET_NATIVE_PROJECT}")
set(DOTNET_NATIVE_PATH ${PROJECT_BINARY_DIR}/dotnet/${DOTNET_NATIVE_PROJECT})
message(STATUS ".Net runtime project build path: ${DOTNET_NATIVE_PATH}")
# *.csproj.in contains:
# CMake variable(s) (@PROJECT_NAME@) that configure_file() can manage and
# generator expression ($<TARGET_FILE:...>) that file(GENERATE) can manage.
configure_file(
${PROJECT_SOURCE_DIR}/dotnet/${DOTNET_PACKAGE}.runtime.csproj.in
${DOTNET_NATIVE_PATH}/${DOTNET_NATIVE_PROJECT}.csproj.in
@ONLY) ###替换其中@xxx@的变量
### dotnet/Mizux.Foo.runtime.csproj.in 复制到 build/dotnet/Mizux.Foo.runtime/csproj.in 并替换其中@xxx@的变量
file(GENERATE
OUTPUT ${DOTNET_NATIVE_PATH}/$<CONFIG>/${DOTNET_NATIVE_PROJECT}.csproj.in
INPUT ${DOTNET_NATIVE_PATH}/${DOTNET_NATIVE_PROJECT}.csproj.in)
###根据build/dotnet/Mizux.Foo.runtime.csproj.in 产生文件 build/dotnet/Release/Mizux.Foo.runtime.csproj.in
###其中$<xxx>的部分会被替换
add_custom_command(
OUTPUT ${DOTNET_NATIVE_PATH}/${DOTNET_NATIVE_PROJECT}.csproj
###build/dotnet/Mizux.Foo.runtime.linux-x64/Mizux.Foo.runtime.linux-x64.csproj
DEPENDS ${DOTNET_NATIVE_PATH}/$<CONFIG>/${DOTNET_NATIVE_PROJECT}.csproj.in
COMMAND ${CMAKE_COMMAND} -E copy ./$<CONFIG>/${DOTNET_NATIVE_PROJECT}.csproj.in ${DOTNET_NATIVE_PROJECT}.csproj
###build/dotnet/Release/Mizux.Foo.runtime.csproj.in 复制到
### build/dotnet/Mizux.Foo.runtime.linux-x64/Mizux.Foo.runtime.linux-x64.csproj
WORKING_DIRECTORY ${DOTNET_NATIVE_PATH}
)
add_custom_target(dotnet_native_package
DEPENDS ${DOTNET_NATIVE_PATH}/${DOTNET_NATIVE_PROJECT}.csproj
COMMAND ${CMAKE_COMMAND} -E make_directory packages
COMMAND ${DOTNET_EXECUTABLE} build -c Release ${DOTNET_NATIVE_PROJECT}/${DOTNET_NATIVE_PROJECT}.csproj
COMMAND ${DOTNET_EXECUTABLE} pack -c Release ${DOTNET_NATIVE_PROJECT}/${DOTNET_NATIVE_PROJECT}.csproj
BYPRODUCTS
dotnet/${DOTNET_NATIVE_PROJECT}/bin
dotnet/${DOTNET_NATIVE_PROJECT}/obj
WORKING_DIRECTORY dotnet
)
add_dependencies(dotnet_native_package mizux-dotnetnative-native)