You've already forked comprehensive-rust
mirror of
https://github.com/google/comprehensive-rust.git
synced 2026-06-12 20:33:33 +02:00
bazel: migrate external mdbook plugins to Bazel
Configure mdbook-i18n-helpers, mdbook-linkcheck2, mdbook-pandoc, and mdbook-svgbob as Bazel external plugins using `rules_rust`. Update `xtask/src/main.rs` to build all preprocessor tools via Bazel, programmatically resolve their paths, copy them to `~/.cargo/bin`. This is a drop-in replacement for the old Cargo based approach. It will go away as we move the `mdbook build` call itself to Bazel, but it's useful in its own since it establishes that we can build the `mdbook` plugins with Bazel.
This commit is contained in:
@@ -13,6 +13,18 @@ use_repo(rust, "rust_toolchains")
|
||||
|
||||
register_toolchains("@rust_toolchains//:all")
|
||||
|
||||
rust_host_tools = use_extension("@rules_rust//rust:extensions.bzl", "rust_host_tools")
|
||||
rust_host_tools.host_tools(
|
||||
name = "rust_host_tools_nightly",
|
||||
sha256s = {
|
||||
"2025-09-01/cargo-nightly-x86_64-unknown-linux-gnu.tar.xz": "9a701f2eb103703c018518066fa7deb476f7ebab548b1c4e2ea0df81ee42a20f",
|
||||
"2025-09-01/rust-std-nightly-x86_64-unknown-linux-gnu.tar.xz": "b3c2d890d9405285e015ab4ceb78087e3ec55c64b0b3030d79102dfe5e622e09",
|
||||
"2025-09-01/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz": "7f5486ae6ece8a734149e5fce6dc8f1bcdcb36b5c5cb53a819569109b445c700",
|
||||
},
|
||||
version = "nightly/2025-09-01",
|
||||
)
|
||||
use_repo(rust_host_tools, "rust_host_tools_nightly")
|
||||
|
||||
crate = use_extension("@rules_rust//crate_universe:extensions.bzl", "crate")
|
||||
crate.from_cargo(
|
||||
name = "crates",
|
||||
@@ -20,3 +32,46 @@ crate.from_cargo(
|
||||
manifests = ["//:Cargo.toml"],
|
||||
)
|
||||
use_repo(crate, "crates")
|
||||
|
||||
# Repositories for mdbook plugins. Add new plugins to the
|
||||
# `mdbook_plugins` repository. If this fails due to conflicts in their
|
||||
# dependencies, isolate it below with additional repositories.
|
||||
crate.spec(
|
||||
artifact = "bin",
|
||||
package = "mdbook-i18n-helpers",
|
||||
repositories = ["mdbook_plugins"],
|
||||
version = "0.3.6",
|
||||
)
|
||||
crate.spec(
|
||||
artifact = "bin",
|
||||
package = "mdbook-linkcheck2",
|
||||
repositories = ["mdbook_plugins"],
|
||||
version = "0.9.1",
|
||||
)
|
||||
crate.spec(
|
||||
artifact = "bin",
|
||||
package = "mdbook-pandoc",
|
||||
repositories = ["mdbook_plugins"],
|
||||
version = "0.10.4",
|
||||
)
|
||||
crate.from_specs(
|
||||
name = "mdbook_plugins",
|
||||
generate_binaries = True,
|
||||
host_tools = "@rust_host_tools_nightly",
|
||||
)
|
||||
use_repo(crate, "mdbook_plugins")
|
||||
|
||||
# mdbook-svgbob depends transitively on sauron-core, which has a
|
||||
# "=0.3.30" dependency on futures. This conflicts with other plugins.
|
||||
crate.spec(
|
||||
artifact = "bin",
|
||||
package = "mdbook-svgbob",
|
||||
repositories = ["svgbob_plugin"],
|
||||
version = "0.2.2",
|
||||
)
|
||||
crate.from_specs(
|
||||
name = "svgbob_plugin",
|
||||
generate_binaries = True,
|
||||
host_tools = "@rust_host_tools_nightly",
|
||||
)
|
||||
use_repo(crate, "svgbob_plugin")
|
||||
|
||||
Generated
+8589
-1
File diff suppressed because one or more lines are too long
+62
-24
@@ -139,33 +139,46 @@ fn install_tools(binstall: bool) -> Result<()> {
|
||||
run_command(&mut cmd)?;
|
||||
}
|
||||
|
||||
// The --locked flag is important for reproducible builds.
|
||||
let tools = [
|
||||
("mdbook", "0.4.52"),
|
||||
("mdbook-svgbob", "0.2.2"),
|
||||
("mdbook-pandoc", "0.10.4"),
|
||||
("mdbook-i18n-helpers", "0.3.6"),
|
||||
("i18n-report", "0.2.0"),
|
||||
("mdbook-linkcheck2", "0.9.1"),
|
||||
];
|
||||
// Tools not yet migrated to be installed with Bazel.
|
||||
let tools = [("mdbook", "0.4.52"), ("i18n-report", "0.2.0")];
|
||||
|
||||
// The --locked flag is important for reproducible builds.
|
||||
for (tool, version) in tools {
|
||||
let mut cmd = Command::new(cargo);
|
||||
cmd.args([install_command, tool, "--version", version, "--locked"]);
|
||||
run_command(&mut cmd)?;
|
||||
}
|
||||
|
||||
// Install local tools from the workspace by building them with
|
||||
// Bazel.
|
||||
// Install local and external tools from the workspace by building
|
||||
// them with Bazel.
|
||||
let workspace_dir = Path::new(env!("CARGO_WORKSPACE_DIR"));
|
||||
|
||||
let bazel_tools = [
|
||||
("//mdbook-course", "mdbook-course"),
|
||||
("//mdbook-exerciser", "mdbook-exerciser"),
|
||||
("@mdbook_plugins//:mdbook-i18n-helpers__mdbook-gettext", "mdbook-gettext"),
|
||||
(
|
||||
"@mdbook_plugins//:mdbook-i18n-helpers__mdbook-xgettext",
|
||||
"mdbook-xgettext",
|
||||
),
|
||||
("@mdbook_plugins//:mdbook-pandoc__mdbook-pandoc", "mdbook-pandoc"),
|
||||
("@svgbob_plugin//:mdbook-svgbob__mdbook-svgbob", "mdbook-svgbob"),
|
||||
(
|
||||
"@mdbook_plugins//:mdbook-linkcheck2__mdbook-linkcheck2",
|
||||
"mdbook-linkcheck2",
|
||||
),
|
||||
];
|
||||
|
||||
let mut cmd = Command::new("bazel");
|
||||
cmd.current_dir(workspace_dir).args([
|
||||
"build",
|
||||
"//mdbook-course",
|
||||
"//mdbook-exerciser",
|
||||
]);
|
||||
cmd.arg("build");
|
||||
for (target, _) in &bazel_tools {
|
||||
cmd.arg(target);
|
||||
}
|
||||
cmd.current_dir(workspace_dir);
|
||||
run_command(&mut cmd)?;
|
||||
|
||||
// Copy compiled tools to ~/.cargo/bin, the same way `cargo
|
||||
// install` would.
|
||||
let cargo_home = match env::var("CARGO_HOME") {
|
||||
Ok(cargo_home) => PathBuf::from(cargo_home),
|
||||
Err(_) => {
|
||||
@@ -174,14 +187,21 @@ fn install_tools(binstall: bool) -> Result<()> {
|
||||
};
|
||||
let bin_dir = cargo_home.join("bin");
|
||||
|
||||
fs::copy(
|
||||
workspace_dir.join("bazel-bin/mdbook-course/mdbook-course"),
|
||||
bin_dir.join("mdbook-course"),
|
||||
)?;
|
||||
fs::copy(
|
||||
workspace_dir.join("bazel-bin/mdbook-exerciser/mdbook-exerciser"),
|
||||
bin_dir.join("mdbook-exerciser"),
|
||||
)?;
|
||||
for (target, name) in bazel_tools {
|
||||
let src = get_bazel_output_path(target)?;
|
||||
let dest = bin_dir.join(name);
|
||||
|
||||
// Bazel creates read-only files, which block subsequent runs.
|
||||
// We fix this by deleting the destination file, if it exists.
|
||||
if let Err(e) = fs::remove_file(&dest)
|
||||
&& e.kind() != std::io::ErrorKind::NotFound
|
||||
{
|
||||
return Err(anyhow!("Failed to remove {}: {}", dest.display(), e));
|
||||
}
|
||||
fs::copy(&src, &dest).with_context(|| {
|
||||
format!("Failed to copy {} to {}", src.display(), dest.display())
|
||||
})?;
|
||||
}
|
||||
|
||||
// Uninstall original linkcheck if currently installed (see issue no 2773)
|
||||
uninstall_mdbook_linkcheck()?;
|
||||
@@ -402,3 +422,21 @@ fn get_output_dir(language: Option<String>, output_arg: Option<PathBuf>) -> Path
|
||||
Path::new("book").join(language.unwrap_or("".to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Queries Bazel to find the output file path for a given target.
|
||||
fn get_bazel_output_path(target: &str) -> Result<PathBuf> {
|
||||
let output = Command::new("bazel")
|
||||
.args(["cquery", "--output=files", target])
|
||||
.output()
|
||||
.with_context(|| format!("Failed to run bazel cquery for {target}"))?;
|
||||
if !output.status.success() {
|
||||
return Err(anyhow!(
|
||||
"bazel cquery failed: {}",
|
||||
String::from_utf8_lossy(&output.stderr)
|
||||
));
|
||||
}
|
||||
let stdout = String::from_utf8(output.stdout)?;
|
||||
let relative_path = stdout.trim();
|
||||
let workspace_dir = Path::new(env!("CARGO_WORKSPACE_DIR"));
|
||||
Ok(workspace_dir.join(relative_path))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user