La route jusqu'à présent
Il y a un an, Chrome a annoncé la prise en charge initiale du débogage WebAssembly natif dans les outils pour les développeurs Chrome.
Nous avons fait preuve d'un soutien de base en marche et nous avons parlé des opportunités l'utilisation des informations DWARF au lieu de les cartes sources s'ouvriront à l'avenir:
- Résoudre les noms de variables
- Types d'impression élégante
- Évaluer des expressions dans les langues sources
- ... et bien plus !
Aujourd'hui, nous avons le plaisir de vous présenter les fonctionnalités annoncées et les progrès réalisés par les équipes d'Emscripten et des outils pour les développeurs Chrome cette année, en particulier pour les applications C et C++.
Avant de commencer, veuillez noter qu'il s'agit encore d'une version bêta vous devez utiliser la dernière version de tous les outils à vos propres risques et, si vous rencontrez des problèmes, veuillez les signaler à https://issues.chromium.org/issues/new?noWizard=true&template=0&component=1456350.
Commençons par le même exemple C simple que la dernière fois:
#include <stdlib.h>
void assert_less(int x, int y) {
if (x >= y) {
abort();
}
}
int main() {
assert_less(10, 20);
assert_less(30, 20);
}
Pour le compiler, nous utilisons la dernière version d'Emscripten.
et transmettre un indicateur -g
, comme dans le post d'origine, pour inclure le débogage
informations:
emcc -g temp.c -o temp.html
Nous pouvons maintenant diffuser la page générée à partir d'un serveur HTTP localhost (pour par exemple, avec serve), et ouvrez-le dans la dernière version de Chrome Canary.
Cette fois, nous avons également besoin d'une extension d'assistance qui s'intègre à Chrome. Les outils de développement vous aident à interpréter toutes les informations de débogage encodée dans le fichier WebAssembly. Veuillez l'installer à l'adresse lien: goo.gle/wasm-debugging-extension
Vous devez également activer le débogage WebAssembly dans les outils de développement Tests : Ouvrez les outils pour les développeurs Chrome, puis cliquez sur l'icône en forme de roue dentée (⚙) En haut à droite du volet "DevTools", accédez au panneau Experiments (Tests). Cochez la case WebAssembly Debugging: Enable DWARF support (Débogage WebAssembly : Activer la prise en charge DWARF).
Lorsque vous fermez Settings (Paramètres), les outils de développement vous suggèrent de s'actualiser. pour appliquer des paramètres, alors c’est exactement ça. C'est tout pour cette session ponctuelle configuration.
Revenez maintenant au panneau Sources et activez Mettre en veille sur les exceptions (icône ⏸), puis cochez la case Mettre en veille sur les exceptions interceptées et actualiser la page. Les outils de développement doivent être mis en veille sur une exception:
Par défaut, il s'arrête sur un code Glue généré par Emscripten, mais sur
À droite, vous voyez une vue Call Stack (Pile d'appel) représentant la trace de la pile de
l'erreur et accéder à la ligne C d'origine qui a appelé
abort
:
Si vous regardez dans la vue Champ d'application, vous pouvez voir les noms et les valeurs d'origine des variables dans le code C/C++. Vous n'avez plus à essayer de comprendre la signification de noms tronqués comme $localN
et leur relation avec le code source que vous avez écrit.
Cela s'applique non seulement aux valeurs primitives telles que les entiers, mais aussi aux valeurs comme les structures, les classes, les tableaux, etc.
Compatibilité avec les types enrichis
Étudions un exemple plus complexe pour les illustrer. Ce dessinons une fractale de Mandelbrot avec le code C++ suivant:
#include <SDL2/SDL.h>
#include <complex>
int main() {
// Init SDL.
int width = 600, height = 600;
SDL_Init(SDL_INIT_VIDEO);
SDL_Window* window;
SDL_Renderer* renderer;
SDL_CreateWindowAndRenderer(width, height, SDL_WINDOW_OPENGL, &window,
&renderer);
// Generate a palette with random colors.
enum { MAX_ITER_COUNT = 256 };
SDL_Color palette[MAX_ITER_COUNT];
srand(time(0));
for (int i = 0; i < MAX_ITER_COUNT; ++i) {
palette[i] = {
.r = (uint8_t)rand(),
.g = (uint8_t)rand(),
.b = (uint8_t)rand(),
.a = 255,
};
}
// Calculate and draw the Mandelbrot set.
std::complex<double> center(0.5, 0.5);
double scale = 4.0;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
std::complex<double> point((double)x / width, (double)y / height);
std::complex<double> c = (point - center) * scale;
std::complex<double> z(0, 0);
int i = 0;
for (; i < MAX_ITER_COUNT - 1; i++) {
z = z * z + c;
if (abs(z) > 2.0)
break;
}
SDL_Color color = palette[i];
SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, color.a);
SDL_RenderDrawPoint(renderer, x, y);
}
}
// Render everything we've drawn to the canvas.
SDL_RenderPresent(renderer);
// SDL_Quit();
}
Comme vous pouvez le voir, cette application est encore relativement petite. Il s'agit d'un seul contenant 50 lignes de code. Cette fois, j'utilise aussi des API externes, comme la bibliothèque SDL pour des images, ainsi que des nombres complexes issus bibliothèque standard C++.
Je vais la compiler avec le même indicateur -g
que ci-dessus pour inclure
informations de débogage. Je demande aussi à Emscripten de fournir le fichier SDL2
bibliothèque et autorisent une mémoire de taille arbitraire:
emcc -g mandelbrot.cc -o mandelbrot.html \ -s USE_SDL=2 \ -s ALLOW_MEMORY_GROWTH=1
Lorsque j'accède à la page générée dans le navigateur, je vois avec des couleurs aléatoires:
Lorsque j'ouvre les outils de développement, je peux à nouveau voir le fichier C++ d'origine. Ce mais comme il n'y a pas d'erreur dans le code (ouf !), un point d'arrêt au début de notre code à la place.
Lorsque nous actualisons la page, le débogueur se met en pause directement dans notre Source C++:
Nous pouvons déjà voir toutes nos variables à droite, mais seulement width
et height
sont initialisés pour le moment. Il n'y a donc pas grand-chose à
inspecter.
Définissons un autre point d'arrêt dans notre boucle principale Mandelbrot, puis reprenons l'exécution pour avancer un peu.
À ce stade, notre palette
a été rempli de couleurs aléatoires. Nous pouvons développer le tableau lui-même, ainsi que les structures SDL_Color
individuelles, et inspecter leurs composants pour vérifier que tout est correct (par exemple, que le canal "alpha" est toujours défini sur une opacité complète). De même, nous pouvons développer
et vérifier les conditions réelles et
les parties imaginaires du nombre complexe stockées dans la variable center
.
Si vous souhaitez accéder à une propriété profondément imbriquée qui est autrement difficile à via la vue Champ d'application, vous pouvez utiliser la console l'évaluation ! Notez toutefois que les expressions C++ plus complexes ne sont pas déjà pris en charge.
Reprenons l'exécution plusieurs fois pour voir comment la x
interne est
ou en consultant à nouveau la vue Portée, en ajoutant
le nom de la variable à la liste de surveillance, en l'évaluant dans la console ou en
en pointant sur la variable dans le code source:
À partir de là, nous pouvons entrer ou passer les instructions C++ et observer comment d'autres variables changent également:
Tout fonctionne très bien lorsqu'une information de débogage est disponible, que faire si nous voulons déboguer un code qui n'a pas été créé avec l'API de débogage ?
Débogage WebAssembly brut
Par exemple, nous avons demandé à Emscripten de fournir
une bibliothèque SDL prédéfinie pour
au lieu de les compiler nous-mêmes à partir de la source,
Le débogueur ne peut actuellement pas trouver les sources associées.
Revenons à l'étape suivante pour accéder à SDL_RenderDrawColor
:
Nous revenons à l'expérience de débogage WebAssembly brute.
Cela semble un peu effrayant, et la plupart des développeurs Web à résoudre, mais il peut arriver que vous souhaitiez déboguer est créée sans informations de débogage, que ce soit parce qu'il s'agit d'une bibliothèque tierce sur laquelle vous n'avez aucun contrôle, ou parce que vous rencontrer l’un de ces bugs qui ne se produit qu’en production.
Pour vous aider, nous avons apporté des améliorations expérience de débogage.
Tout d'abord, si vous avez déjà utilisé le débogage WebAssembly brut,
que le démontage complet est maintenant affiché dans un seul fichier
devinez plus facilement à quelle fonction correspond une entrée Sources wasm-53834e3e/
wasm-53834e3e-7
.
Nouveau schéma de génération de nom
Nous avons également amélioré les noms dans la vue de démontage. Auparavant, vous verriez que des index numériques ou, dans le cas de fonctions, aucun nom.
Nous générons maintenant des noms de la même manière
que d'autres outils de démontage,
à l'aide des indications de la section des noms WebAssembly
les chemins d'importation/exportation et, enfin, si tout le reste échoue, générer
en fonction du type et de l'index de l'élément, par exemple $func123
. Dans la capture d'écran ci-dessus, vous pouvez voir comment cela permet déjà d'obtenir des traces de pile et un désassemblage légèrement plus lisibles.
Lorsqu'aucune information de type n'est disponible, il peut être difficile d'inspecter Toutes les valeurs autres que les primitives. Par exemple, les pointeurs s'affichent. comme des entiers normaux, sans aucun moyen de savoir ce qui est stocké derrière eux dans mémoire.
Inspection de la mémoire
Auparavant, vous ne pouviez développer que l'objet de mémoire WebAssembly, représenté par env.memory
dans la vue Scope (Champ d'application) pour rechercher
octets individuels. Cela fonctionnait dans certains
scénarios insignifiants, mais n'était pas
particulièrement pratique à développer et ne permet pas de réinterpréter les données
dans des formats autres que les valeurs en octets. Nous avons ajouté une nouvelle
fonctionnalité pour vous aider
avec ceci aussi: un inspecteur de mémoire linéaire.
Si vous effectuez un clic droit sur env.memory
, vous devriez maintenant voir
appelée Inspect Memorystore (Inspecter la mémoire) :
Lorsque vous cliquez dessus, un outil d'inspection de mémoire s'affiche. que vous pouvez inspecter la mémoire WebAssembly dans les vues hexadécimales et ASCII, accéder à des adresses spécifiques, et interpréter les données différents formats:
Scénarios avancés et mises en garde
Profiler du code WebAssembly
Lorsque vous ouvrez les outils de développement, le code WebAssembly est "hiérarchisé" à un
version non optimisée pour activer le débogage. Cette version est
beaucoup plus lente,
ce qui signifie que vous ne pouvez pas compter sur console.time
, performance.now
et d'autres méthodes de mesure de la vitesse de votre code. Les outils de développement
car les chiffres obtenus ne reflètent pas les performances réelles
du tout.
Utilisez plutôt le panneau Performance des outils de développement. qui exécutera le code à pleine vitesse et vous fournira une répartition détaillée du temps passé dans différentes fonctions:
Vous pouvez aussi exécuter votre application avec les outils de développement fermés une fois que vous avez terminé, ouvrez-les pour inspecter la console.
Nous améliorerons les scénarios de profilage à l'avenir, mais pour le moment, il s'agit mise en garde à prendre en compte. Pour en savoir plus sur WebAssembly de hiérarchisation, consultez nos documents sur le pipeline de compilation WebAssembly.
Compiler et déboguer sur différentes machines (y compris Docker / hôte)
Lorsque vous compilez dans un Docker, une machine virtuelle ou sur un serveur de compilation distant, vous rencontrerez probablement des situations où les chemins d'accès aux fichiers sources utilisés lors de la compilation ne correspondent pas aux chemins d'accès de votre propre système de fichiers où les outils pour les développeurs Chrome sont en cours d'exécution. Dans ce cas, les fichiers apparaissent Sources, mais son chargement échoue.
Pour résoudre ce problème, nous avons implémenté une fonctionnalité de mappage de chemin d'accès dans les options d'extension C/C++. Vous pouvez l'utiliser pour remapper des chemins arbitraires et pour aider les outils de développement à localiser les sources.
Par exemple, si le projet de votre machine hôte se trouve sous un chemin d'accès
C:\src\my_project
, mais a été créée dans un conteneur Docker où
ce chemin était représenté par /mnt/c/src/my_project
, vous pouvez le remapper
lors du débogage en spécifiant ces chemins d'accès en tant que préfixes:
Le premier préfixe correspondant "gagnant" Si vous connaissez d'autres langages C++
de débogage, cette option est semblable à la commande set substitute-path
dans GDB ou un paramètre target.source-map
dans LLDB.
Déboguer les builds optimisés
Comme pour tout autre langage, le débogage fonctionne mieux si les optimisations sont sont désactivées. Les optimisations peuvent intégrer des fonctions dans une autre, réorganiser du code ou en supprimer certaines parties. risque de perturber le débogueur et, par conséquent, vous, en tant qu'utilisateur.
Si l'expérience de débogage plus limitée ne vous dérange pas et que vous souhaitez tout de même
déboguer un build optimisé, la plupart des optimisations fonctionnent
à l'exception de l'intégration de fonctions. Nous prévoyons d'aborder les
problèmes à l'avenir. Pour le moment, utilisez -fno-inline
pour
la désactiver lors de la compilation avec toute optimisation de niveau -O
, par exemple :
emcc -g temp.c -o temp.html \ -O3 -fno-inline
Séparer les informations de débogage
Les informations de débogage conservent de nombreux détails sur votre code, définis les types, variables, fonctions, champs d'application et emplacements, ainsi que tout ce qui pourrait être utiles au débogueur. Il est donc souvent plus important que le code lui-même.
Pour accélérer le chargement et la compilation du module WebAssembly, vous pouvez
diviser ces informations de débogage dans un composant WebAssembly distinct
. Pour le faire dans Emscripten, transmettez un indicateur -gseparate-dwarf=…
avec
le nom de fichier souhaité:
emcc -g temp.c -o temp.html \ -gseparate-dwarf=temp.debug.wasm
Dans ce cas, l'application principale ne stocke qu'un nom de fichier temp.debug.wasm
, et l'extension d'assistance peut le localiser et le charger lorsque vous ouvrez DevTools.
Associée aux optimisations décrites ci-dessus, cette fonctionnalité peut même les utiliser pour envoyer des versions de production presque optimisées application, puis les déboguer plus tard avec un fichier secondaire local. Dans ce cas, nous devons également remplacer l'URL stockée pour aider l'extension à trouver le fichier secondaire, par exemple :
emcc -g temp.c -o temp.html \ -O3 -fno-inline \ -gseparate-dwarf=temp.debug.wasm \ -s SEPARATE_DWARF_URL=file://[local path to temp.debug.wasm]
À suivre...
Ça fait beaucoup de nouvelles fonctionnalités !
Avec toutes ces nouvelles intégrations, les outils pour les développeurs Chrome deviennent un débogueur puissant non seulement pour JavaScript, mais aussi pour les applications C et C++. Il n'a jamais été aussi facile d'utiliser des applications grâce à une variété et les intégrer à un Web partagé et multiplate-forme.
Cependant, notre voyage n'est pas encore terminé. Certaines des choses que nous allons à partir de là:
- Nettoyer les ébauches de l'expérience de débogage.
- Prise en charge des outils de mise en forme personnalisés.
- Nous nous efforçons d'améliorer profilage pour les applications WebAssembly
- Ajout de la prise en charge de la couverture de code pour faciliter la recherche code inutilisé.
- Amélioration de la prise en charge des expressions dans l'évaluation de la console.
- Ajout de la prise en charge de plus de langues.
- Et bien d'autres…
En attendant, aidez-nous en testant la version bêta actuelle sur votre propre code et en nous signalant les problèmes de problèmes à https://issues.chromium.org/issues/new?noWizard=true&template=0&component=1456350.
Télécharger les canaux de prévisualisation
Vous pouvez utiliser Chrome Canary, Dev ou Bêta comme navigateur de développement par défaut. Ces versions preview vous permettent d'accéder aux dernières fonctionnalités des outils de développement, de tester des API de plates-formes Web de pointe et de détecter les problèmes sur votre site avant vos utilisateurs.
Contacter l'équipe des outils pour les développeurs Chrome
Utilisez les options suivantes pour discuter des nouvelles fonctionnalités et des modifications décrites dans l'article, ou pour tout autre sujet lié aux outils de développement.
- Envoyez-nous vos suggestions ou vos commentaires via crbug.com.
- Signalez un problème lié aux outils de développement en cliquant sur Autres options > Aide > Signalez un problème dans les outils de développement.
- Tweetez à l'adresse @ChromeDevTools.
- Faites-nous part de vos commentaires sur les vidéos YouTube sur les nouveautés des outils de développement ou sur les vidéos YouTube de conseils pour les outils de développement.