diff --git a/.envrc b/.envrc index 09e438af5..e161b60b4 100644 --- a/.envrc +++ b/.envrc @@ -1,2 +1,3 @@ -# If your shell has direnv support, it will automatically open a "nix-shell". -use nix +# If your shell has direnv support, it will automatically open a Nix shell with +# all relevant dependencies to develop this project. +use flake diff --git a/.github/workflows/developer_productivity.yml b/.github/workflows/developer_productivity.yml index cf252c552..0f60b8a79 100644 --- a/.github/workflows/developer_productivity.yml +++ b/.github/workflows/developer_productivity.yml @@ -4,7 +4,7 @@ on: push: pull_request: jobs: - # Job to run change detection + # Job to run change detection for Nix-related files changes: runs-on: ubuntu-latest # Set job outputs to values from filter step. @@ -19,13 +19,14 @@ jobs: filters: | nix-src: - 'nix/**' - - 'shell.nix' + - 'flake.nix' + - 'flake.lock' # This is a convenience test to verify that the toolchain provided by # shell.nix is valid and can build + run the integration test. # # It only runs if the "nix-src" output of the "changes" job is true. nix_shell_toolchain: - name: "Nix toolchain: `cargo xtask run` works" + name: "Nix shell toolchain: `cargo xtask run` works" needs: changes if: ${{ needs.changes.outputs.nix-src == 'true' }} runs-on: ubuntu-latest @@ -34,17 +35,13 @@ jobs: uses: actions/checkout@v4 - uses: Swatinem/rust-cache@v2 - uses: cachix/install-nix-action@v30 - with: - # This channel is only required to invoke "nix-shell". - # Everything inside that nix-shell will use a pinned version of nixpkgs. - nix_path: nixpkgs=channel:nixpkgs-unstable # Dedicated step to separate all the # "copying path '/nix/store/...' from 'https://cache.nixos.org'." - # messages from the actual build output. This job takes ~60secs. + # messages from the actual build output. - name: Prepare Nix Store - run: nix-shell --pure --run "cargo --version" + run: nix develop --command bash -c "cargo --version" - name: Run VM tests run: | COMMAND="cargo xtask run --target x86_64 --headless --ci --tpm=v1" - echo "Executing in nix shell: $COMMAND" - nix-shell --pure --run "$COMMAND" + echo "Executing in Nix shell: $COMMAND" + nix develop --command bash -c "$COMMAND" diff --git a/flake.lock b/flake.lock new file mode 100644 index 000000000..e97a8b0f2 --- /dev/null +++ b/flake.lock @@ -0,0 +1,62 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1740743217, + "narHash": "sha256-brsCRzLqimpyhORma84c3W2xPbIidZlIc3JGIuQVSNI=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "b27ba4eb322d9d2bf2dc9ada9fd59442f50c8d7c", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-24.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1736320768, + "narHash": "sha256-nIYdTAiKIGnFNugbomgBJR+Xv5F1ZQU+HfaBqJKroC0=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "4bc9c909d9ac828a039f288cf872d16d38185db8", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs", + "rust-overlay": "rust-overlay" + } + }, + "rust-overlay": { + "inputs": { + "nixpkgs": "nixpkgs_2" + }, + "locked": { + "lastModified": 1740882709, + "narHash": "sha256-VC+8GxWK4p08jjIbmsNfeFQajW2lsiOR/XQiOOvqgvs=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "f4d5a693c18b389f0d58f55b6f7be6ef85af186f", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 000000000..69f1a6f80 --- /dev/null +++ b/flake.nix @@ -0,0 +1,61 @@ +{ + description = "uefi-rs"; + + inputs = { + # We follow the latest stable release of nixpkgs + nixpkgs.url = "github:nixos/nixpkgs/nixos-24.11"; + rust-overlay.url = "github:oxalica/rust-overlay"; + }; + + outputs = + inputs@{ self, nixpkgs, ... }: + let + # Systems definition for dev shells and exported packages, + # independent of the NixOS configurations and modules defined here. We + # just use "every system" here to not restrict any user. However, it + # likely happens that certain packages don't build for/under certain + # systems. + systems = nixpkgs.lib.systems.flakeExposed; + forAllSystems = + function: nixpkgs.lib.genAttrs systems (system: function nixpkgs.legacyPackages.${system}); + + # We directly instantiate the functionality, without using an + # nixpkgs overlay. + # https://github.com/oxalica/rust-overlay/blob/f4d5a693c18b389f0d58f55b6f7be6ef85af186f/docs/reference.md?plain=1#L26 + rustToolchain = + pkgs: + let + rust-bin = (inputs.rust-overlay.lib.mkRustBin { }) pkgs; + rustToolchainBuilder = import ./nix/rust-toolchain.nix; + in + rustToolchainBuilder { inherit rust-bin; }; + in + { + devShells = forAllSystems (pkgs: { + default = pkgs.mkShell { + packages = with pkgs; [ + nixfmt-rfc-style + + # Integration test dependencies + swtpm + qemu + + # Rust toolchain + (rustToolchain pkgs) + + # Other + cargo-llvm-cov + mdbook + yamlfmt + which # used by "cargo xtask fmt" + ]; + + # Set ENV vars. + # OVMF_CODE="${pkgs.OVMF.firmware}"; + # OVMF_VARS="${pkgs.OVMF.variables}"; + # OVMF_SHELL="${pkgs.edk2-uefi-shell}"; + }; + }); + formatter = forAllSystems (pkgs: pkgs.nixfmt-rfc-style); + }; +} diff --git a/nix/nixpkgs.nix b/nix/nixpkgs.nix deleted file mode 100644 index aced2d386..000000000 --- a/nix/nixpkgs.nix +++ /dev/null @@ -1,5 +0,0 @@ -let - sources = import ./sources.nix { }; - rust-overlay = import sources.rust-overlay; -in -import sources.nixpkgs { overlays = [ rust-overlay ]; } diff --git a/nix/rust-toolchain.nix b/nix/rust-toolchain.nix index d73681544..021a26016 100644 --- a/nix/rust-toolchain.nix +++ b/nix/rust-toolchain.nix @@ -1,5 +1,4 @@ -# Returns the Rust toolchain for Nix compliant to the rust-toolchain.toml file -# but without rustup. +# Returns a Rust toolchain for Nix that matches the one from the toolchain file. { # Comes from rust-overlay diff --git a/nix/sources.json b/nix/sources.json deleted file mode 100644 index e0170c0e8..000000000 --- a/nix/sources.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "nixpkgs": { - "branch": "nixos-24.05", - "description": "Nix Packages collection", - "homepage": null, - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "a9b86fc2290b69375c5542b622088eb6eca2a7c3", - "sha256": "1mssfzy1nsansjmp5ckyl8vbk32va3abchpg19ljyak0xblxnjs1", - "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/a9b86fc2290b69375c5542b622088eb6eca2a7c3.tar.gz", - "url_template": "https://github.com///archive/.tar.gz" - }, - "rust-overlay": { - "branch": "master", - "description": "Pure and reproducible nix overlay of binary distributed rust toolchains", - "homepage": "", - "owner": "oxalica", - "repo": "rust-overlay", - "rev": "ada8266712449c4c0e6ee6fcbc442b3c217c79e1", - "sha256": "1y5fq080nqknps35pmfdyxy7vys1bzdkqzrhh41fxq3jkiw74idg", - "type": "tarball", - "url": "https://github.com/oxalica/rust-overlay/archive/ada8266712449c4c0e6ee6fcbc442b3c217c79e1.tar.gz", - "url_template": "https://github.com///archive/.tar.gz" - } -} diff --git a/nix/sources.nix b/nix/sources.nix deleted file mode 100644 index 757b3125f..000000000 --- a/nix/sources.nix +++ /dev/null @@ -1,250 +0,0 @@ -# This file has been generated by Niv. - -let - - # - # The fetchers. fetch_ fetches specs of type . - # - - fetch_file = - pkgs: name: spec: - let - name' = sanitizeName name + "-src"; - in - if spec.builtin or true then - builtins_fetchurl { - inherit (spec) url sha256; - name = name'; - } - else - pkgs.fetchurl { - inherit (spec) url sha256; - name = name'; - }; - - fetch_tarball = - pkgs: name: spec: - let - name' = sanitizeName name + "-src"; - in - if spec.builtin or true then - builtins_fetchTarball { - name = name'; - inherit (spec) url sha256; - } - else - pkgs.fetchzip { - name = name'; - inherit (spec) url sha256; - }; - - fetch_git = - name: spec: - let - ref = - if spec ? ref then - spec.ref - else if spec ? branch then - "refs/heads/${spec.branch}" - else if spec ? tag then - "refs/tags/${spec.tag}" - else - abort "In git source '${name}': Please specify `ref`, `tag` or `branch`!"; - submodules = if spec ? submodules then spec.submodules else false; - submoduleArg = - let - nixSupportsSubmodules = builtins.compareVersions builtins.nixVersion "2.4" >= 0; - emptyArgWithWarning = - if submodules == true then - builtins.trace ( - "The niv input \"${name}\" uses submodules " - + "but your nix's (${builtins.nixVersion}) builtins.fetchGit " - + "does not support them" - ) { } - else - { }; - in - if nixSupportsSubmodules then { inherit submodules; } else emptyArgWithWarning; - in - builtins.fetchGit ( - { - url = spec.repo; - inherit (spec) rev; - inherit ref; - } - // submoduleArg - ); - - fetch_local = spec: spec.path; - - fetch_builtin-tarball = - name: - throw '' - [${name}] The niv type "builtin-tarball" is deprecated. You should instead use `builtin = true`. - $ niv modify ${name} -a type=tarball -a builtin=true''; - - fetch_builtin-url = - name: - throw '' - [${name}] The niv type "builtin-url" will soon be deprecated. You should instead use `builtin = true`. - $ niv modify ${name} -a type=file -a builtin=true''; - - # - # Various helpers - # - - # https://github.com/NixOS/nixpkgs/pull/83241/files#diff-c6f540a4f3bfa4b0e8b6bafd4cd54e8bR695 - sanitizeName = - name: - (concatMapStrings (s: if builtins.isList s then "-" else s) ( - builtins.split "[^[:alnum:]+._?=-]+" ((x: builtins.elemAt (builtins.match "\\.*(.*)" x) 0) name) - )); - - # The set of packages used when specs are fetched using non-builtins. - mkPkgs = - sources: system: - let - sourcesNixpkgs = import (builtins_fetchTarball { inherit (sources.nixpkgs) url sha256; }) { - inherit system; - }; - hasNixpkgsPath = builtins.any (x: x.prefix == "nixpkgs") builtins.nixPath; - hasThisAsNixpkgsPath = == ./.; - in - if builtins.hasAttr "nixpkgs" sources then - sourcesNixpkgs - else if hasNixpkgsPath && !hasThisAsNixpkgsPath then - import { } - else - abort '' - Please specify either (through -I or NIX_PATH=nixpkgs=...) or - add a package called "nixpkgs" to your sources.json. - ''; - - # The actual fetching function. - fetch = - pkgs: name: spec: - - if !builtins.hasAttr "type" spec then - abort "ERROR: niv spec ${name} does not have a 'type' attribute" - else if spec.type == "file" then - fetch_file pkgs name spec - else if spec.type == "tarball" then - fetch_tarball pkgs name spec - else if spec.type == "git" then - fetch_git name spec - else if spec.type == "local" then - fetch_local spec - else if spec.type == "builtin-tarball" then - fetch_builtin-tarball name - else if spec.type == "builtin-url" then - fetch_builtin-url name - else - abort "ERROR: niv spec ${name} has unknown type ${builtins.toJSON spec.type}"; - - # If the environment variable NIV_OVERRIDE_${name} is set, then use - # the path directly as opposed to the fetched source. - replace = - name: drv: - let - saneName = stringAsChars (c: if isNull (builtins.match "[a-zA-Z0-9]" c) then "_" else c) name; - ersatz = builtins.getEnv "NIV_OVERRIDE_${saneName}"; - in - if ersatz == "" then - drv - else - # this turns the string into an actual Nix path (for both absolute and - # relative paths) - if builtins.substring 0 1 ersatz == "/" then - /. + ersatz - else - /. + builtins.getEnv "PWD" + "/${ersatz}"; - - # Ports of functions for older nix versions - - # a Nix version of mapAttrs if the built-in doesn't exist - mapAttrs = - builtins.mapAttrs or ( - f: set: - with builtins; - listToAttrs ( - map (attr: { - name = attr; - value = f attr set.${attr}; - }) (attrNames set) - ) - ); - - # https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/lists.nix#L295 - range = - first: last: if first > last then [ ] else builtins.genList (n: first + n) (last - first + 1); - - # https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L257 - stringToCharacters = s: map (p: builtins.substring p 1 s) (range 0 (builtins.stringLength s - 1)); - - # https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L269 - stringAsChars = f: s: concatStrings (map f (stringToCharacters s)); - concatMapStrings = f: list: concatStrings (map f list); - concatStrings = builtins.concatStringsSep ""; - - # https://github.com/NixOS/nixpkgs/blob/8a9f58a375c401b96da862d969f66429def1d118/lib/attrsets.nix#L331 - optionalAttrs = cond: as: if cond then as else { }; - - # fetchTarball version that is compatible between all the versions of Nix - builtins_fetchTarball = - { - url, - name ? null, - sha256, - }@attrs: - let - inherit (builtins) lessThan nixVersion fetchTarball; - in - if lessThan nixVersion "1.12" then - fetchTarball ({ inherit url; } // (optionalAttrs (!isNull name) { inherit name; })) - else - fetchTarball attrs; - - # fetchurl version that is compatible between all the versions of Nix - builtins_fetchurl = - { - url, - name ? null, - sha256, - }@attrs: - let - inherit (builtins) lessThan nixVersion fetchurl; - in - if lessThan nixVersion "1.12" then - fetchurl ({ inherit url; } // (optionalAttrs (!isNull name) { inherit name; })) - else - fetchurl attrs; - - # Create the final "sources" from the config - mkSources = - config: - mapAttrs ( - name: spec: - if builtins.hasAttr "outPath" spec then - abort "The values in sources.json should not have an 'outPath' attribute" - else - spec // { outPath = replace name (fetch config.pkgs name spec); } - ) config.sources; - - # The "config" used by the fetchers - mkConfig = - { - sourcesFile ? if builtins.pathExists ./sources.json then ./sources.json else null, - sources ? if isNull sourcesFile then { } else builtins.fromJSON (builtins.readFile sourcesFile), - system ? builtins.currentSystem, - pkgs ? mkPkgs sources system, - }: - rec { - # The sources, i.e. the attribute set of spec name to spec - inherit sources; - - # The "pkgs" (evaluated nixpkgs) to use for e.g. non-builtin fetchers - inherit pkgs; - }; - -in -mkSources (mkConfig { }) // { __functor = _: settings: mkSources (mkConfig settings); } diff --git a/shell.nix b/shell.nix deleted file mode 100644 index 14f0c1206..000000000 --- a/shell.nix +++ /dev/null @@ -1,40 +0,0 @@ -# Sets up a basic shell environment with all relevant tooling to run -# "cargo xtask run|test|clippy". It uses rustup rather than a pinned rust -# toolchain. - -let - sources = import ./nix/sources.nix; - pkgs = import ./nix/nixpkgs.nix; - rustToolchain = pkgs.callPackage ./nix/rust-toolchain.nix { }; -in -pkgs.mkShell { - nativeBuildInputs = with pkgs; [ - # nix related stuff (such as dependency management) - niv - # TODO use "nixfmt" once it is stable - likely in nixpkgs @ NixOS 24.11 - nixfmt-rfc-style - - # Integration test dependencies - swtpm - qemu - - # Rust toolchain - rustToolchain - - # Other - cargo-llvm-cov - mdbook - yamlfmt - which # used by "cargo xtask fmt" - ]; - - # Set ENV vars. - # OVMF_CODE="${pkgs.OVMF.firmware}"; - # OVMF_VARS="${pkgs.OVMF.variables}"; - # OVMF_SHELL="${pkgs.edk2-uefi-shell}"; - - # To invoke "nix-shell" in the CI-runner, we need a global Nix channel. - # For better reproducibility inside the Nix shell, we override this channel - # with the pinned nixpkgs version. - NIX_PATH = "nixpkgs=${sources.nixpkgs}"; -}