Skip to content

Commit

Permalink
Merge pull request #63 from rust-osdev/build-with-cargo-build
Browse files Browse the repository at this point in the history
Make `cargo bootimage` use `cargo build` instead of `cargo xbuild`
  • Loading branch information
phil-opp committed Jul 17, 2020
2 parents c4c9b93 + b3aaf4f commit f5a89b0
Show file tree
Hide file tree
Showing 15 changed files with 108 additions and 75 deletions.
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

0 comments on commit f5a89b0

Please sign in to comment.