CMake: Stripping binaries
When building a release build of your software, a common task is to strip the binaries to remove any debug symbols. Over the years I went through various iterations until I finally ended up with a small, concise and fully decoupled solution which I’d like to share here.
Essentially, everything boils down to a simple call to add_custom_command()
:
add_custom_command(
TARGET "${TARGET}" POST_BUILD
DEPENDS "${TARGET}"
COMMAND $<$<CONFIG:release>:${CMAKE_STRIP}>
ARGS --strip-all $<TARGET_FILE:${TARGET}>
)
A couple of neat things worth noting:
- Using the
POST_BUILD
specifier on theTARGET
parameter together with aDEPENDS
on the target itself ensures that this command is only invoked after the target was built successfully. - We’re using
${CMAKE_SCRIPT}
which takes care of any platform & environment specific handling under the hood. - The
COMMAND
is wrapped in a generator expression which is only enabled when the target is being built in release mode. As we most certainly don’t want to strip a debug build we don’t have to add custom logic only invoking this function in a release build. - Another generator expression is used to extract the target’s output file from the parameter removing the need of manually specifying the binary.
Most larger projects tend to end up with a collection of CMake utility scripts. For my projects, I usually end up creating something like strip.cmake
where the above is simply wrapped in a function accepting a target as a parameter:
function(utils_strip TARGET)
add_custom_command(
TARGET "${TARGET}" POST_BUILD
DEPENDS "${TARGET}"
COMMAND $<$<CONFIG:release>:${CMAKE_STRIP}>
ARGS --strip-all $<TARGET_FILE:${TARGET}>
)
endfunction()
Therefore, one can easily just call utils_strip()
on any executable (including shared library) targets and the rest is taken care of by that function:
set(TARGET my-awesome-software)
add_executable(${TARGET})
utils_strip(${TARGET})
This function has been used successfully under:
- FreeBSD
- Linux
- Windows (with MSYS2)
- MacOS
with Ninja
and Make
/GMake
as build systems.