Lesson 19 · Organize your project
Why not file(GLOB)
The warning against file(GLOB) in the official docs, explained. And the explicit source-list workflow that never surprises you.
You will be tempted to write this:
Don't do thisfile(GLOB SOURCES src/*.cpp) # do not add_executable(app ${SOURCES})
It looks convenient. New files are picked up automatically. But the official documentation explicitly recommends against it. Here is why, and what to do instead.
What the docs say
The failure mode. You add foo.cpp to src/, rebuild, and nothing happens. No error, no new file in the build. Just silent nothing. Because the build system only re-runs CMake when its inputs, the CMakeLists.txt files, change. Not when the filesystem changes.
The suggested fix, CONFIGURE_DEPENDS, has its own problems. It is not reliable on every generator, and even where it works it slows every build with a scan. So it is discouraged too.
Why
A build system that silently misses files is worse than one that requires a one-line edit. The explicit list makes every change visible and reviewable. “I added
foo.cpp” appears as a real diff in git. GLOB trades a few seconds of typing for invisible build breaks. Bad trade.
The workflow
src/
├── CMakeLists.txt
├── main.cpp
├── parser.cpp
└── ui.cpp
src/CMakeLists.txt# Explicit list. Adding a file means adding one line here. add_executable(app main.cpp parser.cpp ui.cpp )
Adding a file means adding one line and reconfiguring, which happens automatically when CMakeLists.txt changes, remember lesson 4. That is the entire cost, and it is the price of never being silently wrong.
target_sources, list sources next to the code
For libraries spread over directories, target_sources keeps the list where the code lives:
libs/calc/CMakeLists.txtadd_library(calc STATIC) target_sources(calc PRIVATE calc.cpp util.cpp ) target_include_directories(calc PUBLIC include)
Note
With
target_sources(... PRIVATE), the add-a-file edit happens in the same file as the code. No need to touch theadd_libraryline at all.
The honest exceptions
CMakeLists.txtis generated by a build system that owns the file list, for example Qt’sautomoc-style tooling, orqt_add_executablewithqt_add_resources. Then GLOB is fine, because something else regenerates your CMake files reliably.install(DIRECTORY ...)and other copying uses of GLOB (headers, data) are fine. The warning targets source files for compilation, because only those trigger the rebuild problem.
Pitfall
If you inherit a project using
file(GLOB ...)withoutCONFIGURE_DEPENDS, a fresh clone may build a different set of files than your local checkout. Classic “works here, broken in CI” material. Exactly the class of bug the explicit list eliminates.
Read the docs