Initial commit

This commit is contained in:
Sebastien Braun 2024-02-08 22:00:00 +00:00
commit e483f73dd4
12 changed files with 479 additions and 0 deletions

77
crane.nix Normal file
View file

@ -0,0 +1,77 @@
craneFlake:
{ config, lib, flake-parts-lib, ... }:
let
inherit (lib) mkOption types mkIf mkDefault mkMerge;
inherit (flake-parts-lib) mkPerSystemOption;
cfg = config.rust.crane;
mkTcDefault = lib.mkOverride 900;
in
{
options = {
rust.crane = {
lib = mkOption {
type = types.anything;
default = craneFlake.lib;
};
};
perSystem = mkPerSystemOption {
_file = ./crane.nix;
options = {
rust.crane = {
toolchain = mkOption {
type = types.nullOr types.package;
default = null;
};
cargo = mkOption {
type = types.package;
};
clippy = mkOption {
type = types.package;
};
rustc = mkOption {
type = types.package;
};
rustfmt = mkOption {
type = types.package;
};
};
};
};
};
config.perSystem = psinputs@{ config, pkgs, system, inputs', ... }:
let cfg' = config.rust.crane;
in
{
config = mkMerge [
{
rust.crane.cargo = mkDefault pkgs.cargo;
rust.crane.rustc = mkDefault pkgs.rustc;
rust.crane.clippy = mkDefault pkgs.clippy;
rust.crane.rustfmt = mkDefault pkgs.rustfmt;
}
(mkIf (cfg'.toolchain != null) {
rust.crane.cargo = mkTcDefault cfg'.toolchain;
rust.crane.rustc = mkTcDefault cfg'.toolchain;
rust.crane.clippy = mkTcDefault cfg'.toolchain;
rust.crane.rustfmt = mkTcDefault cfg'.toolchain;
})
{
_module.args.craneLib = cfg.lib.${system}.overrideScope (_self: _super: {
cargo = cfg'.cargo;
clippy = cfg'.clippy;
rustc = cfg'.rustc;
rustfmt = cfg'.rustfmt;
});
}
];
};
}

2
examples/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
flake.lock
target/

7
examples/crane/Cargo.lock generated Normal file
View file

@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "rusty-hello"
version = "0.1.0"

View file

@ -0,0 +1,8 @@
[package]
name = "rusty-hello"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

43
examples/crane/flake.nix Normal file
View file

@ -0,0 +1,43 @@
{
description = "An example of a shell environment with a Crane-built package";
inputs = {
rust.url = "git+https://forgejo.alt0r.com/braunse/rust-part";
nixpkgs.follows = "rust/nixpkgs";
parts.follows = "rust/parts";
rustManifest.follows = "rust/rustManifest";
};
outputs = inputs: inputs.parts.lib.mkFlake { inherit inputs; } {
imports = [ inputs.rust.flakeModules.crane ];
systems = [ "x86_64-linux" ];
perSystem =
{ pkgs, craneLib, self', ... }: {
packages.rusty-hello = craneLib.buildPackage {
src = craneLib.cleanCargoSource (craneLib.path ./.);
strictDeps = true;
};
checks = {
craneCompilesRustPackage = pkgs.stdenv.mkDerivation {
name = "check-crane-compiles-rust-package";
dontUnpack = true;
buildPhase = ''
set -euo pipefail
# Check that the compilation of our trivial package yielded something we can actually execute.
OUTPUT="$(${self'.packages.rusty-hello}/bin/rusty-hello)"
if [[ "$OUTPUT" != "Rusty-Hello" ]]; then
echo "Received output '$OUTPUT', expected 'Rusty-Hello'" >&2
exit 1
fi
touch $out
'';
};
};
};
};
}

View file

@ -0,0 +1,3 @@
fn main() {
println!("Rusty-Hello");
}

View file

@ -0,0 +1,8 @@
[package]
name = "fenix"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

51
examples/fenix/flake.nix Normal file
View file

@ -0,0 +1,51 @@
{
description = "An example of a shell environment with a Fenix toolchain";
inputs = {
rust.url = "git+https://forgejo.alt0r.com/braunse/rust-part";
nixpkgs.follows = "rust/nixpkgs";
parts.follows = "rust/parts";
rustManifest.follows = "rust/rustManifest";
};
outputs = inputs: inputs.parts.lib.mkFlake { inherit inputs; } {
imports = [ inputs.rust.flakeModules.fenix ];
systems = [ "x86_64-linux" ];
rust.fenix.manifestFile = inputs.rustManifest;
rust.fenix.components = [ "rustfmt" ];
rust.fenix.targetComponents.wasm32-unknown-unknown = [ "rust-std" ];
perSystem =
{ pkgs, fenixToolchain, ... }: {
checks = {
haveRustChain = pkgs.stdenv.mkDerivation {
name = "check-rust-toolchain-is-present";
dontUnpack = true;
buildPhase = ''
set -euo pipefail
echo "Checking for cargo" >&2
${fenixToolchain}/bin/cargo --version >/dev/null
echo "Checking for rustc" >&2
${fenixToolchain}/bin/rustc --version >/dev/null
echo "Checking for rustfmt" >&2
${fenixToolchain}/bin/rustfmt --version >/dev/null
echo "Checking compiler compiles natively" >&2
touch lib.rs
${fenixToolchain}/bin/rustc --crate-type rlib --crate-name nativechecklib lib.rs
echo "Checking compiler compiles for wasm32-unknown-unknown" >&2
${fenixToolchain}/bin/rustc --crate-type rlib --crate-name crosschecklib --target wasm32-unknown-unknown lib.rs
touch $out
'';
};
};
};
};
}

View file

@ -0,0 +1,3 @@
fn main() {
println!("Hello, world!");
}

67
fenix.nix Normal file
View file

@ -0,0 +1,67 @@
fenixFlake:
{ config, inputs, lib, flake-parts-lib, ... }:
with builtins;
let
inherit (lib) mkDefault mkOption types;
inherit (flake-parts-lib) mkPerSystemOption;
cfg = config.rust.fenix;
in
{
options = {
rust.fenix = {
manifestFile = mkOption {
type = types.path;
};
channel = mkOption {
type = types.str;
default = "stable";
};
components = mkOption {
type = types.listOf types.str;
};
targetComponents = mkOption {
type = types.attrsOf (types.listOf types.str);
};
};
perSystem = mkPerSystemOption {
_file = ./fenix.nix;
options = {
rust.fenix.toolchain = mkOption {
type = types.package;
readOnly = true;
};
};
};
};
config.rust.fenix = {
components = [
"cargo"
"rustc"
];
};
config.perSystem = { pkgs, system, inputs', ... }: {
_module.args.fenixToolchain =
let
fenix = fenixFlake.packages.${system};
inherit (fenix) combine;
nativeToolchain = fenix.fromManifestFile cfg.manifestFile;
targetToolchain = t: fenix.targets.${t}.fromManifestFile cfg.manifestFile;
component = tc: c: getAttr c tc;
components = tc: cs: map (component tc) cs;
nativeComponents = components nativeToolchain cfg.components;
targetComponents = concatMap
(t: components (targetToolchain t) cfg.targetComponents.${t})
(attrNames cfg.targetComponents);
in
combine (nativeComponents ++ targetComponents);
};
}

120
flake.lock generated Normal file
View file

@ -0,0 +1,120 @@
{
"nodes": {
"crane": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1706750221,
"narHash": "sha256-NXV6Tfoj29l2Hmif1tz6W14dN7xNLBmHH35EUmGTY80=",
"owner": "ipetkov",
"repo": "crane",
"rev": "6754d3a297f03590d2fb33fa39d97762ad3d4927",
"type": "github"
},
"original": {
"owner": "ipetkov",
"repo": "crane",
"type": "github"
}
},
"fenix": {
"inputs": {
"nixpkgs": [
"nixpkgs"
],
"rust-analyzer-src": []
},
"locked": {
"lastModified": 1706854869,
"narHash": "sha256-MUEwsK16OOG6/j0LZ0R0KhCcvJRKZHVXrBgLX7hZums=",
"owner": "nix-community",
"repo": "fenix",
"rev": "b03d2939685937a327f17df832bf9e8944ed9e3a",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "fenix",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1706683685,
"narHash": "sha256-FtPPshEpxH/ewBOsdKBNhlsL2MLEFv1hEnQ19f/bFsQ=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "5ad9903c16126a7d949101687af0aa589b1d7d3d",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-lib": {
"locked": {
"dir": "lib",
"lastModified": 1706550542,
"narHash": "sha256-UcsnCG6wx++23yeER4Hg18CXWbgNpqNXcHIo5/1Y+hc=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "97b17f32362e475016f942bbdfda4a4a72a8a652",
"type": "github"
},
"original": {
"dir": "lib",
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"parts": {
"inputs": {
"nixpkgs-lib": "nixpkgs-lib"
},
"locked": {
"lastModified": 1706830856,
"narHash": "sha256-a0NYyp+h9hlb7ddVz4LUn1vT/PLwqfrWYcHMvFB1xYg=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "b253292d9c0a5ead9bc98c4e9a26c6312e27d69f",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"root": {
"inputs": {
"crane": "crane",
"fenix": "fenix",
"nixpkgs": "nixpkgs",
"parts": "parts",
"rustManifest": "rustManifest"
}
},
"rustManifest": {
"flake": false,
"locked": {
"narHash": "sha256-uavbdMLBa9A2fTKFRUtWlwRNXCziN/r2ZmQC+sdmHW4=",
"type": "file",
"url": "https://static.rust-lang.org/dist/2023-02-02/channel-rust-nightly.toml"
},
"original": {
"type": "file",
"url": "https://static.rust-lang.org/dist/2023-02-02/channel-rust-nightly.toml"
}
}
},
"root": "root",
"version": 7
}

90
flake.nix Normal file
View file

@ -0,0 +1,90 @@
{
description = "Crane integration with flake-parts";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
parts.url = "github:hercules-ci/flake-parts";
fenix.url = "github:nix-community/fenix";
fenix.inputs.nixpkgs.follows = "nixpkgs";
fenix.inputs.rust-analyzer-src.follows = "";
crane.url = "github:ipetkov/crane";
crane.inputs.nixpkgs.follows = "nixpkgs";
rustManifest = {
url = "https://static.rust-lang.org/dist/2023-02-02/channel-rust-nightly.toml";
flake = false;
};
};
outputs = inputs:
with builtins;
with inputs.nixpkgs.lib;
inputs.parts.lib.mkFlake { inherit inputs; } {
flake.flakeModules = {
crane = import ./crane.nix inputs.crane;
fenix = import ./fenix.nix inputs.fenix;
};
flake.flakeModule = {
imports = attrValues inputs.self.flakeModules;
};
systems = [ "x86_64-linux" ];
perSystem = { pkgs, system, ... }: {
# checks.runExampleChecks = pkgs.stdenv.mkDerivation {
# name = "run-example-checks";
# dontUnpack = true;
# nestedChecks =
# let
# examplesDir = ./examples;
# children = readDir examplesDir;
# exampleDirs = filter (n: children.${n} == "directory") (attrNames children);
# exampleChecks = concatMap
# (d:
# let
# flakeDef = import "${examplesDir}/${d}/flake.nix";
# flakeInputs = inputs // { self = outputs; rust = inputs.self; };
# outputs = flakeDef // (flakeDef.outputs flakeInputs) // { _type = "flake"; inputs = flakeInputs; };
# in
# attrValues (outputs.checks.${system} or { }))
# exampleDirs;
# in
# map toString exampleChecks;
# buildPhase =
# ''
# echo $nestedChecks
# touch $out
# '';
# };
checks =
let
examplesDir = ./. + "/examples";
children = readDir examplesDir;
exampleDirs = filter (n: children.${n} == "directory") (attrNames children);
exampleChecks = map
(dir:
let
flakeDef = import "${examplesDir}/${dir}/flake.nix";
flakeInputs = inputs // {
self = flakeOutputs;
rust = inputs.self;
};
flakeOutputs = flakeDef //
(flakeDef.outputs flakeInputs) // {
_type = "flake";
inputs = flakeInputs;
};
in
flakeOutputs.checks.${system} or { })
exampleDirs;
in
foldl' (sofar: next: sofar // next) { } exampleChecks;
};
};
}