make test
目标自动运行我的一些测试。问题是 CMake 不“理解”我想运行的测试必须被构建,因为它是项目的一部分。因此,我正在寻找一种明确指定这种依赖关系的方法。make test
目标自动运行我的一些测试。问题是 CMake 不“理解”我想运行的测试必须被构建,因为它是项目的一部分。因此,我正在寻找一种明确指定这种依赖关系的方法。其实有一种方法可以使用make test
。你需要将测试可执行文件的构建定义为其中一个测试,然后在测试之间添加依赖关系。具体是这样的:
ADD_TEST(ctest_build_test_code
"${CMAKE_COMMAND}" --build ${CMAKE_BINARY_DIR} --target test_code)
ADD_TEST(ctest_run_test_code test_code)
SET_TESTS_PROPERTIES(ctest_run_test_code
PROPERTIES DEPENDS ctest_build_test_code)
如果你正在使用 CMake >= 3.7,推荐的方法是使用 fixtures:
add_executable(test test.cpp)
add_test(test_build
"${CMAKE_COMMAND}"
--build "${CMAKE_BINARY_DIR}"
--config "$<CONFIG>"
--target test
)
set_tests_properties(test_build PROPERTIES FIXTURES_SETUP test_fixture)
add_test(test test)
set_tests_properties(test PROPERTIES FIXTURES_REQUIRED test_fixture)
以下是操作步骤:
test
,其源文件为test.cpp
test_build
的“测试”,运行Cmake来构建test
目标。test_build
测试标记为test_fixture
夹具的设置任务。test
的测试,它只运行test
可执行文件。test
测试标记为需要test_fixture
夹具。因此,每次要运行test
测试时,它首先运行测试test_build
,该测试会构建必要的可执行文件。
$<CONFIG>
没有设置,--target
将成为 --config
的参数。 - loshad vtapkah$<CONFIG>
总是非空的。它是一个配置名称的生成器表达式:https://cmake.org/cmake/help/latest/manual/cmake-generator-expressions.7.html#id2 无论如何,我会编辑答案将其用引号括起来,因为这没有任何区别。 - John Freemancmake
?我是这样做的:mkdir build; cd build; cmake ..; make
。看起来没有任何默认值,所有相关变量都为空,直到手动设置 CMAKE_BUILD_TYPE
为止。(目前在 Debian 10 上,未检查其他平台) - loshad vtapkahCMakeLists.txt
中,我添加了一个名为build_and_test
的自定义目标,用于构建和运行所有测试:find_package(GTest)
if (GTEST_FOUND)
enable_testing()
add_custom_target(build_and_test ${CMAKE_CTEST_COMMAND} -V)
add_subdirectory(test)
endif()
test/
目录下的各个子项目的CMakeLists.txt
文件中,我将每个测试可执行文件添加为build_and_test
的依赖项:include_directories(${CMAKE_SOURCE_DIR}/src/proj1)
include_directories(${GTEST_INCLUDE_DIRS})
add_executable(proj1_test proj1_test.cpp)
target_link_libraries(proj1_test ${GTEST_BOTH_LIBRARIES} pthread)
add_test(proj1_test proj1_test)
add_dependencies(build_and_test proj1_test)
make build_and_test
而不是make test
(或者make all test
),它的好处是只编译测试代码及其依赖项。很遗憾我不能使用目标名称test
。在我的情况下,这并不太糟糕,因为我有一个顶层脚本,通过调用cmake
和make
进行带外调试和发布(以及交叉编译)构建,并将test
转换为build_and_test
。ctest -V
,它会在测试运行时显示Google Test输出:1: Running main() from gtest_main.cc
1: [==========] Running 1 test from 1 test case.
1: [----------] Global test environment set-up.
1: [----------] 1 test from proj1
1: [ RUN ] proj1.dummy
1: [ OK ] proj1.dummy (0 ms)
1: [----------] 1 test from proj1 (1 ms total)
1:
1: [----------] Global test environment tear-down
1: [==========] 1 test from 1 test case ran. (1 ms total)
1: [ PASSED ] 1 test.
1/2 Test #1: proj1_test ....................... Passed 0.03 sec
make check
,您可能会发现这个维基条目很有用:
http://www.cmake.org/Wiki/CMakeEmulateMakeCheck
我刚刚检查了它是否成功实现(CMake 2.8.10)。make check
时,这将构建所有可执行文件。对于编译时间占主导地位的测试,这使得 ctest -R
无用。 - usr1234567节省你的头痛:
make all test
这对我来说很容易使用,会在运行测试前构建依赖项。鉴于它的简单性,这几乎使原生的make test
功能变得更加方便,因为它让您有选择地运行最后一次编译测试,即使您的代码出现了错误。
make -j4 all && make test
。而且如果使用非 Make 构建工具,这种方法也会不太稳定。 - poolieTEST_INCLUDE_FILES
目录属性来设置在运行测试之前触发构建的脚本。在你的最外层的 CMakeLists.txt
中加入以下代码:set_property(DIRECTORY APPEND
PROPERTY TEST_INCLUDE_FILES "${CMAKE_CURRENT_BINARY_DIR}/BuildTestTarget.cmake")
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/BuildTestTarget.cmake"
"execute_process(COMMAND \"${CMAKE_COMMAND}\""
" --build \"${CMAKE_BINARY_DIR}\""
" --config \"\$ENV{CMAKE_CONFIG_TYPE}\")")
实际测试配置通过环境变量 CMAKE_CONFIG_TYPE
传递到构建中。可选择添加 --target
选项来仅构建测试所需的目标。
这是我制定并一直在使用的内容:
set(${PROJECT_NAME}_TESTS a b c)
enable_testing()
add_custom_target(all_tests)
foreach(test ${${PROJECT_NAME}_TESTS})
add_executable(${test} EXCLUDE_FROM_ALL ${test}.cc)
add_test(NAME ${test} COMMAND $<TARGET_FILE:${test}>)
add_dependencies(all_tests ${test})
endforeach(test)
build_command(CTEST_CUSTOM_PRE_TEST TARGET all_tests)
string(CONFIGURE \"@CTEST_CUSTOM_PRE_TEST@\" CTEST_CUSTOM_PRE_TEST_QUOTED ESCAPE_QUOTES)
file(WRITE "${CMAKE_BINARY_DIR}/CTestCustom.cmake" "set(CTEST_CUSTOM_PRE_TEST ${CTEST_CUSTOM_PRE_TEST_QUOTED})" "\n")
YMMV
Derrick的答案,简化并加注释:
# It is impossible to make target "test" depend on "all":
# https://gitlab.kitware.com/cmake/cmake/-/issues/8774
# Set a magic variable in a magic file that tells ctest
# to invoke the generator once before running the tests:
file(WRITE "${CMAKE_BINARY_DIR}/CTestCustom.cmake"
"set(CTEST_CUSTOM_PRE_TEST ${CMAKE_MAKE_PROGRAM})\n"
)
这并不是完全正确的解决方案,因为它无法解决运行ninja all test
时的并发问题,如果有人这样做的话。相反,现在你有两个ninja进程。
(顺便说一句,我也在这里分享了这个解决方案here。)
所有上面的答案都是完美的。但实际上,CMake使用CTest作为其测试工具,因此完成任务的标准方法(我认为)是:
enable_testing ()
add_test (TestName TestCommand)
add_test (TestName2 AnotherTestCommand)
然后运行cmake和make来构建目标。之后,您可以运行make test,或者只需运行
ctest
你将会得到结果。这已经在 CMake 2.8 下测试过。
详细信息请查看:http://cmake.org/Wiki/CMake/Testing_With_CTest#Simple_Testing