Skip to main content

Flags, Modes & Compile-Time Configuration

beginner11 min readLesson 188 of 204

Debug vs Release changes observable behavior you can detect: __OPTIMIZE__, NDEBUG, and your own feature-test macros form the code-side contract of the build.

The build mode is visible from inside the code

Compilers define markers you can test:

  • __OPTIMIZE__ โ€” GCC/Clang define it when optimizing (-O1+); MSVC does not.
  • NDEBUG โ€” defined by CMake's Release/RelWithDebInfo configurations; it disables assert. Debug/RelWithDebInfo/Release is not just speed: it changes which assertions exist in the binary.
  • Your own macros: -DCJ_LOG_LEVEL=2 becomes #if CJ_LOG_LEVEL >= 2 in code.

Feature-test discipline

Never test compiler identity (#ifdef _MSC_VER) when you mean capability. <version> / __has_include / feature-test macros ask what the toolchain provides:

#include <version>
#ifdef __cpp_lib_format        // capability question
#  include <format>
#endif
#ifdef __cpp_exceptions        // is exception handling on?
#endif

__has_feature (Clang) and __SANITIZE_ADDRESS__ (GCC) report sanitizer state โ€” the code can know whether ASan is watching.

What the fixed sandbox grades

This course's sandbox compiles with -std=c++20 -Wall -Wextra -Wpedantic and no mode toggles โ€” so the graded exercises here test the code side: correct __cpp_* guards, correct NDEBUG-independent logic, and configuration arithmetic that a single translation unit can prove. The full Debug/Release/CI story is in the lesson text, exercised in the projects, not the sandbox.

Now practice

Practice: Compile-Time Build ConfigMake the binary answer build questions itself โ€” capability markers only, provable by static_assert in the same TU.1 challenge ยท ยท ~14 min