BazelCon 2022 findet vom 16. bis 17. November in New York und online statt.
Jetzt anmelden

bzl-Styleguide

Mit Sammlungen den Überblick behalten Sie können Inhalte basierend auf Ihren Einstellungen speichern und kategorisieren.

Auf dieser Seite werden grundlegende Stilrichtlinien für Starlark sowie Informationen zu Makros und Regeln beschrieben.

Starlark ist eine Sprache, die definiert, wie Software erstellt wird. Daher ist es sowohl eine Programmier- als auch eine Konfigurationssprache.

Sie verwenden Starlark, um BUILD-Dateien, Makros und Build-Regeln zu schreiben. Makros und Regeln sind im Wesentlichen Metasprachen und bestimmen, wie BUILD-Dateien geschrieben werden. BUILD-Dateien sind einfach und wiederholen sich.

Die gesamte Software wird häufiger gelesen, als sie geschrieben wurde. Das gilt besonders für Starlark, da Entwickler BUILD-Dateien lesen, um die Abhängigkeiten ihrer Ziele und Details ihrer Builds zu verstehen. Das Lesen findet häufig statt, wenn Sie es eilig haben oder parallel eine andere Aufgabe erledigen. Daher sind Einfachheit und Lesbarkeit sehr wichtig, damit Nutzer BUILD-Dateien schnell parsen und verstehen können.

Wenn ein Nutzer eine BUILD-Datei öffnet, möchte er schnell die Liste der Ziele in der Datei sehen, die Liste der Quellen dieser C++-Bibliothek prüfen oder eine Abhängigkeit von dieser Java-Binärdatei entfernen. Jedes Mal, wenn Sie eine Abstraktionsebene hinzufügen, erschweren Sie es einem Nutzer, diese Aufgaben zu erledigen.

BUILD-Dateien werden auch von vielen verschiedenen Tools analysiert und aktualisiert. Die Datei BUILD kann von Tools möglicherweise nicht bearbeitet werden, wenn sie Abstraktionen verwendet. Je einfacher Ihre BUILD-Dateien sind, desto besser sind die Tools. Wenn eine Codebasis wächst, wird es immer häufiger, Änderungen an vielen BUILD-Dateien vorzunehmen, um eine Bibliothek zu aktualisieren oder eine Bereinigung durchzuführen.

Allgemeine Empfehlungen

Stil

Python-Stil

Im Zweifelsfall sollten Sie den PEP 8-Stilrichtlinien folgen. Verwenden Sie für die Einrückung vier statt zwei Leerzeichen, um der Python-Konvention zu folgen.

Da Starlark nicht Python ist, gelten einige Aspekte des Python-Stils nicht. Beispielsweise weist PEP 8 darauf hin, dass Vergleiche mit Singleton-Stoffen mit is durchgeführt werden, was in Starlark kein Operator ist.

Dock

Dokumentdateien und Funktionen mithilfe von docstrings Verwenden Sie oben in jeder .bzl-Datei einen Docstring und für jede öffentliche Funktion einen Docstring.

Dokumentregeln und Aspekte

Regeln und Aspekte sowie ihre Attribute sowie Anbieter und deren Felder sollten mit dem Argument doc dokumentiert werden.

Namenskonvention

  • Variablen und Funktionsnamen enthalten Kleinbuchstaben, in denen Wörter durch Unterstriche ([a-z][a-z0-9_]*) voneinander getrennt sind, z. B. cc_library.
  • Private Werte auf oberster Ebene beginnen mit einem Unterstrich. Bazel erzwingt, dass private Werte nicht aus anderen Dateien verwendet werden können. Lokale Variablen dürfen kein Unterstrich enthalten.

Zeilenlänge

Wie bei BUILD-Dateien gibt es auch hier keine strenge Längenbeschränkung, da Labels lang sein können. Verwenden Sie nach Möglichkeit maximal 79 Zeichen pro Zeile. Beachten Sie dabei den Python-Stilrichtlinien PEP 8. Diese Richtlinie sollte nicht streng durchgesetzt werden: Mitbearbeiter sollten mehr als 80 Spalten anzeigen, bei automatischen Änderungen werden oft längere Zeilen eingefügt und Menschen sollten keine Zeilen aufteilen, die bereits lesbar sind.

Keyword-Argumente

In Keyword-Argumenten werden Leerzeichen vor und nach dem Gleichheitszeichen bevorzugt:

def fct(name, srcs):
    filtered_srcs = my_filter(source = srcs)
    native.cc_library(
        name = name,
        srcs = filtered_srcs,
        testonly = True,
    )

Boolesche Werte

Ziehen Sie die Werte True und False (statt 1 und 0) für boolesche Werte vor, z. B. wenn Sie ein boolesches Attribut in einer Regel verwenden.

Verwenden Sie die Funktion print() nicht im Produktionscode. Sie ist nur zur Fehlerbehebung vorgesehen und wird alle direkten und indirekten Nutzer Ihrer .bzl-Datei als Spam markieren. Die einzige Ausnahme ist, dass Sie Code senden können, der print() verwendet, wenn er standardmäßig deaktiviert ist und nur durch Bearbeiten der Quelle aktiviert werden kann. Das ist beispielsweise der Fall, wenn alle Verwendungszwecke von print() durch if DEBUG: geschützt sind, wenn DEBUG hartcodiert auf False ist. Überlegen Sie, ob diese Aussagen nützlich genug sind, um die Auswirkungen auf die Lesbarkeit zu rechtfertigen.

Makros

Ein Makro ist eine Funktion, die während der Ladephase eine oder mehrere Regeln instanziiert. Verwenden Sie nach Möglichkeit Regeln anstelle von Makros. Die Build-Grafik, die der Nutzer sieht, ist nicht dieselbe wie die, die Bazel während des Builds verwendet. Makros werden erweitert, bevor Bazel eine Build-Grafikanalyse durchführt.

Wenn etwas schiefgeht, muss der Nutzer deshalb die Implementierung des Makros verstehen, um Build-Probleme zu beheben. Außerdem können bazel query-Ergebnisse schwierig zu interpretieren sein, da die in den Ergebnissen angezeigten Ziele auf die Makroerweiterung zurückzuführen sind. Außerdem sind Aspekte bei Makros nicht erkannt, sodass verschiedene Tools (IDEs und andere) nicht funktionieren.

Ein sicherer Einsatz von Makros ist zum Definieren zusätzlicher Ziele, auf die direkt in der Bazel-CLI oder in BUILD-Dateien verwiesen werden soll: In diesem Fall müssen nur die Endnutzer dieser Ziele über sie informiert sein und alle durch Makros verursachten Build-Probleme sind nie weit von ihrer Nutzung entfernt.

Beachten Sie die folgenden Best Practices für Makros, die generierte Ziele definieren (Implementierungsdetails zum Makro, auf die in der Befehlszeile nicht verwiesen werden soll oder die von Zielen abhängen, die nicht durch dieses Makro instanziiert werden):

  • Ein Makro muss ein Argument name verwenden und ein Ziel mit diesem Namen definieren. Dieses Ziel wird zum Hauptziel des Makros.
  • Für generierte Ziele, also alle anderen durch ein Makro definierten Ziele, gilt Folgendes:
    • Den Namen muss das Präfix <name> oder _<name> vorangestellt werden. Beispiel: name = '%s_bar' % (name).
    • eingeschränkte Sichtbarkeit haben (//visibility:private) und
    • Verwende ein manual-Tag, um eine Erweiterung in Platzhalterzielen zu vermeiden (:all, ..., :* usw.).
  • Die name sollte nur zum Ableiten der Namen von Zielen verwendet werden, die durch das Makro definiert werden, nicht für andere Zwecke. Verwenden Sie beispielsweise nicht den Namen, um eine Abhängigkeits- oder Eingabedatei abzuleiten, die nicht vom Makro selbst generiert wird.
  • Alle im Makro erstellten Ziele sollten in irgendeiner Weise mit dem Hauptziel verknüpft sein.
  • Achten Sie darauf, dass die Parameternamen im Makro konsistent sind. Wenn ein Parameter als Attributwert an das Hauptziel übergeben wird, behalten Sie seinen Namen bei. Wenn ein Makroparameter denselben Zweck wie ein allgemeines Regelattribut hat, z. B. deps, benennen Sie den Namen so, wie Sie es angeben würden (siehe unten).
  • Verwenden Sie beim Aufrufen eines Makros nur Keyword-Argumente. Dies entspricht den Regeln und verbessert die Lesbarkeit stark.

Entwickler schreiben häufig Makros, wenn die Starlark API der relevanten Regeln für ihren speziellen Anwendungsfall nicht ausreicht, unabhängig davon, ob die Regel in Bazel im nativen Code oder in Starlark definiert ist. Wenn dieses Problem bei Ihnen auftritt, fragen Sie den Autor der Regel, ob er die API erweitern kann, um Ihre Ziele zu erreichen.

Als Faustregel gilt, je mehr Makros den Regeln ähneln, desto besser.

Weitere Informationen zu Makros

Regeln

  • Regeln, Aspekte und ihre Attribute sollten Kleinbuchstaben enthalten ("snake case").
  • Regelnamen sind Nomen, die die Hauptart des von der Regel erzeugten Artefakts beschreiben. Dies gilt für die Abhängigkeiten der Regel (oder für die Blattregeln, den Nutzer). Das ist nicht unbedingt ein Dateisuffix. Eine Regel, die C++-Artefakte erzeugt, die als Python-Erweiterungen verwendet werden sollen, wird beispielsweise py_extension genannt. Zu den meisten Sprachen gehören:
    • *_library: eine Zusammenstellungseinheit oder "module"
    • *_binary: ein Ziel, das eine ausführbare Datei oder eine Bereitstellungseinheit erzeugt.
    • *_test: ein Testziel. Dies kann mehrere Tests umfassen. Alle Tests in einem *_test-Ziel müssen Varianten desselben Themas sein, z. B. das Testen einer einzelnen Bibliothek.
    • *_import: ein Ziel, das ein vorkompiliertes Artefakt einschließt, z. B. ein .jar oder ein .dll, das bei der Kompilierung verwendet wird.
  • Verwenden Sie für Attribute dieselben Namen und Typen. Einige allgemein anwendbare Attribute sind:
    • srcs: label_list, durch die Dateien zugelassen werden: Quelldateien, normalerweise von Menschen erstellt.
    • deps: label_list, für die normalerweise keine Dateien zulässig sind: Kompilierungsabhängigkeiten.
    • data: label_list, durch die Dateien zugelassen werden: Datendateien wie Testdaten usw.
    • runtime_deps: label_list: Laufzeitabhängigkeiten, die für die Kompilierung nicht erforderlich sind.
  • Stellen Sie für alle Attribute mit nicht offensichtlichem Verhalten (z. B. Stringvorlagen mit speziellen Ersetzungen oder Tools, die mit bestimmten Anforderungen aufgerufen werden), die Dokumentation mit dem Schlüsselwort doc für die Deklaration des Attributs (attr.label_list() oder Ähnliches) bereit.
  • Regelimplementierungsfunktionen sollten fast immer private Funktionen sein, die mit einem führenden Unterstrich benannt sind. Ein gängiger Stil besteht darin, der Implementierungsfunktion für myrule den Namen _myrule_impl zu geben.
  • Übergeben Sie Informationen zwischen Ihren Regeln über eine klar definierte Anbieterschnittstelle. Deklarieren Sie die Felder des Dokumentanbieters und geben Sie sie an.
  • Berücksichtigen Sie die Erweiterbarkeit. Beachten Sie, dass andere Regeln möglicherweise mit Ihrer Regel interagieren, auf Ihre Anbieter zugreifen und die von Ihnen erstellten Aktionen wiederverwenden möchten.
  • Beachten Sie in Ihren Regeln die Leistungsrichtlinien.