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 :)