Altes QT-Programm statisch linken

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
Benutzeravatar
MartinV
Beiträge: 790
Registriert: 31.07.2015 19:38:52
Wohnort: Hyperion
Kontaktdaten:

Altes QT-Programm statisch linken

Beitrag von MartinV » 18.02.2020 22:02:55

Ich möchte ein altes, aber mir sehr nützliches Programm selbst kompilieren und statisch verlinken.
Es geht um Debiankaptain.
kaptain basiert auf QT4, das jetzt gänzlich aus debian bullseye herausgeflogen ist. Ich kann es nicht mehr starten.
Leider sind meine Kenntnisse in C und QT minimalst, sonst würde ich es lieber auf QT5 portieren.

Kann mir jemand sagen, wie ich kaptain als standalone-Binary statisch kompilieren und linken kann? Auf diese Weise würde es QT4 selbst mitbringen. Meine Erfahrung mit selbst kompilieren ist leider gering.
Als Build-Umgebung würde ich einen Docker Container mit Debian Jessie oder stretch nehmen.
Die Vernunft kann einem schon leidtun. Sie verliert eigentlich immer.

Benutzeravatar
MSfree
Beiträge: 11604
Registriert: 25.09.2007 19:59:30

Re: Altes QT-Programm statisch linken

Beitrag von MSfree » 19.02.2020 08:19:53

MartinV hat geschrieben: ↑ zum Beitrag ↑
18.02.2020 22:02:55
Kann mir jemand sagen, wie ich kaptain als standalone-Binary statisch kompilieren und linken kann?
Beim Kompilieren des Programms muß man wenig bis gar nichts beachten. Da wird nur c/c++-Code in Maschinencode umgesetzt. Das eigentliche Problem ist das Linken, das die Dateien, in denen der Maschinencode steckt (*.o) mit Bibliotheken (z.B. libc und Qt-Libs) zu einem Executable zusammenkopiert wird. Sind die Bibliotheken statisch (erkennbar an der Dateiendung .a), wird auch das Programm ein statisch gelinnktes Programm. Sind die Bibliotheken dynamisch (erkennbar an der Dateiendung .so), wird auch das Programm ein dynamisch gelinktes Programm. Ist eine Mischung vorhanden, werden nur die .so-Dateien dynamisch gelinkt und der Rest statisch.

In deinem Fall würde es reichen, die Qt4-Bibliotheken als statische Bibliotheken zu erstellen. Dazu mußt du aber den Qt4-Code selbst kompilieren. Im Moment bin ich mir aber nichtmal mehr sicher, ob das Erstellen von statischen Qt-Libs überhaupt noch vorgesehen ist, ich habe da was dunkel n Erinnerung, daß das in der Vergangenheit zu Problemen geführt hat und heute nicht mehr vom Qt-Buildprozeß unterstützt wird.

pferdefreund
Beiträge: 3799
Registriert: 26.02.2009 14:35:56

Re: Altes QT-Programm statisch linken

Beitrag von pferdefreund » 19.02.2020 08:29:42

ein weiteres Problem könnte auftauchen, wenn die Anwendung mit dlopen und Konsorten arbeitet. Das geht nur mit .so-Bibliotheken und kann grundsätzlich nicht statisch gelinkt werden. Eventuell die QT4-Bibliotheken besorgen, in einen extra Ordner packen und den vor Programmstart aus der shell mit export LD_LIBRARY_PATH=.... entsprechend vorverketten.
Entspricht im MVS in der JCL dem //JOBLIB DD DSN=deine.biblio.thek.
Dazu könnten dann auch noch andere älterere Libs notwendig werden, - die dann halt auch dorthin packen. Mit etwas Glück muss dann Kaptain noch nicht mal neu kompiliert werden.
Auf die Art betreibe ich heute noch den xmms, der ja bekanntlich mit GTK 1.6 oder so rennt. Ist halt vom Klang her der beste Player - insbesondere mit dem eq-xmms-Plugin, dass für alles und nicht nur für mp3 funktioniert.

Benutzeravatar
MSfree
Beiträge: 11604
Registriert: 25.09.2007 19:59:30

Re: Altes QT-Programm statisch linken

Beitrag von MSfree » 19.02.2020 08:37:05

pferdefreund hat geschrieben: ↑ zum Beitrag ↑
19.02.2020 08:29:42
ein weiteres Problem könnte auftauchen, wenn die Anwendung mit dlopen und Konsorten arbeitet.
Ahh, jetzt, wo du es sagst. Qt verwendet intern dlopen , um eigene shared Objects zu öffnen. Das Styling und Druckfunktionalitäten stecken schon seit langem in .so-Dateien, die mit dlopen geladen werden. Das was auch der Grund, warum man Qt nicht mehr in statisch Bibliotheken bauen kann.

atarixle
Beiträge: 347
Registriert: 20.02.2006 19:30:37

Re: Altes QT-Programm statisch linken

Beitrag von atarixle » 19.02.2020 09:07:04

Eigentlich müsste man QT4 statisch linken können. PS: wenn dlopen dies verhindert, dann geht's wohl doch nicht immer

Ich hatte mal ein QT4.8-Programm für debian 7 (kam noch mit QT4.6) gebaut. (Es handelte sich um das Programm RespeQt, Hilfe bekam ich auf dem AtariAge-Forum. Bei Interesse bitte googlen, ich will hier nicht auf ein anderes Forum verlinken).

Eine andere Möglichkeit ist, ein AppImage aus einer laufenden Installation heraus zu erstellen. Das, so fand ich, war weniger aufwändig. Dass das eigentliche Programm wesentlich größer war, spielte keine Rolle, da man gar nichts kompilieren muss.

pferdefreund
Beiträge: 3799
Registriert: 26.02.2009 14:35:56

Re: Altes QT-Programm statisch linken

Beitrag von pferdefreund » 19.02.2020 14:12:57

Ich würde mir die QT-Debs runterladen, irgendwo hinstellen und das Original alte Programm damit probieren (vorher den LD_LIBRARY_PATH entsprechend anpassen) und schauen was noch fehlt oder passiert. MIt etwas Glück ist der Käse dann schon zum Bahnhof gerollt.

KP97
Beiträge: 3702
Registriert: 01.02.2013 15:07:36

Re: Altes QT-Programm statisch linken

Beitrag von KP97 » 19.02.2020 14:17:54

Eine schmutzige Lösung:
Soviele alte Libs als Abhängigkeit hat das Programm gar nicht. Im Archiv bzw. im Repo sind die ja noch vorhanden, die würde ich einzeln herunterladen und manuell in das richtige Verzeichnis kopieren. Überschrieben werden kann nichts mehr, und das Programm läuft auch.
Ist etwas Arbeit, aber das Kompilieren ist sicher aufwändiger. Dann noch eine kurze Notiz mit den Libs, wenn man die mal wieder entfernen will, damit hat man auch noch die Übersicht.

pferdefreund
Beiträge: 3799
Registriert: 26.02.2009 14:35:56

Re: Altes QT-Programm statisch linken

Beitrag von pferdefreund » 20.02.2020 07:53:03

Na ja, ich würde alles komplett - nicht nur die Libs in einen extra-Ordner packen, und auch dort das Startscript mit den LD_LIBRARY_PATH... reinpacken. Dann bin ich sicher, dass ein apt-get autoremove mir die Libs nicht wieder entsorgt - und wenn ich update, wird ein eigener Ordner ja vom System selbst nie angefasst. Im Notfall kann ich sogar den ganzen Ordner auf eine andere Maschine kopieren (so gleiche Architektur) und solange die LIBC6 und andere noch passen, rennt das problemlos weiterhin.

Benutzeravatar
MartinV
Beiträge: 790
Registriert: 31.07.2015 19:38:52
Wohnort: Hyperion
Kontaktdaten:

Re: Altes QT-Programm statisch linken

Beitrag von MartinV » 21.02.2020 13:23:56

Danke für Eure Tips!

Ein erster Erfolg!
pferdefreund hat geschrieben: ↑ zum Beitrag ↑
19.02.2020 14:12:57
Ich würde mir die QT-Debs runterladen, irgendwo hinstellen und das Original alte Programm damit probieren (vorher den LD_LIBRARY_PATH entsprechend anpassen) und schauen was noch fehlt oder passiert. MIt etwas Glück ist der Käse dann schon zum Bahnhof gerollt.
Ich habe gemäß den Fehlermeldungen nach und nach die Bibliotheken kopiert und den Ordner mit LD_LIBRARY_PATH angegeben. Funktioniert! Die Liste der Bibliotheken:

Code: Alles auswählen

libpng12.so.0            libQtCore.so.4.8     libQtNetwork.so.4.8.6
libpng12.so.0.50.0       libQtCore.so.4.8.6   libQtSql.so.4
libQt3Support.so.4       libQtGui.so.4        libQtSql.so.4.8
libQt3Support.so.4.8     libQtGui.so.4.8      libQtSql.so.4.8.6
libQt3Support.so.4.8.6   libQtGui.so.4.8.6    libQtXml.so.4
libqt3supportwidgets.so  libQtNetwork.so.4    libQtXml.so.4.8
libQtCore.so.4           libQtNetwork.so.4.8  libQtXml.so.4.8.6
Auffallend ist libpng12, das nicht Teil von QT zu sein scheint.
Von jeder lib gibt es mehrere Varianten. Sollte nicht eine davon genügen? (Edit: Doppelte libs auf die so.4 Version zu reduzieren geht.)

Das statisch linken probiere ich auch, in einem Container habe ich Qt4 als static kompilieren können. Mal schauen, wie ich jetzt kaptain damit verlinke.

Statisch gelinkt ist mir immer noch die bevorzugte Lösung, da ich kaptain mit meinen eigenen Programmen anbieten will.
Die Vernunft kann einem schon leidtun. Sie verliert eigentlich immer.

Benutzeravatar
MSfree
Beiträge: 11604
Registriert: 25.09.2007 19:59:30

Re: Altes QT-Programm statisch linken

Beitrag von MSfree » 21.02.2020 13:39:12

MartinV hat geschrieben: ↑ zum Beitrag ↑
21.02.2020 13:23:56
Auffallend ist libpng12, das nicht Teil von QT zu sein scheint.
libpng ist nicht Bestandteil von Qt, das ist eine ganz normale Bibliothek, die aber von Qt benutzt wird (Icons, Symbols...) und daher davon abhängig ist.

libpng12 hat allerdings Sicherheitslücken, die aktiv ausgenutzt werden. Man sollte diese veraltete Version nicht mehr verwenden.
Statisch gelinkt ist mir immer noch die bevorzugte Lösung, da ich kaptain mit meinen eigenen Programmen anbieten will.
Bitte die libpng-Problematik beachten. Du solltest versuchen, deine Qt4 gegen eine neuere libpnpg bauen.

Benutzeravatar
MartinV
Beiträge: 790
Registriert: 31.07.2015 19:38:52
Wohnort: Hyperion
Kontaktdaten:

Re: Altes QT-Programm statisch linken

Beitrag von MartinV » 21.02.2020 20:08:44

MSfree hat geschrieben: ↑ zum Beitrag ↑
21.02.2020 13:39:12
Bitte die libpng-Problematik beachten. Du solltest versuchen, deine Qt4 gegen eine neuere libpnpg bauen.
Danke für den Hinweis!
Statt mit Debian Jessie baue ich jetzt auf Debian buster. Dort gibt es libpng16.
Nach ein paar Stolpersteinen lief die Kompilierung von QT4 durch.
Beim Kompilieren mit make von kaptain bekomme ich jetzt eine Fehlermeldung:

Code: Alles auswählen

communication.h:4:10: fatal error: qsocketnotifier.h: No such file or directory
Die Datei ist aber vorhanden:

Code: Alles auswählen

# find / | grep -i qsocket
/usr/local/Trolltech/Qt-4.8.7/include/QtCore/QSocketNotifier
/usr/local/Trolltech/Qt-4.8.7/include/QtCore/qsocketnotifier.h
/usr/local/Trolltech/Qt-4.8.7/include/Qt/qsocketnotifier.h
/qt4/qt/src/corelib/kernel/qsocketnotifier.cpp
/qt4/qt/src/corelib/kernel/qsocketnotifier.h
/qt4/qt/src/corelib/.moc/release-static/moc_qsocketnotifier.cpp
/qt4/qt/src/corelib/.obj/release-static/qsocketnotifier.o
/qt4/qt/src/corelib/.obj/release-static/moc_qsocketnotifier.o
/qt4/qt/tests/auto/q3socket/tst_qsocket.cpp
/qt4/qt/tests/auto/qsocketnotifier
/qt4/qt/tests/auto/qsocketnotifier/.gitignore
/qt4/qt/tests/auto/qsocketnotifier/qsocketnotifier.pro
/qt4/qt/tests/auto/qsocketnotifier/tst_qsocketnotifier.cpp
/qt4/qt/include/QtCore/QSocketNotifier
/qt4/qt/include/QtCore/qsocketnotifier.h
/qt4/qt/include/Qt/qsocketnotifier.h
Ich nehme an, ich muß irgendwie einen Pfad bekanntgeben. Aber welchen davon, und wie?
Die Vernunft kann einem schon leidtun. Sie verliert eigentlich immer.

Benutzeravatar
MartinV
Beiträge: 790
Registriert: 31.07.2015 19:38:52
Wohnort: Hyperion
Kontaktdaten:

Re: Altes QT-Programm statisch linken

Beitrag von MartinV » 22.02.2020 22:33:00

Ein weiterer Erfolg: Ich habe kaptain mit den Qt4-Bibliotheken statisch gelinkt!

Ich habe leider nicht herausgefunden, wie ich auf das Qt-Verzeichnis richtig verweise, so daß die header-Dateien gefunden werden. Experimente mit Variable CPATH gaben nur andere Folgefehler.

Stattdessen habe ich erfolgreich gepfuscht: Ich habe die Sourcedateien von kaptain in das Qt-Source-Verzeichnis brutal hineinkopiert und make dort gestartet. Damit lief es durch.

Das ist das schöne an Containern: Ich kann nach Belieben im Container-System herumpfuschem, ohne mein Hauptsystem zu beschädigen. :mrgreen:

Einen Schönheitsfehler gibt es noch: Statt als "Executeable" wird es als "Shared object" gesehen. Warum das so ist und wie ich das richtig machen kann, weiß ich nicht. Kann mich jemand aufklären?
Das originale kaptain ergibt:

Code: Alles auswählen

$ file kaptain 
kaptain: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=acfb8e32e64ea3f56c32c52cb5ff49798c067ff8, stripped
Mein selbstgebautes kaptain:

Code: Alles auswählen

$ file kaptain 
kaptain: ELF 64-bit LSB shared object, x86-64, version 1 (GNU/Linux), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=11063ff39a3aaa9d32a8f73855317894af5163aa, not stripped
Ein neues .deb-paket, basierend auf dem Original, habe ich auch schon gebastelt und erfolgreich installieren können. :)
Die Vernunft kann einem schon leidtun. Sie verliert eigentlich immer.

Benutzeravatar
MartinV
Beiträge: 790
Registriert: 31.07.2015 19:38:52
Wohnort: Hyperion
Kontaktdaten:

Re: Altes QT-Programm statisch linken

Beitrag von MartinV » 23.02.2020 13:16:26

Mit diesem Dockerfile baue ich kaptain mit statisch gelinkten Qt4-libs und erzeuge ein neues .deb Paket:

Code: Alles auswählen

# Build kaptain with statically linked Qt4 libraries.
# Generates /deb/kaptain_0.73-3-staticqt4_amd64_debian.deb
# Allows to install kaptain on systems without Qt4 libraries.

FROM debian:buster
RUN echo deb-src http://deb.debian.org/debian buster main >> /etc/apt/sources.list && \
    sed -i "s/main/main contrib non-free/g" /etc/apt/sources.list

# Dependencies
RUN apt-get update && \
    apt-get install -y git-core nano wget tar bison flex qt4-qmake && \
    apt-get build-dep -y qt4-qmake

# Build static libs of Qt4
RUN git clone https://github.com/qt/qt.git
WORKDIR /qt
RUN echo yes | ./configure \
                 -prefix /usr \
                 -release -static -opensource \
                 -qt3support \
                 -nomake tools -nomake tests -nomake examples \
                 -no-multimedia -no-audio-backend -no-phonon -no-phonon-backend \ 
                 -no-svg -no-webkit -no-javascript-jit -no-script -no-scripttools \
                 -no-declarative -no-declarative-debug -no-openssl -no-cups -no-dbus \
                 -no-accessibility
RUN make
RUN make install

# Build kaptain
WORKDIR /
RUN wget https://github.com/mviereck/kaptain/raw/master/kaptain-0.73.tgz && \
    tar -xzf kaptain-0.73.tgz
WORKDIR /kaptain-0.73
ENV QT_SELECT=qt4
RUN qmake kaptain.pro && \
    make

# Generate new .deb package based on Debian jessie kaptain package
RUN mkdir -p /deb/kaptain
WORKDIR /deb
RUN wget http://ftp.debian.org/debian/pool/main/k/kaptain/kaptain_0.73-2_amd64.deb && \
    dpkg-deb -R kaptain_0.73-2_amd64.deb /deb/kaptain
RUN cp /kaptain-0.73/kaptain /deb/kaptain/usr/bin/kaptain && \
    sed -i 's%^Maintainer:.*$%Maintainer: Martin Viereck (not a Debian maintainer. www.github.com/mviereck/kaptain)% ; \
            s%^Installed-Size:.*$%Installed-Size: 15472% ; \
            s%^Version:.*$%Version: 1:0.73-3% ; \
            s%^Depends:.*$%Depends: libc6 (>= 2.14), libgcc1 (>= 1:4.1.1), libpng16-16(>=1.6.28), libstdc++6 (>= 4.9)% ; \
           ' /deb/kaptain/DEBIAN/control && \
    echo " This unofficial build contains statically linked Qt4 libs." >> /deb/kaptain/DEBIAN/control
RUN dpkg-deb -b /deb/kaptain kaptain_0.73-3-staticqt4_amd64_debian.deb
Mein kaptain repository: https://github.com/mviereck/kaptain
Ich habe leider nicht herausgefunden, wie ich auf das Qt-Verzeichnis richtig verweise, so daß die header-Dateien gefunden werden. Experimente mit Variable CPATH gaben nur andere Folgefehler.

Stattdessen habe ich erfolgreich gepfuscht: Ich habe die Sourcedateien von kaptain in das Qt-Source-Verzeichnis brutal hineinkopiert und make dort gestartet. Damit lief es durch.
Das Problem habe ich jetzt etwas anders gelöst: Qt wird jetzt mit "configure -prefix /usr" gebaut, um eine systemweite Installation bei "make install" zu bekommen. So kann ich auf das schmutzige Hineinkopieren von kaptain in den Qt-Ordner verzichten
Einen Schönheitsfehler gibt es noch: Statt als "Executeable" wird es als "Shared object" gesehen. Warum das so ist und wie ich das richtig machen kann, weiß ich nicht. Kann mich jemand aufklären?
Dafür habe ich keine Lösung gefunden.
Die Vernunft kann einem schon leidtun. Sie verliert eigentlich immer.

Antworten