One Build Directory Per CMake Configuration: A CLion Workflow That Actually Scales
Switching CMake build types in one shared directory forces full rebuilds. CLion's CMake profiles give each build type its own directory, restoring fast incremental builds and saner debugging.
08 Mar 2026, 02:01 UTC

Your Debug build works, you switch to Release to check a warning that only appears with optimizations, and now your next Debug build recompiles half the project. The culprit is usually a single shared build directory: CMake caches CMAKE_BUILD_TYPE in CMakeCache.txt, and flipping it invalidates artifacts built with different compiler flags. CLion has a built-in answer to this — multiple CMake profiles, each with its own build directory — and it takes about two minutes to set up.
Why a shared build directory hurts
CMake is a meta-build system: it generates Makefiles or Ninja files once, then your build tool consumes them. The generated files encode the build type, compiler flags, and paths. When the build type changes, CMake re-runs and the build tool sees most object files as out of date, because Debug (-g -O0) and Release (-O3 -DNDEBUG) outputs are fundamentally different.
Keeping one directory per build type means each directory's cache stays stable. Incremental builds then only recompile what you actually edited, and you can keep a working Debug binary around while you test a Release build — no clobbering.
Setting up per-configuration profiles in CLion
CLion models this through CMake profiles. Go to Settings (or Preferences on macOS) → Build, Execution, Deployment → CMake. You'll see a default profile, typically Debug. Use the + button to add more:
- Name: Debug, Release, RelWithDebInfo — anything descriptive.
- Build type: pick from the dropdown; CLion passes this as
-DCMAKE_BUILD_TYPE=.... - Build directory: CLion defaults to
cmake-build-debug,cmake-build-release, etc., under the project root. Keep this convention — it makes directories self-describing. - Build options / environment: per-profile overrides, e.g. extra warnings only in Debug.
Each profile gets its own CMakeCache.txt in its own directory. You can enable several profiles at once; the profile switcher in the toolbar (next to the run configuration selector) decides which one builds and runs.
Worked example: Debug plus RelWithDebInfo
Say you're chasing a crash that vanishes in Debug (a classic sign of undefined behavior or optimization-sensitive code). RelWithDebInfo gives you optimized code with symbols:
- Open Settings → Build, Execution, Deployment → CMake.
- Duplicate the Debug profile, rename it
RelWithDebInfo, set the build type dropdown toRelWithDebInfo. CLion proposescmake-build-relwithdebinfoas the directory — accept it. - Apply, then select the new profile in the toolbar switcher and build (Build → Build Project or the hammer icon).
- Run your existing run configuration under the debugger. Breakpoints now hit in optimized code, with variable values occasionally shown as
<optimized out>— expected, and still far more useful than a bare crash address.
To verify the configuration is what you think it is, open the generated cmake-build-relwithdebinfo/CMakeCache.txt in the editor and check:
CMAKE_BUILD_TYPE:STRING=RelWithDebInfoCLion also surfaces this in the CMake tool window, so you don't have to open the file by hand. Meanwhile your Debug directory is untouched — switch back and your next incremental build only recompiles files you changed since the last Debug build.
Trade-offs and gotchas
- Disk usage multiplies. Each directory holds a full set of object files. For a large project, three or four profiles can mean several gigabytes. Clean a single profile via Build → Clean with that profile active — only its directory is wiped.
- Adding a profile re-runs CMake for that directory. If you pass custom cache variables (
-DENABLE_SANITIZERS=ONand similar), remember to copy them into the new profile's CMake options field; they don't propagate automatically. - Windows path length. Nested build directories under a deep project path can hit the legacy
MAX_PATHlimit. Keep build folders near the project root (the default) rather than inventing deeper hierarchies. - Multi-config generators differ. This whole discussion applies to single-config generators (Makefiles, Ninja), which are CLion's default. If you ever switch to a multi-config generator like Visual Studio or Ninja Multi-Config, build type is chosen at build time instead of configure time, and the one-directory-per-type pattern becomes unnecessary.
Actionable takeaway
If you currently toggle build types by editing CMakeLists.txt or re-running CMake manually, stop. Add one CLion CMake profile per build type you actually use — Debug and RelWithDebInfo cover most debugging needs — and let the toolbar switcher do the work. Your incremental builds get faster, your binaries stop stepping on each other, and CMakeCache.txt in each directory gives you a ground-truth check whenever something behaves oddly. The behavior described here is stable across recent CLion versions (2022.x and later), but confirm the exact settings-panel layout against your installed version, since JetBrains occasionally reorganizes the UI.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.