Archives de l’auteur : Damien Buhl

A propos Damien Buhl

Je me nomme Damien Buhl (alias daminetreg). Développeur embarqué chez Fr. Sauter AG à Basel, anciennement étudiant à l'eXia.Cesi Strasbourg. Le manifeste agile, le développement en C++ avec Boost & Javascript pour le web et l'embarqué, les amis, le sport, la conception UML, la motivation en addition à Linux, Symbian, Android, Qt & Mootools sont pour moi les éléments nécessaires à ma survie.

Développement Web en C++

En attendant MeetingCpp j’ai commencé cet article, car j’étais étonné qu’il n’y ait aucune session prévue au sujet du développement web en C++. Je le finalise ce soir en rentrant de cette magnifique conférence, afin de me donner le temps de faire de mes nombreuses notes de véritables articles sur les sujets abordés et discutés.

En effet on ne trouve pas des masses de tutoriaux, ni de solutions pour le développement web en C++, du fait de la prédominances des langages tels que Php, Spring, Django, Ruby on Rails etc. dans ce domaine.

J’aimerai présenter dans cet article une des solutions existantes en tant que framework de développement web, permettant de parvenir très rapidement à de bons résultats, comme on peut y être habitué avec CodeIgniter, Zend, Django ou Ruby on Rails, mais avec un gain de performance.

Pourquoi du développement web en C++ ?

Avant de rentrer dans des détails d’implémentation, il est possible de se poser la question pourquoi du dévéloppement web en C++ ? En effet avec la pléthore de langages et de frameworks existants destinés à ce problème, on pourrait penser que cela n’a pas d’autre intérêt que la préférence de ce langage.

En réalité, il y a trois raisons qui peuvent mener à choisir de développer une application web ou un site internet en C++ :

  • Hautes performances & haute disponibilité : Benchmark CppCms vs Java, C#, PHP
  • Réduction du nombre de serveurs, ayant pour conséquence la réduction des coûts et de l’impact sur l’environnement : HipHop for Php: Move Fast
  • Ajout d’une interface web (html ou web service) pour une base C++ existante

CppCms parmi d’autres solutions

J’ai eu le loisir de tester et de comparer différentes solutions (i.e. POCO HttpServer, CppCms, FastCgiQt, WebToolkit, QtWebApp, inetd…) et bien qu’il y ait différents avantages et inconvénients pour chaque solution, la librairie la plus flexible et la plus riche qu’il m’ait été donnée de trouver est CppCms.

CppCms est bel et bien un framework et non un système de gestion de contenu comme son nom souhaiterait l’indiquer, il est très semblable au framework Django en Python ou encore à CodeIgniter en PHP, n’ayant pas grand chose à envier à ces derniers en matières de fonctionnalités disponibles (i.e. Moteur de template statique/dynamique, systèmes de cache, json, jsonrpc, url mapping, génération/validation de forms HTML, modules multilingues/multiencodage, validation des entrées, fonctions cryptographiques/hash, gestion des sessions, gestion des vues, logging, accès aux bases de données avec cppdb, connexion avec apache/lighttpd/nginx via SCGI/FCGI ou HTTP…)

En addition le code et la documentation de CppCms est très claire, à tel point que Boost.Locale qui provient de CppCms a été accepté très rapidement.

Boost ou booster ?

CppCms peut laisser un peu sceptique au premier abord, car ce dernier contient une bibliothèque : booster, qui correspond à une petite partie de boost sur lequel le framework se base en addition à des extensions. Il est donc possible d’utiliser boost ou directement booster dans le code client ou de mélanger les deux sans que cela ne pose problème. Il y a des parties de booster qui font double emploi avec boost tel que booster::shared_ptr qu’il m’est impossible de justifier, mais d’autres qui sont très justifiées tel que booster::aio et qui se différencie de Boost.Asio par différents points abordés plus après.

CppCms : Télécharger & Installer

Je pars du principe que vous êtes dans un environnement unix, même si les étapes sont semblables sous windows.

  • Récupérez le code source : http://sourceforge.net/projects/cppcms/files/
  • Récupérez quelques dépendences :
    apt-get install libpcre3-dev zlib1g-dev libgcrypt11-dev libicu-dev python
  • Compilez :
    tar xf cppcms-1.0.2.tar.bz2
    cd cppcms-1.0.2/
    mkdir build
    cd build/
    cmake ..
    make -jX (Où X correspond à votre nombre de coeurs processeur + 1)
    sudo make install

Hello World

Nous allons pour ce premier article visant à présenter CppCms, implémenter l’infatigable “Hello World”.

Un design pattern que l’on retrouve de nos jours dans la quasi-totalité des frameworks webs est le MVC, utile dans le cas de sites webs, il permet de séparer les données ou la logique (i.e. le Modèle) de l’interface graphique (i.e.la Vue) à l’aide d’un glue code traitant les interactions utilisateurs (i.e. le Contrôleur).

Bien que pour ce premier “Hello World” nous n’allons pas utiliser cette organisation, CppCms ne fait pas exception et met à disposition le concept de contrôleur à l’aide de la classe mère cppcms::application, le modèle avec cppcms::base_content et les vues à l’aide du compilateur de fichier .tmpl : cppcms_tmpl_cc qui permet de mélanger C++ et le format de sortie : JSON, HTML…

Une cppcms::application synchrone simple

CppCms propose différents modèles de programmation, celui auquel un développeur web connaissant PHP, Django, Ruby on Rails ou Java est habitué est le modèle synchrone usant différents threads afin de traiter les requêtes reçues. C’est très simple à comprendre et scalable verticalement comme horizontalement via les systèmes de load balancing proposés avec FCGI ou SCGI (e.g. lighttpd mod_fcgi permet de définir plusieurs processus de gestion des requêtes, locaux ou distants).

Ici nous allons utiliser le serveur web intégré à CppCms en créant un petit projet organisé de la façon suivante:

hello_world/config.js :

hello_world/CMakeLists.txt :

Et dans le dossier src, le CMakeLists qui actuellement produit l’executable, hello_world/src/CMakeLists.txt

Et enfin le code de notre application, hello_world/src/SomeController.hpp :

  1. #ifndef SOMECONTROLLER_HPP
  2. #define SOMECONTROLLER_HPP
  3.  
  4. #include <cppcms/application.h>
  5. #include <cppcms/http_response.h>
  6. #include <cppcms/url_dispatcher.h>
  7.  
  8. class SomeController : public cppcms::application {
  9.     public:
  10.         SomeController(cppcms::service &srv) : cppcms::application(srv) {
  11.             dispatcher().assign("/hello",&SomeController::hello,this);
  12.             dispatcher().assign("/bye",&SomeController::bye,this);
  13.             dispatcher().assign(".*",&SomeController::redirect,this);
  14.         }
  15.  
  16.         void redirect() {
  17.             response().set_redirect_header("/hello");
  18.         }
  19.  
  20.         void hello() {
  21.             response().out() <<
  22.                 "<html>"
  23.                 "<body>"
  24.                 " <h1>Hello World</h1>"
  25.                 "</body>"
  26.                 "</html>\n";
  27.  
  28.         }
  29.  
  30.         void bye() {
  31.             response().out() <<
  32.                 "<html>"
  33.                 "<body>"
  34.                 " <h1>Bye</h1>"
  35.                 "</body>"
  36.                 "</html>\n";
  37.         }
  38. };
  39.  
  40. #endif

Afin de démarrer le service web et monter notre application à une url particulière il nous faut un point d’entrée, hello_world/src/main.cpp :

  1. #include <cppcms/applications_pool.h>
  2. #include <cppcms/service.h>
  3. #include <iostream>
  4.  
  5. #include <SomeController.hpp>
  6.  
  7. int main(int argc, char **argv) {
  8.  
  9.     try {
  10.         cppcms::service srv(argc,argv);
  11.         srv.applications_pool().mount(cppcms::applications_factory<SomeController>());
  12.         srv.run();
  13.     } catch(std::exception const &e) {
  14.         std::cerr << e.what() << std::endl;
  15.     }
  16.  
  17.     return 0;
  18. }

Configuration et mount()

Ici l’instance de cppcms::service que nous créons au sein de la fonction int main(int argc, char **argv) de l’application va justement définir sa configuration en fonction du fichier config.js que l’on passe à l’application. Ce fichier respecte un format JSON avec la possibilité en plus de commenter des lignes à l’aide de //.

Il est possible de configurer à l’aide de la clé “service” la façon dont CppCms doit servir des requêtes. Pour cet exemple nous resterons sur la configuration présente, mais pour une mise en production un petit changement vers fcgi ou scgi sera nécessaire (c.f. Configurer CppCms avec des serveurs webs).

Avec cette configuration, CppCms instancie un serveur http utilisant le nombre de threads donnés par worker_threads pour traiter les requêtes, il utilise ainsi la fabrique : cppcms::applications_factory() pour créer SomeController une fois par worker thread qui traite ce type de requêtes. La méthode mount() permet de définir sous quel chemin racine la cppcms::application sera servie, sans second paramètre, mount() utilise SomeController pour répondre à n’importe quelle requête entrante.

L’appel un peu plus loin à srv.run() lance le serveur HTTP ou FCGI/SCGI selon la configuration et démarre une event loop qui distribue les différentes requêtes au threads sur la base du reactor pattern (i.e. Il est possible de configurer quel backend utiliser via la clé “reactor”, avec l’une des valeurs suivantes : “default”, “select”, “poll”, “epoll”, “devpoll”, “kqueue”, cependant cela n’a rien de nécessaire sur les plateformes communes parce que default choisi toujours la meilleure option pour la plateforme en cours. Vous noterez que l’option iocp est manquante, cela résulte dans l’utilisation de select() sur windows).

Plutôt que des threads il est possible d’utiliser des processus pre-forkés en spécifiant la clé : worker_processes. Cela a deux principaux avantages : un crash d’une des instance de SomeController n’affecte que l’unique requête servie par ce dernier et sous la plupart des systèmes d’exploitations, au dessus un certain nombre de thread la gestion de ces derniers devient si complexe que leur coût en performance devient exponentiel (c.f. Scalable Network Programming, Or: The Quest For A Good Web Server (That Survives Slashdot)).

Cependant en restant sous un nombre réaliste de threads, la rapidité sera meilleure qu’avec fork, tout dépends de combien de clients simultanés doivent pouvoir être supportés et de la longueur du traitement de chaque requête, dans cet exemple nous n’utilisons que 10 threads.

Pour exécuter cet exemple sur votre pc, il vous suffit de taper les commandes suivantes :

Assignement d’url

Comme il est possible de le voir dans le fichier SomeController.hpp lors de l’instanciation de ce dernier il est possible de définir quelle méthode doit être appellée à quelle instance à l’aide du header : cppcms/url_dispatcher.h.

Ce dernier ne se limite pas à cette utilisation simpliste, en effet le premier paramètre est une expression régulière, il est ainsi possible de mapper des éléments capturés de l’url en tant que paramètre de la méthode à appeller, de telle sorte que l’on pourrait écrire pour une méthode avec la signature SomeController::getArticle(string categoryName, string articleId):
dispatcher().assign("/getArticle/(s+)/(d+)", &SomeController::getArticle,1,2);

Ainsi la méthode chargée de traiter la requête n’est appellé que si le format de l’url correspond. Cela n’empêche pas pour autant d’accèder directement à l’url complète ou aux paramètres GET, POST etc. à l’aide de la méthode request() retournant un objet de type cppcms::http::request représentant la requête.

Ecriture de la réponse

Comme il est possible de le voir dans les méthodes redirect(), hello() & bye on manipule la réponse http à l’aide de la méthode response() qui retourne un object de type cppcms::http::response et qui possède une API très riche pour manipuler les réponses, avec des méthodes confortables. Vous trouverez également une méthode io_mode() qui peut être définie sur normal, nogzip, raw, asynchronous ou asynchronous_raw.

De nombreuses autres fonctionallités à découvrir

Comme vous avez pu le constater il y a différents modes d’entrées/sorties possibles dans cppcms. Un mode très intéressant, mais peut-être le moins commun pour les personnes ne connaissant pas boost::asio est le mode asynchrone.

Chaque thread qui fait de l’entrée/sortie a la problèmatique de devoir attendre sur l’achèvement d’une entrée ou d’une sortie pour pouvoir continuer les traitements. On peut résoudre ce problème d’entrées/sorties bloquants les thread la majorité du temps, en délégant le transfert des données aux drivers et au matériel. Laissant ces derniers effectuer les entrées/sorties lorsque c’est actuellement le moment ou possible, et répondre ainsi à d’autres entrées/sorties avec le même thread. Cela décuple de façon très importante le nombre de requêtes pouvant être traitées avec le même nombre de threads, cela implique cependant plus de complexité et nécessite de gérer soit-même le nombre de connexions par thread, afin de rendre l’application scalable.

Pour ceux connaissant boost::asio il y a cependant certaines différences dans la façon avec laquelle CppCms implémente les mêmes principes avec sa librairie booster::aio. En effet io_service::run() ne peut être appellée par plusieurs threads à la fois et laisse tourner sa boucle d’évènement jusqu’à ce que stop() soit appellée et non pas lorsqu’il n’y a plus de tâches postées.

booster::aio à l’instar de boost::asio n’utilise pas iocp sur Windows, parce qu’il utilise toujours le Reactor pattern. Un autre point est qu’il y a moins de fonctionnalités que dans boost::asio et est orienté objet plutôt que concepts.

Je posterai sous peu un article expliquant cela plus en détails et présenterai dans quels cas avec CppCms les applications webs asynchrones sont intéressantes, cela ne ferait aucun sens pour notre hello_world, mais plutôt dans le cas d’implémentation de server-push ou de long-polling à l’aide de la classe : cppcms::http::context permettant de conserver une requête en cours sur le serveur et de la servir partiellement sans bloquer un thread par utilisateur, à l’aide de fonctions telles qu’async_flush_output(handler).

Conclusion

Développer des applications webs en C++ n’est plus un problème et a différents avantages, je n’ai présenté ici que la base la plus simple de ce framework, mais il y a de nombreuses fonctionnalités qui méritent d’être connues comme le support de Json::Rpc, le compilateur de vues/templates, les mécanismes de cache intégrés, les classes de sérialisation/désérialisation, la gestion des sessions, des formulaires et de l’internationalisation.

Si vous souhaitez en savoir plus n’hésitez pas à visiter les exemples et la documentation officielle : CppCMS 1.x.x — Stable. Je serai également ravi de vous répondre ou de vous aider.

Meeting C++ – Conférence

Les 9 et 10 novembre 2012 la plus grosse des conférences sur le C++ en europe aura lieu à Düsseldorf en Allemagne.

Alors que j’ai déjà mon ticket et mon hôtel, et qu’il n’y a malheureusement plus de places libres disponible (i.e. elles se sont écoulée très rapidement), je vais me faire la joie de vous rapporter toutes les sessions auxquelles je vais assister durant ces deux jours.

En effet je vous retransmettrai mes notes sous forme d’articles car la conférence va être très riche en enseignements sur le C++11, Qt, Boost, Clang mais également sur la programmation parallèle, telles que les architectures SIMD (i.e. Single Instruction Multiple Data) ou SMP (Symmetric Multiprocessing) et bien plus encore!

C’est un rêve éveillé pour les amoureux du C++, avec la présence de Michael Wong (Directeur de la délegation d’IBM et Canadian pour le standard C++) et Peter Gottschling (Directeur de la délégation allemande du comité de standardisation ISO du C++), mais également des personnalités, tel que l’organisateur de la conférence qui est l’un des Ambassadeurs Qt : Jens Weller.

Etant donné que plusieurs sessions auront lieu en même temps, je ne pourrai assister à toutes (à moins que je ne tente de courrir d’une salle à l’autre, mais je ne suis pas certain que les articles qui en résulteront seront intéréssants :D). Voici donc mon programme que j’ai choisis pour le premier jour :

  • Registration
    • J’ai pensé que ce serait utile ;)
  • Good C++11 Coding Style
    • Le nouveau standard change radicalement les bonnes pratiques que l’on connaissait en C++98 et bien qu’elles se rapprochent de celles de Boost avec C++03, il intègre de nombreux éléments qui vont nous amener à repenser notre façon d’écrire du code, cette présentation de Michael Wong va donner des conseils sur les premières étapes à prendre pour migrer vers le C++11.
  • R-Value References and Move-Constructors in C++11
    • On parle beaucoup des R-Value References et du nouveau Move operator, ainsi que de leurs limitations, cette présentation me permettra d’écrire un article afin de les utiliser au mieux pour améliorer les performances parfois gaspillées par les copies inutiles.
  • Task-based Concurrency for C++ by using Intel TBB
    • La librarie Thread Building Block d’Intel est très intéressante pour la parallélisation des traitements en C++, durant cette session des exemples seront donnés sur la parallélisation via l’usage d’algorithmes génériques parallèles, de conteneurs concurrents mais également sur le paradigme de programmation FBP (flow-based programming).
  • C++11 in Qt5: Challenges and Solutions
    • Avec C++11 Qt va devoir s’adapter pour utiliser efficacement les nouveaux concepts que le langage offre, Thiago Macieira (Responsable de QtCore & QtDBus) et Marc Mutz (Contributeur Qt depuis plus de 10 an) vont mettre en exergue comment, tout en restant compatible avec les différentes plateformes et compilateurs existants, Qt va s’adapter pour le C++11.
  • C++11: An Overview
    • Le mot clé auto du C++11 (i.e. Fini BOOST_AUTO :D), les fonctions lambda, les initializers lists, les variadic templates… Tout ce qui nous passionne sur ce nouveau standard sera présenté par Rainer Grimm, très connu par les lecteurs du Linux-Magazin allemand pour ses excellents articles.
  • LibTooling – building tools for C++ with Clang API
    • Pour ceux qui ont toujours rêvé d’améliorer la suite d’outils réservés au développement en C++, il est de nos jours possible d’utiliser Clang pour parser l’AST de ce langage magnifique et de travailler à l’aide de celui-ci de façon très aisée. Je suis très intéréssé par ce sujet, étant donné que je travaille ces problèmes à l’aide de plugins pour gcc.

Et à la fin du premier jour, il nous sera possible d’avoir un repas tous ensemble grâce à l’un des sponsors de la conférence, qui prouve un véritable engagement pour le C++ : think-cell.

Des sessions très intéressantes telles que la programmation réseau avec boost.asio, la programmation fonctionnelle en général en C++11 et plus particulièrement à l’aide des mécanismes de polymorphisme mais sans notion d’héritage en C++11 seront données le second jour.

Et encore plus concret, un thème pour lequel la communauté Qt a beaucoup d’intérêt en ce moment : le développement d’applications mobiles pour BlackBerry 10. En effet en sus d’Intel, think-cell et KDAB, RIM sponsorise l’évènement, car ces derniers affichent pour leur nouvelle plateforme une ferme volonté de rendre possible le développement en C++/Qml/Javascript avec Qt.

Cette conférence va être géniale, elle signe avec le nouveau standard C++11 et la grande activité du comité depuis lors, une nouvelle ère pour le C++ et la programmation en général. J’espère pouvoir vous en rapporter le plus possible!

Pour en savoir plus : Meeting C++.

Necessitas : Qt pour Android – Alpha Release

Dans un article précédent j’ai pu vous présenter le port de Qt pour Android dans une de ses premières versions. Depuis lors j’ai pu participer au projet en matière de documentation, et j’ai le plaisir de vous annoncer que ce dimanche Qt pour Android est sorti en version Alpha.

Il est désormais possible de mettre en place l’environnement de développement en 5 minutes et l’intégration de Qt Creator pour Android est intuitive comme jamais.

Integration Android pour Qt Creator

Cette Release comme l’a dit BogDan Vatra sur la mailing list est une des plus importantes, car le sdk Necessitas met à disposition tout les outils nécessaires au développement sur Android avec Qt. En effet ce sdk propose Qt précompilé pour les différentes versions du système d’exploitation mobile de Google, Qt Creator pour Android, et l’application Ministro. Ministro est déjà disponible sur le Market de Google, elle télécharge et installe les bibliothèques Qt sur votre système dès qu’une application Qt pour Android en a besoin.

Il est possible de tester Qt sur Android en installant Demo – Aminated tiles qui vous demandera d’installer Ministro afin de télécharger les dépendances de Qt.

Pourquoi des noms latins ?

Les termes Qt et Android ne sont pas utilisés suite à un conseil de Nokia de ne pas utiliser le nom Qt pour des raisons légales, Google quant à lui n’a pas répondu au sujet d’Android.

Necessitas

Le nom Necessitas a été choisi par le fondateur de Qt pour Android pour différentes raisons. Necessitas est la déesse Romaine de la nécessité, et la personnification de la destinée et de la fatalité. Le choix de la déésse de la fatalité est vraisemblablement un clin d’oeil à la récente décision du PDG de Nokia (Stephen Elop) de basculer la stratégie principale de Nokia (Propriétaire actuel de Qt) en matière de téléphonie mobile de MeeGo avec Qt vers Windows Phone 7 sans Qt.

Ministro

Ministro est également un mot latin qui signifie assister, rendre un service, et c’est véritablement ce que cette application fait en téléchargeant et installant sur le système les librairies Qt pour les applications qui en ont besoin. En effet sans lui le projet est quasiment inutile, c’est la garantie que toutes les applications Qt qui seront déployées fonctionneront sur toutes les versions et périphériques Android sans aucunes modifications. Ministro télécharge les librairies Qt nécessaire sur les serveurs de sourceforge, dans une prochaine version cela utilisera les différents mirroirs de sourceforge et ainsi celui le plus proche du périphérique Android connecté.

Industius

eu.licentia.necessitas.industius est le nom du package java de Qt pour Android. Cela signifie assidu et travailleur, c’est la partie du code qui contient les différents bindings JNI et qui charge les librairies Qt, les autres librairies natives et enfin l’application Qt choisie.

Version Alpha

Actuellement il n’y a pas de limitations ni de bugs critiques connus, cependant l’API Qt 4.8.0 n’est pas encore considérée comme stable et c’est pourquoi il ne faudrait pas, pour le moment, envoyer les applications faites avec Necessitas sur le Market d’Android avant que Nokia ou que l’équipe de Qt pour Android ne propose une version stable de Qt 4.8. En effet une version stable aura la garantie d’être toujours disponible à l’aide de l’outil Ministro.

Framework Qt

L’ensemble du Framework Qt est porté (ou alors de petites parties sont encore en cours), toutefois cette version Alpha est distribuée avec le sw plugin platform. sw vient de SingleWindow, c’est un plugin Android qui utilise uniquement une fenêtre Android native pour afficher toutes les fenêtres Qt. Cela ne veut pas dire que vos applications ne peuvent comporter qu’une seule fenêtre, cela signifie simplement que les fenêtres sont affichées au travers de l’implementation du Framebuffer de Qt. Le plugin sw de Qt pour Android fait ainsi simplement la connexion entre le système d’exploitation et l’implémentation du Framebuffer de Qt.

Le seul point négatif de ce plugin est qu’il ne supporte pas les accélerations matérielles telles que l’Open GL. Une fois que le plugin sw sera stable pour une utilisation en production, le plugin mw de Qt pour Android sera mis à jour et permettra l’utilisation des accélérations matérielles OpenGL.

Ainsi hormis QtMobility qui est actuellement en train d’être porté, il vous est possible d’utiliser l’ensemble des bibliothèques Qt pour vos applications Android. ;)

Qt Creator pour Android

“Créez, Gérez, Compilez, Déployez & Deboguez.” – BogDan Vatra, c’est ainsi que ce dernier a présenté l’intégration Android pour Qt Creator. Soit une intégration parfaite de Qt Creator qui vous permet de développer pour Android comme si vous développiez une application de bureau.

Debogage d'application Qt sur Android

SDK & NDK Officiels d’Android + Débogage

Les points qui gênaient un peu dans les premières versions d’android lighthouse ont été modifiés. En effet désormais Necessitas ne fait plus usage d’un Native Development Kit non-officiel et tire pleinement partie des outils officiels d’Android. Aussi le débogage des applications est maintenant possible en remplaçant la version de gdb du ndk officiel par une version plus récente et en choisissant une version d’Android supportant le débogage d’applications natives multi thread.

Installer Necessitas

La documentation du sdk de necessitas est disponible en anglais et est mise à jour sur le wiki officiel du projet: ici.
Elle explique étape par étape comment installer le sdk et comment l’utiliser pour créer une première application. Il ne fait pas sens de la traduire en français (l’ayant moi-même écrite en anglais) car elle est d’une part encore très vivante et d’autre part du fait de sa légèreté il n’est pas nécessaire de comprendre la langue de shakespeare pour la lire. L’installation et la configuration, téléchargement compris est possible en 5 minutes.

Contribuer

Le projet est Open Source et c’est pourquoi je vous invite à y contribuer. En effet il vous est maintenant possible à l’aide de Necessitas d’installer en trois clics le Sdk pour développer des applications Qt sur Android. Les lignes à suivre pour la contribution sont disponibles sur le wiki du projet.
Une liste des tâches est disponible ici ainsi qu’au travers des gestionnaires de tickets du projet sur google code et sur sourceforge.

Conclusion

Afin d’augmenter mes contributions auprès de Freelan et de Necessitas, je me lance dans la réalisation d’un prototype de freelan pour Android. Cela inclus le portage pour Android de la fameuse libsystools. Je pense que l’apport de libsystools sur Android sera intéressant et surtout cela permettra d’avoir freelan: un vpn décentralisé facilement & simplement au bout des doigts. J’ai hâte de vous tenir au courant de l’avancement de ce petit projet. ;)

Développer avec Qt pour Android

C’est possible ?

Dans ce petit article je vais vous parler du développement Android avec Qt et en C++, en effet, j’ai travaillé dernièrement dans une entreprise d’automatisation et de régulation des bâtiments où un des développeurs était en charge d’un projet d’application Android. La qualité de ses développements m’a donné envie de tenter l’aventure. Malgré la magnifique API de Java pour android je voulais pouvoir déployer pour Windows, Linux, Mac, Symbian et Android la même application. Mon choix se portait donc sur mon framework préféré : Qt et naturellement mon langage préféré. Je ne serai jamais assez redevant à Bjarne Stroustrup =D.

Développer des applications basées sur Qt pour android est possible via le projet android-lighthouse, qui fonctionne très bien ! En effet ce dernier rend possible l’exécution d’une application C++/Qt complète ou encore l’utilisation en Java des libraires écrites avec le framework.

Qt Quick UI - BogDan Vatra

Lighthouse

Quant à lighthouse c’est un projet que l’équipe du Framework Qt a lancé avant la version 4.7 pour rendre le framework Qt portable à n’importe quelle plateforme facilement. En effet cela requiert très peu de code spécifique à la plateforme afin de faire fonctionner toutes les librairies Qt.

Depuis quelques semaines lighthouse est passé dans la branche stable de Qt. Grâce à android-lighthouse on peut d’ailleurs voir que le portage des bibliothèques est très rapide. Seulement quelques mois ont été nécessaires pour obtenir une version pleinement (ou presque) fonctionnelle: même les interfaces basées sur le QML fonctionnent! C’est grâce à BogDan Vatra, initiateur du projet, que le port de Qt pour android en est arrivé à cette maturité qui démontre ainsi que Qt peut être porté n’importe où: Code less, do more, deploy everywhere!

Awesome!

Cela rend le portage d’applications Qt sur Android très simple, écrire une application avec le framework Qt signifie que l’on peut désormais la compiler sans effort pour : Symbian, Windows, Mac, Linux & Android ! :) C’est à mon sens parfait pour construire une base de librairies réutilisables dans une entreprise. Dans cette idée il est également possible de développer des bibliothèques basées sur les fonctionnalités de Qt et de les lier avec JNI afin d’apporter des fonctionnalités natives aux applications Java Android existantes.

Je vous présenterai dans cet article les différentes versions d’Android supportées, les quelques limitations et clarifications nécessaires, ainsi que les procédures à suivre afin de compiler pour et lancer sur Android votre application Qt.

Les versions d’Android compatibles

Lorsque le projet Qt android-lighthouse a été créé, seuls les périphériques Android 1.5 étaient supportés avec Qt lié en statique, ce qui n’est plus le cas aujourd’hui. En effet la branche actuelle du dépôt supporte seulement Qt lié dynamiquement (cela réduit l’utilisation de la mémoire – James Noble & Charles Weir 2001 – Small Memory Software, puisque chacune des applications partagent les mêmes bibliothèques Qt). Cette dernière supporte aujourd’hui les versions d’Android actuelles du marché: 1.6, 2.0, 2.1 et 2.2. N’hésitez pas à essayer avec l’émulateur Android car il fonctionne comme les véritables périphériques, plus d’un développeur Android m’en a confirmé ses qualités. :)

Quelques Limitations

Il y a actuellement (25/11/2010) quelques limitations, par exemple le rendu est réalisé uniquement par le software, les accélérations matérielles Open GL ne sont pas utilisées. Toutefois ce n’est certainement qu’une question de jours, car jusqu’aujourd’hui le portage de Qt sur Android a été très rapide et est toujours aussi actif.

Une autre limitation qui sera bientôt fixée d’après les initiateurs du projet est que l’on ne peut utiliser QtMultimedia pour jouer des sons, il y a d’autres solutions pour y parvenir, toutefois le port de QtMultimedia sera bientôt fait, et d’après l’initiateur du projet cela devrait être “le correctif le plus facile” qu’il lui reste à faire.

Quelques Clarifications

Vous n’avez pas besoin d’être “root” ou d’avoir accès au shell root sur votre périphérique pour déployer des applications Qt, cela signifie que vous pourriez envoyer l’application sur le Google Market. Toutefois actuellement il est plutôt déconseillé de le faire, il vaudrait mieux attendre que cela soit plus testé et utilisé (ce que fait actuellement une communauté grandissante: http://groups.google.com/group/android-qt/).

Préparez votre environnement de développement

J’ai écrit les instructions suivantes en m’inspirant de la page http://code.google.com/p/android-lighthouse/wiki/Compile et de ma propre expérience sur Linux 32 bits. Si vous êtes sur Windows vous devriez jeter un oeil au problème suivant: Configure does not work with Cygwin on winxp et appliquer le patch pour cygwin qui est proposé dans l’une des réponses. Enfin si vous êtes sur Mac OS X vous devriez simplement oublier pour le moment (ou bien trouver une solution :p): broken build on mac osx – x86.

Linux semble être la meilleure plateforme pour développer avec Qt pour android actuellement, donc si vous n’utilisez pas cette plateforme, je vous conseille d’essayer avec une Machine Virtuelle, du moins c’est la solution dont je peux vous en assurer le fonctionnement. :)

Actuellement quelques éléments dits sur la page officielle traitant de la compilation de Qt et d’applications Qt pour android ne sont pas vraies, c’est pourquoi je vais vous guider dans la bonne direction pour faire fonctionner votre application Qt sur android, tel que Francisco Dalla Rosa Soares m’a montré cette semaine sur la mailing list d’android-lighthouse. Sans lui je n’aurai jamais pu lancer quoi que ce soit, si ce n’est mon pc portable…

Téléchargement

Avant tout il vous faut télécharger et décompresser QADK, qui est un Kit de Développement natif non officiel pour android, basé sur l’officiel mais avec quelques bibliothèques non supportées en plus:

Après cela il vous faudra cloner le repository git de android-lighthouse qui lui même consiste en un clone du projet Qt lighthouse qui est officiellement fourni par Nokia:

Configurer & Compiler

Vous devrez compiler Qt pour la plateforme visée, il est nécessaire de définir la variable ANDROID_PLATFORM et de faire pointer NDK_ROOT vers le dossier où vous avez décompressé QADK.

La dernière ligne est présente pour cibler les plateformes android 2.0 & 2.1, ce qui fonctionna sans problèmes pour ma part. Utilisez android-4 afin de cibler les plateformes 1.6 et android-8 pour cibler les plateformes 2.2.

Vous pouvez désormais lancer la partie de configuration (n’hésitez pas à aller voir votre petite amie pendant ce temps):

Et enfin vous pouvez compiler le tout:

Changez 3 par le nombre de coeur de votre processeur + un, cela activera la compilation parallèle avec autant de processus.

Il y a une dépendance de Qt qui n’est pas incluse au projet, c’est libcloog-ppl-dev, lancez simplement:

Pour ce que j’ai pu comprendre c’est une librarie utilisée pour l’optimisation de code, qui est destinée à générer du code permettant de passer sur chacun des points d’un Polyèdre. Je suppose que c’est utilisé dans qmake, mais je ne pourrai vous l’assurer. Plus de détails et un exemple sur le site officiel.

Installez Qt sur le Périphérique

Maintenant ce serait sympa d’avoir Qt sur le périphérique Android (ou dans l’émulateur), pour ce faire faites simplement ce que la page de wiki de google code conseille:

Connectez votre Périphérique

Si vous recevez l’erreur adb: command not found, c’est parce que vous êtes nouveau au développement Android (tout comme moi). Vous devez simplement télécharger le dernier sdk d’Android, vous pouvez trouver les instructions détaillées ici et le sdk ici.

Cependant à cette étape de l’article vous avez simplement besoin de télécharger le SDK, de définir le PATH et d’éxécuter:

Ensuite si vous voulez essayer sur votre véritable téléphone vous devrez activer la connexion avec ce dernier, pour y parvenir je vous invite à suivre la petite partie décrite sur le site d’android.

Je suis sur Linux, donc j’ai simplement mis en place la configuration suivante pour mon téléphone LGGT540 sur android 2.1. Sur mon pc avec Ubuntu 10.10 j’ai défini les informations suivantes dans le fichier /etc/udev/rules.d/51-android.rules:
Les fichiers présents dans /etc/udev/rules.d/ sont destinés à définir des règles persistantes pour les périphériques, dont l’une est de changer le CHMOD d’accès à un périphérique, en fonction d’éléments permettant de l’identifier.

Où 1004 vient d’une liste fournie de Vendor Ids pour les périphériques android: http://developer.android.com/guide/developing/device.html#VendorIds/. Prenez celui qui convient. :)

Sur Windows il vous faudra simplement installer les pilotes adb, et sur Mac OS X cela fonctionne sans rien faire, toutefois rappelez vous que android-lighthouse pour Mac OS X ne semble pas fonctionner.

Pour lister les périphériques Android existants vous pouvez lancer: adb devices.

Votre première Application Qt pour Android

Nous n’allons pas écrire notre propre code (oui je sais c’est triste), parce qu’il y a beaucoup de Hello World-like dans les demos du Qt Sdk. Nous allons donc choisir un très simple, afin d’expliquer les choses qui nous intéressent: la configuration de la compilation et comment créer un projet java afin de lancer l’application.

En effet contrairement aux dires du site officiel il n’est pas possible actuellement de compiler directement l’application en temps qu’exécutable natif. Il est nécessaire de la compiler en une bibliothèque dynamique, que l’on chargera à l’aide d’un petit launcher java basé sur les classes fournies par android-lighthouse. Ces dernières sont présentes dans le package com.nokia.qt.QtActivity.

Maintenant allez dans le répertoire /android-lighthouse/demos/mainwindow/, ici vous pouvez ouvrir le fichier mainwindow.pro, qui devrait contenir les configurations suivantes:

Il est réellement important de compiler l’application en tant que bibliothèque dynamique, ainsi pour vos prochaines applications n’oubliez pas d’utiliser les deux premières lignes données ci-dessus. Personnellement j’ai une préférence pour CMake, mais je n’ai pas encore pu préparer de configuration pour android pour le moment, et pourtant cela devrait seulement consister à éditer la méthode qt4_wrap_cpp pour lui donner la version android-lightouse spécialisée de qmake.

En effet pour compiler l’application, il faut utilisez android-lighthouse/bin/qmake afin de générer les fichiers de moc et le Makefile, et non pas la version de qmake que vous avez dans votre PATH.

Voilà, vous ne devez même pas adapter le code de votre application Qt. Le résultat des commandes que vous avez lancées devrait être un fichier so (shared object) avec différents liens symboliques afin de rendre possible la compatibilité entre versions apportée par libtool.

Envoyez simplement celle sans informations de compatibilité de versions sur votre périphérique android: adb push libmainwindow.so /data/local/qt/lib. Une fois que vous avez fait cela, l’application est sur le téléphone, mais rien n’existe pour la lancer.

Créez le Projet Android

Nous allons ainsi créer un launcher en java, basé sur le launcher fourni par le projet android-lighthouse, qui s’occupe tout seul des bindings JNI nécessaires. :D

Tout d’abord créez un projet dans un sous-dossier (javaLoader par exemple)

Créez une classe QtMain.java (vim seul ou avec eclim est un bon outil pour cela):

Et ensuite tapez simplement:

Votre application est installée, et peut facilement être lancée sur votre périphérique à l’aide de:

À propos du débogage

Pour le moment je n’ai hélas pas réussi à déboguer l’application sur le périphérique, mais les sorties consoles sont redirigées, il est donc tout de même possible d’utiliser qDebug pour faire le débogage. Ce n’est pas optimal mais ce n’est qu’en attendant de trouver un moyen simple. Je pense néanmoins que l’outil qadk-r4/ndk-gdb peut rendre le débogage possible, je n’ai pas réussi cependant à faire quoi que ce soit pour l’instant à ce sujet. Je posterai dès que j’y parviendrai. ;)

Qt Creator

Apparemment l’intégration d’Android pour Qt Creator est très avancée mais pas encore dans le dépôtd’après un mail de Tero Savolainen arrivé au moment de poster l’article, sur la liste de diffusion nommé “Re: Qt porting status and some great news” l’intégration de Qt Creator avec Androïd est faite et le débogage est la prochaine fonctionnalité à venir.

Conclusion

Comme vous avez pu le voir il devient très simple de développer nativement pour Android, le projet étant très actif, il y a fort à parier que pour fin décembre les limitations citées devraient avoir disparues et que le débogage soit possible.

Merci beaucoup pour votre lecture, je suis ouvert à toutes vos suggestions et remarques concernant cet l’article. ;)