/flags/cmake/cmake-s-b-source-build-directory
cmake -S . -B build: set the source and build directories
- tool
- CMake
- command
- cmake
- flag
- -S <path-to-source> -B <path-to-build>
- default
- source = the directory given as argument, build = the current directory
- since
- 3.13
cmake -S . -B build configures the project whose top-level CMakeLists.txt is in . (the source directory) and writes all generated files into build (the build directory), creating it if needed. It replaces the older mkdir build && cd build && cmake ... Then build with cmake --build build. Both options exist since CMake 3.13.
Configure and build
cat > CMakeLists.txt <<'EOF'
cmake_minimum_required(VERSION 3.20)
project(demo LANGUAGES NONE)
add_custom_target(hello ALL COMMAND ${CMAKE_COMMAND} -E echo "hello from the build step")
EOF
CM="uv run -q --no-project --python 3.13 --with cmake==4.4.4 --with ninja cmake"
$CM -G Ninja -S . -B build | grep -v 'Build files have been written' | sed 's/ ([0-9.]*s)$//'
$CM --build build | grep -x 'hello from the build step'
ls build | grep -E 'CMakeCache.txt|build.ninja'Output
-- Configuring done -- Generating done hello from the build step CMakeCache.txt build.ninja
The source directory stays clean: everything generated is under build/, which you can delete at any time to start over.
Common combinations
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release # single-config generators (Ninja, Makefiles)
cmake --build build -j 8
cmake -S . -B build-debug -DCMAKE_BUILD_TYPE=Debug # a second build tree from the same source
cmake -S . -B build -G "Visual Studio 17 2022"
cmake --build build --config Release # multi-config generators (Visual Studio, Xcode)
cmake --install build --prefix "$HOME/.local"
cmake --fresh -S . -B build # discard the cache and reconfigure (3.24+)Rules
| Form | Meaning |
|---|---|
| cmake -S src -B build | Explicit source and build directories (3.13+) |
| cmake -B build | Source = current directory |
| cmake -S src | Build directory = current directory |
| cmake .. | Old form: source = .., build = current directory |
| cmake build | If build already has a CMakeCache.txt, reconfigure that existing build tree |
| cmake --build build | Run the native build tool (ninja, make, MSBuild) in that tree |
Why a separate build directory
Without -B, CMake writes CMakeCache.txt, CMakeFiles/ and the generated build files into the current directory. Run from the project root, that is an in-source build: generated files mix with your sources, git status fills up, and cleaning means deleting files one by one. With -B build everything lives in one directory that you add to .gitignore and remove when you want a clean start. You can also keep several trees from one checkout (Debug and Release, two compilers, two generators) side by side.
Options that go with -S and -B
| Option | Phase | What it does |
|---|---|---|
| -G "Ninja" | configure | choose the generator; fixed for the life of the build tree |
| -D VAR=value | configure | set a cache variable such as CMAKE_BUILD_TYPE or CMAKE_INSTALL_PREFIX |
| --preset name | configure | read generator, build directory and variables from CMakePresets.json |
| --fresh | configure | rebuild the cache from scratch, keeping the directory (3.24+) |
| --build build -j N | build | run the native tool with N parallel jobs (3.12+); --parallel is the long form |
| --build build --target name | build | build one target instead of the default ones; --target clean only cleans |
| --build build --clean-first | build | clean, then build |
| --build build -v | build | print the compiler commands that are run |
Errors you may meet
-Spoints to a directory withoutCMakeLists.txt: CMake stops with does not appear to contain CMakeLists.txt. Check the path is the project root, not a subdirectory.- The build directory was created with another generator or another source directory: CMake refuses to reuse it. Delete the directory, choose a new
-Bname, or pass--fresh. - No compiler found while configuring: see No CMAKE_C_COMPILER could be found. The build directory then holds a failed cache; reconfigure after fixing the toolchain.
- An old project fails under CMake 4 with
Compatibility with CMake < 3.5 has been removed; that is unrelated to-Sand-B.
Paths given to -S and -B are relative to the current directory, and both may be absolute. On Windows, quote paths that contain spaces.
FAQ
What is the difference between cmake -B build and mkdir build && cd build && cmake ..?
The result is the same build tree. -S and -B (CMake 3.13+) do it in one command without changing directory, which is easier to script.
Do I have to run cmake -S -B again after editing CMakeLists.txt?
No. cmake --build build notices the change and reconfigures automatically. Run the configure step again only to change cache variables or after deleting the directory.
Where does the compiled program end up?
Inside the build directory, in the subdirectory that matches the source layout unless the project sets output directories. Multi-config generators add a Debug or Release subdirectory.