View RSS Feed

zabsv

Hildenborgs 4k tutorial goes Linux

Rate this Entry
Jag har sneglat på Hildenborgs 4k demo tutorial ett tag, men eftersom jag inte är kompis med vare sig Visual Studio eller Windows så har jag inte riktigt orkat ge mig in på det.

Men nu har det äntligen blivit av

För att vara tydlig så är det här alltså inte någon tutorial i sig, utan det här är bara mina försök att följa principerna i Hildenborgs 4k tutorial på Linux.

Jag har inte hittat någon direkt motsvarighet till Crinkler, men med några små knep kan man få ner storleken en del.

Jag börjar med att klistra in en Linuxanpassad källkod..
Kod:
#include
#include
#include
#include

asm(".globl _start;"
    "_start:;"
    "call main;"
    "movl $1, %eax;"
    "xorl %ebx, %ebx;"
    "int $0x80;"
   );

Display *dpy;
Window root;
GLint att[] = { GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None };
XVisualInfo *vi;
Colormap cmap;
XSetWindowAttributes swa;
Window win;
GLXContext glc;
XWindowAttributes gwa;
XEvent xev;


void DrawTri()
{
    glClearColor(1.0, 1.0, 1.0, 1.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    glBegin(GL_TRIANGLES);
    glColor3f(1.0f, 0.0f, 0.0f);
    glVertex2f(0.0f, 0.5f);
    glColor3f(0.0f, 1.0f, 0.0f);
    glVertex2f(0.5f, -0.5f);
    glColor3f(0.0f, 0.0f, 1.0f);
    glVertex2f(-0.5f, -0.5f);
    glEnd();
}

int main()
{

    dpy = XOpenDisplay(NULL);
    root = DefaultRootWindow(dpy);
    vi = glXChooseVisual(dpy, 0, att);
    cmap = XCreateColormap(dpy, root, vi->visual, AllocNone);
    swa.colormap = cmap;
    swa.event_mask = ExposureMask | KeyPressMask;

    win = XCreateWindow(dpy, root, 0, 0, 600, 600, 0, vi->depth, InputOutput, vi->visual, CWColormap | CWEventMask, &swa);

    XMapWindow(dpy, win);
    XStoreName(dpy, win, "4k tutorial goes Linux");

    glc = glXCreateContext(dpy, vi, NULL, GL_TRUE);
    glXMakeCurrent(dpy, win, glc);
    glEnable(GL_DEPTH_TEST);

    while(1) {
        XNextEvent(dpy, &xev);

        if(xev.type == Expose) {
            XGetWindowAttributes(dpy, win, &gwa);
            glViewport(0, 0, gwa.width, gwa.height);
            DrawTri();
            glXSwapBuffers(dpy, win);
        }else if(xev.type == KeyPress) {
            glXMakeCurrent(dpy, None, NULL);
            glXDestroyContext(dpy, glc);
            XDestroyWindow(dpy, win);
            XCloseDisplay(dpy);
            return(0);
        }
    }
}
Till att börja med så inkluderar GCC alltid libc, så det första man vill göra är att kompilera utan libc. Jag tänker inte fördjupa mig i det utan hänvisar till Hello from a libc-free world på Ksplice

Det går att göra som i exemplet på Ksplice och lägga assemblerkoden i en separat fil. Man kan också infoga den i C++ koden som jag har gjort.

gcc/g++ har en djungel av parametrar för optimering, jag nöjde mig med -Os (optimize for size) och -nostdlib (inkludera inte libc) tills vidare.
Jag hittade ett par 4k tutorials på nätet där man först kör gcc för att skapa en objektfil, och sedan manuellt länkar de bibliotek som behövs. Men det går också bra att låta gcc sköta läkningen automatiskt.
Jag har provat båda varianter, och på mitt system fick jag en fil som var ungefär 100bytes mindre om jag lät gcc sköta allt.
Kod:
$ g++ -Os -nostdlib 4k.cpp -lX11 -lGL
Vill man dela upp det kör man först
Kod:
$ g++ -Os -nostdlib -c 4k.cpp
och sedan
Kod:
$ ld -dynamic-linker /lib64/ld-linux-x86-64.so.2 4k.o /usr/lib/libGL.so /usr/lib/x86_64-linux-gnu/libX11.so
Om man har ett 64 bitars ubuntusystem.
Eller:
Kod:
$ ld -dynamic-linker /lib/ld-linux.so.2 4k.o /usr/lib/i386-linux-gnu/libGL.so /usr/lib/i386-linux-gnu/libX11.so
Om man kör 32-bitars ubuntu.

Fortfarande har vi en bit till 4k gränsen. Men linux har ett litet verktyg för att rensa koden från onödig information.
Kod:
$ strip -s a.out
Även strip har en del parametrar, så liksom för gcc så är det värt att utforska dom och se om det finns mer att hämta.
I alla fall verkar strip inte ta bort riktigt allt, så man får köra något som heter sstrip.
Kör du Ubuntu finns det inget färdigt paket för det (vet inte hur det är med andra varianter av Linux). Så ladda hem ELFkickers från Muppetlabs
Det är bara att packa upp och köra make så har du sstrip i bin katalogen. Kopiera den till ~/bin eller valfri favoritplats
Kod:
$ sstrip a.out
Nu börjar vi närma oss 4k, men för att få ner storleken ytterligare måste vi komprimera filen.
Linux har ett verktyg som heter gzexe som skapar självuppackande arkiv. Ska man vara petig vet jag inte om man kan kalla dom självuppackande eftersom dom anropar gzip för att göra själva uppackningen.
Men dom regler Hildemborg hänvisade till sa att man fick använda det som fanns i standard Windows, så då kan vi nog med gott samvete använda det som finns i standard Linux.
Nåväl gzexe är bra, men det skrevs inte med 4k demos i åtanke. Så vi gör en egen variant.
Skapa en fil som heter t.ex unzip_header med följande innehåll
Kod:
#!/bin/sh
F='/tmp/4k'
tail -n+4 $0|gzip -cd>$F;chmod +x $F;$F;exit
kör sedan
Kod:
$ cp unzip_header 4kZip
$ cat a.out | gzip -n9 >> 4kZip
$ chmod +x 4kZip
Och nu har vi en körbar självuppackande fil på 1.7K
Visserligen nästan dubbelt så stor som Hildenborgs fil, men för att vara mitt första försök att minimera en binär är jag ganska nöjd.
Jag hoppas såklart på att få ner storleken ännu mer, så kom gärna med tips på vad man kan göra för att få ner filstorleken under Linux.

Submit "Hildenborgs 4k tutorial goes Linux" to Digg Submit "Hildenborgs 4k tutorial goes Linux" to del.icio.us Submit "Hildenborgs 4k tutorial goes Linux" to StumbleUpon Submit "Hildenborgs 4k tutorial goes Linux" to Google

Taggar: c++, linux, opengl Lägg till/redigera taggar
Kategorier
Uncategorized

Comments