Comment tester la librairie C++ libwebrtc ?

I. Introduction

Compiler une bibliothèque est relativement facile, mais vous ne savez pas s’il y a des bugs tant que vous ne la liez pas avec un exécutable et que vous n’avez pas exécuté cet exécutable (link, run).

Bien que la compilation de libwebrtc (et libjingle) soient devenues relativement faciles grâce à depot_tools, tester libwebrtc est un vrai problème. Comme les commits sont appliqués, testés et potentiellement retires dans le système de Google, il n’est pas possible d’être certain que la dernière révision (HEAD) soit stable a un moment donne.

En utilisant branch_heads il est possible de compiler et de tester les versions correspondant à une version publiée de Chrome. Cependant, tester des versions plus récentes de libwebrtc / libjingle, comme celles utilisées dans Canary, est quelque chose que l’on voudrait pouvoir faire afin d’être prêt lorsque ces versions entreront en production, mais c’est très difficile. Ce post va aborder deux points : le système de tests de Google (pour les curieux) et la manière d’atteindre le même niveau de test que Google avec quelques lignes de code CMake.

II. Je veux ma propre cascade de test!

La page officielle décrit comment voir les tests en cours d’exécution, ou comment en ajouter de nouveaux, mais pas comment faire pour les démarrer ou les lancer localement. Ce n’est pas que vous ne pouvez pas le faire, c’est juste que c’est assez compliqué de lancer les tests localement et que cela demande une machinerie assez importante. Ce que l’on voudrait vraiment être capable de faire, ce serait d’avoir, au minimum, la capacité de tester localement les résultats de la compilation avant de l’installer ou d’en faire un package (plus sur cela dans un prochain post). Dans le meilleur des cas, on souhaiterait disposer de l’équivalent d’une cascade qui pourrait être lancée à la demande. Tout d’abord, pour les pressés, il n’y a quasiment aucun moyen de réaliser cela par soi-même car l’infrastructure est la propriété de Google et nécessite que vous ayez un compte committer soit pour WebRTC soit pour Chrome. Je ne sais pas si c’est possible, je peux seulement dire que je ne connais personne dans l’écosystème (à l’exception d’un employé de chez Intel) qui bénéficie de ce privilège. Pour les curieux ou ceux qui ont le temps, lisez la suite pour savoir ce que vous pouvez faire pour obtenir le plus proche équivalent.

1. Les infos manquantes pour tester libwebrtc

Cette partie traitera de toutes les infos manquantes dans la page webrtc.org (mais diffusées sur les différentes pages wiki de Chromium) pour vraiment mettre en place les tests à la façon de Google.

Le système utilisé par Google pour le développement de Chromium est super. Honnêtement, il a beaucoup de sens et beaucoup d’efforts ont été déployés pour faire face au grand nombre de développeurs travaillant sur Cromium. La dernière « infra » (comme ils l’appellent) doit pouvoir traiter plus de 200 commits par jour sans interruption, et il semble qu’elle fasse du bon travail. Ceci étant dit, c’est assez démesuré pour quelqu’un qui voudrait seulement travailler sur libwebrtc et il est malheureux que même de petites équipes soient obligées soit d’utiliser ce mastodonte soit de faire l’impasse sur les tests.

La partie d’origine des tests de l’infra est constituée de plusieurs éléments : Gtest pour écrire les tests unitaires, les outils habituels pour intégrer Gtest au processus de construction (gyp, DEPS…), buildbot pour … eh bien, les bots de compilation et une nouvelle infrastructure d’essaimage spéciale (ici et ) couplée avec des tests isolés (ici et ). Je ne vais pas aborder ici GTest, gyp ou DEPS, mais traiter de ce qui doit être mis en place pour pouvoir effectuer les tests après une compilation réussie de libwebrtc. Plus précisément, je vais traiter uniquement des tests concernant libwebrtc en tant que bibliothèque indépendante et non ceux portant sur webrtc-in-chromium et autres tests intégrés (*ces tests sont en effet assez différents, tout spécialement ceux concernant le rendu, le partage d’écran, etc., aussi nous devons y aller pas à pas). Finalement, je vais compiler uniquement la bibliothèque de webrtc.org et non la version Gecko/Firefox (ici aussi, c’est assez différent, j’aime le partage d’écran sous Firefox et leur intégration de H.264, mais encore une fois nous devons y aller étape par étape).

Le lien ci-dessous vous indique pas à pas tout ce dont vous aurez besoin pour configurer en local vos propres buildbot (avec esclaves), trybot et autres.  Notez bien que les liens que je mentionne vers les dépôts pourront être obsolètes quand vous lirez ce post (cible en mouvement RAPIDE…) et vous pourriez vouloir lire le code dans la partie « infra » de depot_tools pour connaître la dernière façon de faire les choses (sic), et plus spécifiquement, le contenu du répertoire /build qui peut être directement extrait de https://chromium.googlesource.com/chromium/tools/build.git . Les dossiers qui configurent les cascades de libwebrtc version autonome se trouvent dans master.client.webrtc . Chaque colonne de la cascade correspond à un buildbot (esclave) dont les informations se trouvent aussi dans le même dossier.

pour en savoir plus
  • https://www.chromium.org/developers/testing/chromium-build-infrastructure

2. Test isolé, c’est quoi ca ?

Après la compilation de libwebrtc vous trouverez votre dossier de compilation (/src/out/<CONFIG> par défaut, <CONFIG> étant soit Debug soit Release) assez encombré.  Parmi tous ces fichiers, vous allez voir quelques exécutables dont le nom contient « isolated » ou « isolated.state ». Ces fichiers sont utilisés par le système d’essaimage pour distribuer les tests (ici et ). Dans notre cas, l’information importante est qu’ils contiennent la liste des fichiers dont vous avez besoin comme arguments pour lancer les tests. Ce sont toujours des travaux en cours, mais ils sont d’ores et déjà assez stables pour pouvoir être utilisés. Il y a 22 tests semblables qui sont listés. Maintenant, si vous regardez la cascade, vous verrez qu’en gros il y a deux types de buildbots, les normaux qui lancent toutes les tests unitaires et les « Large » qui lancent les tests de performances et les longs tests tels que [vie|voe]_auto_test, video_capture_tests et audio_device_tests. Ceux-ci prennent assez de temps à s’exécuter et sont beaucoup plus longs que les autres tests, ce qui justifie de les lancer séparément sur des instances plus costaudes. Tous les tests doivent êtres lancés avec l’argument suplémentaire -test-launcher-bot-mode. Pour être exhaustif, j’ajouterais que vie_ et voe_auto_test sont des exécutables interactifs très puissants qui méritent un post rien que pour eux. J’encourage tout le monde à les utiliser et à regarder leur code source. Quelle source d’inspiration ! Pour être lancés comme des tests vous devez leur ajouter l’argument supplémentaire -automated.

3. Alors, comment faire pour lancer ces tests facilement avec CMake ?

CMake fait partie d’une trilogie (eh oui, encore une), la trilogie CMake/CTest/CDash. CMake est l’outil principal de configuration et de coompilation, CTest est votre principal outil de test et de gestion de gestion de tests, et c’est aussi un client pour CDash, l’équivalent de la cascade, c’est-à-dire un tableau de bord interactif qui interagit avec les résultats envoyés par CTest de vos compilations et des tests. L’avantage c’est que tout est intégré.

NOTE : la meilleure façon de faire serait d’analyser les fichiers isolés et d’en extraire la ligne de commande exacte ainsi que les fichiers de sortie. Dans notre cas, pour simplifier et gagner du temps, nous allons ajouter manuellement les 22 tests un par un et nous ignoreront leur sortie si le test a réussi. On peut améliorer cette méthode, mais elle vous fournira néanmoins 99% de ce que vous souhaitez obtenir en 30 minutes de travail…

Pour activer le module des tests dans CMake vous devez seulement ajouter au script CMake les deux lignes de code suivantes :

  1. enable_testing()
  2. include(CTest)

ATTENTION : sans ces deux lignes, le reste du code ne plantera pas ni ne soulèvera aucune erreur, mais aucun test ne sera généré.

Pour chaque test que vous souhaitez ajouter, vous pouvez utiliser la commande add_test() . Ci-dessous, un exemple qui supporte Windows et Mac pour ajouter un test normal, tout en vérifiant que le nom passé en argument correspond à un fichier existant (rappelez vous : cible en mouvement RAPIDE…):

  1. set( my_test_binary_name « common_audio_unittests »)
  2. set( my_test_binary ${my_test_binary_name) )
  3. if( WIN32 )
  4.     set( my_test_binary ${my_test_binary} exe )
  5. endif()
  6. if( EXISTS ${MY_BUILD_DIR}/${my_test_binary )
  7. add_test(
  8.     NAME                                  imp_${my_test_binary_name}
  9.     COMMAND                        ${my_test_binary} –test-launcher-bot-mode
  10.     WORKING_DIRECTORY ${MY_BUILD_DIR}
  11. )
  12. else()
  13.     message( WARNING « ${my_test_binary} – NOT FOUND. »)
  14. endif()

Vous pouvez recommencer pour d’autres exemples. Le code final peut être consulté ici (et la macro add_webrtc_test est définie ici).

Quand la compilation du projet est terminée, vous pouvez vérifier quels tests ont été ajoutés en lançant cette commande dans le répertoire de compilation : « ctest -N« . Cela donnera la liste des tests sans les lancer. Les commandes « ctest » ou « make test » (sous Mac/Linux) sont équivalentes et lancent tous les tests l’un après l’autre. Pour libwebrtc, il est préférable de ne pas utiliser l’option -jX pour lancer les tests en parallèle car ils accèdent au matériel et peuvent interférer les uns avec les autres. Pour être sûr que personne ne commette cette erreur, vous pouvez ajouter une dépendance entre chaque test et son prédécesseur dans la liste. Nous n’avons pas mis ça en place (même si ça ne représente qu’une seule ligne). Si vous souhaitez voir la sortie des tests sur votre écran, vous pouvez ajouter -V à la ligne de commande. Et voilà, vous pouvez tester la bibliothèque de façon aussi complète que les tests de Google le feraient (enfin presque, il manque la détection des fuites mémoire et autres conflits de threads, mais c’est déjà bien d’avoir les tests. L’ajout des contrôles de fuites mémoire et des calculs de couverture seront expliqués dans un prochain post). Maintenant nous pouvons faire la fête comme si on était en 1999, ou pas ?

NOTE : webrtc_perf_test a besoin d’un accès réseau, de même pour voe_auto_test, ainsi si vous testez sous Windows, il vous faudra soit configurer votre pare-feu pour l’autoriser, manuellement, en cliquant N fois sur autoriser quand vous y êtes invités, soit passer ce test si vous voulez lancer la suite de tests.

4. Ok, je peux lancer tous les tests localement mais je n’ai toujours pas ma cascade !

À ce stade vous en avez assez pour construire et tester la sortie sur une seule machine. C’est une bonne base pour préparer un package de la bibliothèque, un sujet que nous aborderons dans un prochain post. Toutefois vous n’avez aucune visibilité sur le résultat de la compilation de la même base de code sur différents systèmes et compilateurs, avec différentes options de compilateurs, et vous n’avez pas non plus de beau visuel en ligne sur votre tableau de bord.

C’est ici que CDash devient très utile. CDash est le composant serveur de la cascade et CTest peut être très facilement configuré pour envoyer les résultats de la compilation et des tests à un serveur CDash. KitWare, l’une des principales compagnies derrière cmake/ctest/cdash et le lieu de travail des ingénieurs les plus impressionnant avec qui j’ai pu travailler dans ma vie, propose un hébergement gratuit pour les projets open source et des options d’hébergements à un prix très raisonnable. Bien sûr, le code est gratuit et open source et vous pouvez installer votre propre serveur CDash en interne si vous préférez. J’ai choisi d’avoir mon propre petit compte et voici le contenu très simple du fichier CTestConfig.cmake que vous devez ABSOLUMENT garder dans la racine du code source.

  1. set(CTEST_PROJECT_NAME « libwebRTC »)                               # c’est relié a un projet que vous devez avoir préalablement créé sur le serveur.
  2. set(CTEST_NIGHTLY_START_TIME « 00:00:00 EST »)             # L’heure que vous voulez, en général une heure où l’ordinateur n’est pas utilisé.
  3. set(CTEST_DROP_METHOD « http »)
  4. set(CTEST_DROP_SITE « my.cdash.org »)                                  # Cela peut changer en fonction de l’installation de votre serveur.
  5. set(CTEST_DROP_LOCATION « /submit.php?project=libwebRTC »)
  6. set(CTEST_DROP_SITE_CDASH TRUE)

Depuis un répertoire vide (recommandé) vous pouvez lancer ctest -D Experimental pour configurer, compiler, lancer les tests (optionnellement vérifier les fuites mémoire, calculer la couverture…) et envoyer les résultats au tableau de bord. Pour cet exemple, voici à quoi ressemble le tableau de bord (Mac). Vous pouvez aussi voir apparaître las compilations Windows et Linux. Puisque CMake est multi-plateformes il fonctionne effectivement tel quel (sauf pour des détails de ligne de commande et des différences d’extensions) sur toutes les plateformes. Ici chaque ligne est esclave, par opposition à la cascade où c’est une colonne qui est esclave, et vous pouvez cliquer sur le résultat de chaque étape (configuration, compilation, test) pour récupérer les résultats tels qu’ils auraient étés affichés sur l’écran, vous donnant approximativement les mêmes fonctionnalités que le buildbot de la cascade. Éventuellement pour un projet plus mûr cela ressemblerait à ça.

CTest a également la capacité de télécharger des fichiers séparément. Dans un prochain post, j’expliquerais comment l’utiliser pour envoyer automatiquement vers un dépôt public une version compilée de la bibliothèque ou une version package de ces bibliothèques si et seulement si tous les tests ont réussi. Ainsi les développeurs peuvent faire confiance en toute bibliothèque ou paquet mis à disposition, sans avoir à les recompiler et les retester (choisissez vous même votre danse de la victoire).

Lectures suggérées

  • https://www.cmake.org/Wiki/CMake/Testing_With_CTest
  • https://www.cmake.org/Wiki/CMake_Scripting_Of_CTest (niveau avancé : comment mettre en place des instances de construction automatiques.)

III. Conclusion

Le système de Google est certainement plus évolutif que celui présenté ici. Il permet ainsi de déclencher automatiquement des compilations afin de valider des commits, ce qui est top. Alors que CMake/CTest/CDash a été amélioré au cours des 5 dernières années pour faire cela, c’est toujours une fonctionnalité difficile à déployer (POUR AUTANT QUE JE SACHE, je ne suis pas forcément à jour avec les dernières évolutions de CMake). Dans le cas d’un très gros projet (plus de 200 commits par jour …) avec seulement un petit nombre de compagnies impliquées, c’est top.

Ce qui est génial avec le système C^3, c’est que n’importe qui peut bénévolement mettre en place un hôte de compilation et contribuer au journal de bord. Vous avez une configuration inhabituelle (version initiale non publique d’un compilateur, vieille version d’un compilateur [BorlandCC 5.6]…) que personne ne peut tester, vous pouvez néanmoins toujours compiler et rapporter les erreurs pour que les développeurs les voient. Rapporter des erreurs est aussi simple que « ctest -D Experimental ». Si vous configurez votre ordinateur pour être un hôte de compilation nocturne, les développeurs peuvent modifier le code et vérifier si le résultat résout le problème sans avoir accès à votre machine (oui, vous pouvez diriger le bot vers une branche git, afin de ne pas polluer la branche de développement principale ou la branche master pendant le processus d’essais et d’erreurs). Donc, pour les projets plus simples, avec beaucoup de petites équipes qui contribuent (comme une communauté open source autour d’une bibliothèque…), c’est top. La barrière d’entrée est basse, tout en proposant un système assez puissant. Ce mécanisme est disponible depuis des années, et il a été utilisé dans de multiples projets, il est donc facile de trouver des gens qui ont la connaissance des outils (qui utilise depot-tools en dehors des membres du projet chromium ?). Il dispose également une grande base de code dont les gens peuvent s’inspirer. Et il prend en charge ninja…

Ici, en quelques heures, nous avons été capable d’apprendre à tester libwebrtc localement à un niveau équivalent à celui de Google, et à faire un rapport à un tableau de bord hébergé pouvant être partagé. Dans les posts suivants, nous verrons comment ajouter une analyse des fuites mémoire, un calcul de couverture de code (compiler c’est un bon départ, tester c’est mieux, mais quel pourcentage du code testons-nous exactement ?), comment créer des paquets qui permettront d’installer libwebrtc sur des ordinateurs, et comment importer automatiquement une version installée dans des projets utilisant CMake pour configurer leur compilation.

Automatiser la construction de libwebrtc avec CMake.

I. Introduction

Libwebrtc est la base de nombreux produits. C’est, bien sûr, la base de l’implémentation de l’API JavaScript du même nom dans Chrome, Firefox et Opera, mais c’est aussi la base de beaucoup de SDKs et autres produits sur mobiles. Conserver une version de libwebrtc à jour, et testée sur un code de base stable, est, comme chacun le sait, difficile si vous n’êtes pas un employé de chez Google. Ce post est le premier d’une série qui explique pas à pas comment mettre en place un système capable de compiler, tester et générer un installteur de libwebrtc automatiquement sur de nombreuses plateformes. Il fait suite à un précédent post qui expliquait comment fonctionne le système de compilation de Google (depot tools), et va plus se concentrer sur la partie automatisation grâce à CMake.

II. Il existe déjà (quelques) très bonnes ressources

Il n’existe pas de « meilleure solution » pour compiler des bibliothèques. Du moment qu’elles sont compilées, testées et intégrées automatiquement, le boulot est fait. Pour le mobile spécifiquement, les scripts développés par Pristine (voir ci-dessous) font un bon boulot. J’avoue avoir un avis biaisé vis-à-vis de CMake puisque c’est le moteur de production multi-plateformes avec lequel j’ai travaillé pendant la plus grande partie de la dernière décennie, mais il y a de très bonnes raisons qui expliquent pourquoi j’ai continué à utiliser CMake pendant si longtemps. Ainsi, ne pas avoir à gérer les différences de compilateurs est un vrai bonheur. De même, ne pas avoir à se préoccuper des différences de systèmes d’exploitation est tout autant une source de joie. Ajoutez à cela être capable d’ajouter un test à la volée avec une simple commande qui à son tour permettra l’envoi du résultat du test vers le tableau de bord, ce qui est une immense joie. Mais ce n’est pas tout, sachez que Valgrind est supporté par défaut, ce qui est ÉNORME. Enfin, même la génération d’un installeur est facilitée (et oui, tout ce que je viens de lister est multi-plateformes).

Avec cette série de posts, vous serez capable en quelques jours seulement d’implémenter un système très performant assurant à la fois la compilation, les tests et la production d’un installeur pour libwebrtc, alors que ça pourrait facilement vous prendre beaucoup plus de temps (d’après mon expérience).

Bien sûr, si vous disposez déjà d’une infrastructure de tests et d’une solution d’intégration continue, elles ne seront probablement pas très compatibles avec CMake. Mais il est souvent plus efficace de séparer la compilation de libwebrtc de la solution que vous construisez autour de libwebrtc, qu’il s’agisse d’un plugin WebRTC, d’un wrapper Apache Cordova (voir ci-dessous) ou d’un SDK mobile.

Pour approfondir:

III. Comment utiliser CMake au mieux

CMake est un gestionnaire de configuration multi-plateformes multi-compilateurs, parfois appelé système de méta-construction. Sa fonctionnalité principale est de trouver pour vous, sur l’ordinateur hôte, les bibliothèques et les programmes dont vous avez besoin pour votre compilation, et de préparer la génération les cibles (fichiers exécutables, bibliothèques, tests…), quel que soit votre système d’exploitation et votre compilateur.

Au strict minimum, vous pouvez utiliser CMake comme n’importe quel autre langage de script et essayer d’encapsuler le système de génération de libwebrtc dans des appels système. La commande « execute_process » sert à celà. Cette façon de procéder a le désavantage de tout faire au moment de la configuration, et ce de façon linéaire. À chaque fois que vous ferez appel à ce type de script, toutes les commandes seront relancées. Il est préférable de définir les cibles et les dépendances au moment de la configuration (c’est-à-dire la seule fois où vous lancerez directement cmake) et ensuite d’utiliser le compilateur natif pour s’occuper du reste du travail.

Un usage intégral de cmake consisterait à l’utiliser pour remplacer entièrement le système de génération de libwebrtc et redéfinir toutes les bibliothèques, les fichiers exécutables, les fichiers sources correspondants, les options de compilation, etc. Bien que cela soit faisable pour un seul fichier exécutable, ou une bibliothèque, réaliser cette opération pour tout libwebrtc voudrait dire devoir migrer tous les fichiers gyp[i] et s’assurer qu’on les garde synchrones à chaque mise à jour de libwebrtc. N’importe qui, saint d’esprit, qui s’est penché sur la complexité que représentent les 6000 lignes du fichier src/build/common.gypi, n’a aucune envie de s’attaquer à ce genre de tâche.

Dans ce post, nous allons utiliser l’approche: dite de « super build » qui consiste à laisser cmake piloter le système de compilation de Google, importer et lancer les tests, ajouter un support de couverture de code, générer les installeurs et ainsi de suite. Ainsi, nous utiliserons le système de compilation de Google tel quel pour les actions de base, et nous réserverons l’ussge de CMake pour les tâches où il est le meilleur.

IV. C’est parti !

1. Un nouveau module CMake pour détecter depot tools.

CMake dispose d’une collection de modules lui permettant de détecter et d’utiliser vos bibliothèques habituelles plus facilement. Ce mécanisme est multi-plateformes. La plupart de ces modules consistent en du code CMake placé dans un fichier appelé FindXXX.cmake. Vous pouvez appeler ce module en invoquant « find_package( XXX ) ». S’il s’agit d’un paquet obligatoire, vous pouvez demander à find_package de se terminer immédiatement en erreur en ajoutant l’argument REQUIRED, Par exemple, CMake est livré avec un FindGit.cmake pré-installé que nous pouvons utiliser dans notre code en écrivant simplement ceci:

  1. find_package(Git REQUIRED)

Actuellement, depot tools nest pas reconnu par CMake. Toutefois, il existe un mécanisme permettant aux projets CMake d’augmenter les capacités de CMake. Vous pouvez écrire vos propres modules FindXXXXX.cmake et permettre à CMake de les trouver en définissant dans votre code la variable CMAKE_MODULE_PATH . Faites bien attention d’étendre et non pas d’écraser cette variable, dans le cas où votre code serait appelé depuis un autre code CMake (style super génération). Dans notre cas, nous mettons les scripts dans un répertoire « CMake » juste sous le répertoire racine du projet CMake.

  1. set( CMAKE_MODULE_PATH
  2. ${CMAKE_MODULE_PATH} # pour intégration en super construction
  3. ${CMAKE_CURRENT_SOURCE_DIR}/Cmake
  4. )

Le code complet est disponible ici.

Il nous reste encore à écrire le code de FindDepotTools.cmake. CMake fournit toutes les primitives pour cela. Dans notre cas, il suffit seulement de trouver la commande gclient. Tout le reste est pris en charge par CMake pour nous, y compris les différences de système d’exploitation et de chemins.

  1. find_program(DEPOTTOOLS_GCLIENT_EXECUTABLE
  2. NAMES gclient gclient.bat   # indices à propos du nom de l’exécutable. gclient.bat est la version Windows
  3. )
  4. #  En-dessous de cette ligne on trouve le code standard de CMake pour que tous les paquets gèrent les options QUIET, REQUIRED…
  5. include(${CMAKE_ROOT}/Modules/FindPackageHandleStandardARGS.cmake)
  6. find_package_handle_standard_args(DepotTools
  7. REQUIRED_VARS DEPOTTOOLS_GCLIENT_EXECUTABLE
  8. FAIL_MESSAGE »could not find the gclient executable »
  9. )

Maintenant, le cœur du script principal est relativement facile à écrire.

  1. project(webrtc)
  2. set(CMAKE_MODULE_PATH
  3. ${CMAKE_MODULE_PATH}  # pour une intégration dans une super génération.
  4. ${CMAKE_CURRENT_SOURCE_DIR}/Cmake
  5. )
  6. find_package(depottools REQUIRED)
  7. find_package(Git                REQUIRED)

Le code complet est disponible ici.

2. Implémenter « gclient config » comme une commande et une cible personnalisées de CMake.

Maintenant nous voulons lancer la ligne de commande « gclient config » depuis CMake. Cette ligne de commande créera un fichier .gclient qui ne devait pas déjà exister. Si le fichier existe, la commande ne devrait rien faire. De plus, je veux que le système de construction essaye à chaque fois qu’il est lancé. Je veux que ça fonctionne quel que soit le système d’exploitation.

Commençons par définir ce que la commande devrait être d’une manière multi-plateformes.

  1. set( gclient_config
  2. $(DEPOTTOOLS_GCLIENT_EXECUTABLE} config  # gclient a déjà été trouvé automatiquement
  3. –name src
  4. http://chromium.googlesource.com/external/webrtc.git
  5. )
  6. if(WIN32)
  7.     set(gclient_config cmd /c ${gclient_config})  # syntaxe pour le prompt de Windows
  8. endif()

Les premières contraintes surviennent avec le add_custom_command() de CMake. Il permet de créer une commande qui générera un fichier en sortie mais cette commande ne sera pas déclenchée si le fichier existe déjà.

  1. add_custom_command(
  2. OUTPUT ${CMAKE_SOURCE_DIR}/.gclient
  3. COMMAND ${glient_config}
  4. )

Toutefois, rien dans le script ne vous dit quand lancer cette commande personnalisée. C’est là que add_custom_target() entre en scène. Il crée une cible (éventuellement vide) pour le système de génération choisi sur laquelle les commandes pourront s’attacher. Cela permet aussi de définir les dépendances avec d’autres cibles pour définir l’odre de construction/exécution. Dans le cas de la configuration de gclient, il n’y a pas d’étape précédente donc pas de dépendance. En faisant dépendre la cible du fichier généré par la commande vous les liez automatiquement. Le paramètre ALL inclue toujours cette cible dans la génération.

  1. add_custom_target(
  2.      webrtc_configuration ALL
  3.      DEPENDS ${CMAKE_SOURCE_DIR}/.gclient
  4. )

3. Implémenter « gclient sync » et ajouter une dépendance.

Implémenter « gclient sync » est plus ou moins la même chose : définir la commande, ajouter une commande personnalisée, puis ajouter une cible personnalisée. Cependant, cette fois, nous voulons que cette cible s’exécute uniquement APRÈS « gclient config ». Nous devons donc ajouter une dépendance. Le code est auto-explicatif. Notez que nous forçons la commande sync à NE PAS lancer les hooks (option -n).

  1. set(gclient_sync ${DEPOTTOOLS_GCLIENT_EXECUTABLE} sync -n -D -r 88a4298)
  2. if(win32)
  3.    set(gclient_sync cmd /c ${gclient_sync})
  4. endif()
  5. add_custom_command(
  6.    OUTPUT ${CMAKE_SOURCE_DIR}/src/all.gyp
  7.    COMMAND ${gclient_sync}
  8. )
  9. add_custom_target(
  10.    webrtc_synchronization ALL
  11.    DEPENDS ${CMAKE_SOURCE_DIR}/src/all.gyp
  12. )
  13. add_dependencies( webrtc_synchronization webrtc_configuration )

4. Implémenter « gclient runhooks »

Gclient runhooks va produire des fichiers de compilation, donc nous devons être sûr que les paramètres les plus évidents sont définis au préalable. Ninja gère les modes Release et Debug au moment de la compilation, nous n’avons donc pas besoin de nous en soucier pour le moment. Le passage d’une architecture 32 bits à une architecture 64 bits (ou arm pour les mobiles) est géré par des variables d’environnement. CMake a une fonction proxy pour y accéder:

  1. if(DEFINED ENV{GYP_DEFINES})
  2.    message( WARNING « GYP_DEFINES is already set to ENV{GYP_DEFINES} »
  3. else()
  4. if(APPLE)
  5.     set(ENV{GYP_DEFINES} « target_arch=x64 »)
  6. else()
  7.    set(ENV{GYP_DEFINES} « target_arch=ia32 »)
  8. endif()
  9. endif()

Maintenant le reste du code est sensiblement le même qu’avant:

  1. set(gclient_runhooks ${DEPOTTOOLS_GCLIENT_EXECUTABLE}runhooks)
  2. if(WIN32)
  3.  set(gclient_runhooks cmd / c ${gclient_runhooks})
  4. endif()
  5. add_custom_command(
  6.  OUTPUT ${CMAKE_SOURCE_DIR}/src/out  # c’est arbitraire
  7.  COMMAND ${gclient_runhooks}
  8. )
  9. add_custom_target(
  10.   webrtc_runhooks ALL
  11.  DEPENDS ${CMAKE_SOURCE_DIR}/src/out
  12. )
  13. add_dependencies(webrtc_runhooks webrtc_synchronization)

L’intégralité du code pour sync et unhook se trouve ici.

5. Préparer la compilation avec la cible Ninja.

Comme mentionné précédemment, on doit traiter ici les modes Debug / Release. Nous suivons la syntaxe CMake qui, par chance, correspond à la syntaxe Ninja.

  1. if( NOT CMAKE_BUILD_TYPE)       # permet de le mettre dans un « superscript » et de le traiter ici
  2. set(CMAKE_BUILD_TYPE Debug)  # Debug par défaut
  3. endif()

Nous pouvons donc lancer l’habituel.

  1.  set(webrtc_build ninja -v -C ${CMAKE_SOURCE_DIR}/src/out/ ${CMAKE_BUILD_TYPE}
  2.  add_custom_command(
  3.     OUTPUT ${CMAKE_SOURCE_DIR}/src/out/${CMAKE_BUILD_TYPE}/ libwebrtc.a  # c’est arbitraire
  4.     COMMAND ${webrtc_build}
  5. )
  6. add_custom_target(
  7.     webrtc_build ALL
  8.     DEPENDS ${CMAKE_SOURCE_DIR}/src/out/${CMAKE_BUILD_TYPE} /libwebrtc.a
  9. )
  10. add_dependencies(webrtc_build webrtc_runhooks)

6. Enfin nous arrivons à la compilation !

Vous pouvez maintenant lancer cmake une seule fois et ensuite lancer la compilation avec votre compilateur d’origine. Ce code a été testé sur Mac (en utilisant « make ») et Windows (ouvrez webrtc.sln dans MS Visual Studio, et construisez TOUTES les cibles, ou appuyez sur F7).

Le système de compilation de Chromium / Chrome / WebRTC

I. Introduction.

Cet article est une introduction au système de compilation et de gestion du code utilisé par Google dans beaucoup de projets avec une attention particulière sur la compilation de WebRTC. Je ne prétend pas que le contenu soit exhaustif mais cela devrait vous donner une vue d’ensemble sur les étapes à suivre, vous permettant ensuite de creuser plus profond et débuguer plus vite si il y a un problème. Cet article pose aussi les bases pour un article suivant qui traitera de l’automatisation de la compilation. Finalement, vous trouverez ici quelques conseils sur comment modifier le code source vous-même, et re-compiler ensuite. Un article séparée complet sera écrit sur les détails de ce dernier point.

II. depot_tools

« depot_tools » est le nom d’une collection d’outils, utilises via des scripts python, utilisés par l’équipe chrome pour manipuler tout leur processus de développement: gestion des codes sources, tests, infrastructure, etc. Même si pour les étapes simples, comme obtenir le code, tout se résume à des commandes git ou svn, chrome et par extension WebRTC ont une façon dynamique de manipuler les dépendances et les marqueurs de compilation. Il est enfouis dans de multiples fichiers interdépendants (DEPS, gip, gipy, …) et vous devriez *vraiment* éviter de modifier ces fichiers avant d’avoir un besoin spécifique, et de savoir ce que vous faite.

[Mise a Jour] Depuis Decembre 2016, la gestion des projets de compilation est faite via GN et non plus GYP. Les fichiers correspondant sont donc .gn and .gni

Pour approfondir:

  • https://www.chromium.org/developers/how-tos/depottools [OLD]
  • http://commondatastorage.googleapis.com/chrome-infra-docs/flat/depot_tools/docs/html/depottools.html

III. « Fetch » et les recettes (recipes).

Le site officiel (webrtc.org) répertorie les dependences et est une lecture obligatoire avant toute experimentation. Ils recommandent de simplement lancer la ligne de commande « fetch » et de laisser faire. Pour une compilation simple de la dernière version de webrtc cela peut être suffisant mais pour la plupart des utilisations, c’est un peu léger.

Un coup d’oeil au code source de fetch (fetch.py) vous montrera qu’il appelle juste une « recette » (recipe). Les recettes utilisent des valeurs codées en dur comme arguments de commandes internes. Dans le cas de la recette webrtc, la commande fetch va juste écrire ces valeurs dans un fichier .gclient sur le disque, ce qui aura le même résultat qu’un appel à « client config » avec les bons paramètres, puis exécutera l’équivalent d’un appel à « client sync » qui téléchargera le code.

Nous pensons que cela a plus de sens d’appeler explicitement la commande gclient et de garder le contrôle sur ce que nous faisons. Cela permet de rajouter des options, soit pour optimiser soit pour adapter le processus. Par example, pour utiliser une version particulière de webrtc, et non pas la toute dernière.

IV. Configuration gclient et fichier gclient.

Vous pouvez obtenir le même résultat que « fetch » en lançant la ligne de commande suivante:

  1. gclient config -name src https://chromium.googlesource.com /external/webrtc.git

A la base, le code source de webrtc était géré via SVN et webrtc utilisait « trunk » comme nom du repertoire racine. Lors de la migration vers git, le code de libwebrtc c’est rapproche de celui de chrome, et le nom de la racine DOIT être « src » maintenant. Ceci explique la partie « -name src » de la ligne de commande.

Maintenant, si vous regardez le fichier .gclient généré par la recette webrtc de fetch, ou celui généré par la commande ci-dessus vous allez remarquer qu’une ligne manque:

  1. ‘with_branch_heads’: True,

Cette ligne sers a récupérer les informations de synchronisation avec chrome. Ca n’est utile que si vous souhaitez utiliser une version précédente de libwebrtc, synchronisee avec une version de chrome (par example, 57). Malheureusement, cela rajoute 1/2 GB de code a telecharger. La plupart du temps ce n’est pas nécessaire.

Finalement, il y a aussi deux recettes pour iOS et android qui ne font que rajouter une ligne simple au fichier .gclient:

  • « target_os = [ios,mac] »
  • « target_os = [android,unix] »

Cela permet de compiler pour iOS sur un mac, et pour android sur unix (en fait, seulement ubuntu est supporte).

Cela peux parfois valoir la peine d’ajouter la ligne target_os et une ligne de plus: « target_os_only=true » pour réduire la quantité de code a telecharger. Il n’y a aucun paramètre en ligne de commande de gclient pour faire ça (pour le moment), vous devez modifier le fichier .gclient directement vous-même.

Pour plus d’info:

Un fichier .gclient peut effectivement être très complexe comme beaucoup de choses dans webrtc/chrome, beaucoup d’entre elles sont écrites à la main. Le fichier chromium.gclient  code en dur dans le code de WebRTC est un example parfait. Vous pouvez voir que les dépendances personnalisées ont été définies comme un moyen de couper les dépendances originales de chrome. Les développeurs de chrome justifient auprès des développeurs webrtc qui se plaignent du temps que prend de fetch webrtc que cela serait deux fois pire avec webkit activé :-).

Pour ceux qui ont du temps pour optimiser leur version de WebRTC pourraient rechercher ce qu’ils pourraient supprimer pour une construction de production.

[Mise a Jour] – L’équipe de chrome ayant cree des miroirs git pour toutes les dependences, Henrik a enleve la partie chromium et les dependences sont maintenant gérées individuellement et proprement depuis décembre 2016. Cela marque la fin de la migration vers GIT.

V. gclient sync

gclient sync est une commande intéressante avec beaucoup d’options (grep/search pour « CMDsync » dans le fichier client.py). Son rôle principal est d’obtenir le code depuis le lien GIT fourni dans le fichier .gclient, puis d’analyser le fichier DEPS. Si le fichier DEPS contient des commandes additionnelles (hooks), il peut aussi les lancer directement.

Dans notre cas, on préfère séparer les commandes additionelles de la synchronisation. Il y a plusieur raison pour cela, beaucoup d’entre elles seront décrites dans de prochains articles, mais une raison simple est d’être capable d’illustrer combien de temps prend le code webrtc par rapport au temps que prend le code chrome. [Mise a jour] – Obsolete, le code de chrome n’est plus telecharge.

Le résultat de cette analyse de DEPS est le fichier .gclient_entries qui contient des paires de dossiers: une paire contient en premier le nom d’un repertoire local (ici « src ») et le lien GIT original, puis toutes les dépendances. Si vous êtes sous windows, il y aura une dépendance additionnelle à winsdk.

Il y a beaucoup d’options mais nous allons garder les choses simples. Nous allons utiliser -r pour fixer une révision pour que notre construction de production soit plus stable. Nous utiliserons -D pour couper les répertoires qui ne sont plus utilisés. Enfin nous allons utiliser -n pour éviter d’utiliser les commandes additionelles pendant l’étape de synchronisation.

  1. gclient sync -n -D -r 88a4298

La révision marquée ici la signature du commit GIT spécifique avant que l’équipe Google ne change sciemment la gestion des threads, ce qui a casse beaucoup d’implementations exterieures. C’est la réalité du travail avec la dernière version de webrtc, et pourquoi nous allons parler dans d’autres posts de comment tester webrtc une fois compile  avant de l’utiliser en production.

 

VI. gclient runhooks

Les commandes additionnelles (hooks), sont indiquées dans le fichier DEPS.

  • check_root_dir.py    # vérifie juste si vous utilisez « trunk » ou pas pour Rétrocompatibilité.
  • sync_chromium.py # celui que vous allez apprendre à détester. Il faut 40min depuis Mountain View, CA avec 89MB DL.
  • setup_links.py          # regardez ci-dessous.
  • download_from_google_storage   # récupère les fichiers tests.
  • src/webrtc/build/gyp_webrtc.py   #  génère les fichiers de construction – voir ci-dessous.

sync_chromium.py est juste une enveloppe étendue pour « gclient sync ». Puisque le fichier .gclient est présent dans le dossier /chromium, « gclient config » est inutile, et on peux passer directement a « gclient sync ». Il faut noter que cela modifie la variable d’environnement de GYP_DEFINES pour supprimer la NACL tool suite de chrome. Comme vous pouvez le voir, il y a une multitude de façons de faire les choses, elles sont toutes enchevêtrées dans le code source, ce qui le rend assez difficile a manipuler.

setup_links.py est ici pour traiter la compatibilité ascendante. SVN à un (seul?) avantage sur git: vous pouvez directement récupérer les sous répertoires. Quand chrome et webrtc utilisaient svn, quelques sous répertoires de chrome étaient directement récupérés et insérés dans la disposition de webrtc. Maintenant que tout que tout est passé à GIT ce n’est plus possible. Au lieu de modifier le code et les inclusions pour refléter la mise en page (avec tout le code chrome sous le /chromium dir), les ingénieurs de google ont décidé de choisir l’approche rétrocompatible de la création de liens symboliques pour chacun des dossiers insérés précédemment. La mise en page est alors la même et il y a donc continuité. C’est ce que fait setup_links.py. Malheureusement, il en coûte de lancer cette commande comme un administrateur sous windows, qui est une charge supplémentaire.

/src/webrtc/build/gyp_webrtc.py est un fichier très important. C’est le fichier qui va générer les fichier de base de construction dans le gyp et les fichiers gypi d’un côté, de l’autre et quelques variables d’environnement de l’autre. Par défaut, les fichiers ninja seront créés respectivement dans src/out/Debug et src/out/Release. Si vous partez sur une construction automatisée, vous devriez utiliser la version par défaut. Maintenant, si vous voulez être capable de débuguer dans un IDE comme Xcode ou MSVC, il y a des petites étapes supplémentaires a ajouter au processus. Vous povez suivre la page officielle (official page) pour cela à la section build.

Si vous modifiez n’importe lequel des fichiers gyp ou gypi pour ajouter des options de compilateur ou ajouter des projets, vous aurez a relancer gyp_webrtc. Si vous changez le générateur vous devrez aussi le relancer. D’habitude, « gclient runhooks » fait ça pour vous.

VII. Construction.

Cette étape dépend de du choix que vous avez fait avec le respect de vos générateurs gyp. Ici nous allons assumer ninja car le principal but est d’ouvrir un chemin à la compilation automatique (oh oui, et aussi parce que google ne supporte presque que ninja…)

Quelques notes pratiques à propos de ninja et webrtc.

Chaque fichier gyp génèrera, plus ou moins, un fichier .ninja. Si vous regardez le répertoire racine, appelé /out/Debug dans notre cas, vous verrez un fichier principal ninja « build ninja » et tout le reste est dans le sous répertoire obj dont la mise en page interne reflète la disposition de la source webrtc. Une fois la construction faite, les bibliothèques résultantes et les exécutables seront sous la racine pour mac, et où leurs fichirs correspondants .ninja résident sous windows. Ceci fait des plateformes croisées de paquets de codes… Intéressant à écrire. ninja prend en charge la compilation incrémentielle. Donc si vous modifiez un fichier gyp pour ajouter un fichier source, ajouter un projet, etc, vous pouvez régénérer les fichiers ninja et relancer pour compiler seulement ce dont vous avez besoin. Toutefois, si vous faites d’autres modifications, comme changer les paramètres de compilation, ninja ne va pas recompiler si le binaire est toujours présent, et vous devrez le retirer manuellement. Dans la pratique, si le temps n’est pas un vrai problème, pour être sûr, on pourrait vouloir enlever le /out/directory avant de régénérer les fichier ninja et recompiler.

Dans notre cas.

La ligne de commande suivante lance la compilation pour la version Debug de la librairie.

  1. ninja -C /out/Debug

autres lectures

  • https://martine.github.io/ninja/manual.html

C’est facile de parler. Montre moi ton code.

quote-talk-is-cheap-show-me-the-code-linus-torvalds-273528

WebRTC par Dr. ALEX est un blog au sujet de …. WebRTC (surprise!), la technologie elle meme et la communauté qui l’entoure. Comme WebRTC en est à ses débuts, il y a besoin d’un suivi continu, de rapports sur les avancées ainsi que des posts bien documentés sur les développements, déploiements et produits principaux.

En suivant une approche scientifique, autant que possible, toutes les opinions exprimées ici seront appuyées par des données vérifiables / reproductibles. Les sources seront citées de façon appropriée. Nous voulons faire de ce blog un endroit ou la communauté pourra avoir des discussions et échanger des informations au travers des commentaires, nous accueillerons les défis, les idées, les opinions et les oppositions documentés à partir du moment où c’est fait d’une façon polie et courtoise. Pour maintenir le site a jour et la precision du contenu, les articles seront mis à jour, corrigés, amendés et améliorés si de nouvelles informations deviennent disponibles ou si les déclarations originales sont invalidées. Les contributions extérieures seront toujours mentionnées, les auteurs remercies.

Ce blog ne concerne aucun produit commercial et aucune companie même si quelques unes sont citées ou font l’objet de post ce sera pour l’usage de leur technologie. Beaucoup d’opinions exprimées ici sont celles de l’auteur et en aucun cas celles d’une corporation ou d’une affiliation a quelque organisme que ce soit. Si l’auteur a un quelconque conflit d’intérêt, celui-ci sera dévoilé dans le post correspondant.

#WebRTC: Les entreprises se tournent vers l’Asie pour leur croissance.

CafeX a fait une annonce ce week-end au sujet de leur nouveau partenariat au Japon, leur permettant d’augmenter leur ventes en Asie du Sud-Est et du Nord. J’avais terminé mon « Rapport sur WebRTC en Asie » avec un paragraphe special sur le Japon. Ce paragraphe incluait l’analyse de l’approche de « Dialogic » et de « Twilio » pour pénétrer le marche Japonais. Cette nouvelle annonce apporte de l’eau a mon moulin et souligne l’importance de l’Asie pour les fournisseurs de WebRTC, et l’importance du Japon pour rayonner ensuite sur le reste de l’Asie.

INTRODUCTION

Pour l’écosystème autour de WebRTC, CaféX n’est pas un inconnu. Ils ont mis l’accent dès le début sur des solutions qui s’installent et tournent chez le client (« on-premises »), leur permettant d’approcher les entreprises bancaires et autres companies dont l’activité se doit d’être sécurisés et/ou ne peux pas utiliser le cloud public. Ils ont aussi très finement place leurs solution dans la nouvelle vague « omnichannel », qui consiste a multiplier les moyens pour les utilisateurs de contacter l’entreprise. Vous avez un problème avec un produit Darty? Appelez, envoyez un e-mail, discutez avec nous en ligne, ou meme maintenant, faite un appel audio/video directement depuis notre site internet. Récemment, ils ont mis beaucoup en avant leur solution d’aide et de support « LiveAssist ».

L’ASIE COMME RELAIS DE CROISSANCE

La majorité des fournisseurs de solutions WebRTCse concentrent sur l’Amérique du Nord ou l’Union Européenne qui ont un P.I.B. avoisinant les 20 millions de milliards (U.S.D.) pour une population de 506 (A.N.) et 326 (U.E.) millions de personnes. Les vendeurs se battent pour se différencier sur un marché très compétitif desservi par un grand nombre de fournisseurs, ce qui est loin d’être ideal. Ce que ces entreprises voudraient vraiment, en tant que fournisseur WebRTC, ce sont des pays pourvus d’une forte population, d’un grand pouvoir d’achat et d’une connectivité a internet stable et rapide. Donc, la vrai question est: ou aller pour générer de la croissance? L’Asie du nord et une partie de l’Australie/Nouvelle Zélande semblent correspondre …. a premiere vue ….

La chine est un marché énorme avec 1.3 milliards d’habitants et un P.I.B. de 11 millions de milliards (U.S.D.), mais il a ses réglementations propres et un internet ….. « regule ». [Aller faire de business en chine  est une aventure très spécifique, a la fois techniquement et légalement, qui nécessite un grand investissement en temps et en argent]. Pas nécessairement la croissance recherchée.

L’Inde arrive en deuxième position en termes de population avec 1.1 milliard de personnes. De grandes entreprises telles que Google n’ont pas fait de secret sur leur intention de tirer parti de cela pour obtenir une part énorme des futurs 1B utilisateurs. Cependant, les statistiques démographiques cachent le fait que l’Inde n’est pas un marché complètement homogène et que ses infrastructures ne sont pas développées de façon régulière sur tout le territoire. La meilleure illustration de cela est que les Philippines, comptant prés de 10 fois moins de population en âge de travailler, est passé devant l’Inde, dès 2011, pour ce qui est de la sous-traitance et n’ont cessé d’accroître cette avance depuis. En outre, le P.I.B. par habitant (plus proche approximation du pouvoir d’achat moyen par individu dans une nation) est seulement de 1.6K (U.S.D.) alors que le reste de l’Asie du Sud-est est à 4k de moyenne, la Chine à 8K, la Malaisie à 10K, la Corée du Sud et le Japon autour de 30K.

Le Japon a une population bien moins importante que l’Inde ou la Chine avec 126 Millions d’habitants. Par contre il est doté d’une économie très forte avec 4M de P.I.B.. Pour comparaison il compte 10 fois moins d’habitants que l’Inde mais une économie deux fois plus importante! C’est aussi un pays d’affaire très occidental et homogène (non le kansaï-ben n’est pas une vrai langue sauf si vous êtes un inconditionnel des kinki-kids). De plus, la proximité de la Corée du Sud et la facilité a trouver des personnes parlant couramment les deux langues permettent à beaucoup de traiter les deux marchés comme un seul (pour 48M d’habitans de plus; 1.4 milliards (U.S.D.) d’économie). Tout ceci fait du Japon un très bon point de depart pour une extension en Asie.

L’extension suivante est toutefois habituellement plus difficile a choisir.

L’Association des nations de l’Asie du Sud-Est (A.S.E.A.N), qui a débuté seulement récemment, pèse 630 millions d’habitants soit plus que l’U.E. ou l’Amerique du Nord pour un P.I.B. bien plus faible 2.5 Milliard (U.S.D.), mais toujours plus que l’Inde. L’A.S.E.A.N. représente le P.I.B. cumulé du Mexique et du Canada.

L’un des plus gros problème de l’A.S.E.A.N. est l’énorme disparité entre chaque membre de l’association. Alors que les statistiques de l’Indonésie la placent près du Mexique avec près de 1M de P.I.B., elle est loin devant le deuxième groupe de pays (Thaïlande, Malaisie, Philippines et Singapour; dans l’ordre) qui représentent chacun 0.3M de P.I.B.. Comme je l’explique plus en détail dans mon rapport, on ne peut pas couvrir tous ces pays avec un bureau et un stratégie unique. Comme « Wavecell jobs offers » (voir « ventes ») ou « Nexmo » avant eux l’illustrent, alors que vous aurez certainement un QG soit à Hong-Kong soit à Singapour pour des raisons linguistiques, juridiques et fiscales; vous devez avoir une équipe de vente dans chaque pays pour être vraiment en mesure de vendre et créer de la croissance.

ANNONCE DU CAFEX SUR SA STRATEGIE ASIATIQUE

Alors que le choix du japon comme premier point d’entr’e en Asie a beaucoup de sens, l’annonce indique également que: « la Chine, y compris Taywan, Hong-Kong et Macao, Singapour, la Malaisie, la Thaïlande et l’Australie » seront couverts par le même accord. Ce serait une vrai gageure sans compter sur la taille de leur partenaire Japonais ITOCHU. Avec plus de 4 000 employés et plus de 100 bureaux à travers le monde, ITOCHU Corporation a les épaules pour permettre a CafeX d’avoir les moyens de sa croissance. Sa division ICT et services financiers, en particulier, fournit des solutions RTC et VoiP à de nombreuses entreprises, y compris les centres d’appels, et est le véhicule ideal pour le portfolio technique de CafeX. Apres avoir vendu les produits CafeX pour le japon uniquement, ITOCHU a fait un investissement stratégique dans CafeX en décembre 2016 dont l’annonce contient une analyse intéressante du business WebRTC au japon et A.P.A.C.. La dernière annonce du week-end est juste dans la continuité de cet accord global.

CONCLUSION

Comme prévu, les fournisseurs WebRTC se tourne vers l’Asie pour la croissance. Alors que les marchés WebRTC asiatiques sont globalement inexploités, la plupart des fournisseurs se rendent compte que de se lancer seul est difficile et nécessite une véritable stratégie. Certains CPaaS, comme Nexmo ou Twilio, ont étés dans l’obligation d’y aller seuls, mais pour des raisons lie a leur execution. CPaaS, ils dependent de la connection avec les réseaux des opérateurs téléphoniques, et ont donc des le debut de leurs operations affectes des responsable telco (« carrier manager »), qui n’avait pas une fonction de vente, mais plus une fonction de liaison technique. La mise en place de partenariats et de collaborations comme effectuée par CafeX, est un très bon moyen d’aborder la vente sur les marchés asiatiques de manière douce, en particulier pour PaaS (qui ne dépendent pas directement des télécoms). Avec Itochu, CafeX a définitivement marque un grand coup.

How to test LibWebRTC

I. Introduction

Building a library is good, but you do not know if there are any bugs until you exercice the library by linking it against an executable and running it. While building webrtc (and lib jingle) has been made relatively easy thanks to depot_tools and recipes, testing it has been a real problem. Since in the google system, commits are rolled, tested, then potentially unrolled, you cannot trust the HEAD revision to be stable. Using branch_heads you could compile and test the versions corresponding to a specific release of Chrome, however testing newer libwebrtc / libjingle like those that are used in canary is something wants to do to be ready when it moves to production, but it’s very challenging. This post is going to address two points: the testing system in google (for the curious), and how to achieve almost the same level of testing in a few lines of CMake code.

II. I want my own waterfall !

The official page describe how to see the tests being run, and how to add them, but not how to trigger them, or how to run them locally. It’s not that you can’t, it’s just that it’s quite complicated and demand quite a machinery in place. What one really want would be at minimum to have the capacity to test locally the result of the build before installing it or packaging it (more on that in a later post), and in the best case scenario to have the equivalent of a waterfall that could be run on demand. First, for those in a hurry, there is almost no way to do it yourself, as the infrastructure is own by google and require you to have a committer account with either webrtc or chrome. I do not know if it possible, but i can say that I do not know of anybody in the ecosystem (appart from one intel employee) that enjoy this privilege. For those that are curious or have time, see below what you can do to have the closest equivalent.

1. The missing Testing info

This part will deal with all the info missing from the webrtc.org page (but spread around in different chromium wiki pages) to actually set up testing the google way.

The system used by google for the development of chromium is great. Honestly, it makes a lot of sense, and a lot of effort has been put in it to actually scale to the number of developers working on chromium. The latest « infra » as they call it, has to handle more than 200 commits a day without disruption, and is apparently doing a great job at it. That being said, it is quite an overkill for someone who only wants to work on libwebrtc, and it’s unfortunate that smaller team are being forced into using it or surrender testing all together.

The original test part of the infra is made of several parts: Gtest to write the unit tests, the usual tools to integrate it in the build process (gyp, DEPS, …), buildbot for … well, the build bots, and a new special swarming infrastructure (here and here) coupled with isolated tests (here and here) to even scale better. I will not address the GTest, gyp or DEPS parts here, but deal with what need to be in place to test after a successful build of libwebrtc. To be thorough, i will only touch on the standalone libwebrtc, and not the webrtc-in-chromium and other embedded tests (*it s actually quite different, especially for the renderers, screensharing etc, but hey, we have to take it step by step). Finally, I will only build the webrtc.org version and not the gecko/firefox version (here again, quite different, love the screensharing in FF, and H264 integration, but we have to take it step by step).

The link below will take you step by step through everything you need to set up your own buildbot (with slaves), trybot and other locally. Note that the links to the repositories might be obsolete by the time you read this post (FAST moving target …) and you might want to read the code in the « infra » part of depot_tools on disk to know what’s the latest way of doing things (sic), more specifically, /build which can be directly fetched from https://chromium.googlesource.com/chromium/tools/build.git . The files configuring the standalone webrtc waterfall will appear in master.client.webrtc . Each column of the waterfall correspond to a builedbot (slave) whose information is also in the same folder.

further reading

  • https://www.chromium.org/developers/testing/chromium-build-infrastructure

2. Isolated Testing, WTF?

For all the readers working in early stage start up, I want to first make clear that WTF does NOT stand for « Where is the funding ».  After a build of libwebrtc you will find your build folder (/src/out/<CONFIG> by default, <CONFIG> being either Debug or Release) quite crowded. Among all those, you will see some executable with « isolated » and « isolated.state » alongside.  Those files are used by the swarming system to distribute the testing (here and here). In our case, the important information is that they contain the list of the files you need to pass as arguments to the tests to run them. This is still work in progress, but already stable enough to be used. There are 22 tests listed like this. If you then look at the waterfall, you will see that roughly, there are two types of buildbots, the normal ones which run all the unit tests, and the « Large » ones which run performance tests and long tests like [vie|voe]_auto_test, video_capture_tests and the audio_device_tests. Those take quite some time to run, and much longer than the other tests, which justifies running them separately on beefier instances. All the tests need to be run with an extra –test-launcher-bot-mode arguments. Also , for the sake on completeness, both vie_ and voe_auto_test are actually very powerful interactive executable that deserve a post on their own. I encourage everybody to play with it and look at the source code. Inspiring! To be run as a a test, you need to pass them an extra –automated arg.

3. So, how easy it is to support that with CMake?

CMake is part of a trilogy (yeah, another one), CMake/CTest/CDash. CMake is your main configuration and build tool, CTest is, well, your main testing and test suite management tool, but also a client for CDash, the equivalent of the waterfall, i.e. an interactive dashboard to browse an interact with the results of your builds and tests sent by CTest. The advantage here is that it’s all integrated.

NOTE: the best way would be to parse the isolated files, and extract the exact command line, as well as the output files. In our case, for the sake of simplicity, and time, we will manually add the 22 tests one-by-one, and we will ignore the output as long as the test passes. This is thus improvable, but gives you 99% of what you want, in 30mn work ….

to enable testing in CMake, you just need to add the two following lines of code in a CMake script:

  1. enable_testing()
  2. include(CTest)

In the absence of those two lines, the rest of the code will not crash or raise any error, but no test will be generated, be careful about it.

For each test you want to add, you can use the add_test() command. Here is an example below that handles both windows and mac for adding a normal test, while checking that the name you passed correspond to an existing file (remember, FAST moving target …):

  1. set( my_test_binary_name « common_audio_unittests » )
  2. set( my_test_binary ${my_test_binary_name} )
  3. if( WIN32 )
  4.   set( my_test_binary ${my_test_binary}.exe )
  5. endif()
  6. if( EXISTS ${MY_BUILD_DIR}/${my_test_binary )
  7.   add_test(
  8.     NAME                                      imp_${my_test_binary_name}
  9.     COMMAND                           ${my_test_binary} –test-launcher-bot-mode
  10.     WORKING_DIRECTORY  ${MY_BUILD_DIR}
  11.   )
  12. else()
  13.   message( WARNING « ${my_test_binary} – NOT FOUND. » )
  14. endif()

You can rince and repeat. The final code can be seen here (and the macro add_webrtc_test is defined here).

Once you’re done building the project, you can check which tests have been added by running this command in the build directory « ctest -N« . It will not run the tests, just list them. « ctest » or « make test » (under mac/linux) are equivalent and run all the tests one after the other. For webrtc, it is better not to use the -jX options and run tests in parallel as the tests access the hardware and could interfere with one another. To make sure that people do not make this mistake, you could add a dependency between each test and the previous one in the list. We did not implement that (even though it’s only one more line). If you want to see the output of the tests, you can add a -V to the command line. Here you go, you can test the library as thoroughly as google tests it (well, almost, memory leaks and other thread sanitizer are missing, but hey, it s great already. How to add memory leak checks and coverage computation will be explained in a following posts). Now we can party like it’s 1999. Or can we?

NOTE: webrtc_perf_test needs to access the network, and so is voe_auto_test and thus if you re testing under window, you either have to configure your firewall to allow it, manually click-n-allow when prompted or skip that test if you want the test suite to run.

4. Ok I can run all the test locally, but I still don’t have my waterfall!

True. AT this stage you have enough to build and test the output on a single machine. That a good base for packaging the lib, a topic we will address in a following post. However, you don’t have visibility on the result of the build of the same code base on different systems and compiler, with different compiler options, and you also do not have the nice visual dashboard online.

That is where CDash comes in handy. CDash is the server component of the waterfall, and CTest can be very easily configured to send the result of a build and tests to a CDash server. KitWare, one of the main company behind cmake/ctest/cdash and the working place of some of th most impressive engineers I had to work with in my life, is proposing free hosting for open source project, and reasonably inexpensive hosting options. Of course, the code is free and open source and you can install your own CDash server internally if you prefer. I chose to have my own small account, and here is the very simple content of the CTestConfig.cmake file that you MUST keep in the root of the source directory.

  1. set(CTEST_PROJECT_NAME « libwebRTC »)                        # this is linked to a project you must have created in the server beforehand
  2. set(CTEST_NIGHTLY_START_TIME « 00:00:00 EST »)    # Whatever you want, usually a time at which the computer is not used.
  3. set(CTEST_DROP_METHOD « http »)
  4. set(CTEST_DROP_SITE « my.cdash.org »)                               # will change depending on your server install
  5. set(CTEST_DROP_LOCATION « /submit.php?project=libwebRTC »)
  6. set(CTEST_DROP_SITE_CDASH TRUE)

From an empty dir (recommended) you can run ctest -D Experimental to configure, build, run the tests, (optionally check for me leaks, compute coverage, …) and then send the results to the dashboard. For this example, here is what the dashboard looks like (mac, windows). You can see windows and linux build appearing also, since cmake is cross platform it indeed works almost out of the box (except for me command line details and extensions differences) on all platforms. Here each line is a slave (as opposed to a waterfall where a column is a slave), and you can click on the result of each step (configuration, build, test) to get the results as it would have been printed to stdio, giving you approximately the same features as the builedbot waterfall. Eventually for a mature project it can look like this.

CTest also has the capacity to upload files separately. In a following post, I’explain how to use this to automatically drop compiled version of the library or packaged version of those library to a public repository if and only if the tests all passed. Dev can then trust that any binary or package made available is sound, without having to re-compile and re-test themselves (choose your style of victory dance).

further reading

  • http://www.cmake.org/Wiki/CMake/Testing_With_CTest
  • http://www.cmake.org/Wiki/CMake_Scripting_Of_CTest (Advanced! How to set up automated build instances.)

III. Conclusion

The google system is certainly more scalable. It also allows to trigger builds on demand as part of the validation of commits, which is great. While the CMake/CTest/CDash has been improved in the past 5 years to do this, it is still not a feature that is as easy to deploy (AFAIK, I’m not current on CMake). In the case of a very large project (200 commits a day ….) with only a few companies involved, it’s great.

What is great with the C^3 system, is that anybody can volunteer a build host and contribute to dashboard. You have a fancy configuration (early version of a compiler not out, old version of compiler [borlandCC 5.6], …) that nobody can test on, you can still build and report the errors for the Devs to see. It makes reporting errors as simple as « ctest -D Experimental ». If you configure your computer to be a nightly build host, then dev can hack the code and check if the result solves your problem without having access to the machine at all (yes, you can point the bot to a git branch, not to pollute the main dev or master branches during the trial and error process). So for simpler projects, with a lot of smaller teams contributing (like an open source community around a library ….), it is great. The barrier of entry is low, while being quite powerful if you want it to be. It has been around for years, and used in multiple projects, so it s easy to find people with knowledge of the tools (who is using depot-tools outside of the chromium project … ?). It has also a big code base out there for people to inspire themselves from. It supports ninja….

Here, in a few hours, we have been able to learn how to test the libwebrtc locally to the same level than google does, and to report to an hosted Dashboard that can be shared with others. In following posts, we will see how to add memory leak analysis, code coverage computation (compiling is a good start, testing is better, but how much do we test exactly?), how to create packages to install libwebrtc on computers, and how to then automatically import installed versions in projects that use Cmake to configure their build.

Creative Commons License
This work by Dr. Alexandre Gouaillard is licensed under a Creative Commons Attribution 4.0 International License.

This blog is not about any commercial product or company, even if some might be mentioned or be the object of a post in the context of their usage of the technology. Most of the opinions expressed here are those of the author, and not of any corporate or organizational affiliation.