This post is also available in: English (Anglais)
I. Introduction
La plupart des logiciels utilisant libwebrtc ont besoin de pouvoir la modifier pour rajouter des fonctionnalités. Certain vendeurs, comme TokBox, vont changer les paramètres (flags) de compilation de libvpx par example, pour activer le mode d’encodage par couche (SVC) de VP8 dans leurs SDKs mobiles, our avoir une meilleure qualité video. D’autres, tel que Voxeet, vont ajouter des codecs audio supplémentaires, dans leur cas pour emuler de l’audio 3D et reproduire le positionnement des participants dans une conference. Beaucoup, y compris pristine.io, vont vouloir ajouter H.264 pour etre compatibles avec les cartes graphiques de plus d’ordinateurs et de telephones.
Quel que soit le but, chacun aura besoin d’être capable de modifier de façon cohérente le code source d’une bibliothèque qui change souvent, tout en s’assurant que le nombre de patchs et la manière de les appliquer reste gérable dans le temps.
De plus, comme il s’agit d’un code public, il y a des patchs qu’on va proposer et qui profiteront à tous, mais certains utilisateurs pourraient vouloir créer leurs propres patchs privés et les garder pour eux par se différencier. L’architecture de la méthode de gestion des patchs doit permettre cela.
Finalement, juste pour le plaisir, je voulais disposer d’un mécanisme me permettant d’avoir rapidement des patchs à partir du processus de revue et d’integration de nouvelle fonctionnalistes de Google pour profiter de ces nouvelles fonctionnalités de libwebrtc avant même qu’elles n’apparaissent dans Chrome (ou pour tester ces patchs avec mon système).
Dans ce post, nous allons proposer une manière simple, mais efficace, pour aboutir à ce résultat.
II. Mise en œuvre
1. Commandes spécifiques CMake que nous allons utiliser
CMake dispose de la commande add_subdirectory(). Cette commande permet de parcourir l’arborescence du dossier mentionné en argument et à traiter tous les fichiers CMakeLists.txt qu’y s’y trouvent.
- add_subdirectory(Patches)
En conditionnant l’appel à cette commande vous pouvez concevoir une belle structure de dossier pour gérer vos patchs, par example selon le type de plateforme :
- if( APPLE )
- add_subdirectory( mac )
- elseif( WIN32 )
- add_subdirectory( win )
- endif()
2. Création des patchs et conditions spécifiques à libwebrtc
Le code source de libwebrtc est un patchwork de bibliothèques indépendantes qui sont récupérées en fonction des entrees dans le fichier DEPS a la racine. Bien que gclient ait une option pour générer des patchs globaux, nous préférons simplement utiliser git. Ainsi, chaque patch que vous générez est applicable à une arborescence git spécifique et vous devez savoir à quel endroit (racine du patch) l’appliquer.
Nous avons créé une macro CMake pour aider à automatiser cela :
- set_webrtc_patch_target(
- GIT_APPLY_CMD
- APPLY_DIR
- PATCH
- DEPENDS_ON_TARGET
- )
L’option DEPENDS_ON_TARGET nous permet d’être sûr que les patchs sont appliqués après le téléchargement du code.
Le GIT_APPLY_COMMAND apporte de la flexibilité à la commande git que vous utilisez. Certains vont préfèrer l’approche « git diff » / « git apply », alors que d’autres préfèreront « git format-patch » / « git am ». Dans notre cas nous gardons les choses simples :
- set(
- GIT_APPLY_CMD
- git apply –ignore-space-change –ignore-whitespace
- )
3. Comment exécuter une commande clean/undo
Le problème avec les patchs, c’est qu’ils laissent l’arborescence du code source modifie, ce que git n’aime pas.
Quand on utilise git, une façon de retourner à un état propre est faire un reset : « git reset –hard -q« . Cela ramènera tous les fichiers suivis par git dans un état propre, mais peut laisser des fichiers non suivis par git dans l’arborescence, par exemple si vous ajoutez de nouveaux fichiers ou si vous en supprimez d’autres. « git clean -qfdx »est donc nécessaire si vous voulez vous assurer que l’arborescence du code source est revenue dans l’état que vous souhaitez. Le code ressemble à ça :
- set( GIT_RESET_CMD git_reset –hard -q )
- set( GIT_CLEAN_CMD git clean -qfdx )
De plus, vous devez savoir à quel endroit de l’arborescence appliquer ces commandes, donc vous devez noter tous les répertoires où des patchs ont été appliqués. Pour chaque patch, nous allons ajouter dans une liste le répertoire auquel il s’applique. Quand le moment sera venu d’annuler l’application du patch, nous utiliserons cette liste :
- list(REMOVE_DUPLICATES PATCHED_DIRS) # enlève les doublons
- add_custom_target(
- UNPATCH_ALL
- ${CMAKE_COMMAND} -E touch dummy.phony
- )
- foreach( dir ${PATCHED_DIRS} )
- add_custom_command(
- TARGET UNPATCH_ALL POST_BUILD
- COMMAND ${GIT_RESET_CMD}
- COMMAND ${GIT_CLEAN_CMD}
- WORKING_DIRECTORY ${WebRTC_SOURCE_DIR}/${dir}
- COMMENT « Unpatching ${dir} »
- )
- endforeach()
4. Comment intégrer mes patchs privés/propriétaires ?
Avec la commande add_subdirectory() les choses sont relativement simples. Le code ci-dessous vérifie s’il existe un sous-répertoire « PvtPatches » et s’il y en a un, rentre dedans. Vous pouvez utiliser les sous-arborescences git, ou la méthode de votre choix, pour avoir dans votre copie locale un tel répertoire, avec un CMakeFiles copié (hum… largement inspiré) de celui dans Patches et tout sera pour le mieux.
- if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/PvtPatches)
- add_subdirectory(pvtPatches)
- endif()
Notez qu’une attention particulière a été portée à la variable qui contient la liste des répertoires sur lesquels appliquer la commande de reset et de nettoyage, pour que vous puissiez la modifier de l’intérieur des sous-répertoires et qu’elle reste valide. L’option « CACHE » vous assure de la cohérence à travers tout le projet quel que soit le répertoire source. L’option « INTERNAL » est ici pour pour s’assurer que cette variable n’apparaîtra pas dans l’interface graphique qui est distribuée avec CMake.
- set( PATCHED_DIRS « » CACHE INTERNAL « Internal variable. »)
Bien entendu, vous êtes susceptible de devoir relancer l’outil de génération de compilation après avoir appliqué les patchs :
- python /src/webrtc/build/gyp_webrtc.py
III. Conclusion
Vous avez vu dans ce post comment installer un système de patchs simple pour libwebrtc. Bien sûr, ce ne serait pas complet sans quelques examples. Nous laissons a titre d exercice pour le lecteur, l’intégration de quelques patchs Google :
Cheers.
Alex