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

This post is also available in: English (Anglais)

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

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Time limit is exhausted. Please reload CAPTCHA.