Skip to content

Install UEFI targets via rustup #555

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

Merged
merged 5 commits into from
Nov 24, 2022
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
4 changes: 3 additions & 1 deletion BUILDING.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ outside of the `uefi-rs` repo.
```toml
[toolchain]
channel = "nightly"
components = ["rust-src"]

# Install the x86_64 UEFI target; aarch64 and i686 are also available.
targets = ["x86_64-unknown-uefi"]
```

- Build the crate:
Expand Down
44 changes: 8 additions & 36 deletions book/src/tutorial/building.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,60 +3,32 @@
## Nightly toolchain

Rust's nightly toolchain is currently required because uefi-rs uses some
unstable features. The [`build-std`] feature we use to build the
standard libraries is also unstable.
unstable features.

The easiest way to set this up is using a [rustup toolchain file]. In
the root of your repository, add `rust-toolchain.toml`:

```toml
[toolchain]
channel = "nightly"
components = ["rust-src"]
targets = ["x86_64-unknown-uefi"]
```

Here we have specified the `x86_64-unknown-uefi` target; there are also
`i686-unknown-uefi` and `aarch64-unknown-uefi` targets available.

Note that nightly releases can sometimes break, so you might opt to pin
to a specific release. For example, `channel = "nightly-2022-09-01"`.
to a specific release. For example, `channel = "nightly-2022-11-10"`.

## Build the application

Run this command to build the application:

```sh
cargo build --target x86_64-unknown-uefi \
-Zbuild-std=core,alloc
cargo build --target x86_64-unknown-uefi
```

This will produce an x86-64 executable:
`target/x86_64-unknown-uefi/debug/my-uefi-app.efi`.

## Simplifying the build command

The above build command is verbose and not easy to remember. With a bit
of configuration we can simplify it a lot.

Create a `.cargo` directory in the root of the project:

```sh
mkdir .cargo
```

Create `.cargo/config.toml` with these contents:

```toml
[build]
target = "x86_64-unknown-uefi"

[unstable]
build-std = ["core", "alloc"]
```

Now you can build much more simply:

```sh
cargo build
```

[`build-std`]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#build-std
[`rust-toolchain.toml`]: https://rust-lang.github.io/rustup/overrides.html#the-toolchain-file
[rustup toolchain file]: https://rust-lang.github.io/rustup/concepts/toolchains.html
[rustup toolchain file]: https://rust-lang.github.io/rustup/overrides.html#the-toolchain-file
5 changes: 1 addition & 4 deletions rust-toolchain.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
[toolchain]
channel = "nightly"

# Install the `rust-src` component so that `-Zbuild-std` works. This in
# addition to the components included in the default profile.
components = ["rust-src"]
targets = ["aarch64-unknown-uefi", "i686-unknown-uefi", "x86_64-unknown-uefi"]
2 changes: 0 additions & 2 deletions template/.cargo/config.toml

This file was deleted.

1 change: 0 additions & 1 deletion template/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ how to build and run a UEFI application developed using `uefi-rs`.

## File structure

- [`.cargo/config`](./.cargo/config) sets some `build-std` options.
- [`rust-toolchain.toml`](rust-toolchain.toml) sets the nightly channel.
- [`Cargo.toml`](./Cargo.toml) shows the necessary dependencies.
- [`src/main.rs`](./src/main.rs) has a minimal entry point that
Expand Down
2 changes: 1 addition & 1 deletion template/rust-toolchain.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[toolchain]
channel = "nightly"
components = ["rust-src"]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this looks so much better now. Very nice :)

targets = ["aarch64-unknown-uefi", "i686-unknown-uefi", "x86_64-unknown-uefi"]
22 changes: 21 additions & 1 deletion xtask/src/cargo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,19 @@ pub fn fix_nested_cargo_env(cmd: &mut Command) {
cmd.env("PATH", sanitized_path(orig_path));
}

/// Check if the three UEFI targets are installed via rustup (only
/// supported since nightly-2022-11-10).
fn is_target_installed(target: &str) -> Result<bool> {
let output = Command::new("rustup")
.args(["target", "list", "--installed"])
.output()?;
if !output.status.success() {
bail!("failed to get installed targets");
}
let stdout = String::from_utf8(output.stdout)?;
Ok(stdout.lines().any(|x| x == target))
}

#[derive(Debug)]
pub struct Cargo {
pub action: CargoAction,
Expand Down Expand Up @@ -218,7 +231,14 @@ impl Cargo {
}

if let Some(target) = self.target {
cmd.args(["--target", target.as_triple(), "-Zbuild-std=core,alloc"]);
cmd.args(["--target", target.as_triple()]);

// If the target is not installed, use build-std. Keep this
// around until our minimum-supported nightly version is at
// least 2022-11-10.
if !is_target_installed(target.as_triple())? {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you create a follow-up ticket please to remove this eventually?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I went ahead and made a PR: #585

We can merge that after Feb 22, 2023.

cmd.args(["-Zbuild-std=core,alloc"]);
}
}

if self.packages.is_empty() {
Expand Down