Faire une version standalone de son projet

a marqué ce sujet comme résolu.

Hello,

Je suis en train de voir pour créer une version standalone de mon projet écrit en C++ avec Qt, et je rencontre quelques difficultés pour le faire.

Pour ceux qui ne le sauraient pas, on dit qu'un logiciel est délivré en version standalone lorsqu'il fournit son exécutable ainsi que tous les fichiers bibliothèques dont il a besoin, de telle sorte que l'utilisateur final n'a rien à installer pour pouvoir l'utiliser.

Dans mon cas, j'ai pu déterminer grâce à la commande readelf -d deuchnord-hermes | grep NEEDED (où deuchnord-hermes est mon exécutable) que mon programme nécessitait les librairies suivantes pour fonctionner :

  • libQt5Widgets.so.5
  • libQt5Gui.so.5
  • libQt5Xml.so.5
  • libQt5Network.so.5
  • libQt5Core.so.5
  • libstdc++.so.6
  • libgcc_s.so.1
  • libc.so.6

J'ai retrouvé ces librairies sur mon ordinateur servant pour le développement (une machine Arch Linux) dans le répertoire /usr/lib, et je les ai copiées à côté de l'exécutable, un peu comme on le fait habituellement sous Windows avec les DLLs, mais fort est de constater que ce n'est pas suffisant. En effet, lorsque je tente de lancer mon programme sur une machine virtuelle Ubuntu (sur laquelle Qt n'est pas installée), voici ce que j'obtiens :

1
2
3
4
5
6
./deuchnord-hermes: /usr/lib/x86_64-linux-gnu/libQt5Network.so.5: version `Qt_5' not found (required by ./deuchnord-hermes)
./deuchnord-hermes: /usr/lib/x86_64-linux-gnu/libQt5Gui.so.5: version `Qt_5' not found (required by ./deuchnord-hermes)
./deuchnord-hermes: /usr/lib/x86_64-linux-gnu/libQt5Core.so.5: version `Qt_5.6' not found (required by ./deuchnord-hermes)
./deuchnord-hermes: /usr/lib/x86_64-linux-gnu/libQt5Core.so.5: version `Qt_5' not found (required by ./deuchnord-hermes)
./deuchnord-hermes: /usr/lib/x86_64-linux-gnu/libQt5Widgets.so.5: version `Qt_5' not found (required by ./deuchnord-hermes)
./deuchnord-hermes: /usr/lib/x86_64-linux-gnu/libQt5Xml.so.5: version `Qt_5' not found (required by ./deuchnord-hermes)

Pour que vous puissiez mieux visualiser, voici le contenu du répertoire de mon exécutable :

Contenu du répertoire standalone

Qu'est-ce que je fais mal ?

Merci d'avance ^^

+0 -0

Il faut dire au linker dynamique de Linux que les bibliothèques se trouvent à côté de l'exécutable (ce n'est pas là où le linker dynamique de Linux regarde par défaut, contrairement à Windows).

Du coup, pour lancer ton exécutable :

1
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:. ./deuchnord-hermes

LD_LIBRARY_PATH contient une liste de chemins de recherche supplémentaires pour le linker dynamique, séparés par ":". Du coup, dans la commande précédente, on ajoute le chemin actuel (.) aux chemins de recherche.

C'est surtout inutile et une mauvaise idée. Les libs peuvent poser des problèmes de compatibilité. Et sinon, ça risque aussi de faire des doublons et au final de casser le système de packages de linux.

Le mieux, ce serait de faire un dépôt pour chacune des grandes distributions mères (Debian, Fedora, Arch, etc) avec les dépendances bien gérées.

Edit : pour info, c'est ce fonctionnement qui pose des problèmes avec Steam sur Arch. Certaines libs fournies par Steam sont trop vieilles pour des drivers fournis par Arch.

+3 -0

Il faut dire au linker dynamique de Linux que les bibliothèques se trouvent à côté de l'exécutable (ce n'est pas là où le linker dynamique de Linux regarde par défaut, contrairement à Windows).

Du coup, pour lancer ton exécutable :

1
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:. ./deuchnord-hermes

LD_LIBRARY_PATH contient une liste de chemins de recherche supplémentaires pour le linker dynamique, séparés par ":". Du coup, dans la commande précédente, on ajoute le chemin actuel (.) aux chemins de recherche.

victorlevasseur

Je viens d'essayer de faire comme cela, mais j'obtiens les mêmes messages d'erreur :(

C'est surtout inutile et une mauvaise idée. Les libs peuvent poser des problèmes de compatibilité. Et sinon, ça risque aussi de faire des doublons et au final de casser le système de packages de linux.

Le mieux, ce serait de faire un dépôt pour chacune des grandes distributions mères (Debian, Fedora, Arch, etc) avec les dépendances bien gérées.

Edit : pour info, c'est ce fonctionnement qui pose des problèmes avec Steam sur Arch. Certaines libs fournies par Steam sont trop vieilles pour des drivers fournis par Arch.

Phigger

Effectivement, je n'avais plus pensé à cela… Le truc, en ce qui concerne Debian, c'est que je n'ai jamais compris comment se faisait la création et sa gestion d'un dépôt. Pour Arch, j'ai déjà créé un paquet présent dans l'AUR.

+0 -0

Sinon, il y a ça qui peut être utile : https://build.opensuse.org/ Cela permet de générer des paquets pour OpenSUSE, Fedora, Arch Linux et Ubuntu/Debian (uniquement avec les dépôts free pour Ubuntu/Debian). En plus, cela héberge les paquets ainsi générés et fournit les instructions aux utilisateurs sous forme d'une jolie page.

Exemple : https://build.opensuse.org/package/show/home:victorlevasseur/gdevelop (sources et fichiers de conf de la génération de paquets) et http://software.opensuse.org/download.html?project=home%3Avictorlevasseur&package=gdevelop (jolie page d'instructions pour les utilisateurs)

+1 -0

Sinon, il y a ça qui peut être utile : https://build.opensuse.org/ Cela permet de générer des paquets pour OpenSUSE, Fedora, Arch Linux et Ubuntu/Debian (uniquement avec les dépôts free pour Ubuntu/Debian). En plus, cela héberge les paquets ainsi générés et fournit les instructions aux utilisateurs sous forme d'une jolie page.

Exemple : https://build.opensuse.org/package/show/home:victorlevasseur/gdevelop (sources et fichiers de conf de la génération de paquets) et http://software.opensuse.org/download.html?project=home%3Avictorlevasseur&package=gdevelop (jolie page d'instructions pour les utilisateurs)

victorlevasseur

Wow, je ne connaissais pas ce service (c'est d'ailleurs original venant d'une distribution théoriquement « concurrente » à Debian notamment) o_O

Je via zyeuter ça, merci :)

+0 -0

Dans mon cas, j'ai pu déterminer grâce à la commande readelf -d deuchnord-hermes | grep NEEDED (où deuchnord-hermes est mon exécutable) que mon programme nécessitait les librairies suivantes pour fonctionner :

Cela (ainsi que ldd, depends walker et autres outils équivalent) ne permettent de connaitre que les libs linké et chargé au démarrage de l'application par le système. Pas les libs chargées dynamiquement par l'application.

Le problème est que Qt utilise pleins de plugins, en partie pour le support de la partie graphique et pour l'abstraction système.

Je ne sais pas exactement les dépendances dont tu as besoin (cela dépend de ce que tu utilises dans ton appli), mais il manque probablement au moins le plugin platform. Cf http://guillaume.belz.free.fr/doku.php?id=deployer_une_application_qt et les liens vers la doc officielle.

Dans tous les cas, le plus simple est de créer un paquet selon la distribution.

Euh, y a pas moyen de linker de manière static Qt ?

Si. Il faut recompiler manuellement Qt en static puis compiler ton application en static. Cela change la licence d’utilisation de Qt (en gros, la licence devient la GPL ou la licence commerciale).

+0 -0

Si tu parles du générateur de paquets, je n'ai jamais utilisé, mais je suis prêt à parier que cela permet de créer des paquets en fonction des dépendances que tu lui donnes, pas de déterminer les dépendances. Bref, cela ne t'aidera pas si tu ne sais pas quelles sont les dépendances.

+0 -0

@gbdivers Justement, cela crée des paquets pour plusieurs distributions en se basant sur ce que chaque distribution fournit comme paquets (pour Qt par exemple). Il faudra évidemment rédiger les scripts de construction du paquet (pour chaque "type" de paquet : rpm, deb, …). Mais le code sera compilé pour chaque distribution, donc bien mieux compatible qu'en standalone.

Je parlais des dépendances, pas de la création des paquets. Il existe des dizaines de modules Qt, plus les dépendances de GCC, OpenGL, ICU (je crois), les plugins, etc. Est-ce que ce système détermine tout seul quelles sont les dépendances à mettre dans les paquets ou c'est à celui qui créé le script de donner les dépendances ?

Dans le premier cas, le problème de Jérôme Deuchnord est réglé, il suffit de laisser le système faire son boulot. Dans le second cas, cela ne change rien au problème de Jérôme Deuchnord : s'il ne connait pas les dépendances de son programme, il ne pourra pas les donner au système de création de paquets.

+1 -0

Pour les plupart des générateurs de paquets, il suffira de dire qu'il faut qt5 (et donc juste trouver le nom des paquets dans les dépôts).

Avec RPM (Fedora et compagnie), les dépendances runtime peuvent être trouvées toutes seules (sans même citer le nom des paquets !), pas celle de compilation par contre. Pour les autres systèmes, il suffira de dire que le paquet dépend des différents paquets qt5.

Je précise que ma solution permet de répondre à cela :

Effectivement, je n'avais plus pensé à cela… Le truc, en ce qui concerne Debian, c'est que je n'ai jamais compris comment se faisait la création et sa gestion d'un dépôt. Pour Arch, j'ai déjà créé un paquet présent dans l'AUR.

Et non au sujet initial qui est d'embarquer les dépendances (ce qui est une très mauvaise pratique !).

+0 -0

qui est d'embarquer les dépendances (ce qui est une très mauvaise pratique !).

victorlevasseur

Pour installer un logiciel, oui, c'est une mauvaise pratique.

Mais tu oublies qu'il parle de standalone. Je ne suis pas sur qu'il parle de pouvoir utiliser son logiciel sans rien installer (par exemple exécuter sur un clé usb), mais cela reste un besoin réel. Et dans ce cas, ce n'est pas une mauvaise pratique de mettre les dépendances dans le paquet.

Pour les plupart des générateurs de paquets, il suffira de dire qu'il faut qt5 (et donc juste trouver le nom des paquets dans les dépôts).

Comme je disais, il y a plusieurs modules Qt (par exemple, sur Ubuntu, il y en a presque 50 http://askubuntu.com/questions/508503/whats-the-development-package-for-qt5-in-14-04 Voire presque 100 si on compte les versions dev et lib)

Sans compter les autres dépendances (OpenGL, GCC).

Et il restera aussi le problème des plugins. Par exemple, il existe une dizaine de plugins pour les formats d'image, cela ne sert à rien de tous les mettre si on n'utilise pas tous les formats d'images. Idem pour les BdD, inutile de donner tous les plugins si on utiliser qu'un seul type de BdD. Etc pour tous les plugins.

Donc retour au point de départ : il faut probablement qu'il détermine lui même les dépendances (ou alors donner toutes les dépendances, ce qui fait entre 100 et 150 Mo de mémoire).

+0 -0

@gbdivers, franchement, je ne comprends pas ce que tu dis. Il suffit juste de donner les paquets runtime de Qt (et ceux de dev pour la compilation). C'est ce que font tous les autres logiciels qui utilisent Qt sur Linux pour faire leurs paquets. Les dépendances ne sont pas compliqués : juste les modules de Qt utilisés par son logiciel (il les déclare obligatoirement dans son qmake). Malheureusement (ou heureusement), les plugins d'images sont tous fournis ensembles avec le coeur ou la gui de Qt (je ne le sais plus).

D'ailleurs, relis le dernier message de Jérôme : son vrai problème (caché au départ) était de pouvoir proposer son logiciel sur le plus de distributions possibles

+0 -0

D'ailleurs, relis le dernier message de Jérôme : son vrai problème (caché au départ) était de pouvoir proposer son logiciel sur le plus de distributions possibles

victorlevasseur

Effectivement, et je ne voulais pas m'embêter avec les dépôts, ayant eu une mauvaise expérience avec APT. Je pensais donc naturellement que le standalone serait une bonne alternative, mais l'argument de Phigger sur les problèmes de Steam sous Arch a achevé de me convaincre que c'est une mauvaise idée ^^'

+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte