Portabilität von C++ Programmen



  • Hallo zusammen,

    ich würde gerne ein Programm schreiben, dass möglichst portabel ist. Ich habe noch etwas Schwierigkeiten zu verstehen, was ich da genau mit ausliefern muss.

    z.B. habe ich bei der Installation von QT folgendes gemerkt, dass es zwei Ordner gibt einmal für mingw und msvc. Warum ist das nötig? Brauche ich wirklich beides abängig davon, welchen Compiler ich nehme?

    Für mein eigenes Programm, habe ich mit einer CMake Funktion experiment, die "GET_RUNTIME_DEPENDENCIES" heißt. Dabei wurden folgende Sachen installiert:

    ld-2.33.so libc.so.6 libgcrypt.so.20.3.3 libicudata.so.69 liblz4.so.1.9.3 libpcre.so.1 librt.so.1 libsystemd.so.0.32.0
    ld-linux-x86-64.so.2 libdl-2.33.so libglib-2.0.so.0 libicudata.so.69.1 liblzma.so.5 libpcre.so.1.2.13 libsqlite3.so.0 libz.so.1
    libb2.so.1 libdl.so.2 libglib-2.0.so.0.6800.3 libicui18n.so.69 liblzma.so.5.2.5 libpthread-2.33.so libsqlite3.so.0.8.6 libz.so.1.2.11
    libb2.so.1.0.4 libdouble-conversion.so.3 libgomp.so.1 libicui18n.so.69.1 libm-2.33.so libpthread.so.0 libzstd.so.1
    libc-2.33.so libdouble-conversion.so.3.1.5 libgomp.so.1.0.0 libicuuc.so.69 libm.so.6 libQt6Core.so.6 libstdc++.so.6 libzstd.so.1.5.0
    libcap.so.2 libgcc_s.so.1 libgpg-error.so.0 libicuuc.so.69.1 libpcre2-16.so.0 libQt6Core.so.6.1.2 libstdc++.so.6.0.29
    libcap.so.2.51 libgcrypt.so.20 libgpg-error.so.0.32.0 liblz4.so.1 libpcre2-16.so.0.10.2 librt-2.33.so libsystemd.so.0

    Einige Sachen davon erschließen sich mir: Natürlich brauche ich sqlite3 und Qt6, das sind halt meine normalen dependencies.
    Aber brauche ich den anderen Kram wirklich?

    Ich habe schon oft gesehen bei Linux Applikationen das irgendwie kam "Lib XYZ fehlt". Die war dann nicht auf meinem System installiert oder hieß anders etc.
    Das möchte ich gerne vermeiden. Das ist explizit ein Installer der nicht über demn Package Manager geht! Der sollte also nach Möglichkeit auf jeden beliebigen Linux System einfach laufen (für Windows etc. genauso).

    Wäre nett, wenn jemand da etwas Licht ins Dunkeln bringen kann.



  • Für Linux
    Es gibt die Möglichkeit Flatpaks zu verwenden. Wobei das von Nutzern nicht so gerne gesehen ist, da hier die Libraries vom System nicht auf dem neusten Stand gehalten werden können und so Security Fixes nicht automatisch verteilt werden können.

    Die Alternative ist es für die jeweilige Distribution Pakete zu bauen. Wenn man das Paket für das eigentliche Programm installiert werden, die notwendigen Libraries mit installiert, wenn man das Paket richtig gebaut hat.

    Qt6 dürfte allerdings ein Problem sein, weil das in den meisten Distributionen nicht enthalten sein wird.



  • Hi John,

    mir ging es eig. weniger um konkrete Auslieferungsformate. Ich weiß, dass es da bevorzugt Package Manager mit jeweiligen Formaten gibt (.deb, .rpm) oder cross distribution Sachen (flatpak, snap) die in containern laufen oder weiteres wie AppImage.

    Mein Ziel hier ist, und ja ich weiß dass das für Linux die schlechteste aller Möglichkeiten ist, einen normalen Installer (nutze hierfür das Qt Installer Framework), was die App einfach installiert. Also ohne Package Manager, ohne flatpak etc.
    Der Grund hierfür ist das das ganze erstmal nur ein Test sein soll. Der Qt Installer geht auf allen Plattformen und ich möchte aktuell nur ne einfache Möglichkeit haben die Sachen auf Linux, Mac Os und Windows zu installieren. Ohne mich mich lauter plattformspezifischen und distributionsspezifischen Dingen rumzuschlagen (kommt aber noch).

    Bei diesem Test bin ich auf einen Befehl gestoßen von CMake der mir automatisch die RUNTIME_DEPENDENCIES zusammensucht. Hintergrund ist eig. Windows, wo ja die DLLS ins binary Verzeichnis kopiert werden müssen. Auf Linux klappt dieser Befehl aber auch und liefert mir jede Menge Libraries darunter z.B:

    • libpthread
    • libstdc++

    Siehe Eingangspost für die vollständige Liste. Das hat mir alles komplett cmake automatisch installiert.

    Meine Frage konkret war: Brauch ich das? Angenommen mein Ziel ist es, dass meine Applikation portabel ist und einfach auf Debian, Arch, Ubuntu etc. läuft. Ohne Annahmen zu machen, was der Nutzer konkret installiert hat. Muss ich diese Libs dann selbst mitausliefern?

    Als Beispiel wie gesagt z.B. TeamViewer. Die haben auch nen klassischen Installer und bei denen hat dann erstmal irgendne Lib gefehlt. Oder die hieß glaube ich anders auf meinem System. Das will ich vermeiden.

    Sind das also Systemlibs? Hat jedes Linux System eine libstdc++? Oder sollte ich die tatsächlich alle mitausliefern?

    Was bei mir auch noch etwas Verwirrung stiftet ist sowas: https://stackoverflow.com/a/49715904. Scheinbar ist Standard Lib dann nicht auch Standard Lib etc. Worauf muss ich da achten?

    Hoffe Frage ist klarer geworden



  • @Leon0402 sagte in Portabilität von C++ Programmen:

    Meine Frage konkret war: Brauch ich das? Angenommen mein Ziel ist es, dass meine Applikation portabel ist und einfach auf Debian, Arch, Ubuntu etc. läuft. Ohne Annahmen zu machen, was der Nutzer konkret installiert hat. Muss ich diese Libs dann selbst mitausliefern?

    Das hängt wie gesagt davon ab, in welcher Form Du das ausliefern willst.

    • Du baust ein statisches Binary, was komplett mit statischen Libraries gebaut wird. Dann entfällt der ganze folgende Aufwand.
    • Du nutzt dynamische Libraries, dann musst Du entweder die Versionen aus der jeweiligen Distributionen nutzen, eine Flatpak Abhängigkeit haben oder diese mitliefern.
    • Willst Du die der Distribution nutzen, musst Du Dein Programm für jede gewünschte Distributionen und Release bauen. Der übliche Kanon für kommerzielle Programme ist: RHEL, SLES und Ubuntu LTS.
    • Du willst nicht die Distributions Libraries oder ein Flatpak nutzen, dann musst Du die passenden Versionen mitliefern. Dazu kannst Du ganz normal einen Installer nutzen, der die Software z.B. nach /opt/Leon0402/Softwarepackage installiert. Unter /opt/Leon0402/Softwarepackage/lib legst Du dann die Libraries ab, und musst dann noch den LD_LIBRARY_PATH in der startenden Shell anpassen, dann werden die Libraries vom rld auch gefunden.
    • Flatpak kennt auch Abhängigkeiten, so dass man hier nicht alles selbst machen muss. Ich halte das daher für eine der sinnvolleren Wege, wenn man keine Distributionspakete bauen will.

    Sind das also Systemlibs? Hat jedes Linux System eine libstdc++? Oder sollte ich die tatsächlich alle mitausliefern?

    Nein, nicht jede Linux Installation hat eine libstdc++ installiert, und möglicherweise ist es nicht die Version gegen die Du Dein Programm gebaut hast. D.h. solange Du nicht über Distributionspakete oder Flatpak sicher stellst, dass die Abhängigkeiten erfüllt sind, solange muss Du alle Libraries selbst ausliefern.



  • Das hängt wie gesagt davon ab, in welcher Form Du das ausliefern willst.

    Hab ich doch jetzt schon 2x geschrieben. Einen normalen Installer 😃 Also ja die Software landet unter /opt/meineApplikation. Und ich setze auch den LD_LIBRARY_PATH bzw. den RPATH. Das ist nicht das meine Frage / Problem .

    @john-0 sagte in Portabilität von C++ Programmen:

    Nein, nicht jede Linux Installation hat eine libstdc++ installiert, und möglicherweise ist es nicht die Version gegen die Du Dein Programm gebaut hast.

    Das wollte ich etwas genauer wissen 🙂 Also die libstdc++ ist nicht vorinstalliert. Verstehe ich das richtig, dass die libstdc++ die Standard Implementierung vom gcc ist.

    Szenerario: Ich nutze clang Version XYZ, Nutzer hat GCC Version XYZ -> Geht im allgemeinen nicht, da Clang eine eigene Implementierung hat?

    Szeneraio: Ich nutze gcc neue version, Nutzer hat GCC alte version -> Geht ggf. nicht, da nicht kompatibel?

    Wieso sind die verschiedenen Implementierungen im allgemeinen nicht kompatibel? Die Implementieren doch die Standard Lib, die ist doch für beide gleich?

    Gilt das für die anderen oben gelisteten Libaries auch? Oder sind da auch "Standard Libs" dabei, die ein Linux einfach hat.
    Als Beispiel auf Windows habe ich "api-ms-" "ext-ms-" Libraries vor dem installieren raus gefiltert, da das soweit ich weiß System Libraries sind, die jedes Windows hat und nicht ausgliefert werden müssen.

    Edit: Kann man eig. so Sachen wie die libstdc++ statisch bauen? Ich wüsste jetzt erstmal nicht wo ich das konfigurieren könnte.



  • Man kann bestimmte Libraries (libstdc++ bzw. libgcc) mit den Parametern -static-libstdc++ bzw. -static-libgcc statisch linken. Und mit -static gleich alle Libraries.
    Quelle: Stackoverflow



  • @Leon0402 sagte in Portabilität von C++ Programmen:

    Das wollte ich etwas genauer wissen 🙂 Also die libstdc++ ist nicht vorinstalliert. Verstehe ich das richtig, dass die libstdc++ die Standard Implementierung vom gcc ist.

    Jein, es ist die Library, die mit dem gcc für C++ ausgeliefert wird. Allerdings nutzen diese Library auch andere C++ Compiler. Aufpassen muss man bei der Version, da kann es deutliche Unterschiede geben. Funktionieren dürfte der Wechsel von einer ältere Version auf eine neuere Minorrevision, aber aus Erfahrung (Linux ist mittlerweile stabiler geworden) würde ich noch nicht einmal das als garantiert betrachten. Vorher unbedingt ausprobieren.

    Szenerario: Ich nutze clang Version XYZ, Nutzer hat GCC Version XYZ -> Geht im allgemeinen nicht, da Clang eine eigene Implementierung hat?

    Keine Ahnung was clang macht, ich nutze bisher clang nicht, – ja prinzipiell möglich.

    Szeneriao: Ich nutze gcc neue version, Nutzer hat GCC alte version -> Geht ggf. nicht, da nicht kompatibel?

    Ja, wenn zwei unterschiedliche Majorreleases sind, funktioniert es garantiert nicht.

    Wieso sind die verschiedenen Implementierungen im allgemeinen nicht kompatibel? Die Implementieren doch die Standard Lib, die ist doch für beide gleich?

    Die ABI ist für C++ nicht normiert, d.h. jeder Hersteller darf sein eigenes Ding machen, nur die API ist durch die Norm vorgegeben. Daher kann es da nicht unerhebliche Unterschiede geben. Unter Linux wird mittlerweile verstärkt libstdc++ genutzt, aber nicht von allen Compilern.

    Edit: Kann man eig. so Sachen wie die libstdc++ statisch bauen? Ich wüsste jetzt erstmal nicht wo ich das konfigurieren könnte.

    Die libstdc++ musst Du nicht statisch bauen, die ist beim Compiler schon dabei. Du musst die Linkerflags fürs statische Linken entsprechend abändern. @DocShoe hat es freundlicher Weise schon erklärt. Für die anderen Libraries musst Du ggf. Pakete nachinstallieren, aber diese Libraries brauchst Du nicht von Hand zu bauen.


Anmelden zum Antworten