{"id":131,"date":"2016-11-27T15:48:57","date_gmt":"2016-11-27T15:48:57","guid":{"rendered":"http:\/\/renaudguezennec.eu\/?p=131"},"modified":"2025-08-17T20:12:18","modified_gmt":"2025-08-17T20:12:18","slug":"distribuer-une-application-qt","status":"publish","type":"post","link":"http:\/\/renaudguezennec.eu\/index.php\/2016\/11\/27\/distribuer-une-application-qt\/","title":{"rendered":"Distribuer une application Qt"},"content":{"rendered":"<p>Bonjour,<\/p>\n<p>Si vous suivez ce blog, vous savez que je suis d\u00e9veloppeur C++\/Qt et que je contribue beaucoup \u00e0 Rolisteam (<a href=\"http:\/\/www.rolisteam.org\" target=\"_blank\" rel=\"noopener\">www.rolisteam.org<\/a>). C\u2019est un logiciel libre pour faire du jeu de r\u00f4le. Il vise un public assez large. Il est donc multi-plateforme. Il fonctionne sous GNU\/Linux, windows et Mac Os. Je suis un linuxien convaincu mais je d\u00e9veloppe sur les autres syst\u00e8mes pour Rolisteam.<\/p>\n<p>L\u2019aspect d\u00e9veloppement n\u2019est pas vraiment un probl\u00e8me, gr\u00e2ce \u00e0 Qt. Cela marche grosso modo bien. La chose devient plus p\u00e9rilleuse quand il s\u2019agit de distribuer le logiciel.<\/p>\n<p>Dans mon activit\u00e9 professionnelle, j\u2019ai constat\u00e9,\u00a0 qu\u2019il est assez rare qu\u2019un d\u00e9veloppeur connaisse les solutions pour distribuer facilement un logiciel. Je vais essayer ici d\u2019expliquer comment faire. Du moins, comment je fais dans rolisteam et si vous avez d\u2019autres astuces. N\u2019h\u00e9sitez pas \u00e0 en faire part dans les commentaires.<\/p>\n<h3>Pr\u00e9dicat de base:<\/h3>\n<p>Vous avez un logiciel \u00e9crit en C++\/Qt, il est g\u00e9r\u00e9 par un fichier .pro. Certains syst\u00e8mes de build propose des syst\u00e8mes identiques, voir plus puissant mais plus complexe (e.g: cmake). Je me contente d\u2019\u00e9voquer les outils Qt.<\/p>\n<h2>Pour GNU\/Linux :<\/h2>\n<p>Pour ma part, j\u2019ai opt\u00e9 pour une distribution source et la cr\u00e9ation de package Ubuntu. Gr\u00e2ce \u00e0 Launchpad, il est possible de cr\u00e9er un d\u00e9p\u00f4t pour son projet et de soumettre des versions. Il faut l\u2019admettre, c\u2019est tr\u00e8s pratique. Il existe probablement des services pour faire cela pour d\u2019autres distributions.<\/p>\n<p>Des contributeurs ont cr\u00e9\u00e9 des package pour d&#8217;autres distributions (fedora\u2026). Pour arch-linux, j&#8217;ai cr\u00e9e un <a href=\"https:\/\/github.com\/obiwankennedy\/Arch-package-rolisteam\" target=\"_blank\" rel=\"noopener\">script de compilation<\/a> (\u00e0 tester).<\/p>\n<p>L\u2019ensemble des outils utilis\u00e9es ne sont pas des outils Qt. Cela n&#8217;est donc pas le propos de cet article.\u00a0 Je me suis mis de c\u00f4t\u00e9 la t\u00e2che de jeter un coup d\u2019\u0153il \u00e0 <a href=\"http:\/\/appimage.org\/\" target=\"_blank\" rel=\"noopener\">appimage<\/a>. Cela pourrait \u00eatre une solution int\u00e9ressante.<\/p>\n<h2>Pour Windows:<\/h2>\n<h3>Trouver tous les \u00e9l\u00e9ments<\/h3>\n<p>Une application a des d\u00e9pendances. Sous windows, il est courant d\u2019installer l\u2019ex\u00e9cutable et ses d\u00e9pendances dans un m\u00eame dossier. Il est parfois difficile d\u2019identifier les d\u00e9pendances. Rassurez-vous un outil magique a \u00e9t\u00e9 cr\u00e9\u00e9e. Il s\u2019agit de &#8220;<strong>windeployqt.exe<\/strong>&#8220;. C\u2019est un outil distribu\u00e9 avec Qt. Son but est de copier toutes les d\u00e9pendances Qt d\u2019un binaire dans un dossier.<\/p>\n<p>[pastacode lang=&#8221;bash&#8221; manual=&#8221;windeployqt%20%20%2Fchemin%2Fvers%2Fmon%2Fexecutable.exe&#8221; message=&#8221;Commande Windeployqt&#8221; highlight=&#8221;&#8221; provider=&#8221;manual&#8221;\/]<\/p>\n<p>Cette commande va lire le binaire et va copier l\u2019ensemble des d\u00e9pendances identifi\u00e9s \u00e0 c\u00f4t\u00e9 du binaire.<\/p>\n<p>Par soucis de clart\u00e9, je pr\u00e9f\u00e8re utiliser un r\u00e9pertoire propre et distinct du r\u00e9pertoire de compilation.<\/p>\n<p>[pastacode lang=&#8221;bash&#8221; manual=&#8221;windeployqt%20&#8211;dir%20%2Fchemin%2Fvers%2Fun%2Fdossier%2Fpropre%20%2Fchemin%2Fvers%2Fmon%2Fapplication.exe&#8221; message=&#8221;Dossier s\u00e9par\u00e9&#8221; highlight=&#8221;&#8221; provider=&#8221;manual&#8221;\/]<\/p>\n<p>L\u2019ajout du l\u2019argument &#8211;dir permet de d\u00e9finir ce \u00ab<strong>dossier de destination\u00bb<\/strong>.<\/p>\n<p>Une autre difficult\u00e9 entre en jeu quand votre application utilise du QML. En effet, il convient de rajouter un argument \u00e0 la commande afin de permettre \u00e0 l\u2019outil d\u2019aller lire votre code QML pour trouver ses d\u00e9pendances.<\/p>\n<p>[pastacode lang=&#8221;bash&#8221; manual=&#8221;windeployqt%20&#8211;qmldir%20%2Fchemin%2Fvers%2Fle%2Fdossier%2Fdes%2Fqml%20&#8211;dir%20%2Fdossier%2Fpropre%20application.exe&#8221; message=&#8221;Distributer du QML&#8221; highlight=&#8221;&#8221; provider=&#8221;manual&#8221;\/]<\/p>\n<h3>Et apr\u00e8s ?<\/h3>\n<p>Une fois cette \u00e9tape termin\u00e9e, vous aurez dans votre <strong>dossier de destination<\/strong> l\u2019ensemble des d\u00e9pendances Qt (et QML) de votre projets.<\/p>\n<p>Je vous mets un exemple pour un logiciel utilisant Qt5 et un peu de QML le tout fut compil\u00e9 avec Visual Studio.<\/p>\n<blockquote><p>\u251c\u2500\u2500 accessible\/<br \/>\n\u251c\u2500\u2500 audio\/<br \/>\n\u251c\u2500\u2500 bearer\/<br \/>\n\u251c\u2500\u2500 designer\/<br \/>\n\u251c\u2500\u2500 Enginio.dll<br \/>\n\u251c\u2500\u2500 iconengines\/<br \/>\n\u251c\u2500\u2500 icudt52.dll<br \/>\n\u251c\u2500\u2500 icuin52.dll<br \/>\n\u251c\u2500\u2500 icuuc52.dll<br \/>\n\u251c\u2500\u2500 imageformats<br \/>\n\u251c\u2500\u2500 mediaservice<br \/>\n\u251c\u2500\u2500 msvcp120.dll<br \/>\n\u251c\u2500\u2500 msvcr120.dll<br \/>\n\u251c\u2500\u2500 platforms\/<br \/>\n\u2502 \u2514\u2500\u2500 qwindows.dll<br \/>\n\u251c\u2500\u2500 playlistformats\/<br \/>\n\u251c\u2500\u2500 position\/<br \/>\n\u251c\u2500\u2500 printsupport\/<br \/>\n\u251c\u2500\u2500 qml1tooling\/<br \/>\n\u251c\u2500\u2500 qmltooling\/<br \/>\n\u251c\u2500\u2500 Qt5Core.dll<br \/>\n\u251c\u2500\u2500 Qt5Declarative.dll<br \/>\n\u251c\u2500\u2500 Qt5Gui.dll<br \/>\n\u251c\u2500\u2500 Qt5Network.dll<br \/>\n\u251c\u2500\u2500 Qt5OpenGL.dll<br \/>\n\u251c\u2500\u2500 Qt5Qml.dll<br \/>\n\u251c\u2500\u2500 Qt5Quick.dll<br \/>\n\u251c\u2500\u2500 Qt5WebKit.dll<br \/>\n\u251c\u2500\u2500 Qt5Widgets.dll<br \/>\n\u251c\u2500\u2500 Qt5Xml.dll<br \/>\n\u251c\u2500\u2500 Qt5XmlPatterns.dll<br \/>\n\u251c\u2500\u2500 sensorgestures\/<br \/>\n\u251c\u2500\u2500 sensors\/<br \/>\n\u251c\u2500\u2500 sqldrivers\/<br \/>\n\u251c\u2500\u2500 unins000.dat<br \/>\n\u2514\u2500\u2500 unins000.exe<\/p><\/blockquote>\n<p>Si votre projet utilise d\u2019autres biblioth\u00e8ques (zlib \u2026), il convient de rajouter les .dll correspondantes dans le dossier. La derni\u00e8re \u00e9tape est d\u2019inclure le .exe de votre application.<br \/>\nEn double-clickant sur le .exe, il devrait se lancer. Si ce n\u2019est pas le cas, une dll est probablement manquante.<br \/>\nCette proc\u00e9dure est \u00e0 faire apr\u00e8s un changement de version de Qt. Il faut vous assurer que les dll embarqu\u00e9es soient de la bonne version.<\/p>\n<p>A ce stade, il ne reste qu\u2019\u00e0 mettre en place l\u2019outil de publication de votre application.<\/p>\n<p>&nbsp;<\/p>\n<h3>Publication<\/h3>\n<p>Pour cette \u00e9tape, il y a principalement deux m\u00e9thodes:<\/p>\n<p>La m\u00e9thode de l\u2019archive Zip, il suffit d\u2019archiver le <strong>dossier de destination<\/strong> dans une archive .zip. Ce fichier peut \u00eatre extrait sur n\u2019importe quel windows, et cela fonctionnera. Il faudra cr\u00e9er \u00e0 la main les raccourcis et il n\u2019y pas d\u2019autre moyen pour d\u00e9s-installer le logiciel que de supprimer le dossier extrait \u00e0 la main.<\/p>\n<p>L\u2019autre m\u00e9thode est d\u2019utiliser un outil qui va cr\u00e9er un installeur. Les plus connus sont<strong> Inno setup<\/strong> et <strong>NSIS<\/strong>.<br \/>\nJ\u2019utilise pour ma part: InstallForge (<a href=\"http:\/\/installforge.net\">http:\/\/installforge.net<\/a>), il est graphique et simple.<br \/>\nQu\u2019importe l\u2019outil choisi, il faudra lui dire d\u2019installer tous les fichiers de votre <strong>dossier de destination<\/strong> (en respectant la hi\u00e9rarchie des fichiers) chez vos utilisateurs. Ces outils permettent de cr\u00e9er automatiquement des scripts de d\u00e9sinstallation, ils cr\u00e9ent \u00e9galement les raccourcis sur le bureau et la barre de d\u00e9marrage. Ils permettent aussi d\u2019afficher du contenu \u00e0 l\u2019utilisateur (licence, logo du logiciel) et cela lui permet de prendre des d\u00e9cisions, au cours de l\u2019installation (si besoin).<\/p>\n<p>Pour finir, apr\u00e8s cette \u00e9tape, vous aurez un installeur soit en mode .zip, soit un .exe. Il ne reste plus qu\u2019\u00e0 mettre cet installeur accessible \u00e0 vos utilisateurs et c\u2019est bon.<\/p>\n<p>Pensez \u00e0 le tester quand m\u00eame avant de faire des annonces publiques. On sait jamais !<\/p>\n<p>&nbsp;<\/p>\n<h2>Pour Mac OS:<\/h2>\n<p>Pour MacOs, il existe un outil similaire qui s\u2019appelle: macqtdeploy.<br \/>\nIl utilise les m\u00eames param\u00e8tres que la version windows, la seule diff\u00e9rence r\u00e9side dans l\u2019utilisation d\u2019un .app (en lieu et place du .exe).<\/p>\n<p>[pastacode lang=&#8221;bash&#8221; manual=&#8221;macdeploy%20application.app%20-qmldir%3D%2FUser%2Fdossier%2Fvers%2Fcode%2Fqml%20&#8243; message=&#8221;sur MacOs X&#8221; highlight=&#8221;&#8221; provider=&#8221;manual&#8221;\/]<\/p>\n<p>Bien s\u00fbr, cela peut \u00eatre int\u00e9grer dans QtCreator comme \u00e9tape de d\u00e9ployement.<br \/>\nSur MacOs, il est possible de demander \u00e0 Qt de compiler une application dans un bundle (c\u2019est d\u2019ailleurs la solution par d\u00e9faut). Un bundle est un dossier se terminant par \u00ab.app\u00bb. Dans l\u2019environnement graphique de MacOs, un double click lance le logiciel qu\u2019il contient. Il est \u00e9galement possible, d\u2019explorer le contenu du bundle en ligne de commande (cela se comporte comme un dossier) ou par un click droit: \u00ab<strong>afficher le contenu du packet<\/strong>\u00bb en graphique.<\/p>\n<p>Dans tous les cas, l\u2019utilisation de la commande va venir placer l\u2019ensemble des d\u00e9pendances Qt dans le bundle. Pour \u00eatre pr\u00e9cis, les biblioth\u00e8ques sont plac\u00e9es dans le dossier Contents\/Frameworks du bundle. Les modules QML sont dans Resources\/qml.<\/p>\n<p>A l\u2019instar de windows, il faut mettre \u00e9galement d\u2019\u00e9ventuelles autres biblioth\u00e8ques dans le bundle. C\u2019est une \u00e9tape un peu technique. Pour rolisteam, j\u2019utilise zlib, voil\u00e0 le programme bash qui me permet de faire l\u2019ajout et de bien d\u00e9finir les chemins.<\/p>\n<p>[pastacode lang=&#8221;bash&#8221; manual=&#8221;%23!%2Fbin%2Fsh%0A%0A%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%0A%23%20Rolisteam%20%0A%23%20Script%20to%20deploy%20libz%20into%20rolisteam.%0A%23%0A%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%23%0A%0Aecho%20&#8217;Display%20dependancies&#8217;%0Aotool%20-L%20rolisteam.app%2FContents%2FMacOS%2Frolisteam%0A%0A%0A%0Aecho%20&#8217;Create%20directory&#8217;%0Amkdir%20rolisteam.app%2FContents%2FFrameworks%2Flibz.framework%2F%0A%0Aecho%20&#8217;Copy%20lib%20binary&#8217;%0Acp%20%2Fusr%2Flib%2Flibz.1.dylib%20rolisteam.app%2FContents%2FFrameworks%2Flibz.framework%2F%0A%0Aecho%20&#8217;Rewrite%20path%20to%20the%20lib&#8217;%0Ainstall_name_tool%20-change%20%2Fusr%2Flib%2Flibz.1.dylib%20%40executable_path%2F..%2FFrameworks%2Flibz.framework%2Flibz.1.dylib%20rolisteam.app%2FContents%2FMacOS%2Frolisteam&#8221; message=&#8221;Ajouter une d\u00e9pendances \u00e0 un bundle&#8221; highlight=&#8221;&#8221; provider=&#8221;manual&#8221;\/]<\/p>\n<p>En gros, il y a la copie du fichier en lui m\u00eame puis, la modification de l\u2019ex\u00e9cutable pour lui dire d\u2019aller chercher zlib dans le bundle et non sur mon poste. Cette \u00e9tape est tr\u00e8s importante car sinon, votre bundle ne sera pas portable sur une autre machine.<\/p>\n<h3>Et apr\u00e8s ?<\/h3>\n<p>Le fichier .app complet suffit pour \u00eatre install\u00e9 sur une autre machine. Cependant, il est de coutume de distribuer un logiciel par un dmg. Cela permet de le compresser pour faciliter sa distribution et surtout MacOs permet de rendre graphique l&#8217;installation par un dmg.<\/p>\n<p>Pour r\u00e9aliser cela, j\u2019utilise un petit utilitaire: node-appdmg. Il suffit d\u2019un petit fichier de configuration en json pour d\u00e9finir les param\u00e8tres.<\/p>\n<p>[pastacode lang=&#8221;javascript&#8221; manual=&#8221;%7B%0A%20%20%22title%22%3A%20%22Rolisteam%20%20-%20Mac%20Os%20X%22%2C%0A%20%20%22icon%22%3A%20%22rolisteam.icns%22%2C%0A%20%20%22background%22%3A%20%221500-rolisteam.png%22%2C%0A%20%20%22icon-size%22%3A%2080%2C%0A%20%20%22contents%22%3A%20%5B%0A%20%20%20%20%7B%20%22x%22%3A%20448%2C%20%22y%22%3A%20344%2C%20%22type%22%3A%20%22link%22%2C%20%22path%22%3A%20%22%2FApplications%22%20%7D%2C%0A%20%20%20%20%7B%20%22x%22%3A%20192%2C%20%22y%22%3A%20344%2C%20%22type%22%3A%20%22file%22%2C%20%22path%22%3A%20%22rolisteam.app%22%20%7D%0A%20%20%5D%0A%7D&#8221; message=&#8221;Configuration node-appdmg pour rolisteam&#8221; highlight=&#8221;&#8221; provider=&#8221;manual&#8221;\/]<\/p>\n<p>Vous lancez l\u2019utilitaire avec le fichier de configuration et le nom de votre dmg pour obtenir votre dmg tout beau, tout propre.<\/p>\n<blockquote><p>node-appdmg dmg.json monapplication.dmg<\/p><\/blockquote>\n<p>Il ne reste qu\u2019\u00e0 distribuer votre dmg.<\/p>\n<h2>Conclusion<\/h2>\n<p>Nous venons de voir les solutions et les outils mis en place pour rolisteam.<br \/>\nSi vous avez des questions sur les outils,\u00a0 ou si vous voulez en proposer d\u2019autres, les commentaires sont l\u00e0 pour \u00e7a.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Bonjour, Si vous suivez ce blog, vous savez que je suis d\u00e9veloppeur C++\/Qt et que je contribue beaucoup \u00e0 Rolisteam (www.rolisteam.org). C\u2019est un logiciel libre pour faire du jeu de r\u00f4le. Il vise un public assez large. Il est donc multi-plateforme. Il fonctionne sous GNU\/Linux, windows et Mac Os. Je suis un linuxien convaincu mais [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_import_markdown_pro_load_document_selector":0,"_import_markdown_pro_submit_text_textarea":"","footnotes":""},"categories":[80,23],"tags":[40,39,10,36,19],"class_list":["post-131","post","type-post","status-publish","format-standard","hentry","category-fr","category-tutorial","tag-exemple","tag-macos","tag-qt","tag-qt5","tag-windows"],"_links":{"self":[{"href":"http:\/\/renaudguezennec.eu\/index.php\/wp-json\/wp\/v2\/posts\/131","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/renaudguezennec.eu\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/renaudguezennec.eu\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/renaudguezennec.eu\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/renaudguezennec.eu\/index.php\/wp-json\/wp\/v2\/comments?post=131"}],"version-history":[{"count":7,"href":"http:\/\/renaudguezennec.eu\/index.php\/wp-json\/wp\/v2\/posts\/131\/revisions"}],"predecessor-version":[{"id":5076,"href":"http:\/\/renaudguezennec.eu\/index.php\/wp-json\/wp\/v2\/posts\/131\/revisions\/5076"}],"wp:attachment":[{"href":"http:\/\/renaudguezennec.eu\/index.php\/wp-json\/wp\/v2\/media?parent=131"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/renaudguezennec.eu\/index.php\/wp-json\/wp\/v2\/categories?post=131"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/renaudguezennec.eu\/index.php\/wp-json\/wp\/v2\/tags?post=131"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}