cargo-raze est actuellement un produit non maintenu et non pris en charge .
crate_universe
dans rules_rust
est un produit pris en charge et maintenu avec des objectifs similaires.
Nous pensons que crate_universe
prend en charge toutes les fonctionnalités prises en charge par cargo-raze. Nous vous encourageons à essayer d’y migrer. Si vous trouvez un support manquant ou des bugs, veuillez signaler un problème ou un PR contre rules_rust
.
cargo-raze
a été archivé pour refléter la réalité selon laquelle il est peu probable que les PR et les problèmes déposés contre lui soient résolus.
Veuillez contacter #rust dans Bazel Slack si vous souhaitez prendre en charge la maintenance de ce projet.
Un plugin Cargo de support expérimental pour distiller un Cargo.toml au niveau de l'espace de travail dans des cibles BUILD dont le code utilisant Rules_rust peut dépendre directement.
Il ne s'agit pas d'un produit officiel de Google (expérimental ou autre), c'est simplement du code qui appartient à Google.
Ce projet synthétise la logique de résolution des dépendances et certaines fonctionnalités de Cargo telles que les fonctionnalités et construit des scripts en règles exécutables que Bazel peut exécuter pour compiler des caisses Rust. Bien que les règles standards_rust puissent être utilisées pour compiler du code Rust à partir de zéro, la granularité fine de l'écosystème de dépendances rend la transformation des arbres de dépendances basés sur cet écosystème onéreuse, même pour du code avec peu de dépendances.
cargo-raze peut générer des cibles constructibles dans l'un des deux modes suivants : avec ou sans vente. En mode vente, les développeurs utilisent la sous-commande common cargo vendor
pour récupérer les dépendances indiquées par leur espace de travail Cargo.toml dans des répertoires que cargo-raze remplit ensuite avec des fichiers BUILD. En mode non-vendeur, cargo-raze génère une liste plate de fichiers BUILD et une macro au niveau de l'espace de travail qui peut être invoquée dans le fichier WORKSPACE pour extraire automatiquement les dépendances de la même manière que Cargo lui-même.
Dans les deux cas, la première étape consiste à décider où situer les dépendances Cargo dans l’espace de travail. Cette bibliothèque a été conçue en pensant aux monorepos, dans lesquels une organisation décide d'un ensemble de dépendances que tout le monde désigne. Il est prévu que les parties prenantes des dépendances collaborent pour mettre à niveau les dépendances de manière atomique et corrigent simultanément les pannes dans leur base de code. Dans le cas où cela ne serait pas réalisable, il est toujours possible d'utiliser cargo-raze dans un scénario décentralisé, mais il est peu probable que de tels référentiels découplés interagissent bien avec la mise en œuvre actuelle.
Quelle que soit l'approche choisie, les rust_rules doivent être introduites dans l'ESPACE DE TRAVAIL. Voici un exemple :
load ( "@bazel_tools//tools/build_defs/repo:http.bzl" , "http_archive" )
http_archive (
name = "rules_rust" ,
sha256 = "accb5a89cbe63d55dcdae85938e56ff3aa56f21eb847ed826a28a83db8500ae6" ,
strip_prefix = "rules_rust-9aa49569b2b0dacecc51c05cee52708b7255bd98" ,
urls = [
# Main branch as of 2021-02-19
"https://github.com/bazelbuild/rules_rust/archive/9aa49569b2b0dacecc51c05cee52708b7255bd98.tar.gz" ,
],
)
load ( "@rules_rust//rust:repositories.bzl" , "rust_repositories" )
rust_repositories ( edition = "2018" )
Pour les projets Bazel uniquement, les utilisateurs doivent d'abord générer un Cargo.toml standard avec les dépendances qui les intéressent. Prenez soin d'inclure une directive [lib]
afin que Cargo ne se plaigne pas des fichiers sources manquants pour cette caisse fictive. Voici un exemple :
[ package ]
name = " compile_with_bazel "
version = " 0.0.0 "
# Mandatory (or Cargo tooling is unhappy)
[ lib ]
path = " fake_lib.rs "
[ dependencies ]
log = " =0.3.6 "
Une fois le Cargo.toml standard en place, ajoutez les directives [package.metadata.raze]
selon la section suivante.
Presque toutes les configurations de fret canoniques devraient pouvoir fonctionner sur place avec cargo-raze
. En supposant que l'espace de travail Cargo soit désormais imbriqué sous un espace de travail Bazel, les utilisateurs peuvent simplement ajouter RazeSettings à leurs fichiers Cargo.toml à utiliser pour générer des fichiers Bazel.
# Above this line should be the contents of your Cargo.toml file
[ package . metadata . raze ]
# The path at which to write output files.
#
# `cargo raze` will generate Bazel-compatible BUILD files into this path.
# This can either be a relative path (e.g. "foo/bar"), relative to this
# Cargo.toml file; or relative to the Bazel workspace root (e.g. "//foo/bar").
workspace_path = " //cargo "
# This causes aliases for dependencies to be rendered in the BUILD
# file located next to this `Cargo.toml` file.
package_aliases_dir = " . "
# The set of targets to generate BUILD rules for.
targets = [
" x86_64-apple-darwin " ,
" x86_64-pc-windows-msvc " ,
" x86_64-unknown-linux-gnu " ,
]
# The two acceptable options are "Remote" and "Vendored" which
# is used to indicate whether the user is using a non-vendored or
# vendored set of dependencies.
genmode = " Remote "
Dans les projets qui utilisent des espaces de travail Cargo, les utilisateurs doivent organiser tous leurs paramètres raze
dans le champ [workspace.metadata.raze]
du fichier Cargo.toml
de niveau supérieur qui contient la définition [workspace]
. Ces paramètres doivent être identiques à ceux vus dans [package.metadata.raze]
dans la section précédente. Cependant, les paramètres de caisse peuvent toujours être placés dans les fichiers Cargo.toml
des membres de l'espace de travail :
# Above this line should be the contents of your package's Cargo.toml file
# Note that `some-dependency` is the name of an example dependency and
# `<0.3.0` is a semver version for the dependency crate's version. This
# should always be compaitble in some way with the dependency version
# specified in the `[dependencies]` section of the package defined in
# this file
[ package . metadata . raze . crates . some-dependency . '<0 . 3 . 0' ]
additional_flags = [
" --cfg=optional_feature_a " ,
" --cfg=optional_feature_b " ,
]
# This demonstrates that multiple crate settings may be defined.
[ package . metadata . raze . crates . some-other-dependency . '*' ]
additional_flags = [
" --cfg=special_feature " ,
]
En mode distant, un répertoire similaire au mode de vente est sélectionné. Dans ce cas, cependant, il ne contient que des fichiers BUILD, une instruction de vente pour WORKSPACE et des alias pour les dépendances explicites. Une plomberie légèrement différente est requise.
Cela indique à Raze de ne pas s'attendre à ce que les dépendances soient vendues et de générer des fichiers différents.
Tout d’abord, installez cargo-raze.
$ cargo install cargo-raze
Ensuite, exécutez cargo raze depuis le répertoire cargo
$ cargo raze
Enfin, appelez la fonction de récupération de bibliothèque distante dans votre WORKSPACE :
load ( "//cargo:crates.bzl" , "raze_fetch_remote_crates" )
# Note that this method's name depends on your gen_workspace_prefix setting.
# `raze` is the default prefix.
raze_fetch_remote_crates ()
Cela indique à Bazel d'où obtenir les dépendances et comment les construire : en utilisant les fichiers générés dans //cargo
.
Vous pouvez dépendre de n'importe quelle dépendance explicite dans n'importe quelle règle Rust en dépendant de //cargo:your_dependency_name
.
En mode Vendoring, une racine est directement sélectionnée pour héberger les dépendances vendues et devenir la passerelle vers ces règles de construction. //cargo
est conventionnel, mais //third_party/cargo
peut être souhaitable pour satisfaire les besoins organisationnels. La vente directement à la racine n'est pas bien prise en charge en raison de particularités spécifiques à l'implémentation, mais elle pourrait être prise en charge à l'avenir. À partir de maintenant, //cargo
sera le répertoire supposé.
Tout d’abord, installez les outils requis pour la vente et la génération de cibles constructibles.
$ cargo install cargo-raze
Ensuite, vendez vos dépendances à partir du répertoire cargo/. Cela mettra également à jour votre fichier Cargo.lock
.
$ cargo vendor --versioned-dirs
Enfin, générez vos fichiers BUILD, toujours à partir du répertoire cargo/
$ cargo raze
Vous pouvez désormais dépendre de n'importe quelle dépendance explicite dans n'importe quelle règle Rust en dépendant de //cargo:your_dependency_name
.
Cargo-raze peut être entièrement construit dans Bazel et utilisé sans avoir besoin de configurer la cargaison sur la machine hôte. Pour ce faire, ajoutez simplement ce qui suit au fichier WORKSPACE de votre projet :
load ( "@bazel_tools//tools/build_defs/repo:http.bzl" , "http_archive" )
http_archive (
name = "cargo_raze" ,
sha256 = "c664e258ea79e7e4ec2f2b57bca8b1c37f11c8d5748e02b8224810da969eb681" ,
strip_prefix = "cargo-raze-0.11.0" ,
url = "https://github.com/google/cargo-raze/archive/v0.11.0.tar.gz" ,
)
load ( "@cargo_raze//:repositories.bzl" , "cargo_raze_repositories" )
cargo_raze_repositories ()
load ( "@cargo_raze//:transitive_deps.bzl" , "cargo_raze_transitive_deps" )
cargo_raze_transitive_deps ()
Une fois cela en place, les utilisateurs peuvent exécuter la cible @cargo_raze//:raze
pour générer de nouveaux fichiers BUILD. par exemple :
bazel run @cargo_raze//:raze -- --manifest-path= $( realpath /Cargo.toml )
Notez que les utilisateurs utilisant le genmode vendored
devront toujours vendre leurs dépendances d'une manière ou d'une autre, car cargo-raze
ne le fait pas actuellement pour vous.
Certaines caisses exécutent un "script de construction" qui, bien que techniquement illimité dans ce qu'il peut faire, fait généralement l'une des rares choses courantes.
Toutes les options notées ci-dessous sont énumérées dans le fichier src/settings.rs.
Dans certains cas, une caisse utilise uniquement des informations de base pour générer un fichier source Rust. Ces règles de scripts de construction peuvent réellement être exécutées et utilisées dans Bazel en incluant une directive dans votre Cargo.toml avant la génération :
[ package . metadata . raze . crates . clang-sys . '0 . 21 . 1' ]
gen_buildrs = true
Ce paramètre indique à cargo-raze de générer une cible rust_binary pour le script de construction et de diriger ses sorties générées (style OUT_DIR) vers la caisse parent.
Certains scripts de build émettent conditionnellement des directives vers la sortie standard que Cargo sait propager. Malheureusement, il n'est pas si simple de gérer les informations de dépendance générées au moment de la construction, donc si les indicateurs sont connus statiquement (peut-être, puisque la cible de compilation est connue statiquement), ils peuvent être fournis à partir du Cargo.toml, de la manière suivante
[ package . metadata . raze . crates . unicase . '2 . 1 . 0' ]
additional_flags = [
# Rustc is 1.15, enable all optional settings
" --cfg=__unicase__iter_cmp " ,
" --cfg=__unicase__defauler_hasher " ,
]
Les drapeaux ainsi fournis sont directement remis à rustc. Il peut être utile de se référer à la section build-script de la documentation pour interpréter les scripts de build et les directives stdout rencontrés, disponible ici : https://doc.rust-lang.org/cargo/reference/build-scripts.html
Il existe deux manières de fournir les bibliothèques système dont une caisse a besoin pour la compilation. La première consiste à vendre directement la bibliothèque système, à créer une règle BUILD pour celle-ci et à ajouter la dépendance à la caisse -sys
correspondante. Pour openssl, cela peut ressembler en partie à :
[ package . metadata . raze . crates . openssl-sys . '0 . 9 . 24' ]
additional_flags = [
# Vendored openssl is 1.0.2m
" --cfg=ossl102 " ,
" --cfg=version=102 " ,
]
additional_deps = [
" @//third_party/openssl:crypto " ,
" @//third_party/openssl:ssl " ,
]
[ package . metadata . raze . crates . openssl . '0 . 10 . 2' ]
additional_flags = [
# Vendored openssl is 1.0.2m
" --cfg=ossl102 " ,
" --cfg=version=102 " ,
" --cfg=ossl10x " ,
]
Dans certains cas, il peut être préférable de câbler directement une dépendance du système local. Pour ce faire, reportez-vous à la section new_local_repository
de la documentation Bazel. Pour une version précompilée de llvm dans un WORKSPACE, cela peut ressembler à ceci :
new_local_repository (
name = "llvm" ,
build_file = "BUILD.llvm.bazel" ,
path = "/usr/lib/llvm-3.9" ,
)
Dans quelques cas, la caisse système devra peut-être être entièrement remplacée. Cela peut être facilité en supprimant et en complétant les dépendances dans Cargo.toml, pré-génération :
[ package . metadata . raze . crates . sdl2 . '0 . 31 . 0' ]
skipped_deps = [
" sdl2-sys-0.31.0 "
]
additional_deps = [
" @//cargo/overrides/sdl2-sys:sdl2_sys "
]
Certaines caisses fournissent des binaires utiles qui peuvent elles-mêmes être utilisées dans le cadre d'un processus de compilation : Bindgen en est un excellent exemple. Bindgen produit des fichiers sources Rust en traitant des fichiers C ou C++. Une directive peut être ajoutée au Cargo.toml pour indiquer à Bazel d'exposer ces binaires pour vous :
[ package . metadata . raze . crates . bindgen . '0 . 32 . 2' ]
gen_buildrs = true # needed to build bindgen
extra_aliased_targets = [
" cargo_bin_bindgen "
]
Cargo-raze préfixe les cibles binaires avec cargo_bin_
, car bien que Cargo autorise les binaires et les bibliothèques à partager le même nom de cible, Bazel l'interdit.
Actuellement, cargo ne collecte pas de métadonnées sur les caisses qui ne fournissent aucune bibliothèque. Cela signifie que ceux qui les spécifient dans la section [dependencies]
de votre fichier Cargo.toml
n'entraîneront pas de cibles Bazel générées. Cargo-raze a un champ spécial pour gérer ces caisses lors de l'utilisation genmode = "Remote"
:
[ package . metadata . raze . binary_deps ]
wasm-bindgen-cli = " 0.2.68 "
Dans l'extrait ci-dessus, la caisse wasm-bindgen-cli
est définie comme une dépendance binaire et Cargo-raze garantira que les métadonnées de cette caisse et de toute autre caisse définie ici sont incluses dans le répertoire de sortie résultant. Les fichiers de verrouillage pour les cibles spécifiées sous [package.metadata.raze.binary_deps]
seront générés dans un répertoire lockfiles
à l'intérieur du chemin spécifié par workspace_path
.
Notez que le champ binary_deps
peut être placé dans les métadonnées de l'espace de travail et du package. Cependant, une seule définition d'une dépendance binaire peut exister à la fois. Si vous disposez de plusieurs packages qui dépendent d’une seule dépendance binaire, cette définition doit être déplacée vers les métadonnées de l’espace de travail.
En définissant default_gen_buildrs sur true, cargo-raze générera des scripts de construction pour toutes les caisses qui en ont besoin :
[ package . metadata . raze ]
workspace_path = " //cargo "
genmode = " Remote "
default_gen_buildrs = true
Ce paramètre est un compromis entre commodité et exactitude. En l'activant, vous devriez constater que de nombreuses caisses fonctionnent sans avoir à spécifier explicitement d'indicateurs et sans avoir à activer manuellement des scripts de construction individuels. Mais en l'activant, vous autorisez toutes les caisses que vous utilisez à exécuter du code arbitraire au moment de la construction, et les actions qu'elles effectuent peuvent ne pas être hermétiques.
Même si ce paramètre est activé, vous devrez peut-être fournir des paramètres supplémentaires pour quelques caisses. Par exemple, la caisse en anneau a besoin d'accéder à l'arborescence source au moment de la construction :
[ package . metadata . raze . crates . ring . '*' ]
compile_data_attr = " glob([ " **/*.der " ]) "
Si vous souhaitez désactiver le script de build sur une caisse individuelle, vous pouvez le faire comme suit :
[ package . metadata . raze . crates . some_dependency . '*' ]
gen_buildrs = false
Bazel (« rapide », « correct », choisissez-en deux) est un système de construction éprouvé utilisé par Google pour compiler des projets multilingues incroyablement volumineux sans dupliquer les efforts et sans compromettre l'exactitude. Il y parvient en partie en limitant les mécanismes qu'un objet de compilation donné peut utiliser pour découvrir les dépendances et en forçant les unités constructibles à exprimer l'ensemble complet de leurs dépendances. Il s'attend à ce que deux ensembles identiques d'entrées cibles de construction produisent un résultat final équivalent octet par octet.
En échange, les utilisateurs sont récompensés par un système de construction personnalisable et extensible qui compile tout type de cible compilable et permet d'exprimer des « dépendances non conventionnelles », telles que des objets Protobuf, des shaders graphiques précompilés ou du code généré, tout en restant rapide et correct.
Il est également probable (bien que cela n'ait pas encore été démontré avec des tests de référence) que les grandes applications construites en gardant à l'esprit les atouts de Bazel : des unités de construction hautement granulaires, se compileront beaucoup plus rapidement car elles sont capables de mettre en cache de manière plus agressive et d'éviter la recompilation d'autant de code lors de l'itération.
Pour le meilleur ou pour le pire, l’écosystème Rust dépend fortement des caisses Cargo afin de fournir des fonctionnalités souvent présentes dans les bibliothèques standards. C'est en fait une chose fantastique pour l'évolution du langage, car il décrit un processus structuré de stabilisation (crate expérimentale -> caisse 1.0 -> RFC -> inclusion dans stdlib), mais cela signifie que les personnes qui n'ont pas accès à cet écosystème doivent réinventer de nombreuses roues.
En mettant cela de côté, il existe également des caisses fantastiques qui aident les développeurs Rust à interagir avec les systèmes et bibliothèques standard de l'industrie, ce qui peut considérablement accélérer le développement du langage.
Bien que la charge d'émuler les fonctionnalités de Cargo (lorsque cela est possible !) soit élevée, cela semble être le seul moyen de maintenir les garanties (exactitude, reproductibilité) dont dépend Bazel pour rester performant. Il est possible et probable qu'avec les RFC en vol, Cargo devienne suffisamment flexible pour lui permettre d'être utilisé directement pour la compilation, mais à ce stade, il semble qu'il soit en réalité plus facile de maintenir un semblant de parité des fonctionnalités que d'éviter toutes les arêtes vives introduites par traiter Cargo comme le compilateur Rust.
Avec un peu d'huile de coude, il est possible de construire presque tout, y compris des projets qui dépendent d'openssl-sys. De nombreuses caisses système nécessiteront d'identifier la bibliothèque système qu'elles enveloppent, et soit de la vendre dans le projet, soit d'indiquer à Bazel où elle se trouve sur votre système. Certains peuvent nécessiter des ajustements mineurs de la source, comme l'élimination des exigences de variables d'environnement de chargement codées en dur. Les correctifs peuvent être non triviaux dans quelques cas, mais un bon nombre des caisses les plus populaires ont été créées dans un exemple de dépôt, disponible sur https://github.com/acmcarther/cargo-raze-crater
Consultez ces exemples de configuration de caisse :
Utilisation du mode vendu :
Utilisation du mode distant :
Compilation d'OpenSSL :
La section [package.metadata.raze]
est dérivée d'une structure déclarée dans impl/src/settings.rs.