1
0
mirror of https://github.com/google/comprehensive-rust.git synced 2025-08-08 00:12:51 +02:00

Support setting language and output directory in cargo xtask (#2776)

In addition to simplifying building locally (no need to set an
environment variable), this makes it possible to use the `cargo xtask
build` command in the CI and specify any output location, rather than
relying on the build.sh script.

---------

Co-authored-by: Eric Githinji <egithinji@google.com>
This commit is contained in:
Eric Githinji
2025-07-31 12:54:26 +03:00
committed by GitHub
parent 16d25dbed7
commit 5fc5893fbf
2 changed files with 73 additions and 30 deletions

View File

@ -76,12 +76,12 @@ cargo xtask install-tools
Here is a summary of the various commands you can run in the project.
| Command | Description |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `cargo install-tools` | Install all the tools the project depends on. |
| `cargo serve` | Start a web server with the course. You'll find the content on http://localhost:3000. |
| `cargo serve` | Start a web server with the course. You'll find the content on http://localhost:3000. To serve any of the translated versions of the course, add the language flag (`--language` or `-l`) followed by xx, where xx is the ISO 639 language code (e.g. `cargo xtask serve -l da` for the Danish translation). |
| `cargo rust-tests` | Test the included Rust snippets. |
| `cargo web-tests` | Run the web driver tests in the tests directory. |
| `cargo build-book` | Create a static version of the course in the `book/` directory. Note that you have to separately build and zip exercises and add them to book/html. To build any of the translated versions of the course, run MDBOOK_BOOK__LANGUAGE=xx mdbook build -d book/xx where xx is the ISO 639 language code (e.g. da for the Danish translation). [TRANSLATIONS.md](TRANSLATIONS.md) contains further instructions. |
| `cargo build-book` | Create a static version of the course in the `book/` directory. Note that you have to separately build and zip exercises and add them to book/html. To build any of the translated versions of the course, add the language flag (`--language` or `-l`) followed by xx, where xx is the ISO 639 language code (e.g. `cargo xtask build -l da` for the Danish translation). [TRANSLATIONS.md](TRANSLATIONS.md) contains further instructions. |
> **Note** On Windows, you need to enable symlinks
> (`git config --global core.symlinks true`) and Developer Mode.

View File

@ -20,8 +20,8 @@
//! the tools.
use anyhow::{Ok, Result, anyhow};
use clap::{Parser, ValueEnum};
use std::path::Path;
use clap::{Parser, Subcommand};
use std::path::{Path, PathBuf};
use std::{env, process::Command};
fn main() -> Result<()> {
@ -38,11 +38,11 @@ fn main() -> Result<()> {
)]
struct Cli {
/// The task to execute
#[arg(value_enum)]
#[command(subcommand)]
task: Task,
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum)]
#[derive(Subcommand)]
enum Task {
/// Installs the tools the project depends on.
InstallTools,
@ -51,9 +51,25 @@ enum Task {
/// Tests all included Rust snippets.
RustTests,
/// Starts a web server with the course.
Serve,
/// Create a static version of the course in the `book/` directory.
Build,
Serve {
/// ISO 639 language code (e.g. da for the Danish translation).
#[arg(short, long)]
language: Option<String>,
/// Directory to place the build. If not provided, defaults to the book/ directory (or the book/xx directory if a language is provided).
#[arg(short, long)]
output: Option<PathBuf>,
},
/// Create a static version of the course.
Build {
/// ISO 639 language code (e.g. da for the Danish translation).
#[arg(short, long)]
language: Option<String>,
/// Directory to place the build. If not provided, defaults to the book/ directory (or the book/xx directory if a language is provided).
#[arg(short, long)]
output: Option<PathBuf>,
},
}
fn execute_task() -> Result<()> {
@ -62,15 +78,14 @@ fn execute_task() -> Result<()> {
Task::InstallTools => install_tools()?,
Task::WebTests => run_web_tests()?,
Task::RustTests => run_rust_tests()?,
Task::Serve => start_web_server()?,
Task::Build => build()?,
Task::Serve { language, output } => start_web_server(language, output)?,
Task::Build { language, output } => build(language, output)?,
}
Ok(())
}
fn install_tools() -> Result<()> {
println!("Installing project tools...");
let path_to_mdbook_exerciser =
Path::new(env!("CARGO_WORKSPACE_DIR")).join("mdbook-exerciser");
let path_to_mdbook_course =
@ -136,7 +151,6 @@ fn run_web_tests() -> Result<()> {
fn run_rust_tests() -> Result<()> {
println!("Running rust tests...");
let path_to_workspace_root = Path::new(env!("CARGO_WORKSPACE_DIR"));
let status = Command::new("mdbook")
@ -156,15 +170,26 @@ fn run_rust_tests() -> Result<()> {
Ok(())
}
fn start_web_server() -> Result<()> {
fn start_web_server(
language: Option<String>,
output_arg: Option<PathBuf>,
) -> Result<()> {
println!("Starting web server ...");
let path_to_workspace_root = Path::new(env!("CARGO_WORKSPACE_DIR"));
let status = Command::new("mdbook")
.current_dir(path_to_workspace_root.to_str().unwrap())
.arg("serve")
.status()
.expect("Failed to execute mdbook serve");
let mut command = Command::new("mdbook");
command.current_dir(path_to_workspace_root.to_str().unwrap());
command.arg("serve");
if let Some(language) = &language {
println!("Language: {}", &language);
command.env("MDBOOK_BOOK__LANGUAGE", &language);
}
command.arg("-d");
command.arg(get_output_dir(language, output_arg));
let status = command.status().expect("Failed to execute mdbook serve");
if !status.success() {
let error_message = format!(
@ -176,15 +201,23 @@ fn start_web_server() -> Result<()> {
Ok(())
}
fn build() -> Result<()> {
fn build(language: Option<String>, output_arg: Option<PathBuf>) -> Result<()> {
println!("Building course...");
let path_to_workspace_root = Path::new(env!("CARGO_WORKSPACE_DIR"));
let status = Command::new("mdbook")
.current_dir(path_to_workspace_root.to_str().unwrap())
.arg("build")
.status()
.expect("Failed to execute mdbook build");
let mut command = Command::new("mdbook");
command.current_dir(path_to_workspace_root.to_str().unwrap());
command.arg("build");
if let Some(language) = &language {
println!("Language: {}", &language);
command.env("MDBOOK_BOOK__LANGUAGE", language);
}
command.arg("-d");
command.arg(get_output_dir(language, output_arg));
let status = command.status().expect("Failed to execute mdbook build");
if !status.success() {
let error_message = format!(
@ -195,3 +228,13 @@ fn build() -> Result<()> {
}
Ok(())
}
fn get_output_dir(language: Option<String>, output_arg: Option<PathBuf>) -> PathBuf {
// If the 'output' arg is specified by the caller, use that, otherwise output to the 'book/' directory
// (or the 'book/xx' directory if a language was specified).
if let Some(d) = output_arg {
d
} else {
Path::new("book").join(language.unwrap_or("".to_string()))
}
}