CMake project directory structure

Nested / recursive CMake

It’s a good idea to breakup project code into distinct subdirectories. It can be useful to have a CMakeLists.txt for each of these directories, that are included from the top-level CMakeLists.txt.

Let’s say you have C code in a main directory, with a subdirectory io/.

Top-level CMakeLists.txt:

project(benchmarks C)
enable_testing()

add_subdirectory(io)

add_executable(benchIO bench.c)
target_link_libraries(benchIO iohdf)

and in io/CMakeLists.txt:

project(io C)
enable_testing()

add_library(iohdf ...)

add_executable(testh5 testh5.c)
target_link_libraries(testh5 iohdf)

add_test(NAME h5io COMMAND testh5)

Build a little test script in io/ directory to test just HDF5 I/O, and compile the whole program from the top level directory, then

ctest -V

from the build directory to test the main program and subdirectory libraries.

Cmake Directory variables

To reliably control relative path operations, use

  • ${PROJECT_SOURCE_DIR} to refer to individual subdirectories where the various CMakeLists.txt are
  • ${CMAKE_SOURCE_DIR} to refer to the highest level CMakeLists.txt directory

Edit all CMakeLists.txt recursively

On Linux / Unix systems, edit all CMakeLists.txt in a project with a command like

gedit $(find -name CMakeLists.txt)