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 the TARGET parameter together with a DEPENDS 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.

comments powered by Disqus