CMake中的全局自定义目标 [英] Global custom target in CMake
问题描述
我想用CMake编写一个小的单元测试系统,我可以轻松地将其复制并粘贴到我的所有项目中,所以我想到了:
I wanted to write a little Unit-test system with CMake that I can easily copy and paste in all my projects so I came up with this:
include(CMakeParseArguments)
set(UNIT_TEST "unit_tests")
add_custom_target(${UNIT_TEST} ALL VERBATIM)
function(add_unit_test dependency)
cmake_parse_arguments(UT_ "" "NAME" "" ${ARGN})
if(NOT ${UT_NAME})
set(${UT_NAME} ${ARG0})
endif()
add_test(${ARGN})
add_dependencies(${UNIT_TEST} ${dependency})
add_custom_command(TARGET ${UNIT_TEST}
COMMENT "Run tests"
POST_BUILD COMMAND ctest
ARGS -R ${UT_NAME} --output-on-failures
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
VERBATIM)
endfunction(add_unit_test)
我希望它可以像这样正常运行,并运行我将在项目中添加的所有单元测试,方法是调用add_unit_test(dep ...)
,该编译器具有先编译的依赖项,然后再使用与add_test(...)
相同的参数.实际上,此错误显示出来:
I hoped that it would work fine like that and run all unit tests I would add in my project by calling add_unit_test(dep ...)
with a dependency to compile before and then the same arguments as for add_test(...)
. In reality this error shows up:
CMake Warning (dev) at cmake/testing.cmake:13 (add_custom_command):
Policy CMP0040 is not set: The target in the TARGET signature of
add_custom_command() must exist. Run "cmake --help-policy CMP0040" for
policy details. Use the cmake_policy command to set the policy and
suppress this warning.
The target name "unit_tests" is unknown in this context.
Call Stack (most recent call first):
source/test/CMakeLists.txt:10 (add_unit_test)
This warning is for project developers. Use -Wno-dev to suppress it.
为什么此时目标尚不明确? include(cmake/testing.cmake)
是我在项目构建脚本中在cmake_minimum_required
之后调用的第一件事,所以不可能是因为尚未调用add_custom_target(${UNIT_TEST} ALL VERBATIM)
.
Why exactly is the target unknown at this point? include(cmake/testing.cmake)
is the first thing I call after cmake_minimum_required
in my project build script, so it can't be because add_custom_target(${UNIT_TEST} ALL VERBATIM)
hasn't been called yet.
是否可以将自定义命令添加到UNIT_TEST目标?
Is there a way I can add a custom command to the UNIT_TEST target?
推荐答案
只是遇到您的问题并试图重现您的问题.
Just came across your question and tried to reproduce your problem.
我的第一个建议是:如果您调用enable_testing()
,您将直接获得CMake生成的运行测试"目标.请参见 CMake:使用CTest进行测试:
My first recommendation would be: if you call enable_testing()
you directly get a "Run Tests" target generated by CMake. See CMake: Testing with CTest:
构建项目后,您可以通过以下方式执行所有测试
Once you have built the project, you can execute all tests via
make test
使用Makefile生成器,或通过重建RUN_TESTS目标 你骑.在内部,这运行CTest来实际执行测试; 你也可以执行
with Makefile generators, or by rebuilding the RUN_TESTS target in your IDE. Internally this runs CTest to actually perform the testing; you could just as well execute
ctest
在您构建的二进制目录中.
in the binary directory of your build.
调试您的给定代码
如果我将有效目标命名为add_unit_test()
的第一个参数,则不会出现CMP0040
错误.因此,只需再次检查您是否指定了有效的目标即可.
If I name a valid target as the first parameter of your add_unit_test()
I don't get the CMP0040
error. So just check again that you give a valid target.
但是您的脚本中有一些错误.这是一个工作版本:
But your script has some errors in it. Here is a working version:
include(CMakeParseArguments)
enable_testing()
set(UNIT_TEST "unit_tests")
add_custom_target(${UNIT_TEST} ALL)
function(add_unit_test dependency)
cmake_parse_arguments(UT "" "NAME" "COMMAND" ${ARGN} )
if("${UT_NAME}" STREQUAL "")
set(${UT_NAME} "${ARGV1}")
endif()
add_test(${ARGN})
add_dependencies(${UNIT_TEST} ${dependency})
add_custom_command(TARGET ${UNIT_TEST}
COMMENT "Run tests"
POST_BUILD COMMAND ctest
ARGS -C $<CONFIGURATION> -R "^${UT_NAME}$" --output-on-failures)
endfunction(add_unit_test)
- 添加了
enable_testing()
- 删除了
cmake_parse_arguments(UT ...)
中 - 用
STREQUAL ""
比较空字符串
- 在
ARGV1
中添加了V
并使用了第二个参数(索引0为dependency
) - 已删除不需要
VERBATIM
- 添加了所需的
-C $<CONFIGURATION>
参数(请参见如何使用cmake构建项目后运行ctest ) - 将RegEx更改为
"^${UT_NAME}$"
以进行精确名称匹配 - Added
enable_testing()
- Removed the trailing
_
ofUT
incmake_parse_arguments(UT ...)
- Compare for empty string with
STREQUAL ""
- Added a
V
toARGV1
and going for the second parameter (index 0 isdependency
) - Removed not needed
VERBATIM
- Added needed
-C $<CONFIGURATION>
parameter (see How to run ctest after building my project with cmake) - Changed the RegEx to
"^${UT_NAME}$"
for exact name matching
UT
的尾随_
将上面的代码移动到名为UnitTest.cmake
的文件中,我已经成功使用以下主要CMakeLists.txt
测试了
Moving the above code into a file called UnitTest.cmake
I have successfully tested with the following main CMakeLists.txt
:
cmake_minimum_required(VERSION 2.8)
project(Example CXX)
include(${CMAKE_CURRENT_LIST_DIR}/UnitTest.cmake)
file(WRITE foo.cc "#include <windows.h>\nint main() {\nreturn 0;\n}")
add_executable(MyTest foo.cc)
add_unit_test(MyTest NAME SomeTest COMMAND $<TARGET_FILE:MyTest>)
add_executable(MyTest2 foo.cc)
add_unit_test(MyTest2 NAME SomeTest2 COMMAND $<TARGET_FILE:MyTest2>)
这篇关于CMake中的全局自定义目标的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!