CMake中的全局自定义目标 [英] Global custom target in CMake

查看:468
本文介绍了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 ...)
  • UT的尾随_
  • STREQUAL ""
  • 比较空字符串
  • ARGV1中添加了V并使用了第二个参数(索引0为dependency)
  • 已删除不需要VERBATIM
  • 添加了所需的-C $<CONFIGURATION>参数(请参见如何使用cmake构建项目后运行ctest )
  • 将RegEx更改为"^${UT_NAME}$"以进行精确名称匹配
    • Added enable_testing()
    • Removed the trailing _ of UT in cmake_parse_arguments(UT ...)
    • Compare for empty string with STREQUAL ""
    • Added a V to ARGV1 and going for the second parameter (index 0 is dependency)
    • 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
    • 将上面的代码移动到名为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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆