feat: rust template #26

Open
liketechnik wants to merge 6 commits from liketechnik/feat/rust-template into main
14 changed files with 424 additions and 0 deletions

View file

@ -34,6 +34,10 @@
path = ./direnv;
description = "An empty devshell with direnv support";
};
rust = {
path = ./rust;
description = "Rust specific template providing packaging, dev-shell & cross-compilation; based on fenix.";
};
};
formatter = forAllSystems (pkgs: pkgs.nixfmt-rfc-style);
};

38
rust/.editorconfig Normal file
View file

@ -0,0 +1,38 @@
root = true
[*]
indent_style = tab
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.nix]
indent_style = space
indent_size = 2
insert_final_newline = false
[*.rs,Cargo.toml]
indent_size = 4
insert_final_newline = false
[*.md]
indent_size = 2
trim_trailing_whitespace = false
insert_final_newline = false
[*.{json,json5,yaml,yml,webmanifest}]
indent_style = space
indent_size = 2
[*.toml]
indent_style = unset
indent_size = 0
[*.lock]
indent_style = unset
insert_final_newline = unset
[Makefile]
indent_style = tab

2
rust/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
result
target/

6
rust/Cargo.lock generated Normal file
View file

@ -0,0 +1,6 @@
# placeholder for the real Cargo.lock,
# so that evaluating the flake does not fail due to missing files,
# before using `cargo init` to create the 'real' files
version = 3
[[package]]

9
rust/Cargo.toml Normal file
View file

@ -0,0 +1,9 @@
# placeholder for the real Cargo.toml,
# so that evaluating the flake does not fail due to missing files,
# before using `cargo init` to create the 'real' files
[package]
name = "bin"
version = "0.1.0"
[profile.release]
overflow-checks = true

9
rust/default.nix Normal file
View file

@ -0,0 +1,9 @@
(import (
let
lock = builtins.fromJSON (builtins.readFile ./flake.lock);
in
fetchTarball {
url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz";
sha256 = lock.nodes.flake-compat.locked.narHash;
}
) { src = ./.; }).defaultNix

164
rust/flake.nix Normal file
View file

@ -0,0 +1,164 @@
{
inputs = {
flake-compat = {
url = "github:edolstra/flake-compat";
flake = false;
};
nixpkgs.url = "github:NixOs/nixpkgs/nixos-unstable";
fenix = {
url = "github:nix-community/fenix";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs =
{
self,
nixpkgs,
fenix,
...
}@inputs:
let
cargoMeta = builtins.fromTOML (builtins.readFile ./Cargo.toml);
packageName = cargoMeta.package.name;
forSystems =
function:
nixpkgs.lib.genAttrs [ "x86_64-linux" ] (
system:
let
pkgs = import nixpkgs {
inherit system;
overlays = [ (final: prev: { ${packageName} = self.packages.${system}.${packageName}; }) ];
};
fenixPkgs = fenix.packages.${pkgs.system};
fenixChannel = fenixPkgs.toolchainOf {
channel = "nightly";
date =
builtins.replaceStrings [ "nightly-" ] [ "" ]
(builtins.fromTOML (builtins.readFile ./rust-toolchain.toml)).toolchain.channel;
sha256 = "sha256-SzEeSoO54GiBQ2kfANPhWrt0EDRxqEvhIbTt2uJt/TQ=";
};
toolchainFor =
pkgs:
with fenixPkgs;
combine [
minimal.cargo
minimal.rustc
targets.${pkgs.rust.lib.toRustTarget pkgs.stdenv.targetPlatform}.latest.rust-std
];
rustPlatformFor =
pkgs:
let
toolchain = toolchainFor pkgs;
in
pkgs.makeRustPlatform {
cargo = toolchain;
rustc = toolchain;
};
crossPackageFor =
pkgs:
let
rustPlatform = rustPlatformFor pkgs;
in
{
"${packageName}-cross-${pkgs.stdenv.hostPlatform.config}${
if pkgs.stdenv.hostPlatform.isStatic then "-static" else ""
}" = pkgs.callPackage (./. + "/nix/packages/${packageName}.nix") {
inherit cargoMeta rustPlatform;
flake-self = self;
};
};
in
function {
inherit
system
pkgs
fenixPkgs
fenixChannel
toolchainFor
rustPlatformFor
crossPackageFor
;
}
);
in
{
formatter = forSystems ({ pkgs, ... }: pkgs.alejandra);
checks = forSystems (
{ pkgs, fenixChannel, ... }:
{
rustfmt =
pkgs.runCommand "check-rustfmt"
{
nativeBuildInputs =
let
fenixRustToolchain = fenixChannel.withComponents [
"cargo"
"rustfmt-preview"
];
in
[ fenixRustToolchain ];
}
''
cd ${./.}
cargo fmt -- --check
touch $out
'';
}
);
packages = forSystems (
{
pkgs,
fenixChannel,
system,
crossPackageFor,
...
}:
{
${packageName} = pkgs.callPackage (./. + "/nix/packages/${packageName}.nix") {
inherit cargoMeta;
flake-self = self;
rustPlatform = pkgs.makeRustPlatform {
cargo = fenixChannel.toolchain;
rustc = fenixChannel.toolchain;
};
};
default = self.packages.${system}.${packageName};
}
// crossPackageFor pkgs.pkgsCross.musl64.pkgsStatic
// crossPackageFor pkgs.pkgsCross.musl32.pkgsStatic
// crossPackageFor pkgs.pkgsCross.aarch64-multiplatform-musl.pkgsStatic
// crossPackageFor pkgs.pkgsCross.armv7l-hf-multiplatform.pkgsStatic
// crossPackageFor pkgs.pkgsCross.mingwW64.pkgsStatic
);
devShells = forSystems (
{ pkgs, fenixChannel, ... }:
let
fenixRustToolchain = fenixChannel.withComponents [
"cargo"
"clippy-preview"
"rust-src"
"rustc"
"rustfmt-preview"
];
in
{
default = pkgs.callPackage (./. + "/nix/dev-shells/${packageName}.nix") {
inherit fenixRustToolchain cargoMeta;
};
ci = pkgs.callPackage (./nix/dev-shells/ci.nix) { inherit fenixRustToolchain cargoMeta; };
}
);
};
}

45
rust/justfile Normal file
View file

@ -0,0 +1,45 @@
# move bin.nix files under nix/
# to the correct place
# for the new package name $packageName
# (i.e. $packageName.nix)
# delete this after running it
setup packageName:
mv nix/dev-shells/bin.nix "nix/dev-shells/{{ packageName }}.nix"
mv nix/packages/bin.nix "nix/packages/{{ packageName }}.nix"
rm Cargo.lock Cargo.toml
# pass --vcs none to disable addition to .gitignore
# (which would add the Cargo.lock to it)
cargo init --vcs none --lib --edition 2021 --name "{{ packageName }}"
# generate inital lockfile
cargo build
# make sure nix sees new *.nix files
git add .
build:
cargo build
build-release:
cargo build --release
run:
cargo run
run-release:
cargo run --release
format:
cargo fmt --check
eclint -exclude "{Cargo.lock,flake.lock}"
format-fix:
cargo fmt
eclint -exclude "{Cargo.lock,flake.lock}" -fix
lint:
cargo clippy
lint-fix:
cargo clippy --fix
reuse:
reuse lint

View file

@ -0,0 +1,34 @@
{
cargoMeta,
pkgs,
mkShell,
fenixRustToolchain,
bashInteractive,
cargo-edit,
reuse,
just,
eclint,
}:
mkShell {
inputsFrom = [ pkgs.${cargoMeta.package.name} ];
packages = [
fenixRustToolchain
bashInteractive
# for upgrading dependencies (i.e. versions in Cargo.toml)
cargo-edit
reuse
just
eclint
];
shellHook = ''
unset SOURCE_DATE_EPOCH
just --list --list-heading $'just <task>:\n'
'';
}

View file

@ -0,0 +1,37 @@
{
cargoMeta,
pkgs,
mkShell,
fenixRustToolchain,
bashInteractive,
reuse,
just,
eclint,
commitlint,
}:
mkShell {
inputsFrom = [ pkgs.${cargoMeta.package.name} ];
packages = [
fenixRustToolchain
bashInteractive
reuse
just
eclint
# nix develop ".#ci" --command --
# eclint
# -exclude "Cargo.lock"
# -exclude "flake.lock"
commitlint
# nix develop ".#ci" --command --
# commitlint
# --color false --verbose
# --from $(git rev-list --max-parents=0 HEAD | head -n 1)
# --to HEAD
];
}

36
rust/nix/packages/bin.nix Normal file
View file

@ -0,0 +1,36 @@
{
lib,
flake-self,
cargoMeta,
rustPlatform,
}:
let
fs = lib.fileset;
sourceFiles = fs.unions [
(fs.maybeMissing ../../src)
(fs.maybeMissing ../../Cargo.toml)
(fs.maybeMissing ../../Cargo.lock)
];
in
rustPlatform.buildRustPackage {
inherit (cargoMeta.package) version;
pname = cargoMeta.package.name;
src = fs.toSource {
root = ../../.;
fileset = sourceFiles;
};
cargoLock.lockFile = ../../Cargo.lock;
VERGEN_IDEMPOTENT = "1";
VERGEN_GIT_SHA =
if flake-self ? "rev" then
flake-self.rev
else if flake-self ? "dirtyRev" then
flake-self.dirtyRev
else
lib.warn "no git rev available" "NO_GIT_REPO";
VERGEN_GIT_BRANCH = if flake-self ? "ref" then flake-self.ref else "";
VERGEN_GIT_COMMIT_TIMESTAMP = flake-self.lastModifiedDate;
}

4
rust/rust-toolchain.toml Normal file
View file

@ -0,0 +1,4 @@
[toolchain]
channel = "nightly-2023-12-21"
components = ["rust-analyzer", "rust-src"]
profile = "default"

27
rust/rustfmt.toml Normal file
View file

@ -0,0 +1,27 @@
edition = "2021"
version = "Two"
newline_style = "Unix"
format_generated_files = false
hard_tabs = true
tab_spaces = 4
max_width = 80
doc_comment_code_block_width = 80
comment_width = 80
error_on_line_overflow = true
error_on_unformatted = true
normalize_comments = true
normalize_doc_attributes = true
use_try_shorthand = true
imports_granularity = "Crate"
group_imports = "StdExternalCrate"
reorder_impl_items = true
match_block_trailing_comma = true
use_field_init_shorthand = true

9
rust/shell.nix Normal file
View file

@ -0,0 +1,9 @@
(import (
let
lock = builtins.fromJSON (builtins.readFile ./flake.lock);
in
fetchTarball {
url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz";
sha256 = lock.nodes.flake-compat.locked.narHash;
}
) { src = ./.; }).shellNix