[HOWTO] optimiertes commandline ProjectX mit GCC (gcj)

  • Neues HOWTO, 11.Oktober 2007


    Leider habe ich es nicht mehr geschafft, mit dem GCC-4.2 die .java-Files direkt zu compilieren, deshalb wird der Bytecode vom originalen Sun JDK erzeugt


    Build-Abhängigkeiten:


    Runtime-Abhängigkeiten:

    • libgcj
    • zlib1g
    • eventuell cairo, gtk, ...? (nicht direkt, aber über die libgcj -- noch zu testen auf einem LFS-System)


    Vorgehensweise:
    [list=1]
    [*]Compiler-Optimierungen wählen, z.B. für einen Athlon64
    (unbedingt auf den eigenen Prozessortyp anpassen!)


    Code
    export GCJFLAGS="-O3 -fomit-frame-pointer -pipe -march=k8"


    [*]ProjectX entpacken und build-script anpassen zum compilieren ohne GUI:


    Code
    unzip ProjectX_Source_0.90.3.01.zip
    cd ProjectX_Source_0.90.3.01
    sed -i -e's:sources.lst:noguisources.lst:' build.sh


    [*]Compilieren in Byte-Code:


    Code
    . ./build.sh


    [*]Libraries compilieren:


    Code
    cd lib
    gcj -c $GCJFLAGS -o jakarta-oro-2.0.8.o jakarta-oro-2.0.8.jar
    gcj -c $GCJFLAGS -Ijakarta-oro-2.0.8.jar -o commons-net-1.3.0.o \
            commons-net-1.3.0.jar
    cd ..


    [*]ProjectX compilieren und strippen:


    Code
    gcj $GCJFLAGS -fno-bounds-check -fno-store-check -fjni -encoding \
            "ISO-8859-1" --main=net.sourceforge.dvb.projectx.common.Start \
            -Dawt.toolkit=gnu.java.awt.peer.headless.HeadlessToolkit \
            -oprojectx -Ilib/commons-net-1.3.0.jar -Ilib/jakarta-oro-2.0.8.jar \
            ProjectX.jar lib/jakarta-oro-2.0.8.o lib/commons-net-1.3.0.o
    strip --strip-all projectx


    [/list=1]


    Hier noch ein bisher ungetesteter patch für das burn-plugin um die nativ compilierte Version von projectx zu verwenden:





    --- Ab hier folgt eine ALTE Version für GCC-4.1.x ---


    Hier mal eine Schritt für Schritt Anleitung, wie man sich projectx als optimierten native code compiliert.


    [edit] ACHTUNG: Leider habe ich gerade einen unschönen Effekt entdeckt: Das Binary ist abhängig von GTK+ und einem laufenden X-Server. Für den Headless-Einsatz ist das natürlich sehr hässlich :(



    Voraussetzungen:
    - ProjectX Source 0.90.4
    - GCC 4.1.x mit gcj und libgcj


    getestet auf Debian testing mit GCC 4.1.1 und auf einem LFS System mit GCC 4.1.2


    1. ProjectX entpacken und angehängten Patch einspielen

    Code
    unzip ProjectX_Source_eng_0.90.4.00.zip
    cd ProjectX_Source_0.90.4
    patch -Np1 -i ../ProjectX_0.90-gcc-build-fixes.1.diff

    Der Patch ergänzt ein paar explizite typecasts in einem source-file, die gcj unbedingt haben will.


    2. Optimierungen setzen (das hängt natürlich vom Prozessortyp ab). Ich habe folgendes gemacht:

    Code
    export GCJFLAGS="-g0 -O3 -fomit-frame-pointer -pipe -march=athlon-xp"


    3. Mitgelieferte libraries compilieren

    Code
    cd lib
    gcj -c $GCJFLAGS -o jakarta-oro-2.0.8.o jakarta-oro-2.0.8.jar
    gcj -c $GCJFLAGS -Ijakarta-oro-2.0.8.jar -o commons-net-1.3.0.o \
            commons-net-1.3.0.jar
    cd ..


    4. ProjectX selbst compilieren

    Code
    gcj -c $GCJFLAGS -fno-bounds-check -fno-store-check -fjni \
            -encoding "ISO-8859-1" -Ilib/commons-net-1.3.0.jar \
            -Ilib/jakarta-oro-2.0.8.jar -oprojectx.o @noguisources.lst

    Die Flags schalten Exceptions für Fehler im Umgang mit Arrays aus. Sollte ProjectX tatsächlich einen solchen Fehler haben ist die Folge undefiniertes Verhalten anstatt einer aussagekräftigen Exception. Wer will kann die Flags natürlich auch weglassen.


    5. Benötigte Resourcen

    Code
    gcj -c -o ac3.o --resource ac3.bin resources/ac3.bin
    gcj -c -o pjxresources_en.o --resource pjxresources_en.properties \
            resources/pjxresources_en.properties


    6. Linken

    Code
    gcj $GCJFLAGS --main=net.sourceforge.dvb.projectx.common.Start -o projectx \
            projectx.o ac3.o pjxresources_en.o \
            lib/jakarta-oro-2.0.8.o lib/commons-net-1.3.0.o


    Nach dieser Prozedur hat man ein dynamisch gegen libgcj gelinktes ca. 2.5 MB großes binary im aktuellen Verzeichnis. Durch strippen lässt es sich auf ca. 1.7 MB verkleinern:

    Code
    strip --strip-all projectx


    Ich habe damit testweise eine VDR-Aufnahme mit einer Video-, einer AC3- und zwei mp2-Tonspuren demuxt, es hat anstandslos funktioniert :)


    Grüße, Felix


    PS: Eventuell lässt sich noch weiter optimieren indem man
    - die verwendeten Libraries im Quellcode besorgt und ohne Umweg über Bytecode direkt mit gcj compiliert
    - ProjectX in Teile zerlegt, die mit JNI compiliert werden müssen, und solche, für die man CNI verwenden kann

  • Hi zirias,


    danke für die Anleitung! Hast Du mal auf die Performance geschaut - bringt's was ? Ich habe bei mir den Eindruck, die Festplatte ist der Flaschenhals. Oder willst Du nur die Installation von Java vermeiden?


    Übringens gibt es hier einen interessanten Patch "Faster IDCT support for Linux".


    Gruß, ollo

  • Also meine Motivation für's "ausknobeln" war, projectx in einem schlanken LFS system ohne Java-VM zu installieren. Daraus wurde jetzt leider erstmal nichts, nachdem ich germerkt habe, dass es ohne GTK+ nicht läuft :(


    Eine Lösung scheint allerdings in Sicht: GCC 4.2 bietet offenbar ein headless AWT, ähnlich wie Sun. Ich bin gerade am runterladen und werde das HOWTO bei Erfolg entsprechend ergänzen :)


    Was Performance angeht: Native code sollte /immer/ schneller sein. Ab welcher Rechenleistung das wirklich spürbar wird weiß ich allerdings nicht.


    Danke für den interessanten Link!


    Grüße, Felix

    Asrock A75 Pro4-M
    Debian wheezy (testing, stock) (aktuell 2012-08-24: Linux 3.2, VDR 1.7.28)
    vdr-sxfe (xineliboutput)
    Pioneer VSX-520-K

  • Sehr schöne Idee. :)


    Wenns nun noch ohne weitere Abhängigkeiten ginge..

  • Ich bin dran ;)


    GCC 4.2 hat leider doch nicht, was ich brauche. Die aktuelle GNU Classpath Library hat allerdings
    gnu.java.awt.peer.headless.HeadlessToolkit, ich nehme stark an, dass es damit geht.


    Mit Google habe ich RPMs von gcc-java-dev gefunden, die das enthalten, also ist es offenbar möglich, diese aktuelle Classpath Library in die libgcj von GCC einzubauen. Das versuche ich gerade; leider kompiliert der Testrechner nicht gerade schnell :)


    Wer das Glück hat, dass seine Distribution eine libgcj ausliefert, die diese Klasse schon hat, kann es testen: Einfach ein -Dawt.toolkit=gnu.java.awt.peer.headless.HeadlessToolkit in das Kommando zum Linken. Kommt dann aber beim Startversuch diese Exception:

    Code
    Exception in thread "main" java.awt.AWTError: Cannot load AWT toolkit: gnu.java.awt.peer.headless.HeadlessToolkit

    dann ist die Klasse leider nicht vorhanden und man müsste im Zweifelsfall GCC selbst neu kompilieren wie ich es gerade versuche.


    Grüße, Felix

    Asrock A75 Pro4-M
    Debian wheezy (testing, stock) (aktuell 2012-08-24: Linux 3.2, VDR 1.7.28)
    vdr-sxfe (xineliboutput)
    Pioneer VSX-520-K

    Einmal editiert, zuletzt von zirias ()

  • Kleines Update:


    "Headless" ist möglich mit einer libgcj, die classpath 0.93 oder höher enthält.


    Dazu muss im Schritt für's Linken -Dawt.toolkit=gnu.java.awt.peer.headless.HeadlessToolkit angegeben werden.


    Einige Distributionen haben wohl classpath 0.93 in ihre aktuelle gcc-Version "backported", ein Versuch könnte es also wert sein.


    Offiziell wird classpath-0.93 wohl erst in gcc 4.3 erscheinen.


    Ich habe auch mit gcc-4.3 (aus dem aktuellen subversion) getestet, habe dann aber aufgegeben, denn:


    Die Abhängigkeit von GTK+ / Cairo lässt sich leider nicht vermeiden, man kann lediglich auf einen X-Server verzichten. GTK+ und Cairo extra für ProjectX zu compilieren war mir dann doch zu dumm, werde es für's erste mit einer Java-VM versuchen :(


    Bleibt zu hoffen, dass in naher Zukunft bei ProjectX endlich sauber zwischen den Schichten getrennt wird (GUI und business-logic ...)


    Für alle, die gerne mit gcc-4.3 bauen möchten und auch die Abhängigkeit von GTK+ und Cairo akzeptieren noch ein paar Tips:


    - gjc 4.3 braucht ecj.jar - siehe sript "download-ecj" in contrib. Angeblich wird ecj.jar korrekt erkannt wenn es im basis-verzeichnis von gcc liegt, ich habe aber die gegenteilige erfahrung gemacht: Es ist auf jeden fall sicherer, ./configure die Option --with-ecj-jar=7full/path/to/ecj.jar mitzugeben.


    - Compilieren von mehreren .java-Files in ein einzelnes Object-File (.o) ist mit gcj-4.3 nicht mehr möglich. Am einfachsten ist es, aus dem obigen Howto das Compilieren von projectX und das Linken mit den Libs und den Resourcen in einen einzigen Befehl zusammenzufassen:

    Code
    gcj -c $GCJFLAGS -fno-bounds-check -fno-store-check -fjni \
            -encoding "ISO-8859-1" --main=net.sourceforge.dvb.projectx.common.Start \
            -Ilib/commons-net-1.3.0.jar -Ilib/jakarta-oro-2.0.8.jar -oprojectx.o \
            -Dawt.toolkit=gnu.java.awt.peer.headless.HeadlessToolkit \
            -oprojectx.o @noguisources.lst ac3.o pjxresources_en.o\
            lib/jakarta-oro-2.0.8.o lib/commons-net-1.3.0.o


    So, das war's soweit ... Falls sich entweder seitens ProjectX oder seitens GCC weitere Verbesserungen ergeben, die ich mitbekomme, werde ich hier ergänzen.


    Grüße, Felix

    Asrock A75 Pro4-M
    Debian wheezy (testing, stock) (aktuell 2012-08-24: Linux 3.2, VDR 1.7.28)
    vdr-sxfe (xineliboutput)
    Pioneer VSX-520-K

  • So, großes Update, siehe erstes Posting :)


    ProjectX lässt sich aktuell leider nicht ganz ohne JDK bauen (zumindest habe ich es nicht geschafft), aber das Resultat ist von Sun JDK oder JRE unabhängig. Ob es auch von X unabhängig ist werde ich noch testen müssen, zumindest läuft es schonmal ohne $DISPLAY.


    Grüße, Felix

    Asrock A75 Pro4-M
    Debian wheezy (testing, stock) (aktuell 2012-08-24: Linux 3.2, VDR 1.7.28)
    vdr-sxfe (xineliboutput)
    Pioneer VSX-520-K

  • EDIT: Oh man, ich sollte besser hinschauen! Ich habe ja gcj 4.1.2 und nicht wie in der ersten Anleitung 4.2.1!
    Mit der zweiten Anleitung für 4.1.x hat alles geklappt :)


    Ich bekomme beim Kompilieren mit gcj 4.1.2 folgenden Fehler:



    System ist ein Zenwalk (Slackware) Linux mit:

    Code
    root[ProjectX_Source_0.90.3.01]# java -version
    java version "1.6.0_02"
    Java(TM) SE Runtime Environment (build 1.6.0_02-b05)
    Java HotSpot(TM) Server VM (build 1.6.0_02-b05, mixed mode)
  • Zitat

    Original von thenktor
    EDIT: Oh man, ich sollte besser hinschauen! Ich habe ja gcj 4.1.2 und nicht wie in der ersten Anleitung 4.2.1!
    Mit der zweiten Anleitung für 4.1.x hat alles geklappt :)


    Ich weiß, das kommt jetzt SEHR spät (hab jetzt doch recht lange kein vdr-portal gelesen), aber trotrzdem:


    Ich würde dir raten, auf GCC 4.2+ zu aktualisieren. Erst ab dieser Version habe ich es geschafft, das "HeadlessToolkit" von GNU Classpath mit ProjectX zu benutzen -- also im Endeffekt einen von X11 unabhängigen native build zu erstellen. Das war ursprünglich auch mal ein 'Zweck der Übung' ;)

    Asrock A75 Pro4-M
    Debian wheezy (testing, stock) (aktuell 2012-08-24: Linux 3.2, VDR 1.7.28)
    vdr-sxfe (xineliboutput)
    Pioneer VSX-520-K

  • Ist egal, ich benutze jetzt einfach das normale Java Projext X, hab extra ein Paket davon für die Zenwalk Distribution gebaut. Und da ich ab und zu auch andere Pakete für Zenwalk baue, bin ich sowieso auf die gcc Version der Distribution festgelegt.
    Aber danke für die Hilfe und frohe Weihnachten!

  • Hallo,


    ich habe es mit gcc-4.2.0 versucht und die lib haben geklappt.
    bei projectx bekomme ich jedoch:


    Code
    >>main<<-Klasse kann ohne Binden nciht angegeben werden


    Weiß jemand was damit gemeind ist?


    ich verwenden gcc-4.2.0 und ProjectX 0.90.4.


    MfG,
    Thomas


  • Ich glaube ja -- Vrmutung: du hast im letzten Kommando noch das '-c' flag, was den GCC anweist, nur zu kompilieren (und nicht zu linken). Das muss weg, wie es auch oben in der Anleidtung steht. Die main-Klasse (als Einstiegspunkt für das fertige Binary) kann erst im letzten Schritt angegeben werden und da muss gelinkt werden ;)


    Die Übersetzung "Binden" finde ich dafür irgendwie nicht so gelungen. Mal noch ein allgemeiner Tip: Wenn man Fehlermeldungen "googlen" will (oder manchmal auch sonst) ist es hilfreich, die originale Sprache zu haben. "LANG=C" vor das Kommando stellen ;)

    Asrock A75 Pro4-M
    Debian wheezy (testing, stock) (aktuell 2012-08-24: Linux 3.2, VDR 1.7.28)
    vdr-sxfe (xineliboutput)
    Pioneer VSX-520-K

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!