16

How can you add binary stripping to CMake for gcc and clang as a post-processing step but only in release builds? MSVC strips by default so it does not have to be handled.

One of the problems is that clang does not have a -s compilation flag but gcc does so doing it this way does not work.

Another idea is to use the strip command. The -s switch again exists on Linux but not on XCode (this is Apple's development toolchain).

So the final choice is to use the strip command without any arguments besides the binary itself which appears to be a decent generic solution. How can this be used in CMake?

BullyWiiPlaza
  • 17,329
  • 10
  • 113
  • 185
  • Here (https://stackoverflow.com/q/53409479/8034839) is how I do for Android CMake to invoke `strip` command. – shizhen Dec 10 '18 at 01:15

2 Answers2

15

In CMake add_custom_command can execute post build commands such as strip. The PROJECT_NAME variable is defined as your target binary e.g.

# Set the project name
set(PROJECT_NAME "MyProject")
project(${PROJECT_NAME})

Place the following code after add_executable of your CMakeLists.txt:

# Strip binary for release builds
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
    COMMAND $<$<CONFIG:release>:${CMAKE_STRIP} ${PROJECT_NAME}>)

CMAKE_STRIP is the file path to the platform's strip utility (e.g. /usr/bin/strip on Linux). The $<$<CONFIG:cfg>:str> generator expression will expand to str when building the configuration cfg, and to an empty string otherwise. In this scenario, this directly means "call strip when building in Release, and do nothing otherwise". Note that the CONFIG generator is case insensitive on your build type, and will work when using multi-config generators.

Adrien
  • 65
  • 5
BullyWiiPlaza
  • 17,329
  • 10
  • 113
  • 185
  • In my case, the command must split into multiple section, like: COMMAND "$<$:${CMAKE_STRIP}>" --strip-unneeded "$<$:$>" , as $<$:${CMAKE_STRIP} ${PROJECT_NAME}> will be parse as executable command. – FarmerLi Nov 19 '21 at 06:32
  • Link to the docs: https://cmake.org/cmake/help/latest/command/add_custom_command.html#build-events – inkychris Feb 23 '22 at 10:30
  • Hello @BullyWiiPlaza, I have a similar issue and I am trying your solution. But I am getting error like: `add_custom_command Wrong syntax. A TARGET and OUTPUT can not both be specified.` Can you please let me know what could be the issue here? – Preeti Jun 02 '22 at 13:49
3

While using add_custom_command, I was having issues with the COMMAND generator expression containing spaces. The ARGS option can be used while still toggling the inclusion of the custom command through a generator expression for the COMMAND option:

add_custom_command(
  TARGET "${TARGET}" POST_BUILD
  DEPENDS "${TARGET}"
  COMMAND $<$<CONFIG:release>:${CMAKE_STRIP}>
  ARGS --strip-all $<TARGET_FILE:${TARGET}>
)

This results in strip --strip-all myapp being called when config is release, but no command being called when it's not, despite the args being specified in a separate option.

inkychris
  • 1,179
  • 2
  • 12
  • 18
  • Hello @inkychris, I have a similar issue and I am trying your solution. But I am getting error like: `add_custom_command Wrong syntax. A TARGET and OUTPUT can not both be specified.` Can you please let me know what could be the issue here? – Preeti Jun 02 '22 at 13:58
  • I can't really help without seeing what your actual command call looks like, but the error message suggests that you're trying to specify the `TARGET` and `OUTPUT`, which `add_custom_command` doesn't support. If you're using this on a target, you don't need to specify `OUTPUT`. – inkychris Jun 06 '22 at 13:17
  • At first this doesn't work, but changing `ARGS --strip-all $ ` into `ARGS --strip-all "${TARGET}"` will work – KuhakuPixel Dec 09 '22 at 08:50