tag:linuxfr.org,2005:/tags/cmake/public
LinuxFr.org : les contenus étiquetés avec « cmake »
2022-02-24T09:24:09+01:00
/favicon.png
tag:linuxfr.org,2005:News/40868
2022-02-21T09:25:29+01:00
2022-02-21T09:46:08+01:00
Génération de fichiers AAB Android pour GCompris
Licence CC By‑SA http://creativecommons.org/licenses/by-sa/4.0/deed.fr
<div><p>GCompris est une application éducative pour les enfants de 2 à 10 ans. À chaque sortie, une dépêche sur LinuxFr.org décrit les changements.<br>
Pour une fois, cette dépêche ne concerne pas une sortie mais est un peu plus technique et raconte mes péripéties pour générer un paquet dans le nouveau format Android AAB (<a href="https://en.wikipedia.org/wiki/Android_App_Bundle">Android App Bundle</a>) sorti en mai 2018 (d’après <a href="https://android-developers.googleblog.com/2021/06/the-future-of-android-app-bundles-is.html">https://android-developers.googleblog.com/2021/06/the-future-of-android-app-bundles-is.html</a>).</p>
</div><ul></ul><div><h2 class="sommaire">Sommaire</h2>
<ul class="toc">
<li>
<ul>
<li><a href="#toc-lhistorique">L’historique</a></li>
<li><a href="#toc-qt-514-et-android">Qt 5.14 et Android</a></li>
<li><a href="#toc-les-embrouilles">Les embrouilles</a></li>
<li><a href="#toc-un-peu-de-nettoyage">Un peu de nettoyage</a></li>
<li><a href="#toc-mise-%C3%A0-jour-du-code-pour-g%C3%A9rer-qt-514">Mise à jour du code pour gérer Qt 5.14</a></li>
<li><a href="#toc-trop-propre">Trop propre ?</a></li>
<li><a href="#toc-autres-subtilit%C3%A9s">Autres subtilités</a></li>
<li><a href="#toc-alors-%C3%A7a-marche">Alors, ça marche ?</a></li>
</ul>
</li>
</ul>
<h3 id="toc-lhistorique">L’historique</h3>
<p>Pour l’histoire, GCompris a été ré-écrit en C++/QML/JavaScript en <a href="//linuxfr.org/news/gcompris-change-de-moteur">2014</a> et est disponible sur Android depuis <a href="//linuxfr.org/news/gcompris-officiellement-sur-android">2015</a>. Il est aussi disponible sur Windows, Linux, macOS, Ubuntu Touch et la compilation gérait à un moment Sailfish OS (mais bon, ce n’est probablement plus fonctionnel depuis que nous sommes passés à Qt 5.9 minimum).</p>
<p>Il y a deux dépendances externes que nous compilons via un ExternalModule : <a href="https://github.com/qml-box2d/qml-box2d">qml-box2d</a> (qui est un wrapper de Box2D en QML) et OpenSSL (compilé pour Android seulement).</p>
<p>J’avais mis en place la compilation avec CMake depuis quasiment le début en 2014.<br>
J’étais jeune à l’époque et moins expérimenté, donc il y a eu pas mal d’essais, de bidouilles et autres incantations pour que ça marche ©.</p>
<p>GCompris essaie de gérer les 2-3 précédentes versions LTS de Qt. La version actuelle est compilable à partir de la version Qt 5.9.</p>
<p>Pour Android, nous essayons de gérer à la fois Qt 5.12 et Qt 5.15 pour la prochaine version (la 5.12 nous permet de déployer sur les <a href="https://doc.qt.io/qt-5.12/android.html">Android 4.1</a>, la 5.15 à partir d'<a href="https://doc.qt.io/qt-5/android.html">Android 5.0</a>), sachant qu’il y aura une coupure nette avec Qt 6, car il n’y a pas la compatibilité QML entre les versions 5 et 6 (qui elle cible à partir d'<a href="https://doc.qt.io/qt-6/android.html">Android 6.0</a>).</p>
<h3 id="toc-qt-514-et-android">Qt 5.14 et Android</h3>
<p>Pour en revenir au sujet principal, Qt, depuis sa version 5.14 permet de générer à la fois des APK mais aussi des <a href="https://www.qt.io/blog/qt-5.14-android-multi-abi-and-cmake">AAB pour Android</a>.<br>
La génération d’un binaire (APK ou AAB) passe par l’outil <a href="https://doc.qt.io/qt-5/deployment-android.html#androiddeployqt">androiddeployqt</a> qui prend en entrée un fichier JSON définissant les propriétés pour créer le binaire et divers autres paramètres pour créer en mode debug, release, signé…<br>
La version fournie depuis Qt 5.14 possède entre autres une option pour générer un AAB.<br>
Malheureusement, suite aux besoins qui ont évolué, le fichier JSON a aussi été modifié et n’est plus compatible avec l’ancien.<br>
Pareil, pour le fichier de « AndroidManifest.xml » qui a évolué de façon non compatible.</p>
<p>Par défaut CMake permet de ne générer que pour une seule architecture. La solution proposée par Qt est de définir les architectures que l’on veut déployer dans la configuration CMake : ANDROID_BUILD_ABI_<em>abi</em>, avec <em>abi</em> étant dans armeabi-v7a, arm64-v8a, x86 et x86_64. Ensuite il s’occupera tout seul de compiler <em>n</em> fois le logiciel en créant des <a href="https://cmake.org/cmake/help/latest/module/ExternalProject.html">ExternalProject</a> pour chaque architecture sauf pour l’architecture définie par ANDROID_ABI (qui, elle, sera faite dans le dossier de build par défaut).</p>
<p>Un autre billet de <a href="https://www.volkerkrause.eu/2020/02/29/kf5-android-qt5-14.html">blog</a>, écrit par un autre membre la communauté KDE, permet de voir les changements.</p>
<h3 id="toc-les-embrouilles">Les embrouilles</h3>
<p>Comme indiqué précédemment, GCompris a fait sa propre tambouille pour faire fonctionner les générations. Par exemple, nous disposons de nos propres targets dans CMake (apk_debug, apk_release) alors que Qt fournit par défaut une target APK.<br>
Nous surchargeons aussi le fichier <a href="https://github.com/qt/qtbase/blob/5.15.2/src/corelib/Qt5AndroidSupport.cmake#L41-L64">JSON</a> et <a href="https://github.com/qt/qtbase/blob/5.15.2/src/android/templates/AndroidManifest.xml">AndroidManifest.xml</a> pour les remplir à notre façon.<br>
OpenSSL était généré via un script qui ne fonctionnait que pour deux targets (avec un bon if dans le <a href="https://invent.kde.org/education/gcompris/-/blob/4aa2fa837c499fbdd5f845bd307639662cacb2d3/android/CMakeLists.txt#L139-183">CMakeLists.txt</a> pour choisir).<br>
Les bibliothèques compilées (Box2D, GCompris et OpenSSL) n’étaient pas générées au bon endroit par défaut et ça rendait la création des AAB compliquée.<br>
La ligne pour lancer CMake était… lourde et compliquée :</p>
<pre><code class="bash"> cmake -DCMAKE_TOOLCHAIN_FILE<span class="o">=</span>/usr/share/ECM/toolchain/Android.cmake <span class="se">\</span>
-DCMAKE_BUILD_TYPE<span class="o">=</span>release <span class="se">\</span>
-DANDROID_ARCHITECTURE<span class="o">=</span>arm <span class="se">\</span>
<span class="nv">DQt5_DIR</span><span class="o">=</span><span class="si">${</span><span class="nv">Qt5_BaseDIR</span><span class="si">}</span>/<span class="si">${</span><span class="nv">QtTarget</span><span class="si">}</span>/lib/cmake/Qt5 <span class="se">\</span>
-DQt5Qml_DIR<span class="o">=</span><span class="si">${</span><span class="nv">Qt5_BaseDIR</span><span class="si">}</span>/<span class="si">${</span><span class="nv">QtTarget</span><span class="si">}</span>/lib/cmake/Qt5Qml <span class="se">\</span>
-DQt5Network_DIR<span class="o">=</span><span class="si">${</span><span class="nv">Qt5_BaseDIR</span><span class="si">}</span>/<span class="si">${</span><span class="nv">QtTarget</span><span class="si">}</span>/lib/cmake/Qt5Network <span class="se">\</span>
-DQt5Core_DIR<span class="o">=</span><span class="si">${</span><span class="nv">Qt5_BaseDIR</span><span class="si">}</span>/<span class="si">${</span><span class="nv">QtTarget</span><span class="si">}</span>/lib/cmake/Qt5Core <span class="se">\</span>
-DQt5Quick_DIR<span class="o">=</span><span class="si">${</span><span class="nv">Qt5_BaseDIR</span><span class="si">}</span>/<span class="si">${</span><span class="nv">QtTarget</span><span class="si">}</span>/lib/cmake/Qt5Quick <span class="se">\</span>
-DQt5Gui_DIR<span class="o">=</span><span class="si">${</span><span class="nv">Qt5_BaseDIR</span><span class="si">}</span>/<span class="si">${</span><span class="nv">QtTarget</span><span class="si">}</span>/lib/cmake/Qt5Gui <span class="se">\</span>
-DQt5Multimedia_DIR<span class="o">=</span><span class="si">${</span><span class="nv">Qt5_BaseDIR</span><span class="si">}</span>/<span class="si">${</span><span class="nv">QtTarget</span><span class="si">}</span>/lib/cmake/Qt5Multimedia <span class="se">\</span>
-DQt5Svg_DIR<span class="o">=</span><span class="si">${</span><span class="nv">Qt5_BaseDIR</span><span class="si">}</span>/<span class="si">${</span><span class="nv">QtTarget</span><span class="si">}</span>/lib/cmake/Qt5Svg <span class="se">\</span>
-DQt5Widgets_DIR<span class="o">=</span><span class="si">${</span><span class="nv">Qt5_BaseDIR</span><span class="si">}</span>/<span class="si">${</span><span class="nv">QtTarget</span><span class="si">}</span>/lib/cmake/Qt5Widgets <span class="se">\</span>
-DQt5LinguistTools_DIR<span class="o">=</span><span class="si">${</span><span class="nv">Qt5_BaseDIR</span><span class="si">}</span>/<span class="si">${</span><span class="nv">QtTarget</span><span class="si">}</span>/lib/cmake/Qt5LinguistTools <span class="se">\</span>
-DQt5Sensors_DIR<span class="o">=</span><span class="si">${</span><span class="nv">Qt5_BaseDIR</span><span class="si">}</span>/<span class="si">${</span><span class="nv">QtTarget</span><span class="si">}</span>/lib/cmake/Qt5Sensors <span class="se">\</span>
-DQt5AndroidExtras_DIR<span class="o">=</span><span class="si">${</span><span class="nv">Qt5_BaseDIR</span><span class="si">}</span>/<span class="si">${</span><span class="nv">QtTarget</span><span class="si">}</span>/lib/cmake/Qt5AndroidExtras <span class="se">\</span>
..</code></pre>
<h3 id="toc-un-peu-de-nettoyage">Un peu de nettoyage</h3>
<p>Au lieu de foncer tête la première dans le tas, il a d’abord fallu rendre le code existant un peu plus propre et se remettre en phase le plus possible avec la façon que Qt utilise pour générer les APK.</p>
<p>Comme tout bon développeur, j’ai donc regardé ce qui était fait ailleurs et surtout la <a href="https://github.com/qt/qtbase/blob/5.15.2/src/corelib/Qt5AndroidSupport.cmake">doc de Qt</a>.<br>
Dans ce fichier, on voit comment Qt gère les architectures, les arguments qu’il fournit à ses projets pour <a href="https://github.com/qt/qtbase/blob/5.15.2/src/corelib/Qt5AndroidSupport.cmake#L154-L181">les autres architectures</a>, <a href="https://github.com/qt/qtbase/blob/5.15.2/src/corelib/Qt5AndroidSupport.cmake#L154-L181">les cibles</a>… Bref, le Graal de la documentation !<br>
La variable un peu « magique » pour générer les AAB à garder en mémoire est CMAKE_LIBRARY_OUTPUT_DIRECTORY qui aura dans les sous-projets la valeur du dossier de sortie du projet principal.<br>
La première étape a donc été de nettoyer notre propre code pour pouvoir compiler avec seulement les mêmes options qui sont passées l’ExternalProject (car sinon, nous n’arriverions pas à compiler pour les autres architectures). </p>
<pre><code>cmake -DCMAKE_TOOLCHAIN_FILE=/usr/share/ECM/toolchain/Android.cmake \
-DCMAKE_ANDROID_API=16 \
-DCMAKE_BUILD_TYPE=Release \
-DANDROID_ABI=$1 \
-DCMAKE_FIND_ROOT_PATH=${Qt5_BaseDIR}/${QtTarget}/lib/ \
-DQt5_DIR=${Qt5_BaseDIR}/${QtTarget}/lib/cmake/Qt5
</code></pre>
<p>Au lieu de mettre directement CMAKE_PREFIX_PATH, on a gardé Qt5_DIR (et dans le <a href="https://invent.kde.org/education/gcompris/-/blob/b7d4c41b8c01cb7142660361eefb66e0092a876d/CMakeLists.txt#L36">CMakeLists.txt</a>, on met <code>CMAKE_PREFIX_PATH = Qt5_DIR</code>), pour ne pas impacter la compilation pour les autres les systèmes d’exploitation.</p>
<p>Pour OpenSSL, <a href="https://www.kdab.com/">KDAB</a> fournit des scripts pour compiler sur <a href="https://github.com/KDAB/android_openssl">toutes les plateformes</a>. En s’inspirant de ce qui était fait, on a réussi à tout gérer dans l’ExternalProject, en gérant proprement l’architecture, sans avoir recours à des scripts externes et gérer l’installation dans <a href="https://invent.kde.org/education/gcompris/-/blob/b7d4c41b8c01cb7142660361eefb66e0092a876d/android/CMakeLists.txt#L167-185">le bon dossier</a> (le CMAKE_LIBRARY_OUTPUT_DIRECTORY du dessus !).</p>
<p>Jusqu’ici, rien qui ne permet de mieux compiler en Qt 5.15 (que ce soit des APK ou des AAB) mais du code bien plus propre et plus maintenable qui fonctionne toujours sur Qt 5.12.</p>
<h3 id="toc-mise-à-jour-du-code-pour-gérer-qt-514">Mise à jour du code pour gérer Qt 5.14</h3>
<p>Le <a href="https://github.com/qml-box2d/qml-box2d">plugin qml-box2d</a> est une dépendance externe qui se base sur qmake pour compiler.<br>
qmake, dans les projets depuis 5.14, génère maintenant cinq fichiers Makefile : un par architecture (Makefile.Armeabi-v7a, Makefile.Arm64-v8a, Makefile.X86 et Makefile.X86_64) et un principal qui va appeler les quatre autres. Évidemment, ce n’est pas ce que l’on souhaite, on veut juste compiler pour notre architecture (et chaque sous-projet compilera pour la sienne). Ce n’est pas grave, nous avons notre petite variable <em>ANDROID_ABI</em> qui contient : armeabi-v7a, arm64-v8a, x86 et x86_64 donc il suffit de le concaténer via CMake au moment d’appeler le build de Box2D et de faire un <code>make -f Makefile.${ANDROID_ABI}</code>.<br>
Le problème, si vous n’avez pas remarqué, est que les Makefile ont leur première lettre de l’architecture en majuscule. Il n’y a pas de solution « facile » pour convertir la première lettre seulement, donc on a dû utiliser <a href="https://invent.kde.org/education/gcompris/-/blob/b7d4c41b8c01cb7142660361eefb66e0092a876d/cmake/box2d.cmake#L96-105">une solution pas très belle mais qui marche</a>.</p>
<h3 id="toc-trop-propre">Trop propre ?</h3>
<p>Évidemment, après avoir testé, cela fonctionnait <em>presque</em> bien. Il manquait la bibliothèque Box2D dans les paquets… Après avoir réfléchi à comment faire sans toucher aux autres plateformes, une solution extrêmement crade (mais fonctionnelle…) était de rajouter une copie du fichier dans <a href="https://invent.kde.org/education/gcompris/-/commit/c3ce352674ca084c6f0b4370f9d54d9966e05921">le « bon » dossier</a>.</p>
<p>Autre souci, les APK générés faisaient 10 Mio de plus que la version compilée avec Qt 5.12. Suite au passage à Qt 5.14, il y a eu des changements sur la façon de gérer les « assets » (modules QML…) de Qt. Avant, les fichiers étaient copiés dans le dossier assets directement, mais depuis 5.14, ils mettent tous les fichiers dans un fichier de ressources <a href="https://doc.qt.io/qt-5/rcc.html">rcc</a>.<br>
Pour je ne sais quelle raison non expliquée dans la documentation, dans le système de build, ils ont décidé de ne plus compresser les fichiers rcc qui sont dans les <a href="https://github.com/qt/qtbase/blob/5.15.2/src/android/templates/build.gradle#L67-L70,%20ajout%C3%A9%20dans%20https://codereview.qt-project.org/c/qt/qtbase/+/270573">assets</a>.</p>
<p>Côté GCompris, on génère des rcc par activité qui contiennent le code QML, JavaScript et les images associées. Il y en a pour 80 Mio actuellement et évidemment, avec la non compression de ces fichiers, on perdait 10 Mio de compression.<br>
La solution « temporaire » a été de dupliquer le fichier <a href="https://invent.kde.org/education/gcompris/-/commit/6c7e6e991820bcd79b4a499965beff529ed48391">build.gradle</a> qui gère la compilation Android pour commenter cette non-compression.</p>
<p>À un certain point, il faudra voir pour migrer les rcc des activités dans des vrais plugins QML. L’avantage premier sera la compilation de ce code (donc plus rapide d’après les posts de blog : <a href="https://www.qt.io/blog/the-new-qtquick-compiler-technology">https://www.qt.io/blog/the-new-qtquick-compiler-technology</a> et <a href="https://www.qt.io/blog/the-numbers-performance-benefits-of-the-new-qt-quick-compiler">https://www.qt.io/blog/the-numbers-performance-benefits-of-the-new-qt-quick-compiler</a>).<br>
Mais dans ce cas-là, cela voudra dire qu’on compile pour chaque architecture les activités (sachant que les images, qui prennent le plus de place, ne seront pas plus compressées) et donc cela risque d’exploser la taille du fichier AAB (voir dessous pour plus de détails sur son contenu) et ne sera plus portable entre différentes plateformes (on aurait pu imaginer à un certain point créer une activité sous Linux, la copier sur un serveur et pouvoir l’installer puis la charger dynamiquement sur n’importe quel système d’exploitation).</p>
<h3 id="toc-autres-subtilités">Autres subtilités</h3>
<p>Il y a eu d’autres subtilités sur lesquelles je ne vais pas trop m’étaler, par exemple, le dossier dans lequel on génère les assets doit s’appeler android-build (ce qui évite les copies).<br>
On a dû garder nos propres fichiers JSON plutôt que d’utiliser celui fourni par Qt, car, de ce que j’ai compris de la <a href="https://github.com/qt/qtbase/blob/5.15.2/src/corelib/Qt5AndroidSupport.cmake#L99-L107">doc</a>, les variables sont des propriétés attachées à la cible de la bibliothèque et je n’ai pas eu le temps de me pencher plus dessus.</p>
<h3 id="toc-alors-ça-marche">Alors, ça marche ?</h3>
<p>Et bien oui ! La génération des APK séparément fonctionne <a href="https://invent.kde.org/education/gcompris/-/blob/b7d4c41b8c01cb7142660361eefb66e0092a876d/tools/android_build_all_apk.sh">en passant les bons paramètres</a>.<br>
Pour les AAB, qui dit « nouveau format » dit « mais comment ça marche et j’en fais quoi de ça moi ».</p>
<p>Il existe un utilitaire <a href="https://github.com/google/bundletool/releases">bundletool</a> qui permet de générer un fichier APKS à partir d’un fichier AAB. Un APKS est une archive contenant plusieurs APK.<br>
Dans notre cas, il y a trois types d’APK dans l’archive :</p>
<ul>
<li>base-<em>${ANDROID_ABI}</em> (arm64_v8a, armeabi_v7a, x86 et x86_64)</li>
<li>base-hdpi, base-ldpi… (un par résolution)</li>
<li>base-master.apk (le fichier contenant les assets, commun à toutes les architectures)</li>
</ul>
<p>Lorsqu’un périphérique demandera à Google de télécharger le jeu, il va se baser sur l’architecture et la résolution pour ne fournir que les trois APK nécessaires et installer ce qu’il faut.</p>
<p>Une documentation basique a été écrite dans le <a href="https://gcompris.net/wiki/Qt_Quick_development_process#Creating_an_aab_and_testing_it">wiki de GCompris</a> pour savoir comment le tester et déployer sur son périphérique Android avec l’outil bundletool.</p>
<p>Sachant que Google a rendu obligatoire depuis août 2021 la création des nouveaux projets sur le Google Play Store à passer obligatoirement par des fichiers AAB, il ne saurait tarder que même les projets qui étaient créés avant doivent aussi y passer bientôt.</p>
<p>Un autre avantage est qu’en utilisant un AAB, la limite de l’APK téléchargé est maintenant de 150 Mio à la place de 100 Mio pour un APK unique (GCompris est très proche de cette limite).</p>
</div><div><a href="https://linuxfr.org/news/generation-de-fichiers-aab-android-pour-gcompris.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/126776/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/news/generation-de-fichiers-aab-android-pour-gcompris#comments">ouvrir dans le navigateur</a>
</p>
Johnny_Jazeix
Lawless
BAud
palm123
Benoît Sibaud
Ysabeau 🧶 🧦
https://linuxfr.org/nodes/126776/comments.atom
tag:linuxfr.org,2005:Diary/39968
2021-10-24T21:24:13+02:00
2021-10-24T21:24:13+02:00
TapTempo en CMake
Licence CC By‑SA http://creativecommons.org/licenses/by-sa/4.0/deed.fr
<p>Cher journal,</p>
<p>voilà un certains temps qu’il n’y a pas eu de nouveau portage de <a href="//linuxfr.org/tags/taptempo/public">TapTempo</a> alors je propose aujourd’hui une version en <a href="https://cmake.org/">CMake</a>.</p>
<p>CMake n’est pas vraiment un langage de programmation, c’est plutôt un <a href="https://fr.wikipedia.org/wiki/CMake">système de construction logicielle multiplateforme</a>, dixit Wikipédia. Cependant, il intègre un langage de script qui permet de piloter la configuration logicielle. J’ai donc essayé de reproduire le comportement de TapTempo avec ce <a href="https://fr.wikipedia.org/wiki/Langage_d%C3%A9di%C3%A9">DSL</a>.</p>
<p>Les prérequis pour un portage de TapTempo sont :</p>
<ol>
<li>afficher du texte à l’écran</li>
<li>réagir à des entrées utilisateur</li>
<li>avoir accès à une horloge monotone précise à la milliseconde</li>
<li>pouvoir sauvegarder des valeurs dans des variables</li>
<li>pouvoir effectuer des calculs mathématiques simples sur des variables</li>
</ol>
<p>Hélas, CMake ne remplit pas tous ces critères, mais on peut les contourner. Commençons par ceux qui sont présents nativement. </p>
<p>En CMake, c’est la commande <a href="https://cmake.org/cmake/help/latest/command/message.html"><code>message</code></a> qui permet d’afficher du texte à l’écran. Pour effectuer des calculs mathématiques simples on utilise <a href="https://cmake.org/cmake/help/latest/command/math.html"><code>math</code></a> et on stocke des valeurs arbitraires dans des variables avec les commandes <a href="https://cmake.org/cmake/help/latest/command/set.html"><code>set</code></a> et <a href="https://cmake.org/cmake/help/latest/command/list.html"><code>list</code></a>.</p>
<p>Ça se corse avec l’horloge. CMake possède bien la commande <a href="https://cmake.org/cmake/help/latest/command/string.html#timestamp"><code>string(TIMESTAMP, ...)</code></a> pour récupérer le temps courant mais son implémentation n’est précise qu’à la seconde. J’ai retrouvé un <a href="https://gitlab.kitware.com/cmake/cmake/-/issues/19335">ticket demandant une précision à la milliseconde</a> mais qui n’a pas bougé depuis 2 ans. Tant pis pour la précision, ce sera un TapTempoGrossoModo !</p>
<p>Pour pouvoir gérer les tempi au-delà de 60 bpm qui comportent plusieurs frappes par secondes on ne peut pas utiliser l’algorithme original qui se base sur les intervalles entre deux frappes. Pour contourner cette limitation, on va compter le nombre d’entrées utilisateur par seconde puis effectuer le calcul du tempo sur les <code>N</code> dernières secondes. Ça fonctionne, mais il faut que l’utilisateur garde le même rythme pendant ces <code>N</code> secondes pour être précis, donc impossible de détecter des changements rapides de tempo à moins d’avoir un <code>N</code> petit mais avec une précision médiocre. D’ailleurs la formule pour le nombre de secondes nécessaires pour une précision <code>p</code> donnée est <code>N = 60 / p</code>. Ainsi, avec 10 secondes on a une précision de 6 bpm et pour une précision de 1 bpm il faut enregistrer 60 secondes de frappes. Dans le code ci-dessous j’ai limité à 5 secondes pour une précision de 12 bpm, un peu grossier mais suffisant pour l’exercice.</p>
<p>Plus embêtant, CMake ne permet pas d’interagir pendant son exécution. C’est un comportement tout à fait logique pour un logiciel de configuration de construction, mais cela ne m’arrange pas pour ce portage. Encore une solution de contournement : utiliser la commande <a href="https://cmake.org/cmake/help/latest/command/execute_process.html"><code>execute_process</code></a> pour lancer un mini script <code>bash</code> avec la commande :</p>
<pre><code>read var
echo "$var"
</code></pre>
<p>On récupère alors l’entrée utilisateur dans la variable CMake pointée dans la commande <code>execute_process</code>. Avec ce mécanisme on pourrait même invoquer directement le programme <code>taptempo</code> original, mais ce serait de la triche !</p>
<p>Voilà, tout cela mis ensemble ça donne le script ci-dessous. Pour le lancer, il faut le copier dans un fichier <code>CMakeLists.txt</code> et exécuter la commande <code>cmake</code> avec comme argument le répertoire qui contient ce fichier.</p>
<pre><code class="cmake"><span class="nb">cmake_minimum_required</span><span class="p">(</span><span class="s">VERSION</span> <span class="s">3.15</span><span class="p">)</span>
<span class="nb">project</span><span class="p">(</span><span class="s">CMakeTapTempo</span><span class="p">)</span>
<span class="nb">find_program</span><span class="p">(</span><span class="s">BASH</span> <span class="s">NAMES</span> <span class="s">bash</span><span class="p">)</span>
<span class="nb">message</span><span class="p">(</span><span class="s2">"Hit enter key for each beat (q to quit)."</span><span class="p">)</span>
<span class="nb">set</span><span class="p">(</span><span class="s">current_keystroke_count</span> <span class="s">0</span><span class="p">)</span>
<span class="nb">set</span><span class="p">(</span><span class="s">keystroke_count_history</span> <span class="s">0</span> <span class="s">0</span> <span class="s">0</span> <span class="s">0</span> <span class="s">0</span><span class="p">)</span>
<span class="nb">set</span><span class="p">(</span><span class="s">last_timestamp</span> <span class="s">0</span><span class="p">)</span>
<span class="nb">set</span><span class="p">(</span><span class="s">should_stop</span> <span class="s2">""</span><span class="p">)</span>
<span class="nb">while</span><span class="p">(</span><span class="s">NOT</span> <span class="s">should_stop</span><span class="p">)</span>
<span class="nb">execute_process</span><span class="p">(</span><span class="s">COMMAND</span> <span class="s2">"${BASH}"</span> <span class="s2">"-c"</span>
<span class="s">[=[</span>
<span class="s">read</span> <span class="s">var</span>
<span class="s">echo</span> <span class="s2">"$var"</span>
<span class="s">]=]</span>
<span class="s">WORKING_DIRECTORY</span> <span class="o">${</span><span class="nv">CMAKE_CURRENT_LIST_DIR</span><span class="o">}</span>
<span class="s">OUTPUT_VARIABLE</span> <span class="s">user_input</span>
<span class="s">RESULT_VARIABLE</span> <span class="s">ret_code</span>
<span class="s">OUTPUT_STRIP_TRAILING_WHITESPACE</span>
<span class="s">ERROR_STRIP_TRAILING_WHITESPACE</span>
<span class="p">)</span>
<span class="nb">if</span><span class="p">(</span><span class="s">user_input</span><span class="p">)</span>
<span class="nb">set</span><span class="p">(</span><span class="s">should_stop</span> <span class="s2">"1"</span><span class="p">)</span>
<span class="nb">endif</span><span class="p">()</span>
<span class="nb">if</span><span class="p">(</span><span class="s">NOT</span> <span class="s">should_stop</span><span class="p">)</span>
<span class="nb">string</span><span class="p">(</span><span class="s">TIMESTAMP</span> <span class="s">current_timestamp</span> <span class="s2">"%s"</span><span class="p">)</span>
<span class="nb">if</span><span class="p">(</span><span class="s">current_timestamp</span> <span class="s">EQUAL</span> <span class="s">last_timestamp</span><span class="p">)</span>
<span class="nb">math</span><span class="p">(</span><span class="s">EXPR</span> <span class="s">current_keystroke_count</span> <span class="s2">"${current_keystroke_count} + 1"</span><span class="p">)</span>
<span class="nb">else</span><span class="p">()</span>
<span class="nb">set</span><span class="p">(</span><span class="s">last_timestamp</span> <span class="o">${</span><span class="nv">current_timestamp</span><span class="o">}</span><span class="p">)</span>
<span class="nb">list</span><span class="p">(</span><span class="s">PREPEND</span> <span class="s">keystroke_count_history</span> <span class="o">${</span><span class="nv">current_keystroke_count</span><span class="o">}</span><span class="p">)</span>
<span class="nb">list</span><span class="p">(</span><span class="s">POP_BACK</span> <span class="s">keystroke_count_history</span><span class="p">)</span>
<span class="nb">set</span><span class="p">(</span><span class="s">current_keystroke_count</span> <span class="s">1</span><span class="p">)</span>
<span class="nb">endif</span><span class="p">()</span>
<span class="nb">set</span><span class="p">(</span><span class="s">total_keystroke_count</span> <span class="s">0</span><span class="p">)</span>
<span class="nb">foreach</span><span class="p">(</span><span class="s">keystroke_count</span> <span class="o">${</span><span class="nv">keystroke_count_history</span><span class="o">}</span><span class="p">)</span>
<span class="nb">math</span><span class="p">(</span><span class="s">EXPR</span> <span class="s">total_keystroke_count</span> <span class="s2">"${total_keystroke_count}+${keystroke_count}"</span><span class="p">)</span>
<span class="nb">endforeach</span><span class="p">()</span>
<span class="nb">list</span><span class="p">(</span><span class="s">LENGTH</span> <span class="s">keystroke_count_history</span> <span class="s">history_length</span><span class="p">)</span>
<span class="nb">math</span><span class="p">(</span><span class="s">EXPR</span> <span class="s">tempo</span> <span class="s2">"(${total_keystroke_count} * 60) / ${history_length}"</span><span class="p">)</span>
<span class="nb">message</span><span class="p">(</span><span class="s2">"${tempo} bpm"</span><span class="p">)</span>
<span class="nb">endif</span><span class="p">()</span>
<span class="nb">endwhile</span><span class="p">()</span>
<span class="nb">message</span><span class="p">(</span><span class="s2">"Bye Bye!"</span><span class="p">)</span></code></pre>
<p>Sûrement que des experts CMake trouveront à redire et leurs commentaires sont les bienvenus !</p>
<div><a href="https://linuxfr.org/users/mzf/journaux/taptempo-en-cmake.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/125784/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/users/mzf/journaux/taptempo-en-cmake#comments">ouvrir dans le navigateur</a>
</p>
mzf
https://linuxfr.org/nodes/125784/comments.atom
tag:linuxfr.org,2005:Post/42341
2021-08-30T16:48:45+02:00
2021-08-30T16:52:59+02:00
Kitware recrute développeurs(ses) C++, Python, Web sur Lyon
<p>Bonjour,</p>
<p><a href="https://www.kitware.fr/">Kitware</a> est l'entreprise derrière des logiciels libres phares tels que CMake, ParaView, VTK, 3D Slicer, LidarView… qui sont régulièrement cités sur LinuxFr.</p>
<p>Face à une forte croissance, nous recrutons actuellement plusieurs profils de développeurs/développeuses pour travailler sur ces outils dans nos locaux de Lyon, situés juste à côté du parc de la tête d'or.</p>
<ul>
<li><a href="https://jobs.lever.co/kitware/2315a31c-cada-47d5-8a97-50862a63b97d">Développeur(se) R&D en Imagerie Médicale</a></li>
<li><a href="https://jobs.lever.co/kitware/4f584b12-18b0-4bdd-8414-ed268a26c7aa">Ingénieur R&D en visualisation scientifique et logiciels open source</a></li>
<li><a href="https://jobs.lever.co/kitware/7f43a57d-663f-416d-9e7d-e59cb4679695">Développeur(se) Python</a></li>
<li><a href="https://jobs.lever.co/kitware/9c28a19f-dfcd-490d-89aa-850ca6bc9160">Développeur(se) R&D C++</a></li>
<li><a href="https://jobs.lever.co/kitware/b60af2f8-2154-4ba2-ae85-0dd43d66a4c0">Développeur(se) Web JavaScript</a></li>
<li><a href="https://jobs.lever.co/kitware/5791dcc7-4da1-4557-b3d7-07e61d60bb4f">Ingénieur Logiciel</a></li>
</ul>
<p>Si vous souhaitez que votre travail ait un impact positif réel sur le monde à travers des logiciels 100% libres alors l'aventure Kitware est sûrement ce qu'il vous faut !</p>
<p>La liste complète des postes ouverts est disponible sur cette page :<br>
<a href="https://jobs.lever.co/kitware?location=Lyon%2C%20France">https://jobs.lever.co/kitware?location=Lyon%2C%20France</a></p>
<p>À bientôt !</p>
<div><a href="https://linuxfr.org/forums/general-petites-annonces/posts/kitware-recrute-developpeurs-ses-c-python-web-sur-lyon.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/125265/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/forums/general-petites-annonces/posts/kitware-recrute-developpeurs-ses-c-python-web-sur-lyon#comments">ouvrir dans le navigateur</a>
</p>
kitware
https://linuxfr.org/nodes/125265/comments.atom
tag:linuxfr.org,2005:Post/38272
2017-07-05T21:46:29+02:00
2017-07-05T23:11:30+02:00
[Résolu] Qt, cmake et debian…
<p>Bonjour,</p>
<p>J’essaye de compiler un projet qui est une simple dérivation de <a href="http://doc.qt.io/qt-5/qttestlib-tutorial1-example.html">l’exemple officiel</a>.</p>
<p>Par contre, le reste de mon projet utilise cmake. J’ai essayé plusieurs valeur de version minimale sans succès. Pour cmake j’ai regardé : <a href="http://doc.qt.io/qt-5/cmake-manual.html">ici pour l’officiel</a> et <a href="http://kdab.developpez.com/tutoriels/cmake-qt-5/">là pour le non officiel</a>.</p>
<p>Je suis sous debian 9 avec les paquets qt installé. On retrouve les fichiers d’inclusion dans <code>/usr/include/x86_64-linux-gnu/qt5</code>. Je compile avec gcc qui me dit qu’il ne trouve pas les include :'(.</p>
<p>Si quelqu’un a une idée pour m’orienter.</p>
<p>Voici le fichier cpp :</p>
<pre><code class="c++"><span class="cp">#include</span> <span class="cpf"><QtTest/QtTest></span><span class="cp"></span>
<span class="k">class</span> <span class="nc">MainTest</span><span class="o">:</span><span class="k">public</span> <span class="n">QObject</span>
<span class="p">{</span>
<span class="n">Q_OBJECT</span>
<span class="k">private</span> <span class="nl">slots</span><span class="p">:</span>
<span class="kt">void</span> <span class="n">toUpper</span><span class="p">();</span>
<span class="p">};</span>
<span class="kt">void</span> <span class="n">MainTest</span><span class="o">::</span><span class="n">toUpper</span><span class="p">()</span>
<span class="p">{</span>
<span class="n">QString</span> <span class="n">str</span> <span class="o">=</span> <span class="s">"Hello"</span><span class="p">;</span>
<span class="n">QVERIFY</span><span class="p">(</span><span class="n">str</span><span class="p">.</span><span class="n">toUpper</span><span class="p">()</span> <span class="o">==</span> <span class="s">"HELLO"</span><span class="p">);</span>
<span class="p">}</span>
<span class="n">QTEST_MAIN</span><span class="p">(</span><span class="n">MainTest</span><span class="p">)</span>
<span class="cp">#include</span> <span class="cpf">"MainTest.moc"</span><span class="cp"></span></code></pre>
<p>Le cmakelist :</p>
<pre><code class="cmake"><span class="nb">cmake_minimum_required</span><span class="p">(</span><span class="s">VERSION</span> <span class="s">3.1.0</span><span class="p">)</span>
<span class="nb">project</span><span class="p">(</span><span class="s">test</span><span class="p">)</span>
<span class="nb">add_executable</span><span class="p">(</span><span class="s">test</span> <span class="s">src/MainTest.cpp</span><span class="p">)</span>
<span class="c"># Find includes in corresponding build directories</span>
<span class="nb">set</span><span class="p">(</span><span class="s">CMAKE_INCLUDE_CURRENT_DIR</span> <span class="s">ON</span><span class="p">)</span>
<span class="c"># Instruct CMake to run moc automatically when needed.</span>
<span class="nb">set</span><span class="p">(</span><span class="s">CMAKE_AUTOMOC</span> <span class="s">ON</span><span class="p">)</span>
<span class="c"># Find the QtWidgets library</span>
<span class="nb">find_package</span><span class="p">(</span><span class="s">Qt5Test</span> <span class="s">REQUIRED</span><span class="p">)</span>
<span class="c"># Use the Widgets module from Qt 5.</span>
<span class="c">#target_link_libraries(helloworld Qt5::Widgets)</span></code></pre>
<p>La compilation :</p>
<pre><code class="bash">$ cmake ../test/
-- The C compiler identification is GNU <span class="m">6</span>.3.0
-- The CXX compiler identification is GNU <span class="m">6</span>.3.0
-- Check <span class="k">for</span> working C compiler: /usr/bin/cc
-- Check <span class="k">for</span> working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - <span class="k">done</span>
-- Detecting C compile features
-- Detecting C compile features - <span class="k">done</span>
-- Check <span class="k">for</span> working CXX compiler: /usr/bin/c++
-- Check <span class="k">for</span> working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - <span class="k">done</span>
-- Detecting CXX compile features
-- Detecting CXX compile features - <span class="k">done</span>
-- Configuring <span class="k">done</span>
-- Generating <span class="k">done</span>
-- Build files have been written to: /…/build_test
$ make
Scanning dependencies of target <span class="nb">test</span>
<span class="o">[</span> <span class="m">50</span>%<span class="o">]</span> Building CXX object CMakeFiles/test.dir/src/MainTest.cpp.o
/…/src/MainTest.cpp:5:25: fatal error: QtTest/QtTest: Aucun fichier ou dossier de ce <span class="nb">type</span>
<span class="c1">#include <QtTest/QtTest></span>
^
compilation terminated.
CMakeFiles/test.dir/build.make:62 : la recette pour la cible « CMakeFiles/test.dir/src/MainTest.cpp.o » a échouée
make<span class="o">[</span><span class="m">2</span><span class="o">]</span>: *** <span class="o">[</span>CMakeFiles/test.dir/src/MainTest.cpp.o<span class="o">]</span> Erreur <span class="m">1</span>
CMakeFiles/Makefile2:67 : la recette pour la cible « CMakeFiles/test.dir/all » a échouée
make<span class="o">[</span><span class="m">1</span><span class="o">]</span>: *** <span class="o">[</span>CMakeFiles/test.dir/all<span class="o">]</span> Erreur <span class="m">2</span>
Makefile:83 : la recette pour la cible « all » a échouée
make: *** <span class="o">[</span>all<span class="o">]</span> Erreur <span class="m">2</span>
$</code></pre><div><a href="https://linuxfr.org/forums/programmation-c/posts/resolu-qt-cmake-et-debian.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/112240/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/forums/programmation-c/posts/resolu-qt-cmake-et-debian#comments">ouvrir dans le navigateur</a>
</p>
Anthony Jaguenaud
https://linuxfr.org/nodes/112240/comments.atom
tag:linuxfr.org,2005:Diary/37350
2017-06-07T21:02:50+02:00
2017-06-07T21:02:50+02:00
Version minimum de CMake
Licence CC By‑SA http://creativecommons.org/licenses/by-sa/4.0/deed.fr
<p>Bonjour Nal,</p>
<p>Je vais bientôt me retrouver face à un dilemme insoluble : choisir la bonne version minimum de CMake pour écrire un <code>CMakeLists.txt</code>. Jusqu'à présent, ma <a href="https://www.debian.org/">distribution préférée</a> avait CMake 3.0.2 dans sa mouture <code>stable</code>. Donc, c'est celle que j'utilisais et c'est celle que je prenais comme version minimum. Déjà, ça me posait un certain nombre de problème parce que dans Ubuntu Trusty (la LTS de 2014), qui est installé dans mon univ, CMake en est à la version 2.8.12 et que je veux bien faire un effort mais bon voilà. </p>
<p>Dans la prochaine Debian stable prévue pour très bientôt (voir la dépêche en cours de rédaction), CMake passe directement en 3.7.2. Et là, je me dis «Modern CMake» toussa, ça va être trop bien. Sauf qu'à y regarder de plus près, tout le monde n'en est pas à CMake 3.7 et que je n'ai sans doute pas besoin de toutes les fonctionnalités de CMake 3.7.</p>
<p>En regardant un peu, je me dis qu'il manque <code>target_compile_features</code> qui peut être sympa (apparu en 3.1). Mais sur le reste, je ne vois pas bien ce que les versions suivantes pourraient avoir de vital. Alors, cher Nal, voici ma question : est-ce que tu utilises Modern CMake ? De quelle fonctionnalité indispensable vais-je avoir besoin qui va changer ma vie avec CMake ? Éclaire ma lanterne !</p><div><a href="https://linuxfr.org/users/rewind/journaux/version-minimum-de-cmake.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/112041/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/users/rewind/journaux/version-minimum-de-cmake#comments">ouvrir dans le navigateur</a>
</p>
rewind
https://linuxfr.org/nodes/112041/comments.atom
tag:linuxfr.org,2005:Diary/36371
2016-02-09T21:46:12+01:00
2016-02-09T21:46:12+01:00
CMake mon amour
Licence CC By‑SA http://creativecommons.org/licenses/by-sa/4.0/deed.fr
<p><a href="https://cmake.org/">CMake</a> c'est comme Marmite(*), on l'aime ou on le hait. Pour moi, cela est fortement sujet a mon état du moment.</p>
<p>Aujourd'hui je suis en complète admiration. Car je viens de découvrir deux astuces très intéressantes pour simplifier mes <code>CMakeLists.txt</code></p>
<h3 id="compilation">Compilation</h3>
<p>Plutôt que de forcer <code>--std=c++11</code> dans la liste de ces flags, ces deux petites lignes suffisent pour utiliser la version c++11 du standard</p>
<pre><code># require C++11 standard by default
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
</code></pre>
<p>La second ligne est nécessaire pour forcer une erreur si le compilateur ne le permet pas, autrement une version antérieur sera quand même tente parce qu'on se sait jamais.</p>
<p>Il est aussi possible de choisir le standard cible par cible </p>
<pre><code>add_library(foo foo.cpp)
set_property(TARGET foo PROPERTY CXX_STANDARD 11)
</code></pre>
<p>Encore mieux ! Parfois seulement une partie du standard est nécessaire. Et on peux choisir features par features :</p>
<pre><code>add_library(mylib requires_constexpr.cpp)
target_compile_features(mylib PUBLIC cxx_constexpr)
</code></pre>
<p>PUBLIC impose que toutes les cibles dépendantes de cette bibliothèques (internes au projet) seront aussi compilés avec les flags nécessaires.</p>
<p>Les exemples sont tirés de la <a href="https://cmake.org/cmake/help/v3.4/manual/cmake-compile-features.7.html">documentation officielles</a>. Il y a bien plus de possibilités !</p>
<p>La même interface est bien sur disponible pour des projets en C uniquement. (avec les variables/propriétés <em><em>C</em></em> au lieu de <em><em>CXX</em></em>)</p>
<h3 id="répertoire-dinstallation">Répertoire d'installation</h3>
<p>Plutôt que d'essayer de chercher si il faut installer dans lib,lib32,lib64 ou autre, on peut laisser faire le module <code>GNUInstallDirs</code>. Ce module va définir les variables <code>CMAKE_INSTALL_<dir></code> and <code>CMAKE_INSTALL_FULL_<dir></code> pour différents <code><dir></code> (pour les exécutables, les bibliothèques, les données, …) </p>
<pre><code>include(GNUInstallDirs)
# the libraries install dir
set( LIBRARY_INSTALL_DIR
${CMAKE_INSTALL_FULL_LIBDIR}
CACHE PATH "Installation directory for libraries"
)
set( BIN_INSTALL_DIR
${CMAKE_INSTALL_FULL_BINDIR}
CACHE PATH "Installation directory for executables"
)
</code></pre>
<p>It's magic ! La <a href="https://cmake.org/cmake/help/v3.4/module/GNUInstallDirs.html">documentation officielle</a> donne tous les détails nécessaires.</p>
<h3 id="la-morale-de-cette-histoire-">La morale de cette histoire :</h3>
<p>Même si c'est pénible, il me semble que chercher internet pour des solutions concernant CMake vous donnera forcément une mauvaise solution. Se pencher dans la documentation officielle (qui laisse parfois a désirer) est la seule façon d'obtenir un <code>CMakeLists.txt</code> a peu prés correct.</p>
<p>La prochaine fois, (si jamais, juste pour me contredire) j'expliquerais comment j'ai réussi a intégrer les 'sanitizers' et la compilation utilisant la <a href="https://fr.wikipedia.org/wiki/Optimisation_dirig%C3%A9e_par_les_profils">PGO</a>.</p>
<p>(*) oui bon…don't judge my references, I've never find anything like BBC4 yet… <a href="https://www.youtube.com/watch?v=FWQqgfE1YaM">https://www.youtube.com/watch?v=FWQqgfE1YaM</a> , if you ever need some explanation…</p><div><a href="https://linuxfr.org/users/manawy/journaux/cmake-mon-amour.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/108152/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/users/manawy/journaux/cmake-mon-amour#comments">ouvrir dans le navigateur</a>
</p>
manawy
https://linuxfr.org/nodes/108152/comments.atom
tag:linuxfr.org,2005:Post/35382
2015-05-18T12:53:18+02:00
2015-05-18T12:53:18+02:00
Compilation distribuée DISTCC/CMAKE
<p>Bonjour,</p>
<p>nous utilisons actuellement cmake et distcc sur nos postes de développement pour générer notre projet.</p>
<p>Je ne maitrise pas bien cmake, mais je suis déjà mis les pieds dedans pour deux-trois modifications.</p>
<p>Afin de pouvoir générer des patchs versionnés de notre projet, j'aurai besoin de m'assurer que les librairies et binaires aient le même md5sum (ou autre méthode je suis preneur), à chaque génération que je pourrait lancer, si aucun changement dans le code, dans les paramètres de compilation, etc ..</p>
<p>En gros, je voudrais être certain que si je compile maintenant, et disons dans 10 jours, sans aucun changement dans le projet ou autre, j'aurai mes binaires avec le même md5sum.</p>
<p>Est-ce faisable ? Y-a-t'il un FLAG de compilation pour ça ? Est-ce que c'est gcc qui gère ça tout seul ?</p>
<p>Merci d'avance pour votre aide.<br>
Sylvain</p><div><a href="https://linuxfr.org/forums/general-general/posts/compilation-distribuee-distcc-cmake.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/105781/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/forums/general-general/posts/compilation-distribuee-distcc-cmake#comments">ouvrir dans le navigateur</a>
</p>
sygirard
https://linuxfr.org/nodes/105781/comments.atom
tag:linuxfr.org,2005:Post/35318
2015-05-02T11:01:58+02:00
2015-05-03T15:00:48+02:00
[Résolu] valgrind & cmake
<p>Bonjour.</p>
<p>J'essaie de trouver les fonctions d'un programme (dont je ne suis pas l'auteur, donc un peu la flemme d'aller customiser un CMakeLists.txt juste pour passer 2 options) qui consomment le plus de temps d'exécution (avec callgrind), pour voir s'il y a moyen d'optimiser intelligemment.</p>
<p>J'ai regardé la doc de callgrind, et il y est conseillé de compiler, sous gcc, avec les options "-g -01".<br>
Quelqu'un sait-il s'il est possible de passer ces options à CMake sans devoir modifier le fichier CMakeLists.txt?</p><div><a href="https://linuxfr.org/forums/programmationautre/posts/resolu-valgrind-cmake.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/105633/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/forums/programmationautre/posts/resolu-valgrind-cmake#comments">ouvrir dans le navigateur</a>
</p>
freem
https://linuxfr.org/nodes/105633/comments.atom
tag:linuxfr.org,2005:Diary/35280
2014-09-26T09:28:41+02:00
2014-09-26T22:39:55+02:00
Retour aux sources
Licence CC By‑SA http://creativecommons.org/licenses/by-sa/4.0/deed.fr
<h2 id="amour-gloire-et-cpp">Amour, gloire et cpp</h2>
<p>Bonjour Nal,</p>
<p>Si tu suis régulièrement mes aventures, tu sais que depuis quelques années je n'utilise plus qu'une seule plateforme de développement pour tous mes <a href="http://devnewton.bci.im">projets</a>: Java.</p>
<p>Portable, performant et surtout productif, ce mariage de raison n'a pas empêché quelques aventures avec <a href="http://devnewton.bci.im/fr/cemetery">Python ou Javascript</a>, mais est resté assez solide.</p>
<p>Toutefois je n'ai jamais complètement pu oublier mon premier amour pour le C++, celui-ce ne cessant de se rappeler à mon bon souvenir, me promettant <a href="http://cpprocks.com/c11-a-visual-summary-of-changes/">qu'il n'était plus le même</a>, <a href="https://isocpp.org/blog/2014/08/we-have-cpp14">qu'il avait changé</a>.</p>
<p>J'ai fini par craquer et convenu d'un rendez-vous autour d'un prototype de jeu de sport dont je te reparlerais bientôt j'espère, bien que je ne sache pas si j'irais jusqu'au bout. En effet, la mise en place du projet n'a pas été un retour aux sources chaudes, mais plutôt une douche glacée façon ice bucket challenge avec un seau oublié pendant 3 mois dans un congélateur industriel.</p>
<h2 id="le-choix-des-larmes">Le choix des larmes</h2>
<p>Le panel de choix de l'outillage a été très décevant.</p>
<p>J'ai essayé quelques IDE, avant de me rendre compte que Eclipse ou Netbeans sont les seuls à proposer une bonne complétion, du refactoring qui marche et à ne pas planter lamentablement (kdevelop, c'est de toi que je parle). Les meilleurs IDE C++ sont donc en Java…</p>
<p>Pour le gestionnaire de projet, c'est bien simple, ça n'existe pas. Je n'ai trouvé aucun outil qui semble seulement s'approcher du centième de ce que fait un maven hors de la boite. Il faut donc utiliser une sorte script de compilation et gérer ses dépendances à la main comme à la préhistoire de l'informatique. J'ai pris cmake, car tout le monde semble l'utiliser de nos jours, mais mes yeux saignent en voyant le genre d'horreurs qu'il faut écrire:</p>
<pre><code class="c++"> <span class="k">if</span> <span class="p">(</span><span class="err">$</span><span class="p">{</span><span class="n">CMAKE_CXX_COMPILER_ID</span><span class="p">}</span> <span class="n">STREQUAL</span> <span class="s">"GNU"</span> <span class="n">OR</span> <span class="err">$</span><span class="p">{</span><span class="n">CMAKE_CXX_COMPILER_ID</span><span class="p">}</span> <span class="n">STREQUAL</span> <span class="s">"Clang"</span><span class="p">)</span>
<span class="n">set</span><span class="p">(</span><span class="n">CMAKE_CXX_FLAGS</span> <span class="s">"${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic -std=c++11"</span><span class="p">)</span>
<span class="n">set</span><span class="p">(</span><span class="n">CMAKE_CXX_FLAGS_DEBUG</span> <span class="s">"${CMAKE_CXX_FLAGS} -g"</span><span class="p">)</span>
<span class="n">set</span><span class="p">(</span><span class="n">CMAKE_CXX_FLAGS_RELEASE</span> <span class="s">"${CMAKE_CXX_FLAGS} -O2"</span><span class="p">)</span>
<span class="n">endif</span><span class="p">()</span></code></pre>
<p>J'ai aussi regardé comment faire de la cross compilation, créer des packages ou des binaires portables: là aussi il n'y a rien de bien au point, juste des tutoriaux ou des recommandations au détour d'un blog ou d'un forum.</p>
<h2 id="le-vent-du-changement-cest-maintenant">Le vent du changement c'est maintenant</h2>
<p>Une fois passée la douloureuse mise en place du projet, j'ai quand même été content de voir que C++ a bien changé. Fini les functors, vive les lambdas! Enfin vous voilà, smart pointers dans la STL! Oh et boost qui s'est bonifié avec le temps!</p>
<p>Je peux enfin écrire sans honte de belles lignes de code comme celles ci-dessous sans recourir à 150000 lignes de templates, de macros et de libs externes:</p>
<pre><code class="c++"> <span class="n">boost</span><span class="o">::</span><span class="n">property_tree</span><span class="o">::</span><span class="n">read_json</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="n">pt_nanim</span><span class="p">);</span>
<span class="n">boost</span><span class="o">::</span><span class="n">filesystem</span><span class="o">::</span><span class="n">path</span> <span class="n">parent_path</span> <span class="o">=</span> <span class="n">boost</span><span class="o">::</span><span class="n">filesystem</span><span class="o">::</span><span class="n">path</span><span class="p">(</span><span class="n">path</span><span class="p">).</span><span class="n">parent_path</span><span class="p">();</span>
<span class="k">auto</span> <span class="n">collec</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">make_shared</span><span class="o"><</span><span class="n">nanim</span><span class="o">::</span><span class="n">collection</span><span class="o">></span><span class="p">();</span>
<span class="k">for</span> <span class="p">(</span><span class="k">auto</span><span class="o">&</span> <span class="nl">pt_animation</span> <span class="p">:</span> <span class="n">pt_nanim</span><span class="p">.</span><span class="n">get_child</span><span class="p">(</span><span class="s">"animations"</span><span class="p">))</span> <span class="p">{</span>
<span class="k">auto</span> <span class="n">anim</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">make_shared</span><span class="o"><</span><span class="n">nanim</span><span class="o">::</span><span class="n">animation</span><span class="o">></span><span class="p">();</span>
<span class="k">for</span> <span class="p">(</span><span class="k">auto</span><span class="o">&</span> <span class="nl">pt_frame_child</span> <span class="p">:</span> <span class="n">pt_animation</span><span class="p">.</span><span class="n">second</span><span class="p">.</span><span class="n">get_child</span><span class="p">(</span><span class="s">"frames"</span><span class="p">))</span> <span class="p">{</span>
<span class="k">auto</span> <span class="n">pt_frame</span> <span class="o">=</span> <span class="n">pt_frame_child</span><span class="p">.</span><span class="n">second</span><span class="p">;</span>
<span class="p">...</span></code></pre>
<p>Si le langage a bien évolué sur des points qui me faisaient mordre mon clavier tous les jours à l'époque, je constate qu'il n'a pas bougé d'un poil sur des sujets fondamentaux:</p>
<ul>
<li>l'absence de système de modules: des entêtes avec #ifndef … #endf en 2014, c'est très moche.</li>
<li>j'ai une <a href="https://github.com/devnewton/superpaflaballe">dizaine de classes</a> et la compilation se fait déjà longuette.</li>
<li>toujours pas de stacktrace lors d'une exception.</li>
</ul><h2 id="si-tu-reviens-je-compile-tout">Si tu reviens, je compile tout</h2>
<p>Ah Nal! Tu l'auras compris, retrouver une ancienne amour, c'est souvent se rendre compte que tout a changé pour que rien ne change.</p>
<p>A ton avis, dois-je continuer cette aventure risquée ou revenir à la Raison?</p><div><a href="https://linuxfr.org/users/devnewton/journaux/retour-aux-sources.epub">Télécharger ce contenu au format EPUB</a></div> <p>
<strong>Commentaires :</strong>
<a href="//linuxfr.org/nodes/103407/comments.atom">voir le flux Atom</a>
<a href="https://linuxfr.org/users/devnewton/journaux/retour-aux-sources#comments">ouvrir dans le navigateur</a>
</p>
devnewton 🍺
https://linuxfr.org/nodes/103407/comments.atom