Search code examples
c++cgcccmakeld

Why GCC --gc-sections and -ffunction-sections is not working? (cmake build)


I wonder why the GCC compiler flag -ffunction-sections and linker flag --gc-sections don't eliminate unnecessary resp. unreferenced symbols/functions code from my final executable. Why is it not working as expected and described in the GCC documentation?

Probably I have overseen some unintended reference !?

Checked already using to this very nice method: GCC --gc-sections and finding symbol dependencies with /DISCARD/ in linker script. No success. There is no reference to my ununsed functions.

No chance to automatically eliminate dead code !? Why ???


Solution

  • The answer is quite simple (in my case):

    I am using CMake to build my project and it is inserting the flag -rdynamic !
    To my knowledge the combination of -rdynamic and --gc-sections options is not mentioned anywhere in the GCC documentation. There should be a warning like this:
    -rdynamic renders --gc-sections useless bcs. all symbols are implicitly referenced.

    See also: What exactly does `-rdynamic` do and when exactly is it needed?

    Of course only CMake users are affected by this... (without knowing):

    CMP0065

    Do not add flags to export symbols from executables without the :prop_tgt:ENABLE_EXPORTS target property.

    CMake 3.3 and below, for historical reasons, always linked executables on some platforms with flags like -rdynamic to export symbols from the executables for use by any plugins they may load via dlopen. CMake 3.4 and above prefer to do this only for executables that are explicitly marked with the :prop_tgt:ENABLE_EXPORTS target property.

    The OLD behavior of this policy is to always use the additional link flags when linking executables regardless of the value of the :prop_tgt:ENABLE_EXPORTS target property.

    The NEW behavior of this policy is to only use the additional link flags when linking executables if the :prop_tgt:ENABLE_EXPORTS target property is set to True.

    This policy was introduced in CMake version 3.4. Unlike most policies, CMake version |release| does not warn by default when this policy is not set and simply uses OLD behavior. See documentation of the :variable:CMAKE_POLICY_WARNING_CMP0065 <CMAKE_POLICY_WARNING_CMP<NNNN>> variable to control the warning.

    To get rid of the mostly unnecessary -rdynamic CMakeLists.txt just add cmake_policy(SET CMP0065 NEW)