In order to be able to run ctest from the top level build directory, it is necessary that enable_testing() is invoked in the top level CMakeLists.txt file. The CTest module invokes enable_testing() based on the value of BUILD_TESTING.
CTest: Module must be included at the top level #145
pull purpleKarrot wants to merge 1 commits into bitcoin-core:master from purpleKarrot:fix-testing changing 2 files +1 −2-
purpleKarrot commented at 2:19 PM on February 1, 2025: contributor
-
hebasto commented at 2:27 PM on February 1, 2025: member
I don't think this project should
include(CTest)in the first place. Besides callingenable_testing(), it also performs some CDash-related actions, which are unnecessary. -
purpleKarrot commented at 2:37 PM on February 1, 2025: contributor
The minimum replacement would be:
option(BUILD_TESTING "Build the testing tree." ON) include(CTestUseLaunchers) if(BUILD_TESTING) enable_testing() endif()The
CTestUseLaunchersmodule should not be omitted. -
hebasto commented at 2:38 PM on February 1, 2025: member
The
CTestUseLaunchersmodule should not be omitted.Why?
- purpleKarrot force-pushed on Feb 1, 2025
-
purpleKarrot commented at 2:40 PM on February 1, 2025: contributor
Because otherwise cmake produces an error when
CTEST_USE_LAUNCHERSis on. -
ryanofsky commented at 5:50 PM on February 3, 2025: collaborator
These changes look good to me and make sense to the extent I understand them (which is not very much), but it would be helpful to have some steps to reproduce, just to be able to see what was broken and compare different fixes that have been suggested here.
-
purpleKarrot commented at 9:35 PM on February 3, 2025: contributor
Try executing the following commands and see what error you get:
mkdir build cd build cmake .. make -j 10 ctest -j 10The way you probably used to invoke testing on the command line is the following:
make -j 10 checkThis worked, because the
checktarget is defined in a subdirectory where testing was enabled. However, there is a catch with this approach:What do you think how many tests are executed in parallel when the target
checkis built with-j 10? The answer is: one. The-joption is passed to the build tool, so the build tool runs 10 jobs in parallel. One of these jobs is to launchctestwithout any options. So the tests are executed without any parellelization. (Which is not a big problem in this repository, because there is just one test anyway. But people will want to use the same approach (or user-specific aliases) to build and test any CMake project.)Therefore, the best recommendation is to run
ctestexplicitly, not via a build target. Make sure that the default target builds all tests whenBUILD_TESTINGis enabled, otherwise the tests will report failure because their executable is not found. -
ryanofsky commented at 12:50 PM on February 4, 2025: collaborator
Thanks!
The previous version of this PR 9d841a416c39a2ff31982f937ae5345bff9e5ee8 looks much more straightforward than current version 5f9162fbaa788db54bf9b1eda2dad0102b1be20c, and doesn't add a new build option, so I would really prefer it. @hebasto you wrote https://github.com/chaincodelabs/libmultiprocess/pull/145#issuecomment-2628973879 "I don't think this project should include(CTest) in the first place" because it is doing some unnecessary things. Why is this a problem? The build is written in cmake not rust so by definition is going to do a lot of unnecessary things, I would want to know what practical downsides to simple
include(CTest)are if any -
hebasto commented at 1:04 PM on February 4, 2025: member
@hebasto you wrote #145 (comment) "I don't think this project should include(CTest) in the first place" because it is doing some unnecessary things. Why is this a problem? The build is written in cmake not rust so by definition is going to do a lot of unnecessary things, I would want to know what practical downsides to simple
include(CTest)are if anyFor example,
include(CTest)creates unusedDartConfiguration.tclin the build tree. I don't think this is a user-facing drawback, though. However, this pertains to the intentions behind the code. If the intention is to enable test generation for theadd_test()command, the CMake docs state:CMake only generates tests if the
enable_testing()command has been invoked. -
in CMakeLists.txt:18 in 5f9162fbaa outdated
9 | @@ -10,6 +10,12 @@ if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) 10 | set(CMAKE_CXX_STANDARD_REQUIRED YES) 11 | endif() 12 | 13 | +option(BUILD_TESTING "Build the testing tree." ON) 14 | +if(BUILD_TESTING) 15 | + enable_testing() 16 | +endif() 17 | + 18 | +include(CTestUseLaunchers)
hebasto commented at 1:07 PM on February 4, 2025:What scenarios would this be useful for in this project?
purpleKarrot commented at 1:28 PM on February 4, 2025: contributorSome background information about this
DartConfiguration.tclfile: https://purplekarrot.net/blog/building-and-testing-with-cmake.html https://purplekarrot.net/blog/refactoring-ctest.htmlIt is no longer up to date, because some of the refactoring has already be done.
ryanofsky commented at 1:28 PM on February 4, 2025: collaboratorI'd be fine with either calling include(CTest) or enable_testing() unconditionally, since the intention should be to always enable testing. I don't think a separate build option should be required. If include(CTest) does unnecessary things, that's an implementation detail of CMake, which should only matter if it has a noticeable impact on performance.
So unless a bare enable_testing() call breaks something, I’d prefer using that. If it does break use cases, then include(CTest) would be fine.
purpleKarrot commented at 2:22 PM on February 4, 2025: contributorProprietary software is developed and tested by a single entity. Very often, the configuration for CI is located in the project's repository and the CI configuration is intertwined with the project configuration (example: the project configuration has options for sanitizers and coverage).
For software that is developed in public, a separation of project configuration and CI configuration brings advantages. Ideally, everyone is able to contribute CI resources, sometimes for platforms the project's main developers do not even have access to. Project configuration should be written in a way that it supports the widest range of CI configurations and that just means: Make no assumption about what software is installed, what environment variables are set, and what cmake variables are set.
This also includes the cmake variable
CTEST_USE_LAUNCHERS: Don't assume whether it is set or not, the project should be able to be configured in both cases. But when it is set andCTestUseLaunchersis not included, cmake will produce the following error:CMake Error: CTEST_USE_LAUNCHERS is enabled, but the RULE_LAUNCH_COMPILE global property is not defined. Did you forget to include(CTest) in the toplevel CMakeLists.txt ?Hence, having
include(CTest)in the toplevel CMakeLists.txt probably really is the most convenient approach. I agree that the added.tclfile and targets likeNightlyCoverageare a bit annoying. But that is something that should be fixed in upstream cmake.purpleKarrot force-pushed on Feb 4, 2025in CMakeLists.txt:13 in e7329aed0f outdated
9 | @@ -10,6 +10,7 @@ if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) 10 | set(CMAKE_CXX_STANDARD_REQUIRED YES) 11 | endif() 12 | 13 | +include(CTest)
ryanofsky commented at 3:58 PM on February 4, 2025:In commit "CTest: Module must be included at the top level" (e7329aed0f711400d7a14ce8d5edbede03b1e75b)
Would it work to move this include down by other includes like
include(GNUInstallDirs)below around line 45? This compat_find include on line 13 is meant to be a special case, not primary place where includes are located.Also, in case we do decide to make this include conditional based on whether a build option is set, or whether this is a top-level project it would be better if this happened below where more conditions should be known.
ryanofsky approvedryanofsky commented at 3:59 PM on February 4, 2025: collaboratorCode review ACK e7329aed0f711400d7a14ce8d5edbede03b1e75b.
I like idea of project/ci separation and just in general, minimizing any assumptions we make about how this build will be used and keeping it generic. If there are practical problems with this include we can address them but at a high level this seems like a good approach.
purpleKarrot force-pushed on Feb 4, 202563ac092dddCTest: Module must be included at the top level
In order to be able to run `ctest` from the top level build directory, it is necessary that `enable_testing()` is invoked in the top level CMakeLists.txt file. The `CTest` module invokes `enable_testing()` based on the value of `BUILD_TESTING`.
hebasto approvedhebasto commented at 7:25 PM on February 4, 2025: memberACK 63ac092ddd8156b5eb56f2302b3d03ba739cf9ce, tested on Ubuntu 24.04:
$ cmake -B build $ cmake --build build -t mptests $ ctest --test-dir buildryanofsky merged this on Feb 5, 2025ryanofsky closed this on Feb 5, 2025ryanofsky referenced this in commit 1d75538a32 on Feb 5, 2025ryanofsky referenced this in commit 9437e6846f on Feb 7, 2025ryanofsky referenced this in commit a4a8f7a7ba on Feb 7, 2025hebasto commented at 7:31 AM on February 8, 2025: memberI don't think this project should
include(CTest)in the first place. Besides callingenable_testing(), it also performs some CDash-related actions, which are unnecessary.I forgot to mention another drawback of using
include(CTest).This command introduces the
BUILD_TESTINGcache variable, which can sneak into downstream projects.For example, in https://github.com/bitcoin/bitcoin/pull/31741, after reconfiguring with
-DENABLE_IPC=ON,BUILD_TESTINGappears in the CMake cache along with the Bitcoin Core project'sBUILD_TESTS, which might be confusing at the very least.ryanofsky referenced this in commit 3a95817ece on Feb 10, 2025ryanofsky referenced this in commit a7f0669320 on Feb 10, 2025ryanofsky commented at 5:26 AM on February 10, 2025: collaboratorre: https://github.com/chaincodelabs/libmultiprocess/pull/145#issuecomment-2644563297
This command introduces the
BUILD_TESTINGcache variable, which can sneak into downstream projects.Opened #161 to try to fix this, which gets rid of
BUILD_TESTINGbut has other side effects. If you have ideas on how to improve it, would be helpful to have feedback there.ryanofsky referenced this in commit 011fc53aea on Feb 10, 2025Sjors referenced this in commit 6aabfcb615 on Feb 10, 2025Sjors referenced this in commit 1746618e08 on Feb 13, 2025ryanofsky referenced this in commit 83e40d3b52 on Feb 24, 2025ryanofsky referenced this in commit 8619f03ec2 on Feb 24, 2025ryanofsky referenced this in commit cbb7b41c20 on Feb 24, 2025fanquake referenced this in commit 01f7715766 on Feb 25, 2025fanquake referenced this in commit ba0a4391ff on Feb 25, 2025janus referenced this in commit 86cb86b050 on Sep 1, 2025bitcoin-core locked this on Feb 10, 2026Contributors
This is a metadata mirror of the GitHub repository bitcoin-core/libmultiprocess. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-04-20 20:30 UTC
More mirrored repositories can be found on mirror.b10c.me