Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions README.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@ ostool build --config custom-build.toml
# Temporarily override Cargo package / binary target
ostool build --config custom-build.toml --package paging-test --bin basic

# Temporarily build a Cargo test target
ostool build --config custom-build.toml --package paging-test --test kernel_axtest

# Build in specified working directory
ostool --workdir /path/to/project build
```
Expand All @@ -124,7 +127,7 @@ ostool run qemu --dtb-dump
# Run with specific Qemu config file
ostool run qemu --qemu-config my-qemu.toml

# Run after temporarily overriding Cargo package / binary target
# Run after temporarily overriding Cargo package / binary/test target
ostool run qemu --package paging-test --bin basic

# Run with U-Boot
Expand All @@ -142,7 +145,7 @@ ostool board ls
# Run on a remote board
ostool board run

# Run a specific Cargo binary target on a remote board
# Run a specific Cargo binary/test target on a remote board
ostool board run --package paging-test --bin basic
```

Expand Down Expand Up @@ -175,6 +178,11 @@ package = "my-os-kernel"
# set it here or pass `--bin <name>` when the package has multiple binaries.
bin = "my-os-kernel"

# Test target name. Use this for executable `[[test]]` targets, such as
# `harness = false` kernel tests. This is mutually exclusive with `bin`;
# it can also be selected with `--test <name>`.
# test = "my-os-kernel-axtest"

# Enabled features
features = ["page-alloc-4g"]

Expand Down Expand Up @@ -205,7 +213,7 @@ post_build_cmds = ["make post-process"]
to_bin = true
```

Command-line `--package`/`--bin` overrides are applied to the final Cargo
Command-line `--package`/`--bin`/`--test` overrides are applied to the final Cargo
selection before `${package}` variable expansion and someboot `build-info.toml`
argument injection.

Expand Down
13 changes: 10 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@ ostool build --config custom-build.toml
# 临时覆盖 Cargo package / binary target
ostool build --config custom-build.toml --package paging-test --bin basic

# 临时构建 Cargo test target
ostool build --config custom-build.toml --package paging-test --test kernel_axtest

# 在指定工作目录中构建
ostool --workdir /path/to/project build
```
Expand All @@ -124,7 +127,7 @@ ostool run qemu --dtb-dump
# 指定 Qemu 配置文件运行
ostool run qemu --qemu-config my-qemu.toml

# 临时覆盖 Cargo package / binary target 后运行
# 临时覆盖 Cargo package / binary/test target 后运行
ostool run qemu --package paging-test --bin basic

# 使用 U-Boot 运行
Expand All @@ -142,7 +145,7 @@ ostool board ls
# 在远端开发板上运行
ostool board run

# 在远端开发板上运行指定 Cargo binary target
# 在远端开发板上运行指定 Cargo binary/test target
ostool board run --package paging-test --bin basic
```

Expand Down Expand Up @@ -175,6 +178,10 @@ package = "my-os-kernel"
# 包内有多个 binary 时建议设置,或在命令行传 `--bin <name>`。
bin = "my-os-kernel"

# test target 名称。用于构建可执行 `[[test]]` 目标,例如 `harness = false`
# 的内核测试;与 `bin` 互斥,也可在命令行传 `--test <name>`。
# test = "my-os-kernel-axtest"

# 启用的特性
features = ["page-alloc-4g"]

Expand Down Expand Up @@ -204,7 +211,7 @@ post_build_cmds = ["make post-process"]
to_bin = false
```

命令行 `--package`/`--bin` 会先覆盖 `.build.toml` 中的 Cargo 包/二进制选择,再用于
命令行 `--package`/`--bin`/`--test` 会先覆盖 `.build.toml` 中的 Cargo 包/目标选择,再用于
`${package}` 变量展开和 someboot `build-info.toml` 自动参数注入。

#### 自定义构建系统示例
Expand Down
5 changes: 3 additions & 2 deletions ostool/src/board/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -400,11 +400,12 @@ dtb_file = "${package}/board.dtb"
crate::build::activate_build_config(
&mut invocation,
&BuildConfig {
system: BuildSystem::Cargo(Cargo {
system: BuildSystem::Cargo(Box::new(Cargo {
env: HashMap::new(),
target: "aarch64-unknown-none".into(),
package: "kernel".into(),
bin: None,
test: None,
features: vec![],
log: None,
extra_config: None,
Expand All @@ -414,7 +415,7 @@ dtb_file = "${package}/board.dtb"
pre_build_cmds: vec![],
post_build_cmds: vec![],
to_bin: false,
}),
})),
},
None,
)
Expand Down
2 changes: 1 addition & 1 deletion ostool/src/board/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ pub async fn cargo_run_board(
run_board(
invocation,
&BuildConfig {
system: BuildSystem::Cargo(cargo.clone()),
system: BuildSystem::Cargo(Box::new(cargo.clone())),
},
build_config_path,
board_config,
Expand Down
61 changes: 49 additions & 12 deletions ostool/src/build/artifact_selector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ impl CargoExecutableArtifact {
pub(crate) fn select_executable_artifact(
executable_artifacts: &[CargoExecutableArtifact],
explicit_bin: Option<&str>,
explicit_test: Option<&str>,
default_run: Option<&str>,
package: &str,
) -> anyhow::Result<ResolvedCargoArtifact> {
Expand All @@ -68,10 +69,21 @@ pub(crate) fn select_executable_artifact(
});
}

if let Some(test) = explicit_test {
return executable_artifacts
.iter()
.rev()
.find(|candidate| candidate.target_name() == test)
.map(|candidate| candidate.artifact().clone())
.ok_or_else(|| {
anyhow!(
"test target `{test}` was not built for package `{package}`; check system.Cargo.test or --test"
)
});
}

if executable_artifacts.is_empty() {
bail!(
"no executable bin artifact found in cargo JSON output for package `{package}`; ostool currently resolves only Cargo bin targets"
);
bail!("no executable artifact found in cargo JSON output for package `{package}`");
}

if let Some(candidate) = executable_artifacts
Expand Down Expand Up @@ -123,17 +135,18 @@ mod tests {
fn select(
artifacts: &[CargoExecutableArtifact],
explicit_bin: Option<&str>,
explicit_test: Option<&str>,
default_run: Option<&str>,
package: &str,
) -> anyhow::Result<ResolvedCargoArtifact> {
select_executable_artifact(artifacts, explicit_bin, default_run, package)
select_executable_artifact(artifacts, explicit_bin, explicit_test, default_run, package)
}

#[test]
fn select_executable_artifact_uses_explicit_bin_first() {
let artifacts = vec![candidate("kernel"), candidate("kernel-qemu")];

let selected = select(&artifacts, Some("kernel-qemu"), None, "kernel").unwrap();
let selected = select(&artifacts, Some("kernel-qemu"), None, None, "kernel").unwrap();

assert_eq!(
selected.elf_path(),
Expand All @@ -145,19 +158,43 @@ mod tests {
fn select_executable_artifact_errors_when_explicit_bin_was_not_built() {
let artifacts = vec![candidate("kernel")];

let err = select(&artifacts, Some("missing-bin"), None, "kernel").unwrap_err();
let err = select(&artifacts, Some("missing-bin"), None, None, "kernel").unwrap_err();

assert!(
err.to_string()
.contains("binary target `missing-bin` was not built")
);
}

#[test]
fn select_executable_artifact_uses_explicit_test_target() {
let artifacts = vec![candidate("kernel"), candidate("axtest_kernel")];

let selected = select(&artifacts, None, Some("axtest_kernel"), None, "kernel").unwrap();

assert_eq!(
selected.elf_path(),
Path::new("/tmp/ostool-target/debug/axtest_kernel")
);
}

#[test]
fn select_executable_artifact_errors_when_explicit_test_was_not_built() {
let artifacts = vec![candidate("kernel")];

let err = select(&artifacts, None, Some("missing-test"), None, "kernel").unwrap_err();

assert!(
err.to_string()
.contains("test target `missing-test` was not built")
);
}

#[test]
fn select_executable_artifact_prefers_package_name_before_default_run() {
let artifacts = vec![candidate("helper"), candidate("kernel")];

let selected = select(&artifacts, None, Some("helper"), "kernel").unwrap();
let selected = select(&artifacts, None, None, Some("helper"), "kernel").unwrap();

assert_eq!(
selected.elf_path(),
Expand All @@ -169,7 +206,7 @@ mod tests {
fn select_executable_artifact_uses_default_run_without_package_name_binary() {
let artifacts = vec![candidate("helper"), candidate("boot-test")];

let selected = select(&artifacts, None, Some("boot-test"), "kernel").unwrap();
let selected = select(&artifacts, None, None, Some("boot-test"), "kernel").unwrap();

assert_eq!(
selected.elf_path(),
Expand All @@ -181,7 +218,7 @@ mod tests {
fn select_executable_artifact_uses_single_binary_as_fallback() {
let artifacts = vec![candidate("helper")];

let selected = select(&artifacts, None, None, "kernel").unwrap();
let selected = select(&artifacts, None, None, None, "kernel").unwrap();

assert_eq!(
selected.elf_path(),
Expand All @@ -191,16 +228,16 @@ mod tests {

#[test]
fn select_executable_artifact_errors_on_empty_cargo_output() {
let err = select(&[], None, None, "kernel").unwrap_err();
let err = select(&[], None, None, None, "kernel").unwrap_err();

assert!(err.to_string().contains("no executable bin artifact found"));
assert!(err.to_string().contains("no executable artifact found"));
}

#[test]
fn select_executable_artifact_errors_on_ambiguous_multiple_binaries() {
let artifacts = vec![candidate("kernel-qemu"), candidate("kernel-uboot")];

let err = select(&artifacts, None, None, "kernel").unwrap_err();
let err = select(&artifacts, None, None, None, "kernel").unwrap_err();

let rendered = err.to_string();
assert!(rendered.contains("multiple binary targets"));
Expand Down
Loading
Loading