I'm trying to create a minimal sized executable for a demoscene contest. I'm trying to minimize the size of the executable by linking it myself.
Here is my minimal main.c, taken from http://www.int21.de/linux4k/ It draws a white triangle on the screen:
#include "SDL/SDL.h"
#include "GL/gl.h"
void _start(){
SDL_Event event;
SDL_SetVideoMode(640,480,0,SDL_OPENGL|SDL_FULLSCREEN);
SDL_ShowCursor(SDL_DISABLE);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-1.33,1.33,-1,1,1.5,100);
glMatrixMode(GL_MODELVIEW);
glEnable(GL_DEPTH_TEST);
glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT);
glLoadIdentity();
glBegin(GL_TRIANGLES);
glVertex3i(1,1,-10);
glVertex3i(1,-1,-10);
glVertex3i(-1,1,-10);
glEnd();
SDL_GL_SwapBuffers();
do{
SDL_PollEvent(&event);
} while (event.type!=SDL_KEYDOWN);
SDL_Quit();
}
I am using void _start()
instead of int main()
, because I don't want to use the C runtime. Here are my build commands (my machine is running Ubuntu Linux):
gcc -c main.c
ld -dynamic-linker /lib64/ld-linux-x86-64.so.2 -lc -lSDL -lGL main.o -o main
The program crashes on SDL_SetVideoMode. gdb reports:
Program received signal SIGSEGV, Segmentation fault.
_dl_map_object_from_fd (name=0x7ffff77dfcec "libXrender.so.1", fd=-1, fbp=0x7fffffffd908,
realname=0x601de0 "/usr/lib/x86_64-linux-gnu/libXrender.so.1", loader=<optimized out>, l_type=<optimized out>,
mode=-1879048190, stack_endp=0x7fffffffdc68, nsid=0) at dl-load.c:1574
What is wrong? If I change void _start()
to int main()
, and compile the whole thing with gcc main.c -o main -lSDL -lGL
, it works just fine. This working version and the self-linked broken version have exactly the same list of linked libraries when I inspect the executables with ldd
.
TL;DR: Patient: "Doctor, it hurts when I do ${THAT}" – Doctor: "Then don't do ${THAT}".
If you don't want to have the C runtime in there you must make sure that you don't use any code that relies on the C runtime being available and more importantly being initialized. SDL strongly depends on the facilities of libc (which is why you probably added that -lc
so that SDL can be properly linked), so when you link it, you need all that libc stuff. However for libc to properly work it must be initialized, which is what _start()
does.
If you want to get your executable size down, which yes also involved getting rid of the (bloated GNU) libc, you'll have to do a lot of things yourself and/or patch libraries you use not to rely on the things you want to remove.