mirror of
https://github.com/esp-rs/esp-hal.git
synced 2025-09-28 21:00:59 +00:00
Make xtask work on Windows, add run-example
command (#1215)
* Make xtask work on Windows, add `run-example` command * Fix xtask for non-Windows users * Use `find_map`
This commit is contained in:
parent
0c99d8bb60
commit
e81957ee98
@ -13,7 +13,7 @@ pub fn run(args: &[String], cwd: &Path) -> Result<()> {
|
||||
bail!("The `cwd` argument MUST be a directory");
|
||||
}
|
||||
|
||||
let status = Command::new("cargo")
|
||||
let status = Command::new(get_cargo())
|
||||
.args(args)
|
||||
.current_dir(cwd)
|
||||
.stdout(Stdio::piped())
|
||||
@ -29,6 +29,37 @@ pub fn run(args: &[String], cwd: &Path) -> Result<()> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Execute cargo with the given arguments and from the specified directory.
|
||||
pub fn run_with_input(args: &[String], cwd: &Path) -> Result<()> {
|
||||
if !cwd.is_dir() {
|
||||
bail!("The `cwd` argument MUST be a directory");
|
||||
}
|
||||
|
||||
let _status = Command::new(get_cargo())
|
||||
.args(args)
|
||||
.current_dir(cwd)
|
||||
.stdout(std::process::Stdio::inherit())
|
||||
.stderr(std::process::Stdio::inherit())
|
||||
.stdin(std::process::Stdio::inherit())
|
||||
.status()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_cargo() -> String {
|
||||
#[cfg(target_os = "windows")]
|
||||
let cargo = if let Ok(cargo) = std::env::var("CARGO_HOME") {
|
||||
format!("{cargo}/bin/cargo")
|
||||
} else {
|
||||
String::from("cargo")
|
||||
};
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
let cargo = String::from("cargo");
|
||||
|
||||
cargo
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct CargoArgsBuilder {
|
||||
toolchain: Option<String>,
|
||||
|
@ -131,7 +131,7 @@ pub fn build_documentation(
|
||||
open: bool,
|
||||
) -> Result<()> {
|
||||
let package_name = package.to_string();
|
||||
let package_path = workspace.join(&package_name);
|
||||
let package_path = windows_safe_path(&workspace.join(&package_name));
|
||||
|
||||
log::info!("Building '{package_name}' documentation targeting '{chip}'");
|
||||
|
||||
@ -146,6 +146,11 @@ pub fn build_documentation(
|
||||
builder = builder.arg("--open");
|
||||
}
|
||||
|
||||
// If targeting an Xtensa device, we must use the '+esp' toolchain modifier:
|
||||
if target.starts_with("xtensa") {
|
||||
builder = builder.toolchain("esp");
|
||||
}
|
||||
|
||||
let args = builder.build();
|
||||
log::debug!("{args:#?}");
|
||||
|
||||
@ -160,7 +165,7 @@ pub fn load_examples(path: &Path) -> Result<Vec<Metadata>> {
|
||||
let mut examples = Vec::new();
|
||||
|
||||
for entry in fs::read_dir(path)? {
|
||||
let path = entry?.path();
|
||||
let path = windows_safe_path(&entry?.path());
|
||||
let text = fs::read_to_string(&path)?;
|
||||
|
||||
let mut chips = Vec::new();
|
||||
@ -254,6 +259,55 @@ pub fn build_example(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Run the specified example for the specified chip.
|
||||
pub fn run_example(
|
||||
package_path: &Path,
|
||||
chip: Chip,
|
||||
target: &str,
|
||||
example: &Metadata,
|
||||
) -> Result<()> {
|
||||
log::info!(
|
||||
"Building example '{}' for '{}'",
|
||||
example.example_path().display(),
|
||||
chip
|
||||
);
|
||||
if !example.features().is_empty() {
|
||||
log::info!(" Features: {}", example.features().join(","));
|
||||
}
|
||||
|
||||
let bin = if example
|
||||
.example_path()
|
||||
.strip_prefix(package_path)?
|
||||
.starts_with("src/bin")
|
||||
{
|
||||
format!("--bin={}", example.name())
|
||||
} else {
|
||||
format!("--example={}", example.name())
|
||||
};
|
||||
|
||||
let mut features = example.features().to_vec();
|
||||
features.push(chip.to_string());
|
||||
|
||||
let mut builder = CargoArgsBuilder::default()
|
||||
.subcommand("run")
|
||||
.arg("-Zbuild-std=alloc,core")
|
||||
.arg("--release")
|
||||
.target(target)
|
||||
.features(&features)
|
||||
.arg(bin);
|
||||
|
||||
// If targeting an Xtensa device, we must use the '+esp' toolchain modifier:
|
||||
if target.starts_with("xtensa") {
|
||||
builder = builder.toolchain("esp");
|
||||
}
|
||||
|
||||
let args = builder.build();
|
||||
log::debug!("{args:#?}");
|
||||
|
||||
cargo::run_with_input(&args, package_path)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Build the specified package, using the given toolchain/target/features if
|
||||
/// provided.
|
||||
pub fn build_package(
|
||||
@ -332,3 +386,8 @@ pub fn bump_version(workspace: &Path, package: Package, amount: Version) -> Resu
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Make the path "Windows"-safe
|
||||
pub fn windows_safe_path(path: &Path) -> PathBuf {
|
||||
PathBuf::from(path.to_str().unwrap().to_string().replace("\\\\?\\", ""))
|
||||
}
|
||||
|
@ -16,6 +16,8 @@ enum Cli {
|
||||
BuildExamples(BuildExamplesArgs),
|
||||
/// Build the specified package with the given options.
|
||||
BuildPackage(BuildPackageArgs),
|
||||
/// Run the given example for the specified chip.
|
||||
RunExample(RunExampleArgs),
|
||||
/// Bump the version of the specified package(s)
|
||||
BumpVersion(BumpVersionArgs),
|
||||
}
|
||||
@ -59,6 +61,18 @@ struct BuildPackageArgs {
|
||||
toolchain: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Args)]
|
||||
struct RunExampleArgs {
|
||||
/// Package to run example from.
|
||||
#[arg(value_enum)]
|
||||
package: Package,
|
||||
/// Which chip to run the examples for.
|
||||
#[arg(value_enum)]
|
||||
chip: Chip,
|
||||
/// Which example to run
|
||||
example: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Args)]
|
||||
struct BumpVersionArgs {
|
||||
/// How much to bump the version by.
|
||||
@ -84,6 +98,7 @@ fn main() -> Result<()> {
|
||||
Cli::BuildDocumentation(args) => build_documentation(&workspace, args),
|
||||
Cli::BuildExamples(args) => build_examples(&workspace, args),
|
||||
Cli::BuildPackage(args) => build_package(&workspace, args),
|
||||
Cli::RunExample(args) => run_example(&workspace, args),
|
||||
Cli::BumpVersion(args) => bump_version(&workspace, args),
|
||||
}
|
||||
}
|
||||
@ -119,7 +134,7 @@ fn build_examples(workspace: &Path, mut args: BuildExamplesArgs) -> Result<()> {
|
||||
}
|
||||
|
||||
// Absolute path of the package's root:
|
||||
let package_path = workspace.join(args.package.to_string());
|
||||
let package_path = xtask::windows_safe_path(&workspace.join(args.package.to_string()));
|
||||
|
||||
// Absolute path to the directory containing the examples:
|
||||
let example_path = if args.package == Package::Examples {
|
||||
@ -142,12 +157,62 @@ fn build_examples(workspace: &Path, mut args: BuildExamplesArgs) -> Result<()> {
|
||||
|
||||
fn build_package(workspace: &Path, args: BuildPackageArgs) -> Result<()> {
|
||||
// Absolute path of the package's root:
|
||||
let package_path = workspace.join(args.package.to_string());
|
||||
let package_path = xtask::windows_safe_path(&workspace.join(args.package.to_string()));
|
||||
|
||||
// Build the package using the provided features and/or target, if any:
|
||||
xtask::build_package(&package_path, args.features, args.toolchain, args.target)
|
||||
}
|
||||
|
||||
fn run_example(workspace: &Path, mut args: RunExampleArgs) -> Result<()> {
|
||||
// Ensure that the package/chip combination provided are valid:
|
||||
validate_package_chip(&args.package, &args.chip)?;
|
||||
|
||||
// If the 'esp-hal' package is specified, what we *really* want is the
|
||||
// 'examples' package instead:
|
||||
if args.package == Package::EspHal {
|
||||
log::warn!(
|
||||
"Package '{}' specified, using '{}' instead",
|
||||
Package::EspHal,
|
||||
Package::Examples
|
||||
);
|
||||
args.package = Package::Examples;
|
||||
}
|
||||
|
||||
// Absolute path of the package's root:
|
||||
let package_path = xtask::windows_safe_path(&workspace.join(args.package.to_string()));
|
||||
|
||||
// Absolute path to the directory containing the examples:
|
||||
let example_path = if args.package == Package::Examples {
|
||||
package_path.join("src").join("bin")
|
||||
} else {
|
||||
package_path.join("examples")
|
||||
};
|
||||
|
||||
// Determine the appropriate build target for the given package and chip:
|
||||
let target = target_triple(&args.package, &args.chip)?;
|
||||
|
||||
// Load all examples and parse their metadata:
|
||||
let example = xtask::load_examples(&example_path)?
|
||||
.iter()
|
||||
// Filter down the examples to only those for which the specified chip is supported:
|
||||
.filter(|example| example.supports_chip(args.chip))
|
||||
.find_map(|example| {
|
||||
if example.name() == args.example {
|
||||
Some(example.clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
|
||||
if let Some(example) = example {
|
||||
xtask::run_example(&package_path, args.chip, target, &example)?;
|
||||
} else {
|
||||
log::error!("Example not found or unsupported for the given chip");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn bump_version(workspace: &Path, args: BumpVersionArgs) -> Result<()> {
|
||||
// Bump the version by the specified amount for each given package:
|
||||
for package in args.packages {
|
||||
|
Loading…
x
Reference in New Issue
Block a user