0

I'm having trouble calling ctest from the top of a super-project.

I'm running a nested project; a project with lots of sub-projects which also sometimes have sub-projects. This is handled with cmake.

superproject
├── project1
│   ├── subproject1a
│   └── subproject1b
├── project2
│   ├── subproject2a
│   └── subproject2b
│   ...
└── projectN
    ├── subprojectN1
    │   ...
    └── subprojectNn

In some projects and most sub-projects, we define test cases using ctest. These are defined in the CMakeLists.txt files at the lowest level applicable (subproject).

The cmake sections used to define, compile and declare ctests at the lowest levels look like this:

# ${subprojectName} was set earlier in this file
enable_testing()
file(GLOB TEST_SRCS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} test/*.cpp)
foreach(testSrc ${TEST_SRCS})

        get_filename_component(testName ${testSrc} NAME_WE)
        set(testName ${subprojectName}_${testName})

        add_executable(${testName} ${testSrc})
        target_link_libraries(${testName} ${subprojectName} Boost::unit_test_framework Boost::dynamic_linking)

        add_test(NAME ${testName} COMMAND ${testName})
endforeach(testSrc)

I'd like to be able to run ctest like so:

mkdir build && cd build
cmake .. 
cmake --build .
ctest

However, currently I need to do this:

mkdir build && cd build
cmake ..
cmake --build .
cd project1/subproject1a
ctest
cd ../subproject1b
ctest
...
cd ../subprojectNn
ctest

The problem is that the ctest instructions will only be created at the cmake level where add_test() was called. Is there a way for me to promote a list of ${testName}s to the scope of the superproject? If so, I could then iterate through that list and call add_test from the root (though I might still have some issues with the working directory).

My current direction to solving this is manually creating a CTestTestfile.cmake in the build directory's root, and adding add_subdirectory to point to all projects. If I run ctest from this situation, then things work. If I could get cmake to generate a CTestTestfile.cmake like this, then I'd be happy.

Stewart
  • 4,356
  • 2
  • 27
  • 59
  • 2
    `The problem is that the ctest instructions will only be created at the cmake level where add_test() was called.` - Most likely it is `enable_testing()` call which creates infrastructure for ctest, not a `add_test()` call. – Tsyvarev Jan 31 '18 at 21:05
  • Yes, this works! The highest level now has `enable_testing()` and `add_test()` is called at any arbitrary level below that. I can call `ctest` from the super project now. If you make this an answer, I'll accept it. – Stewart Feb 01 '18 at 07:36
  • When I wrote my previous comment, I actually wanted to simply correct your sentence. I didn't think about the decision at that time :D – Tsyvarev Feb 01 '18 at 08:09

1 Answers1

2

It is call

enable_testing()

which creates infrustructure for ctest in current directory.

You may use this call in the super-project CMakeLists.txt, so you will be able to run ctest from the top-level build directory.

Tsyvarev
  • 60,011
  • 17
  • 110
  • 153
  • Might be important to note: The `enable_testing()` directive must be placed in the root/parent CMakeLists before the `add_subdirectory` directives, even if those are enabling testing as well. – Superlokkus Jan 06 '19 at 13:15
  • Last time I have check that, `enable_testing` could be placed in the subdirectory, and `ctest` works from that subdirectory (not from the top-level build directory). May be things have been changed since that time. – Tsyvarev Jan 09 '19 at 04:34