Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make cargo bootimage use cargo build instead of cargo xbuild #63

Merged
merged 10 commits into from
Jul 17, 2020
Merged
14 changes: 6 additions & 8 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,6 @@ jobs:

- name: "Install Rustup Components"
run: rustup component add rust-src llvm-tools-preview
- name: "Install cargo-xbuild"
run: cargo install cargo-xbuild --debug

# install QEMU
- name: Install QEMU (Linux)
Expand Down Expand Up @@ -103,20 +101,20 @@ jobs:
shell: bash {0}
working-directory: example-kernels

- name: 'Run `cargo xrun` for "runner" kernel'
- name: 'Run `cargo run` for "runner" kernel'
run: |
cargo xrun
cargo run
if [ $? -eq 109 ]; then (exit 0); else (exit 1); fi
shell: bash {0}
working-directory: example-kernels/runner

- run: cargo xtest
- run: cargo test
working-directory: example-kernels/runner-test
name: 'Run `cargo xtest` for "runner-test" kernel'
name: 'Run `cargo test` for "runner-test" kernel'

- run: cargo xtest -Z doctest-xcompile
- run: cargo test -Z doctest-xcompile
working-directory: example-kernels/runner-doctest
name: 'Run `cargo xtest -Z doctest-xcompile` for "runner-doctest" kernel'
name: 'Run `cargo test -Z doctest-xcompile` for "runner-doctest" kernel'

check_formatting:
name: "Check Formatting"
Expand Down
6 changes: 5 additions & 1 deletion Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Now you can build the kernel project and create a bootable disk image from it by
cargo bootimage --target your_custom_target.json [other_args]
```

The command will invoke [`cargo xbuild`](https://github.com/rust-osdev/cargo-xbuild), forwarding all passed options. Then it will build the specified bootloader together with the kernel to create a bootable disk image.
The command will invoke `cargo build`, forwarding all passed options. Then it will build the specified bootloader together with the kernel to create a bootable disk image.

### Running

Expand Down Expand Up @@ -60,6 +60,10 @@ Configuration is done through a through a `[package.metadata.bootimage]` table i

```toml
[package.metadata.bootimage]
# The cargo subcommand that will be used for building the kernel.
#
# For building using the `cargo-xbuild` crate, set this to `xbuild`.
build-command = ["build"]
# The command invoked with the created bootimage (the "{}" will be replaced
# with the path to the bootable disk image)
# Applies to `bootimage run` and `bootimage runner`
Expand Down
2 changes: 2 additions & 0 deletions example-kernels/.cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[unstable]
build-std = ["core", "compiler_builtins"]
21 changes: 15 additions & 6 deletions example-kernels/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion example-kernels/basic/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ authors = ["Philipp Oppermann <dev@phil-opp.com>"]
edition = "2018"

[dependencies]
bootloader = "0.9.3"
bootloader = "0.9.7"
x86_64 = "0.11.0"
3 changes: 2 additions & 1 deletion example-kernels/runner-doctest/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ authors = ["Philipp Oppermann <dev@phil-opp.com>"]
edition = "2018"

[dependencies]
bootloader = "0.9.3"
bootloader = "0.9.7"
x86_64 = "0.11.0"
rlibc = "1.0.0"

[package.metadata.bootimage]
test-success-exit-code = 33 # (0x10 << 1) | 1
Expand Down
2 changes: 2 additions & 0 deletions example-kernels/runner-doctest/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#![test_runner(crate::test_runner)]
#![reexport_test_harness_main = "test_main"]

extern crate rlibc;

/// add two numbers
///
/// ```
Expand Down
3 changes: 2 additions & 1 deletion example-kernels/runner-test/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ name = "no-harness"
harness = false

[dependencies]
bootloader = "0.9.3"
bootloader = "0.9.7"
x86_64 = "0.11.0"
rlibc = "1.0.0"

[package.metadata.bootimage]
test-success-exit-code = 33 # (0x10 << 1) | 1
Expand Down
2 changes: 2 additions & 0 deletions example-kernels/runner-test/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#![test_runner(crate::test_runner)]
#![reexport_test_harness_main = "test_main"]

extern crate rlibc;

pub fn test_runner(tests: &[&dyn Fn()]) {
for test in tests.iter() {
test();
Expand Down
2 changes: 1 addition & 1 deletion example-kernels/runner/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ authors = ["Philipp Oppermann <dev@phil-opp.com>"]
edition = "2018"

[dependencies]
bootloader = "0.9.3"
bootloader = "0.9.7"
x86_64 = "0.11.0"

[package.metadata.bootimage]
Expand Down
5 changes: 3 additions & 2 deletions src/bin/cargo-bootimage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use anyhow::{anyhow, Context, Result};
use bootimage::{
args::{BuildArgs, BuildCommand},
builder::Builder,
help,
config, help,
};
use std::{
env,
Expand Down Expand Up @@ -43,9 +43,10 @@ pub fn main() -> Result<()> {

fn build(args: BuildArgs) -> Result<()> {
let mut builder = Builder::new(args.manifest_path().map(PathBuf::from))?;
let config = config::read_config(builder.manifest_path())?;
let quiet = args.quiet();

let executables = builder.build_kernel(&args.cargo_args(), quiet)?;
let executables = builder.build_kernel(&args.cargo_args(), &config, quiet)?;
if executables.is_empty() {
return Err(anyhow!("no executables built"));
}
Expand Down
22 changes: 11 additions & 11 deletions src/builder/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,19 @@ pub enum BuildKernelError {
)]
XbuildNotFound,

/// Running `cargo xbuild` failed.
/// Running `cargo build` failed.
#[error("Kernel build failed.\nStderr: {}", String::from_utf8_lossy(.stderr))]
XbuildFailed {
BuildFailed {
/// The standard error output.
stderr: Vec<u8>,
},

/// The output of `cargo xbuild --message-format=json` was not valid UTF-8
/// The output of `cargo build --message-format=json` was not valid UTF-8
#[error("Output of kernel build with --message-format=json is not valid UTF-8:\n{0}")]
XbuildJsonOutputInvalidUtf8(std::string::FromUtf8Error),
/// The output of `cargo xbuild --message-format=json` was not valid JSON
BuildJsonOutputInvalidUtf8(std::string::FromUtf8Error),
/// The output of `cargo build --message-format=json` was not valid JSON
#[error("Output of kernel build with --message-format=json is not valid JSON:\n{0}")]
XbuildJsonOutputInvalidJson(json::Error),
BuildJsonOutputInvalidJson(json::Error),
}

/// Represents an error that occurred when creating a bootimage.
Expand All @@ -59,7 +59,7 @@ pub enum CreateBootimageError {
/// Building the bootloader failed
#[error("Bootloader build failed.\nStderr: {}", String::from_utf8_lossy(.stderr))]
BootloaderBuildFailed {
/// The `cargo xbuild` output to standard error
/// The `cargo build` output to standard error
stderr: Vec<u8>,
},

Expand All @@ -76,12 +76,12 @@ pub enum CreateBootimageError {
error: io::Error,
},

/// The output of `cargo xbuild --message-format=json` was not valid UTF-8
/// The output of `cargo build --message-format=json` was not valid UTF-8
#[error("Output of bootloader build with --message-format=json is not valid UTF-8:\n{0}")]
XbuildJsonOutputInvalidUtf8(std::string::FromUtf8Error),
/// The output of `cargo xbuild --message-format=json` was not valid JSON
BuildJsonOutputInvalidUtf8(std::string::FromUtf8Error),
/// The output of `cargo build --message-format=json` was not valid JSON
#[error("Output of bootloader build with --message-format=json is not valid JSON:\n{0}")]
XbuildJsonOutputInvalidJson(json::Error),
BuildJsonOutputInvalidJson(json::Error),
}

/// There is something wrong with the bootloader dependency.
Expand Down
42 changes: 23 additions & 19 deletions src/builder/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! Provides functions to build the kernel and the bootloader.

use crate::config::Config;
use cargo_metadata::Metadata;
use error::{BootloaderError, BuildKernelError, BuilderError, CreateBootimageError};
use std::{
Expand Down Expand Up @@ -37,25 +38,26 @@ impl Builder {
&self.manifest_path
}

/// Builds the kernel by executing `cargo xbuild` with the given arguments.
/// Builds the kernel by executing `cargo build` with the given arguments.
///
/// Returns a list of paths to all built executables. For crates with only a single binary,
/// the returned list contains only a single element.
///
/// If the quiet argument is set to true, all output to stdout is suppressed.
pub fn build_kernel(
&self,
&mut self,
args: &[String],
config: &Config,
quiet: bool,
) -> Result<Vec<PathBuf>, BuildKernelError> {
if !quiet {
println!("Building kernel");
}

// try to run cargo xbuild
// try to build kernel
let cargo = std::env::var("CARGO").unwrap_or_else(|_| "cargo".to_owned());
let mut cmd = process::Command::new(&cargo);
cmd.arg("xbuild");
cmd.args(&config.build_command);
cmd.args(args);
if !quiet {
cmd.stdout(process::Stdio::inherit());
Expand All @@ -66,42 +68,44 @@ impl Builder {
error: err,
})?;
if !output.status.success() {
// try executing `cargo xbuild --help` to check whether cargo-xbuild is installed
let mut help_command = process::Command::new("cargo");
help_command.arg("xbuild").arg("--help");
help_command.stdout(process::Stdio::null());
help_command.stderr(process::Stdio::null());
if let Ok(help_exit_status) = help_command.status() {
if !help_exit_status.success() {
return Err(BuildKernelError::XbuildNotFound);
if config.build_command.starts_with(&["xbuild".into()]) {
// try executing `cargo xbuild --help` to check whether cargo-xbuild is installed
let mut help_command = process::Command::new("cargo");
help_command.arg("xbuild").arg("--help");
help_command.stdout(process::Stdio::null());
help_command.stderr(process::Stdio::null());
if let Ok(help_exit_status) = help_command.status() {
if !help_exit_status.success() {
return Err(BuildKernelError::XbuildNotFound);
}
}
}
return Err(BuildKernelError::XbuildFailed {
return Err(BuildKernelError::BuildFailed {
stderr: output.stderr,
});
}

// Retrieve binary paths
let mut cmd = process::Command::new(cargo);
cmd.arg("xbuild");
cmd.args(&config.build_command);
cmd.args(args);
cmd.arg("--message-format").arg("json");
let output = cmd.output().map_err(|err| BuildKernelError::Io {
message: "failed to execute kernel build with json output",
error: err,
})?;
if !output.status.success() {
return Err(BuildKernelError::XbuildFailed {
return Err(BuildKernelError::BuildFailed {
stderr: output.stderr,
});
}
let mut executables = Vec::new();
for line in String::from_utf8(output.stdout)
.map_err(BuildKernelError::XbuildJsonOutputInvalidUtf8)?
.map_err(BuildKernelError::BuildJsonOutputInvalidUtf8)?
.lines()
{
let mut artifact =
json::parse(line).map_err(BuildKernelError::XbuildJsonOutputInvalidJson)?;
json::parse(line).map_err(BuildKernelError::BuildJsonOutputInvalidJson)?;
if let Some(executable) = artifact["executable"].take_string() {
executables.push(PathBuf::from(executable));
}
Expand Down Expand Up @@ -161,11 +165,11 @@ impl Builder {
}
let mut bootloader_elf_path = None;
for line in String::from_utf8(output.stdout)
.map_err(CreateBootimageError::XbuildJsonOutputInvalidUtf8)?
.map_err(CreateBootimageError::BuildJsonOutputInvalidUtf8)?
.lines()
{
let mut artifact =
json::parse(line).map_err(CreateBootimageError::XbuildJsonOutputInvalidJson)?;
json::parse(line).map_err(CreateBootimageError::BuildJsonOutputInvalidJson)?;
if let Some(executable) = artifact["executable"].take_string() {
if bootloader_elf_path
.replace(PathBuf::from(executable))
Expand Down
Loading