How to make introjucer strip symbols and dead code?


#1

Is there any reason why introjucer does not automatically set the symbol stripping options for XCode?
Anybody have a post-build shell script that works in Introjucer?


#2

You might want to debug a release build, e.g. for performance profiling, etc.

Personally, I just add a “strip” command to the script that creates the installer package of the finished binary.


#3

Hi,

For Xcode target you can add “DEPLOYMENT_POSTPROCESSING = YES, STRIP_INSTALLED_PRODUCT = YES” in the ‘Custom Xcode flags’ field.
And you may use “gcc -s” option for others?

Remarks:

  1. The first approach works well while i did not test the second.
  2. AFAIK the “-s” option is not implemented in the Mac OS X version of gcc. So you need to manage both ways if you use multiple targets.

#4

Ok, that will work for stripping symbols, but what about dead code?

I just enabled -dead_strip in the linker and -gfull in compiler and sizes when down by 40% on my projects.
Maybe worth going for a dead code strip option in the introjucer?

More Info:
https://developer.apple.com/library/mac/#documentation/performance/Conceptual/CodeFootprint/Articles/CompilerOptions.html


#5

Wow, that really does strip it down - I think I’ll add those flags by default in a release build, can’t think of any reason not to!

TBH I’m a bit surprised that removing dead code wouldn’t just be a linker’s default behaviour… I can’t think of any reason why you’d ever want dead code left in an executable, even if you’re debugging.


#6

Yes, i thought also it should be default.

(disclaimer: I’m new to xcode, so better take somebody else advice on which options you need to enable)


#7

Hi,

In Xcode to strip dead code you need:

GCC_GENERATE_DEBUGGING_SYMBOLS = YES
GCC_DEBUGGING_SYMBOLS = full
DEAD_CODE_STRIPPING = YES

And that implies to generate debugging symbols fully. For now the Introjucer seems to do the contrary in the release mode.
You may strip them with:

DEPLOYMENT_POSTPROCESSING = YES
STRIP_INSTALLED_PRODUCT = YES
STRIP_STYLE = debugging

But i’m not experienced enough to have an opinion about what should be the default options nor provide an extensive pro/cons presentation.


#8

I’ve tried those settings before without much luck, but adding the compiler flags directly like OBO suggested certainly did. I’ve tweaked the introjucer now to do this, and our Tracktion installer size just shrank by about 20%!


#9

Just for info, I’ve been able to strip a little further enabling every strip releated parameter in XCode instead of the two compiler flags.


#10

Hi,

I built the tip “Introjucer” and it puts (at least in Xcode) the -gfull option in ‘ld’ flags ; Correct me if i’m wrong but shouldn’t it be a ‘gcc’ flag?

And if i’m right ; that imply to let them in the product (without more stripping).

MacBook-de-nicolas:sdk-build nicolas$ mxodump -a

/Users/nicolas/work/sdk-build/Jojo.mxo

00000020 - 01 0000 ENSYM 
00000020 - 00 0000   FUN 
00000000 - 01 0000    SO 
00000d2c - 01 0000 BNSYM 
00000039 - 01 0000 ENSYM 
00000039 - 00 0000   FUN 
000000a0 - 00 0000   FUN 
000000a0 - 01 0000 ENSYM 
00000dcc - 01 0000 BNSYM 
00000e0c - 01 0000 BNSYM 
00000020 - 00 0000   FUN 
00000020 - 01 0000 ENSYM 
00000dec - 01 0000 BNSYM 
00000e6a s  stub helpers
00000000 - 00 0000    SO /Users/nicolas/Work/Jojo/Sources/Jojo/Builds/MacOSX/../../Source/
00000000 - 00 0000   SOL /Users/nicolas/Work/Jojo/Sources/Jojo/Builds/MacOSX/../../Source/Jojo.cpp
51fe5b4d - 00 0001   OSO /Users/nicolas/Work/Jojo/Sources/Jojo/Builds/MacOSX/build/Jojo.build/Release/Jojo.build/Objects-normal/i386/Jojo.o
00000000 - 00 0000    SO Jojo.cpp
00000e0c - 01 0000   FUN __Z8jojo_newP6symbollP4atom
00000e0c t __Z8jojo_newP6symbollP4atom
00000dcc - 01 0000   FUN __Z9jojo_bangP5_jojo
00000dcc t __Z9jojo_bangP5_jojo
00000dec - 01 0000   FUN __Z9jojo_freeP5_jojo
00000dec t __Z9jojo_freeP5_jojo
00001020 - 09 0000 STSYM __ZL10jojo_class
00001020 b __ZL10jojo_class
00000000 t __mh_bundle_header
         U _class_addmethod
         U _class_new
         U _class_register
         U _gensym
00000d2c T _main
00000d2c - 01 0000   FUN _main
         U _object_alloc
         U _post
         U dyld_stub_binder

#11

Thanks chaps. I did a few experiments and tweaked the way it’s done now. Can’t find any other ways to improve it further, but let me know if you do. (Bear in mind that I’m deliberately not stripping the release build, because I want it to remain debuggable, just stripping the dead code).


#12

Hi,

IMHO the code below can properly strip the dead code AND strip the debugging symbols WITHOUT alter the rest of the table.

        else
        {
            defines.set ("_NDEBUG", "1");
            defines.set ("NDEBUG", "1");
            s.add ("GCC_GENERATE_DEBUGGING_SYMBOLS = YES");
            s.add ("GCC_DEBUGGING_SYMBOLS = full");
            s.add ("GCC_SYMBOLS_PRIVATE_EXTERN = YES");
            s.add ("DEAD_CODE_STRIPPING = YES");
            s.add ("DEPLOYMENT_POSTPROCESSING = YES");
            s.add ("STRIP_INSTALLED_PRODUCT = YES");
            s.add ("STRIP_STYLE = debugging");
        }

Introjucer built and test on a dummy plug-in:

Release:

MacBook-de-nicolas:macos nicolas$ nm -a jojo
00000e6a s  stub helpers
00000e0c t __Z8jojo_newP6symbollP4atom
00000dcc t __Z9jojo_bangP5_jojo
00000dec t __Z9jojo_freeP5_jojo
00001020 b __ZL10jojo_class
00000000 t __mh_bundle_header
         U _class_addmethod
         U _class_new
         U _class_register
         U _gensym
00000d2c T _main
         U _object_alloc
         U _post
         U dyld_stub_binder

Debug:

00000030 - 01 0000 ENSYM 
00000030 - 00 0000   FUN 
00000000 - 01 0000    SO 
00000cc0 - 01 0000 BNSYM 
00000076 - 01 0000 ENSYM 
00000076 - 00 0000   FUN 
000000c0 - 00 0000   FUN 
000000c0 - 01 0000 ENSYM 
00000d80 - 01 0000 BNSYM 
00000de0 - 01 0000 BNSYM 
00000030 - 00 0000   FUN 
00000030 - 01 0000 ENSYM 
00000db0 - 01 0000 BNSYM 
00000e7a s  stub helpers
00000000 - 00 0000    SO /Users/nicolas/Work/Jojo/Sources/Jojo/Builds/MacOSX/../../Source/
00000000 - 00 0000   SOL /Users/nicolas/Work/Jojo/Sources/Jojo/Builds/MacOSX/../../Source/Jojo.cpp
51fe9272 - 00 0001   OSO /Users/nicolas/Work/Jojo/Sources/Jojo/Builds/MacOSX/build/Jojo.build/Debug/Jojo.build/Objects-normal/i386/Jojo.o
00000000 - 00 0000    SO Jojo.cpp
00000de0 - 01 0000   FUN __Z8jojo_newP6symbollP4atom
00000de0 T __Z8jojo_newP6symbollP4atom
00000d80 - 01 0000   FUN __Z9jojo_bangP5_jojo
00000d80 T __Z9jojo_bangP5_jojo
00000db0 - 01 0000   FUN __Z9jojo_freeP5_jojo
00000db0 T __Z9jojo_freeP5_jojo
00001020 b __ZL10jojo_class
00001020 - 09 0000 STSYM __ZL10jojo_class
00000000 t __mh_bundle_header
         U _class_addmethod
         U _class_new
         U _class_register
         U _gensym
00000cc0 - 01 0000   FUN _main
00000cc0 T _main
         U _object_alloc
         U _post
         U dyld_stub_binder

But take care, i didn’t test the trick intensively as i’m a newbie with the “Introjucer” and i do not have a complete project right now on which i could observe dead code stripping in action :wink:


#13

Like I already explained a few times now, I do NOT want it to strip the symbols! That’d prevent debugging of the release build, which is often essential.

The way it’s currently implemented should achieve the smallest possible binary if you use a separate post-build ‘strip’ command. Since it’s fair to assume that anyone who’s actually shipping a product must have some kind of custom script to build their installer package, I think that’s the most appropriate place to do the strip.


#14

Will test this when i get a moment.
Just a question: Windows Release builds are always stripped from symbols, right?


#15

[quote=“OBO”]Will test this when i get a moment.
Just a question: Windows Release builds are always stripped from symbols, right?[/quote]

I think the introjucer has an option to keep debugging symbols in there, but yes, in Windows the stripping is generally done by the linker, not by external tools.


#16

Hi,

Sorry for misunderstanding, i thought you was refering only to the symbol table as in your code GCC_GENERATE_DEBUGGING_SYMBOLS = NO.

        {
            defines.set ("_NDEBUG", "1");
            defines.set ("NDEBUG", "1");
            s.add ("GCC_GENERATE_DEBUGGING_SYMBOLS = NO");
            s.add ("GCC_SYMBOLS_PRIVATE_EXTERN = YES");
            s.add ("DEAD_CODE_STRIPPING = YES");
        }