CMake:目标“test”不构建测试,目标“all”会构建。

4
我创建了一个命令行便携脚本化的工业化不可知构建系统,有助于快速构建多个依赖项目而不必依赖特定的IDE或构建工厂。它是不可知的,因为它不基于单个构建引擎。我使用了cmake创建第一个版本,因为我的项目大多是C++,但这将会发展(例如包括gradle或其他)。也就是说,我不以CMake为中心,它只是实现目标的一个工具,即易于移植的C ++项目构建。此前我考虑使用BJam,如果有更多的文档,我会一直使用它。
然而,结果是我非常依赖CMake来执行构建和单元测试。截至今天,我意识到测试是在“全部”目标下构建并在“测试”目标下运行。
对于CMake 2- (例如Unix Makefiles生成器):
make all  # Build project AND tests
make test # Run tests

使用CMake 3+和任何生成器:

cmake --build . --target all  # Build project AND tests
cmake --build . --target test # Run tests

我想知道是否有办法将“构建项目”阶段与“构建测试”阶段分开(因为在我的构建系统中,将测试构建和运行测试组合在一起感觉更自然)。
重要说明:我不想通过翻转BUILD_TESTING来引导项目的一个视角或另一个视角。想法是有三个阶段,如下所示:
cmake --build . --target <project>     # 1. Build project only
cmake --build . --target <build_tests> # 2. Build tests
cmake --build . --target <run_tests>   # 3. Run tests

如果我选择不运行测试,我可以直接从上面的第一阶段进入安装阶段,但运行第三阶段将触发先前的依赖阶段。
有什么线索吗?(如果没有,我怀疑我将不得不直接问CMake开发人员......)
提前致谢。谢谢。

可能是CMake&CTest:make test不会构建测试的重复问题。 - usr1234567
我看到了这个问题,抱怨说如果我理解正确的话,在运行测试之前没有构建它们的问题是“CMake不‘理解’我想要运行的测试是项目的一部分,因此必须先构建它。” - tomoyo255
我没有这样的问题。测试构建和运行都很好。然而,我感到尴尬的是,测试是在“all”目标下构建的,而不是在实际需要运行单元测试时构建的。就职业而言,我碰巧使用其他工具,比如Visual Studio,构建解决方案从不构建测试,而运行单元测试会构建它。这更加自然。当我构建以进行调试时,我不想等待所有测试都被构建完成,我想尽快进行调试。只有在持续集成中才有意义执行每个单元测试或者当你计划推送时才有意义。 - tomoyo255
tomoyo255:从技术上讲,你的问题可以分为两个相对独立的问题:1.如何在“所有”目标上不构建测试。2.如何在运行“run_tests”目标之前构建测试。从这个角度来看,这个问题是“过于宽泛”的,因为它包含了不止一个问题。而且,@usr1234567提到的问题实际上是第二个问题的重复。但我认为你的问题整体上很有用,整体上的答案可以帮助你和许多其他读者。 - Tsyvarev
1个回答

4
假设您选择build_tests目标来构建测试可执行文件,并选择run_tests目标来运行它们:
  1. Defining targets:

    add_custom_target(build_tests)
    # 'run_tests' triggers 'ctest'.
    add_custom_target(run_tests COMMAND ${CMAKE_CTEST_COMMAND})
    # 'run_tests' implies 'build_tests'
    add_dependencies(run_tests build_tests)
    
  2. Creating test's executables, so they won't be built by default but with build_tests target.

    # Do not build 'test1' by default
    add_executable(test1 EXCLUDE_FROM_ALL ...)
    # 'build_tests' implies (among other things) building 'test1'
    add_dependencies(build_tests test1)
    

我尝试从“all”目标(EXCLUDE_FROM_ALL)中排除测试,但它们仍然被构建。使用Unix Makefile生成器,我可以看到所有目标仍通过makefile依赖项触发单元测试构建。此外,测试高级目标不能再与您的提议一起使用(我意识到您模仿了我用作占位符的目标名称)。应该使用自定义目标(不同于高级目标如all、install、test...),我认为这会损失真正的“test”目标所提供的所有内容。无论如何,感谢您的想法。我会再考虑一下。 - tomoyo255
我可以看到所有目标仍然通过makefile依赖触发单元测试构建。这在使用EXCLUDE_FROM_ALL选项时是不太可能的。或者这样的依赖关系是由其他代码引起的。 - Tsyvarev
这似乎并不能解决问题,如果测试被排除在外,make test 将不依赖于构建测试,因此不会运行任何测试。我真的很惊讶 OP 想要的不是默认行为,目前 make install 会触发构建测试,这毫无意义。 - definelicht
@jlicht:1. 我的回答假设使用 make run_tests(而不是 make test)来构建测试并运行它们。这个假设写在第一句话中。2. 在我的代码片段中,可执行文件 test1 既不会使用 make 构建,也不会使用 make install 安装。根据问题帖子和评论的理解,OP 正好想要这样的行为,但由于某些原因他无法实现。 - Tsyvarev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接