如果你要
- 在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.execmake.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的自定义命令# 模式为outputadd_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_BUILDCOMMAND 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 CopyTaskPOST_BUILDCOMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/config ${CMAKE_CURRENT_SOURCE_DIR}/etcCOMMAND ${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 clifind_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(GENERATEOUTPUT ${DOTNET_NATIVE_PATH}/$<CONFIG>/${DOTNET_NATIVE_PROJECT}.csproj.inINPUT ${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.csprojDEPENDS ${DOTNET_NATIVE_PATH}/$<CONFIG>/${DOTNET_NATIVE_PROJECT}.csproj.inCOMMAND ${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.csprojWORKING_DIRECTORY ${DOTNET_NATIVE_PATH})add_custom_target(dotnet_native_packageDEPENDS ${DOTNET_NATIVE_PATH}/${DOTNET_NATIVE_PROJECT}.csprojCOMMAND ${CMAKE_COMMAND} -E make_directory packagesCOMMAND ${DOTNET_EXECUTABLE} build -c Release ${DOTNET_NATIVE_PROJECT}/${DOTNET_NATIVE_PROJECT}.csprojCOMMAND ${DOTNET_EXECUTABLE} pack -c Release ${DOTNET_NATIVE_PROJECT}/${DOTNET_NATIVE_PROJECT}.csprojBYPRODUCTSdotnet/${DOTNET_NATIVE_PROJECT}/bindotnet/${DOTNET_NATIVE_PROJECT}/objWORKING_DIRECTORY dotnet)add_dependencies(dotnet_native_package mizux-dotnetnative-native)
