dimanche 6 novembre 2016

Développement d'applications avec Ubuntu Phone - Défaite partielle

Eh beh, mes tentatives de faire tourner quelque chose de vaguement 3D sur mon Ubuntu Phone se révèlent plus difficiles que prévu. J'ai compris beaucoup de choses, et réalisé que j'en ignorais encore plus. Petit topo.

Tout d'abord, dès que l'on commence à parler dépendances, il faut commencer par comprendre le système de paquets Ubuntu, appelé "click". C'est une nième réponse au problème des dépendances de paquet, et qui vise à fournir un petit paquet qui ne dépende que de l'installation par défaut. Le paquet doit donc fournir directement toutes les dépendances de l'application. J'ai trouvé les explications sur le sujet plutôt limitées, et le plus simple semble pour l'instant de faire de la compilation statique.

Ce que cela veut dire, c'est que l'on ne peut pas se reposer sur les paquets Ubuntu pour construire son application. En effet, ces paquets ne seront pas disponibles sur le téléphone, et même si vous arriviez à copier les bibliothèques dans le paquet click, elles dépendent certainement elles-mêmes de bibliothèques dynamiques.

Ensuite, parlons de l'environnement de cross-compilation : Le système lxd (voir post précédent) fournit une sorte de chroot, qui représente l'environnement du téléphone. Dans cette chroot, gcc, g++, ld, et tous les autres, sont en mode cross-compilation vers armhf.

Étant donné tout cela, l'approche qui semble fournir des résultats (c'est à dire, quelque chose d'autre qu'un crash immédiat) est de compiler soi-même au sein de la chroot toutes les dépendances nécessaires à l'application, vers des bibliothèques statiques.

Un exemple avec OpenSceneGraph : j'obtiens un shell vers la chroot (Tools => Options => Ubuntu => bouton "Maintain" de la "build target"). Depuis le chroot, l'on voit quand même son /home, j'y ai donc téléchargé le code d'OpenSceneGraph, et j'ai créé un répertoire build comme indiqué dans les instructions de compilation. Ensuite, l'on installe quelques en-têtes manquantes, et l'on compile OpenSceneGraph.

apt-get install libqt5opengl5-dev:armhf
aptitude install libgl1-mesa-dev:armhf
cmake ../OpenSceneGraph -DOPENGL_PROFILE="GLES2" \
-DCMAKE_INSTALL_PREFIX=/usr -DBUILD_OSG_APPLICATIONS:BOOL=OFF \
-DDYNAMIC_OPENSCENEGRAPH=OFF -DDYNAMIC_OPENTHREADS=OFF
make
make install

Une fois arrivé à ce niveau, j'ai ajouté la lignes LIBS += -losgViewer -losgDB -losgManipulator -losgGA -losgUtil -losgText -losg -lOpenThreads -ldl à mon fichier .pro, et j'ai copié un exemple d'intégration QT5 et OpenSceneGraph. Ça compile, youpie !

Et là, j'ai eu un bel écran blanc, soit-disant parce que j'utilisais un composant QT5 non supporté, que l'application osait utiliser un shader, et un peu de baratin additionnel de la même farine.

Conclusion ? Je ne suis pas très sûr. Il faut certainement que je tente une autre approche pour intégrer QT5 et OpenSceneGraph. Mais peut-être est-ce voué à l'échec de faire de la 3D sur un téléphone bas de gamme ? Peut-être que de la 2D, en utilisant directement la SDL et sans passer par QT, serait plus simple ? Ais-je vraiment envie de me taper la compilation de la SDL ? Est-ce que Mir (le serveur graphique de chez Ubuntu) va me causer des soucis ? Est-ce que finalement, je ne suis pas plutôt fait pour la programmation sur desktop ?

jeudi 3 novembre 2016

Développement d'applications sur Ubuntu Phone - Installation de l'environnement

Utilisant maintenant Ubuntu comme système d'exploitation principal, rien de m'empêche d'installer l'environnement de développement Ubuntu Phone ! Youpie !

Dans les faits, ce fut un poil plus compliqué que prévu. Ce qui n'aide pas, c'est que manifestement (mais on s'en doutait un peu), le développement d'applications pour les téléphones Ubuntu reste un marché de niche, et qu'il y a donc très peu de ressources en dehors du site d'Ubuntu lui-même. Donc, si l'on se retrouve confronté à un problème dans leur tutoriel, il faudra lutter pour s'en sortir.

Les explications sont donc ici. Et après, c'est la jungle... Je me suis en particulier beaucoup battu avec lxd. Alors, lxd, je ne connaissais pas, mais il s'agit d'une sorte de chroot, qui semble être utilisé pour faire de la cross compilation. Jusqu'ici, tout va bien, mais la chose refusait de démarrer. Finalement, en bidouillant bien plus que de raison avec les logs de systemd, j'ai fini par comprendre qu'il y avait conflit entre lxd d'une part, et bind9 d'autre part (j'avais bien entendu installé bind9 et mis dnssec en place), lequel conflit peut se résoudre en forçant bind9 à n'écouter qu'en ipv4, sur le loopback, ce qui me convient (mais ne conviendra pas à quelqu'un qui veut fournir du DNS au reste de son réseau local, ou, pire, utiliser IPV6). J'ai donc à la fin de mon /etc/bind/named.conf.options :

listen-on-v6 { none; };
listen-on { 127.0.0.1; };

Une fois cette épreuve surmontée, et lxd démarré (il faut insister, apparemment), qcreator apparait ! Hourra ! Mais un dernier obstacle se dresse devant le développeur amaigri. En effet, il faut créer le "kit", qui permet la cross-compilation. Et si on le créé avant d'avoir connecté le téléphone, on est garanti de se planter, et de se retrouver avec des programmes C++ qui foirent lamentablement. D'ailleurs, n'essayez pas de connecter le téléphone à travers le Wifi, malgré l'impression que QCreator y arrive, utilisez un bon vieux cable USB et le tour est joué. Ensuite, depuis la page "Devices", vous pourrez créer un kit correspondant au téléphone, qui devrait fonctionner tout seul.

Les exemples de projet sont suffisamment complets pour pouvoir démarrer : en particulier, QCreator débarque avec un projet en QML pur, en QML avec un backend C++, et en C++ pur avec injection de QML.

Comme premier projet, j'aimerais bien voir si j'arrive à intégrer OpenSceneGraph à une application Ubuntu Phone.

mercredi 2 novembre 2016

Ubuntu, KVM et Windows

Maintenant que je suis passé à un processeur i5, le monde merveilleux de la virtualisation s'ouvre à moi. L'idée est de se débarrasser enfin du double boot, et de le remplacer par des machines virtuelles, plus flexibles et plus rapides à démarrer en cas de besoin. En particulier, ayant besoin parfois de faire du développement sous Windows, il me faut une machine virtuelle Windows.

La mort de mon précédent PC n'ayant normalement pas d'incidence sur ma license Windows Vista (oui, c'est vieux), j'ai essayé d'installer la chose sur KVM, le système de virtualisation qui vient avec le noyau. Bien que doté d'une interface un peu austère, il est extrêmement puissant. En particulier, il est possible d'obtenir une grosse amélioration des performances en utilisant des pilotes spécifiques pour l'accès au disque et au réseau au sein de l'OS virtualisé. Ça se passe très bien avec Debian, mais c'est un petit peu moins direct avec Windows.

Je vous la fait courte, avec Windows Vista, ça ne marche juste pas. J'ai tout essayé, mais je reste bloqué tout au début de l'écran de chargement.

En revanche, avec Windows 7, c'est nettement mieux. Le truc pour obtenir directement une installation rapide et cohérente, c'est de s'assurer que le disque virtuel est de type "virtio", de monter l'image du disque d'installation de Windows dans un premier lecteur virtuel, et de monter une image spéciale fournie par KVM et qui contient les pilotes dans un deuxième lecteur virtuel (ouf!).

Au démarrage, Windows 7 voit bien un D: contenant l'installation, et un E: contenant des pilotes, mais pas de C:. Il propose alors d'installer les pilotes. Une fois le bon pilote choisi depuis le E: dans la catégorie "virtblo", il voit alors un C:, et peut s'installer dessus tranquillement, et à toute berzingue si vous avez eu la bonne idée de le laisser tourner sur un SSD. Et à partir de là, vous avez un beau Windows qui tourne à une vitesse très proche d'une installation native (modulo les applications demandeuses en terme de graphisme, tels les jeux vidéos, la magie a quand même des limites).

Mais bon (troll inside), avec les pilotes graphiques libres et propriétaires de chez monsieur AMD, tripotée de jeux sur Steam, et un client Citrix qui fonctionne du tonnerre (ne me jugez pas, c'est le boulot!), a-t-on vraiment besoin de Windows?

mardi 1 novembre 2016

Nouveau PC

Mon ordinateur est mort! Après 8 ans de bons et loyaux services, la machine a rendu l'âme dans un dernier soubresaut. Je n'ai pas trop creusé les causes du décès, mais j'étais à peu près sûr que le disque était encore en forme, et mes données saines et sauves. Direction Tottenham Court Road, l'équivalent de notre bonne vieille rue Montgallet, mais en nettement moins impressionnant. Ma nouvelle bête est un i5 avec 8Go de RAM, un SSD de 124 Go et un disque dur de 1 To, et une carte graphique Radeon RX 480.

Je me suis un peu battu avec l'UEFI, et j'ai fini par abandonner l'installation de Debian pour une Ubuntu pour laquelle AMD fournit de beaux drivers propriétaires. Le tout fonctionne particulièrement bien, et le SSD change vraiment la vie. Le démarrage de la machine et des applications est démentiel.

À noter, j'ai décidé de mettre tout le disque sur le SSD, en ne mettant sur le HDD que la partition de swap, le /var/log, et une grosse partition "data" que j'accède via un lien symbolique et sur lequel je peux mettre le bousin un peu lourdingue (collection de photos, principalement).

lundi 3 octobre 2016

Ubuntu Phone 1 an après, mes impressions sur Linuxfr

J'ai fait un petit résumé de mes impressions après plus d'une année d'utilisation de mon Ubuntu Phone. Intéressantes réactions des inconditionnels et des moins convaincus.

dimanche 4 septembre 2016

Nested namespace definition

Entrée remarquée dans c++17 de la fonctionnalité de définition des espaces de noms imbriqués. C'est à dire qu'au lien de mettre des séries de "namespace a { namespace b { namespace c { ...", l'on peut directement écrire "namespace a::b::c { ...". Ça ne va pas changer la vie de qui que ce soit, mais pourquoi pas. Comme d'hab, le petit programme d'exemple:

#include <iostream>

namespace a::b::c // magie!!!!
{
  void f()
  {
    std::cout << "Ouh là, c'est profond!" << std::endl;
  }
}

int main()
{
  a::b::c::f();
  
  return 0;
}

vendredi 2 septembre 2016

Folding expressions

Youpie, gcc 6.1 a débarqué dans Debian! C'est une excellente occasion pour se plonger dans les nouveautés du standard. Parlons donc d'une fonctionnalité que j'avais complètement zappé, les "folding expression". L'idée est de fournir du sucre syntaxique pour permettre d'appliquer certains opérateurs à l'ensemble des paramètres variadiques d'une fonction. Dit comme ça, cela semble assez abstrait, mais puisque comme disait Napoléon, un petit bout de code vaut mieux que de grands discours, voici un exemple.

L'idée est donc d'écrire une fonction qui peut prendre un nombre quelconque d'arguments, et en retourner la somme. Avec une "folding expression", rien de plus simple! La syntaxe est un peu absconse, "(... [operator] args)" (ne pas oublier les parenthèses!), mais ça fait le boulot.

#include <iostream>

template<typename ...ARGS>
int variadicAdd(ARGS... args)
{
  return (... + args);
}

int main()
{
  std::cout << variadicAdd(3, 2, 7, 8, 4, 5) << std::endl;
  return 0;
}

Comme vous voyez, c'est tout bête. L'on aurait pu coder la même fonctionnalité avec des appels récursifs, mais c'est quand même beaucoup plus succinct comme ça. L'on peut "replier" les expressions avec tout un tas d'opérateurs, et j'attends avec impatience de voir ce que l'on va inventer avec cette construction.