I just read on how to remove alot of dependencies on system libs in windows C code which resulted in a very small executable. What I tried in Nim was just:
var a = 1
and:
nimrod compile --deadCodeElim:on --opt:size lab1.nim
But due to system.c, lab.exe becomes 168kb for that one line.
Are there more ways to tell the compiler to remove more or are there other ways to step around it?
You can also try clang with LTO as backend instead of gcc. See my test:
system.nim(2126, 10) Error: cannot open 'panicoverride'
How do I get around the panicoverride error?
Also I tried changing switching to clang but ran into this (using windows8, and couldnt find gold to link with!?):
clang.exe -o w:nimcodejunklab1.exe w:nimcodejunknimcachesystem.o w:nimcodejunknimcachelab1.o system.o : error LNK2019: unresolved external symbol fileno referenced in function systemInit system.o : error LNK2019: unresolved external symbol setmode referenced in function systemInit w:nimcodejunklab1.exe : fatal error LNK1120: 2 unresolved externals clang.exe: error: linker command failed with exit code 1120 (use -v to see invocation) Error: execution of an external program failed
For anyone interested:
Interesting that windows executables are much larger than on Linux...
For clang LTO backend: I had some difficulties to get it work on my Gentoo Linux box, because the default has to be still gcc for my box. I wrote how I solved it, but I can not tell you for Windows... But you should test a plain C program first -- when that does not work, Nim will not also.
Generally: Testing with an input file which does nothing may not make much sense -- even an stupid compiler may notice that there is no output and no other activity and simple generate a few byte minimal dummy file. And: GC is generally needed, because std lib may use it. I once did a test compile without CG and noticed a size difference of a few 10 kB -- I really thing GC will be larger than 9kB. So question is what makes the 9k difference you noticed. And what is you motivation at all? File size is important for embedded devices, but not really for PC. I guess, when you really wants to investigate this topic, you may look at the generated C code in nimcache directory. Generally Nim is good with file size, and may become even better when developers have solved all the other more important topics. Rust was very bad with filesize in early days, and someone told me some months ago that Rust generates still larger files than Nim.
thx Araq nimrod compile --deadCodeElim:on --opt:size --stackTrace:off --lineTrace:off -d:release --os:standalone lab1.nim
now generated ~134 kb of .exe
with clang it generaed 79 kb of .exe (but omitting the .exe since the line generated was:
clang.exe -o w:nimcodejunklab1 w:nimcodejunknimcachepanicoverride.o w:nimcodejunknimcachesystem.o w:nimcodejunknimcachelab1.o
So 168 to 79 kb is realtivly easy.
Compile time with gcc = 178ms, with clang about 128ms
IF we want to go even smaller the question is if we can make the compiler kill even more dead code or make it compile without the CRT in windows. In this post: https://forums.handmadehero.org/index.php/forum?view=topic&catid=4&id=79 he takes an empty windows program in c that compiles to 68KB and shows how avoid the c/c++ runtime and reducing the size to about 2.5KB (admittingly he adds code at the end). Also he is compiling using vcc (cl.exe) and not clang, implying that the code could be even smaller.
Are there any other steps we can do in Nim, in order to reduce the size beyond my 134KB/79KB ?
Are there any other steps we can do in Nim, in order to reduce the size beyond my 134KB/79KB?
You can do everything that your link says you can do with Visual C/C++. --app:gui produces a WinMain entry point instead of main on Windows.
I have to mention that Rust can already do dynamic linking, with only 8kB executable size.
https://mail.mozilla.org/pipermail/rust-dev/2014-July/010731.html
Of course not very portable -- but for Gentoo Users like me dynamic linking would be nice...
cd /home/stefan/gitnim/Nimrod/
nim c -d:release lib/nimrtl.nim
nim c -d:release -d:useNimRtl test.nim ==> only 11kB binary with gcc on Gentoo Linux! Really nice!
"Note: Currently the creation of nimrtl.dll with thread support has never been tested and is unlikely to work!" (http://nim-lang.org/nimc.html)
is it still relevant?
It seems that the nimbase.h #including limits.h, stddef.h, stdint.h and float.h might be the cause of the size but who am I to say. It just seems that we should be able to kill more code for a smaller program.
~100KB (give or take) for a program that really doesnt do anything seems hefty.
Well if i could generate a map file that might tell us.
I cant seem to get clang to do so even when I compile (nim) with -d:-Wl,-map,output.map
I might try and compile using vcc, there I know how to get the map file at least.
As a curiosity I might say that if I just make a C program doing nothing but needing window.h, it turns the "exact" same size (give or take some odd bytes). So it could be that we are always using windows.h in windows builds and that is the root of the size. Would be interesting to build a header file with the code from that build and have a flag allowing for minimal builds on your own risk.