I've got a relatively small codebase in nim but i'm seeing the final library (stripped) to exceed 1.2 megabytes (which i was a bit surprised considering the overall project size).
Current Size Analysis (1.2M total for the shared library, 2.4 for the static one):
__TEXT: 1.17MB (executable code and read-only data)
__DATA: 16KB (initialized data)
others: 48KB (symbol table, debug info)
lib/libxyz.a (2.4M total):
Contains 93 object files, with the largest contributors being:
regvm_compiler.nim.c.o: 127KB
regvm_exec.nim.c.o: 128KB
system.nim.c.o: 103KB (Nim runtime)
tables.nim.c.o: 128KB (Nim tables implementation)
expression_analysis.nim.c.o: 97KB
parser.nim.c.o: 76KB
I'm using this and also manually stripping it afterwards, if i nm i just see the {.exportc.} i'm interested int and that's it (but i also saw NimMain even tho i have --noMain in the commandline):
define:danger
checks:off
threads:off
panics:on
--passC:"-O3 -fomit-frame-pointer -fvisibility=hidden -fvisibility-inlines-hidden -march=native"
--passL="-Wl,-dead_strip -Wl,-dead_strip"
I know 1.2mb nowadays is nothing, but i'm mostly curious what i could do to strip it more (i can probably disable at compile time some features, but was trying to avoid it).
I tried lto and my static library went from 2.4M to 4.3M 😅 (while the shared library is mostly unchanged).
Of course that it will probably shrink when doing the final binary, but anyway 🤷
If you're using gcc and linking via ld.bfd you can use the following in your config.nims:
switch(
"t",
"-Os -flto=auto -flto-compression-level=3 -fuse-linker-plugin -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-plt",
)
switch(
"l",
"-Wl,-O1,-s,-z,noexecstack,-z,now,-z,pack-relative-relocs,-z,relro,--as-needed,--gc-sections,--sort-common,--hash-style=gnu -Os -flto=auto -flto-compression-level=3 -fuse-linker-plugin -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-plt",
)
I've got a relatively small codebase in nim ...
Well Nim is the ultimate code compression language. I've seen a 2200 line module expanding to 120_000 lines due to heavy template use. So "relatively small codebase" doesn't mean anything...
I usually just use eu-strip from elfutils package. It's handy for cross-compiling, because strip only works on native binaries.
But if you want to squeeze binary size even more, see UPX.
Programs and libraries compressed by UPX are completely self-contained and run exactly as before, with no runtime or memory penalty for most of the supported formats.
In my experience, it can compress Nim binaries down to 30% of it's original size.