feat: rust template

This commit is contained in:
Florian Warzecha 2024-05-06 22:00:10 +02:00
parent af8d3f5deb
commit a517191742
Signed by: liketechnik
GPG key ID: 4BE8C7D97F910C60
14 changed files with 402 additions and 0 deletions

View file

@ -34,6 +34,10 @@
path = ./direnv; path = ./direnv;
description = "An empty devshell with direnv support"; 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); formatter = forAllSystems (pkgs: pkgs.nixfmt-rfc-style);
}; };

36
rust/.editorconfig Normal file
View file

@ -0,0 +1,36 @@
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_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_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

146
rust/flake.nix Normal file
View file

@ -0,0 +1,146 @@
{
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";
};
nix-filter = {
url = "github:numtide/nix-filter";
};
};
outputs =
{
self,
nixpkgs,
fenix,
nix-filter,
...
}@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}; }) ];
};
fenix-pkgs = fenix.packages.${system};
fenix-channel = fenix-pkgs.toolchainOf {
channel = "nightly";
date =
builtins.replaceStrings [ "nightly-" ] [ "" ]
(builtins.fromTOML (builtins.readFile ./rust-toolchain.toml)).toolchain.channel;
sha256 = "sha256-SzEeSoO54GiBQ2kfANPhWrt0EDRxqEvhIbTt2uJt/TQ=";
};
makeCrossPackage =
packageName: pkgsCross:
let
pkgs = builtins.throw "defining cross pkg, accessing pkgs is a bug";
in
{
"${packageName}-cross-${pkgsCross.stdenv.hostPlatform.config}${
if pkgsCross.stdenv.hostPlatform.isStatic then "-static" else ""
}" =
let
toolchain =
with fenix-pkgs;
combine [
minimal.cargo
minimal.rustc
targets.${pkgsCross.rust.lib.toRustTarget pkgsCross.stdenv.targetPlatform}.latest.rust-std
];
in
pkgsCross.callPackage (./. + "/nix/packages/${packageName}.nix") {
inherit cargoMeta;
flake-self = self;
nix-filter = import inputs.nix-filter;
rustPlatform = pkgsCross.makeRustPlatform {
cargo = toolchain;
rustc = toolchain;
};
};
};
in
function {
inherit
system
pkgs
fenix-pkgs
fenix-channel
makeCrossPackage
;
}
);
in
{
formatter = forSystems ({ pkgs, ... }: pkgs.alejandra);
packages = forSystems (
{
pkgs,
fenix-channel,
system,
makeCrossPackage,
...
}:
{
${packageName} = pkgs.callPackage (./. + "/nix/packages/${packageName}.nix") {
inherit cargoMeta;
flake-self = self;
nix-filter = import inputs.nix-filter;
rustPlatform = pkgs.makeRustPlatform {
cargo = fenix-channel.toolchain;
rustc = fenix-channel.toolchain;
};
};
default = self.packages.${system}.${packageName};
}
// makeCrossPackage packageName pkgs.pkgsCross.musl64.pkgsStatic
// makeCrossPackage packageName pkgs.pkgsCross.musl32.pkgsStatic
// makeCrossPackage packageName pkgs.pkgsCross.aarch64-multiplatform-musl.pkgsStatic
// makeCrossPackage packageName pkgs.pkgsCross.armv7l-hf-multiplatform.pkgsStatic
// makeCrossPackage packageName pkgs.pkgsCross.mingwW64.pkgsStatic
);
devShells = forSystems (
{
pkgs,
fenix-pkgs,
fenix-channel,
...
}:
let
fenixRustToolchain = fenix-channel.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
];
}

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

@ -0,0 +1,34 @@
{
lib,
flake-self,
cargoMeta,
nix-filter,
rustPlatform,
}:
rustPlatform.buildRustPackage {
inherit (cargoMeta.package) version;
pname = cargoMeta.package.name;
src = nix-filter {
root = ../../.;
include = [
"src"
"Cargo.toml"
"Cargo.lock"
];
};
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