Add abstraction for debug info
There are various separate issues covering aspects of this, so I'm creating a dedicated issue so we can focus discussions to help move this towards an implementable outcome.
We currently set the default compiler flags in configuration-specific variables CMAKE_<LANG>_FLAGS_<CONFIG>
. These mix flags for optimization and debugging (and RTTI and exception handling for MSVC), a number of which no longer align with what developers expect as defaults. Projects have to resort to string replacements to change from these defaults, which is fragile and requires projects to hard-code the platform-specific flags to be replaced. #23374 proposes abstracting out the optimization flags, while this issue here proposes doing the same for the flags related to debug info.
I propose we define a new target property, DEBUG_INFO_TYPE
which specifies the debug info handling for that target. The property would need to support generator expressions to allow for configuration-specific values. Following the usual pattern, this property would be initialised by an associated CMAKE_DEBUG_INFO_TYPE
variable. That variable could potentially have a toolchain-specific default value. For discussion, I propose the following valid values for the property:
-
NONE
and/or empty: No debug information is generated.. -
EMBEDDED
: Debug information is generated and stored directly in the object file. This is the default behavior for gcc and clang, and corresponds to/Z7
for MSVC. -
SEPARATE
: Debug information is generated and stored in a separate file. For targets that are executables or shared/module libraries, this would be a single file for the binary. For MSVC, this would be the PDB file and corresponds to/Zi
or/ZI
(see below). For macOS, it corresponds to a dSYM file. For elf binaries, this would probably be a.dwp
file formed by combining individual.dwo
files from a split dwarf arrangement.
For compilers that don't support one of the above options, it would be an error to ask for that debug info type. This would be likely for the SEPARATE
case with some older embedded toolchains, for example (the TI compiler comes to mind).
MSVC supports an "edit and continue" feature, which requires a different debug flag (/ZI
rather than /Zi
). We could model that with a separate property, or we could add an EDIT_AND_CONTINUE
value to the above property, which only MSVC would be likely to implement. I am currently leaning toward a separate MSVC-specific property, but could be convinced either way.
Some references for existing issues that already discuss aspects of this topic, or are related:
- #20812 Default MSVC release flags suboptimal
- #21765 Default MSVC debug flags different to IDE defaults
-
#10189 (closed) Default MSVC debug to
/ZI
instead of/Zi
-
#19549 (closed) Default MSVC release flags should set
/Zi
or/ZI
- #20256 Separate debug information
- #21705 Disable or customize default compiler flags
- #19676 Swift applications are not debuggable by default (probably applies to all languages, not just Swift)
- #20610 Add abstraction for enabling RTTI and exceptions
- #19084 Difficulties with target_compile_options() (this has some useful detailed discussion)
Out-of-scope for this issue, but once this issue and #23374 are implemented (maybe #20610 too), some follow-on work which could be considered includes (these would deserve their own separate issues):
- Consider no longer setting any
CMAKE_<LANG>_FLAGS_<CONFIG>
variables at all. Instead, use the optimization and debug abstractions, which should default to the relevant setting based on the active configuration type (Debug
,Release
, etc). We can still support those variables if users or projects set them, but we wouldn't populate them by default any more (would need a policy). - Consider whether to rationalise the default set of configurations in
CMAKE_CONFIGURATION_TYPE
to justDebug
andRelease
, where we would still produce debug artefacts for Release by default, but as separate files (i.e. use theSEPARATE
debug type by default for Release). This would better align with what IDEs like Xcode and Visual Studio do by default, and probably with what most developers typically need. Embedded folks might be a counter-argument with their different needs for minimizing size, but I think that still falls under the optimization abstraction (#23374).