Skip to content

Commit f244a23

Browse files
JohnsterIDxezon
authored andcommitted
feat(cmake): Add debug symbol stripping for MinGW Release builds (#2067)
Implement complete debug symbol separation for MinGW-w64 Release builds, matching MSVC PDB workflow. Debug symbols are now generated with -g and then stripped to separate .debug files post-build. Changes: - cmake/debug_strip.cmake: New module with add_debug_strip_target() function - Automatically finds toolchain objcopy and strip tools - Three-step process: extract symbols, strip exe, add debug link - Only applies to Release builds (Debug keeps embedded symbols) - cmake/compilers.cmake: Enable -g for all Release builds - Removed MinGW exception that was skipping debug symbols - Added comment explaining stripping workflow - CMakeLists.txt: Include debug_strip.cmake module - Generals/Code/Main/CMakeLists.txt: Apply stripping to g_generals - GeneralsMD/Code/Main/CMakeLists.txt: Apply stripping to z_generals Result files (Release): - generalsv.exe (12 MB, stripped) + generalsv.exe.debug (231 MB, symbols) - generalszh.exe (13 MB, stripped) + generalszh.exe.debug (250 MB, symbols) Benefits: - Crash dump analysis support (crashpad, breakpad) - Post-mortem debugging with full symbols - Performance profiling of optimized code - Parity with MSVC (exe + pdb workflow) - Smaller shipped binaries (symbols separate) Debug builds keep symbols embedded for development convenience. Tools used: GNU Binutils objcopy and strip
1 parent 29dc6b4 commit f244a23

5 files changed

Lines changed: 111 additions & 5 deletions

File tree

CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ project(genzh LANGUAGES C CXX)
3636
# This file handles extra settings wanted/needed for different compilers.
3737
include(cmake/compilers.cmake)
3838

39+
# Debug symbol stripping for Release builds (MinGW)
40+
include(cmake/debug_strip.cmake)
41+
3942
include(FetchContent)
4043

4144
# MinGW-w64 specific configuration

Generals/Code/Main/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,3 +85,9 @@ if(MSVC)
8585
RTS.RC
8686
)
8787
endif()
88+
89+
# Strip debug symbols to separate file for MinGW Release builds
90+
# This creates generalsv.exe.debug (similar to MSVC .pdb files)
91+
if(MINGW AND COMMAND add_debug_strip_target)
92+
add_debug_strip_target(g_generals)
93+
endif()

GeneralsMD/Code/Main/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,9 @@ if(MSVC)
7474
RTS.RC
7575
)
7676
endif()
77+
78+
# Strip debug symbols to separate file for MinGW Release builds
79+
# This creates generalszh.exe.debug (similar to MSVC .pdb files)
80+
if(MINGW AND COMMAND add_debug_strip_target)
81+
add_debug_strip_target(z_generals)
82+
endif()

cmake/compilers.cmake

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,10 @@ if(MSVC)
3434
add_link_options("/INCREMENTAL:NO")
3535
else()
3636
# We go a bit wild here and assume any other compiler we are going to use supports -g for debug info.
37-
# For MinGW, skip adding -g to Release builds
38-
if(NOT (MINGW AND CMAKE_BUILD_TYPE STREQUAL "Release"))
39-
string(APPEND CMAKE_CXX_FLAGS_RELEASE " -g")
40-
string(APPEND CMAKE_C_FLAGS_RELEASE " -g")
41-
endif()
37+
# Add debug symbols to Release builds for crash dump analysis, profiling, and post-mortem debugging.
38+
# For MinGW, symbols will be stripped to separate .debug files (matching MSVC PDB workflow).
39+
string(APPEND CMAKE_CXX_FLAGS_RELEASE " -g")
40+
string(APPEND CMAKE_C_FLAGS_RELEASE " -g")
4241
endif()
4342

4443
set(CMAKE_CXX_STANDARD_REQUIRED ON)

cmake/debug_strip.cmake

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# TheSuperHackers @build JohnsterID 05/01/2026 Add debug symbol stripping for MinGW Release builds
2+
# Debug Symbol Stripping for MinGW-w64 Release Builds
3+
#
4+
# Separates debug symbols from executables into .debug files, matching MSVC PDB workflow.
5+
# This reduces shipped binary size while preserving symbols for crash analysis.
6+
7+
# Find the required tools for symbol stripping
8+
if(MINGW)
9+
# Use the cross-compiler toolchain's objcopy and strip
10+
# These should be in the same directory as the compiler
11+
get_filename_component(COMPILER_DIR ${CMAKE_CXX_COMPILER} DIRECTORY)
12+
13+
find_program(MINGW_OBJCOPY
14+
NAMES ${CMAKE_CXX_COMPILER_TARGET}-objcopy
15+
${CMAKE_SYSTEM_PROCESSOR}-w64-mingw32-objcopy
16+
objcopy
17+
HINTS ${COMPILER_DIR}
18+
DOC "MinGW objcopy tool for extracting debug symbols"
19+
)
20+
21+
find_program(MINGW_STRIP
22+
NAMES ${CMAKE_CXX_COMPILER_TARGET}-strip
23+
${CMAKE_SYSTEM_PROCESSOR}-w64-mingw32-strip
24+
strip
25+
HINTS ${COMPILER_DIR}
26+
DOC "MinGW strip tool for removing debug symbols"
27+
)
28+
29+
if(MINGW_OBJCOPY AND MINGW_STRIP)
30+
message(STATUS "Debug symbol stripping enabled:")
31+
message(STATUS " objcopy: ${MINGW_OBJCOPY}")
32+
message(STATUS " strip: ${MINGW_STRIP}")
33+
set(DEBUG_STRIP_AVAILABLE TRUE)
34+
else()
35+
message(WARNING "Debug symbol stripping not available - tools not found")
36+
if(NOT MINGW_OBJCOPY)
37+
message(WARNING " objcopy not found")
38+
endif()
39+
if(NOT MINGW_STRIP)
40+
message(WARNING " strip not found")
41+
endif()
42+
set(DEBUG_STRIP_AVAILABLE FALSE)
43+
endif()
44+
45+
# Function to strip debug symbols from a target and create a separate .debug file
46+
#
47+
# This implements a three-step process:
48+
# 1. Extract debug symbols to separate file
49+
# 2. Strip debug symbols from main executable
50+
# 3. Add debug link so debuggers can find the symbols
51+
#
52+
# Usage:
53+
# add_debug_strip_target(target_name)
54+
#
55+
# Result (for Release builds only):
56+
# program.exe - Stripped executable (smaller)
57+
# program.exe.debug - Debug symbols (can be distributed separately)
58+
#
59+
function(add_debug_strip_target target_name)
60+
if(NOT DEBUG_STRIP_AVAILABLE)
61+
return()
62+
endif()
63+
64+
# Only strip Release builds
65+
# Debug builds keep symbols embedded for development convenience
66+
if(CMAKE_BUILD_TYPE STREQUAL "Release")
67+
add_custom_command(TARGET ${target_name} POST_BUILD
68+
# Step 1: Extract all debug sections to separate file
69+
COMMAND ${MINGW_OBJCOPY}
70+
--only-keep-debug
71+
$<TARGET_FILE:${target_name}>
72+
$<TARGET_FILE:${target_name}>.debug
73+
74+
# Step 2: Strip debug sections from executable
75+
COMMAND ${MINGW_STRIP}
76+
--strip-debug
77+
--strip-unneeded
78+
$<TARGET_FILE:${target_name}>
79+
80+
# Step 3: Add GNU debug link (debuggers use this to find symbols)
81+
COMMAND ${MINGW_OBJCOPY}
82+
--add-gnu-debuglink=$<TARGET_FILE:${target_name}>.debug
83+
$<TARGET_FILE:${target_name}>
84+
85+
COMMENT "Stripping debug symbols from ${target_name} (Release)"
86+
VERBATIM
87+
)
88+
89+
message(STATUS "Debug symbol stripping configured for target: ${target_name}")
90+
endif()
91+
endfunction()
92+
endif()

0 commit comments

Comments
 (0)