Julien Jorge's Personal Website

Un environnement de dev dans son téléphone

Mon Aug 26, 2024

Ce post a été publié sur LinuxFr.org. Vous pouvez le lire là bas, ainsi que les commentaires associés

Bonjour ’nal :)

J’étais tranquille en train de me promener dans le store F-Droid quand TermuC (GitHub) a traversé mon écran. Son descriptif m’interpelle :

TermuC is a simple C/C++ IDE backed on powerful Termux. Install Termux first and install clang in Termux to supply the compiler and language server.

« Ah tiens, marrant », me dis-je, « il y aurait moyen de développer directement sur le téléphone ? Je me demande comment ça se met ».

Je suis la doc, qui indique de commencer par installer Termux (GitHub) et d’ensuite installer Clang dans Termux. Go pour le descriptif de Termux :

Termux combines powerful terminal emulation with an extensive Linux package collection.

Attends, que…oi ?! Tu veux dire que je peux avoir un terminal avec un gestionnaire de paquets et tout et tout, directement sur mon téléphone ? Ah mais délire. J’installe.

Un environnement de dev avec Termux.

Termux s’installe facilement et ne demande que des autorisation très basiques. Si tu n’utilises pas F-Droid tu peux aussi le retrouver dans le Play Store. TermuC communique avec Termux via le système d’Intent d’Android qui nécessite une autorisation supplémentaire.

Perso ce besoin m’a un peu refroidi même s’il n’y a pas vraiment de raison. Ajoute à cela que je n’ai pas apprécié d’IDE depuis le siècle dernier et tu comprendras que je me suis contenté du terminal de Termux. Chez moi ça se présente comme ceci :

Sans surprise, c’est effectivement un terminal. Le clavier est augmenté d’une série de touches bien pratiques : modificateurs, navigation, slash et tiret.

Il semblerait que le système soit basé sur Debian puisqu’on peu y utiliser apt pour installer les paquets. Les dépôts sont ceux de Termux, indépendants de Debian. Très bien, allez hop : apt install clang cmake emacs git ninja. Et voilà, ça fonctionne déjà.

Quelques pièges

Alors ça fonctionne, ça fonctionne… Oui, mais ce n’est pas si simple. J’ai récupéré Bim!, le jeu que je développe, et tenté de le compiler. Je me suis pris une petite leçon de portabilité du code !

__ANDROID__ n’est pas ce que tu crois.

Habituellement, et il me semble que c’est une pratique reconnue, j’utilise la définition du préprocesseur C __ANDROID__ pour savoir si je suis en train de compiler du code natif pour une l’application Android. J’insiste que ce qui m’intéresse est de savoir que c’est une application au sens Play Store.

Or, lors d’une compilation dans l’environnement Termux, __ANDROID__ est bien défini. Cela fait tout à fait sens, mais ça surprend. En effet, quand j’ai des bouts de code qui font des appels JNI, ça n’a aucun intérêt de les activer dans le terminal. J’ai donc dû abandonner cette définition du préprocesseur et passer l’info explicitement, par exemple en détectant la variable CMake CMAKE_ANDROID_NDK qui est définie par la toolchain Android lors de l’utilisation du NDK. À partir de là je peux définir une macro pour activer ou désactiver le code destiné à l’application Android.

/tmp n’existe pas.

On finit par oublier à l’usage mais il n’y a pas d’obligation à avoir un dossier /tmp sous Linux, et la bonne façon de récupérer le répertoire temporaire est d’utiliser la variable d’environnement TMPDIR. Après une mise à jour de GoogleTest et d’un petit projet à moi, plus de problème sur ce point. Enfin presque. Il semblerait que cette variable d’environnement ne soit pas définie dans l’image Docker Ubuntu 24.04, ce qui a donné des surprises sur la CI. Bon ben dans ce cas je repasse sur /tmp en secours, tant pis.

D’ailleurs, d’une manière générale, on ne peut pas compter sur l’arborescence traditionnelle pour les fichiers dans Termux. Tout est stocké dans /data/data/com.termux/files/, ce qui fait que les chemins classiques ne vont pas coller. Il est intéressant néanmoins de voir que le système va gérer correctement le shebang des scripts pour pointer vers l’interpréteur situé dans cette arborescence.

Au passage, une friture sympa proposée par l’app est d’« ouvrir » les fichiers téléchargés pour en fait les copier dans ~/downloads. J’ai cru que j’allais souffrir pour importer un zip téléchargé via Firefox et en fait ça s’est fait en deux-trois clics touchers.

La lib C n’est pas GNU lib C

La lib C utilisée par Termux est celle du système, soit Bionic, la lib C d’Android. Dans les grandes lignes ça ne change pas grand chose, dans le détail ça donne quelques surprises. Pour moi ça a coincé sur l’absence du fichier monetary.h, mais en fait je n’en avait pas vraiment besoin. C’était un prérequis pour Boost.Locale qui elle-même était tirée par une autre dépendance, iscool::core. En découpant cette dernière afin de rendre ses parties désactivables, j’ai pu me libérer de Boost.Locale. Tant mieux, ça me fera moins de trucs à compiler.

Il n’y a pas des masses de ressources

Il y a huit cœurs sur mon téléphone, mais seulement 3.5 Go de RAM. En général ça va, mais quand on lance un ninja qui va exécuter en parallèle plein de jobs gourmands en mémoire, ça se passe mal. C’est assez flippant de lancer une compilation, partir visiter un site dans Firefox et voir le téléphone se bloquer. Pour contourner le problème, il n’y a pas de mystère, il faut lancer moins de jobs. Dommage que le parallélisme de Ninja ne puisse être contrôlé par une variable d’environnement, ça éviterait de le faire au cas par cas.

Éventuellement, si le build est fait via cmake --build, il y aurait la variable d’environnement CMAKE_BUILD_PARALLEL_LEVEL qui devrait faire l’affaire.

À l’usage

Au final on arrive à programmer directement sur le téléphone mais ça dépend pas mal de la tache à effectuer. J’ai pu écrire une série de tests, pour une centaine de lignes, et même quelques ajustements à gauche à droite. Faire un script Bash pour remplacer les commentaires de licences et mettre la ligne SPDX dans tous les fichiers sources, pareil, ça se fait bien.

Par contre quand j’ai tenté une refacto du code du matchmaking (le regroupement des demandes de parties de la part des joueurs afin qu’ils puissent jouer ensemble), c’était galère. Pour le coup je me suis senti bien à l’étroit dans les 56 colonnes et 29 lignes du terminal. Moi qui code habituellement avec deux fichiers côte à côte à l’écran, là c’était dur. Et je n’espérais même pas pouvoir tester le code en local ; il aurait fallu pouvoir lancer un serveur et au moins deux clients… Bref, ce n’est sans doute pas le meilleur environnement pour coder une application client-serveur.

Autre élément impossible à tester : quand la CI a sorti une erreur de compilation avec G++ en activant AddressSanitizer. J’ai été incapable d’utiliser ce dernier sur le téléphone, quant à installer G++ je n’ai même pas essayé !

Conclusion, oui c’est sympa mais seulement pour des bricoles. Et Termux est un beau projet :)