CMake中的全局自定义目标

时间:2015-04-05 11:49:32

标签: unit-testing cmake target

我想用CMake写一个小单元测试系统,我可以轻松地复制并粘贴到我的所有项目中,所以我想出了这个:

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(...)相同的参数。实际上,这个错误出现了:

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)

有没有办法可以将自定义命令添加到UNIT_TEST目标?

1 个答案:

答案 0 :(得分:1)

刚刚遇到了您的问题并尝试重现您的问题。

我的第一个建议是:如果你致电enable_testing(),你会直接获得由CMake生成的“运行测试”目标。见CMake: Testing with CTest

  

构建项目后,您可以通过

执行所有测试
make test
     

使用Makefile生成器,或者通过重建RUN_TESTS目标   你骑。在内部,它运行CTest以实际执行测试;   你也可以执行

ctest
     

在构建的二进制目录中。

调试您的指定代码

如果我将有效目标命名为add_unit_test()的第一个参数,则表示我未收到CMP0040错误。因此,请再次检查您是否提供了有效的目标。

但是你的脚本中有一些错误。这是一个工作版本:

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()
  • 删除_
  • UT的结尾cmake_parse_arguments(UT ...)
  • 将空字符串与STREQUAL ""
  • 进行比较
  • V添加ARGV1并转到第二个参数(索引0为dependency
  • 删除不需要VERBATIM
  • 添加了所需的-C $<CONFIGURATION>参数(请参阅How to run ctest after building my project with cmake
  • 将RegEx更改为"^${UT_NAME}$"以获取完全匹配的名称

将上述代码移至名为UnitTest.cmake的文件中我已成功使用以下主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>)