diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index defd90183..32607792d 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -159,3 +159,13 @@ jobs: - name: Build run: cargo xtask build + + build_feature_permutations: + name: Check that the build works for all feature combinations + runs-on: ubuntu-latest + steps: + - name: Checkout sources + uses: actions/checkout@v3 + + - name: Build + run: cargo xtask build --feature-permutations diff --git a/uefi/Cargo.toml b/uefi/Cargo.toml index 652949f10..cfdb3d230 100644 --- a/uefi/Cargo.toml +++ b/uefi/Cargo.toml @@ -19,6 +19,7 @@ logger = [] # were observed on the VirtualBox UEFI implementation (see uefi-rs#121). # In those cases, this feature can be excluded by removing the default features. panic-on-logger-errors = [] +unstable = [] [dependencies] bitflags = "1.3.1" diff --git a/uefi/src/lib.rs b/uefi/src/lib.rs index efecfcd5a..f61bc7a90 100644 --- a/uefi/src/lib.rs +++ b/uefi/src/lib.rs @@ -32,6 +32,12 @@ //! is not a high-performance logger. //! - `panic-on-logger-errors` (enabled by default): Panic if a text //! output error occurs in the logger. +//! - `unstable`: Enable functionality that depends on [unstable +//! features] in the nightly compiler. Note that currently the `uefi` +//! crate _always_ requires unstable features even if the `unstable` +//! feature is not enabled, but once a couple more required features +//! are stabilized we intend to make the `uefi` crate work on the +//! stable channel by default. //! //! The `global_allocator` and `logger` features require special //! handling to perform initialization and tear-down. The @@ -48,13 +54,14 @@ //! //! [`GlobalAlloc`]: alloc::alloc::GlobalAlloc //! [`uefi-services`]: https://crates.io/crates/uefi-services +//! [unstable features]: https://doc.rust-lang.org/unstable-book/ #![feature(abi_efiapi)] #![feature(maybe_uninit_slice)] #![feature(negative_impls)] #![feature(ptr_metadata)] -#![feature(error_in_core)] #![cfg_attr(feature = "alloc", feature(vec_into_raw_parts))] +#![cfg_attr(feature = "unstable", feature(error_in_core))] #![cfg_attr(docsrs, feature(doc_auto_cfg))] #![no_std] // Enable some additional warnings and lints. diff --git a/uefi/src/result/error.rs b/uefi/src/result/error.rs index 930e91a4b..26634c1f6 100644 --- a/uefi/src/result/error.rs +++ b/uefi/src/result/error.rs @@ -46,4 +46,5 @@ impl Display for Error { } } +#[cfg(feature = "unstable")] impl core::error::Error for Error {} diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml index a710f626e..817b33b28 100644 --- a/xtask/Cargo.toml +++ b/xtask/Cargo.toml @@ -11,6 +11,7 @@ clap = { version = "4.0.4", features = ["derive"] } fatfs = { git = "https://github.com/rafalh/rust-fatfs.git", rev = "87fc1ed5074a32b4e0344fcdde77359ef9e75432" } fs-err = "2.6.0" heck = "0.4.0" +itertools = "0.10.5" # Use git as a temporary workaround for https://github.com/rust-osdev/uefi-rs/issues/573. mbrman = { git = "https://github.com/cecton/mbrman.git", rev = "78565860e55c272488d94480e72a4e2cd159ad8e" } nix = "0.25.0" diff --git a/xtask/src/cargo.rs b/xtask/src/cargo.rs index 2a9d3f99b..c617268ff 100644 --- a/xtask/src/cargo.rs +++ b/xtask/src/cargo.rs @@ -45,24 +45,55 @@ impl Package { #[derive(Clone, Copy, Debug)] pub enum Feature { - GlobalAllocator, + // `uefi` features. Alloc, + GlobalAllocator, Logger, + PanicOnLoggerErrors, + Unstable, + + // `uefi-services` features. + PanicHandler, + Qemu, + ServicesLogger, + // `uefi-test-runner` features. Ci, } impl Feature { fn as_str(&self) -> &'static str { match self { - Self::GlobalAllocator => "global_allocator", Self::Alloc => "alloc", + Self::GlobalAllocator => "global_allocator", Self::Logger => "logger", + Self::PanicOnLoggerErrors => "panic-on-logger-errors", + Self::Unstable => "unstable", + + Self::PanicHandler => "uefi-services/panic_handler", + Self::Qemu => "uefi-services/qemu", + Self::ServicesLogger => "uefi-services/logger", Self::Ci => "uefi-test-runner/ci", } } + /// Get the features for the given package. + pub fn package_features(package: Package) -> Vec { + match package { + Package::Uefi => vec![ + Self::Alloc, + Self::GlobalAllocator, + Self::Logger, + Self::PanicOnLoggerErrors, + Self::Unstable, + ], + Package::UefiServices => vec![Self::PanicHandler, Self::Qemu, Self::ServicesLogger], + Package::UefiTestRunner => vec![Self::Ci], + _ => vec![], + } + } + /// Set of features that enables more code in the root uefi crate. pub fn more_code() -> Vec { vec![Self::GlobalAllocator, Self::Alloc, Self::Logger] diff --git a/xtask/src/main.rs b/xtask/src/main.rs index eec7e429c..3ad1ba282 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -12,12 +12,39 @@ mod util; use anyhow::Result; use cargo::{fix_nested_cargo_env, Cargo, CargoAction, Feature, Package, TargetTypes}; use clap::Parser; +use itertools::Itertools; use opt::{Action, BuildOpt, ClippyOpt, DocOpt, Opt, QemuOpt}; use std::process::Command; use tempfile::TempDir; use util::{command_to_string, run_cmd}; +fn build_feature_permutations(opt: &BuildOpt) -> Result<()> { + for package in [Package::Uefi, Package::UefiServices] { + let all_package_features = Feature::package_features(package); + for features in all_package_features.iter().powerset() { + let features = features.iter().map(|f| **f).collect(); + + let cargo = Cargo { + action: CargoAction::Build, + features, + packages: vec![package], + release: opt.build_mode.release, + target: Some(*opt.target), + warnings_as_errors: true, + target_types: TargetTypes::BinsExamplesLib, + }; + run_cmd(cargo.command()?)?; + } + } + + Ok(()) +} + fn build(opt: &BuildOpt) -> Result<()> { + if opt.feature_permutations { + return build_feature_permutations(opt); + } + let cargo = Cargo { action: CargoAction::Build, features: Feature::more_code(), diff --git a/xtask/src/opt.rs b/xtask/src/opt.rs index 1b73ad85f..3f1ec3ef2 100644 --- a/xtask/src/opt.rs +++ b/xtask/src/opt.rs @@ -62,6 +62,11 @@ pub struct BuildOpt { #[clap(flatten)] pub build_mode: BuildModeOpt, + + /// Build multiple times to check that different feature + /// combinations work. + #[clap(long, action)] + pub feature_permutations: bool, } /// Run clippy on all the packages.