feat: rust template #26
|
@ -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
38
rust/.editorconfig
Normal 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
2
rust/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
result
|
||||
target/
|
6
rust/Cargo.lock
generated
Normal file
6
rust/Cargo.lock
generated
Normal 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
9
rust/Cargo.toml
Normal 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
9
rust/default.nix
Normal 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
164
rust/flake.nix
Normal 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
45
rust/justfile
Normal 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
|
34
rust/nix/dev-shells/bin.nix
Normal file
34
rust/nix/dev-shells/bin.nix
Normal 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'
|
||||
'';
|
||||
}
|
37
rust/nix/dev-shells/ci.nix
Normal file
37
rust/nix/dev-shells/ci.nix
Normal 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
36
rust/nix/packages/bin.nix
Normal 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
4
rust/rust-toolchain.toml
Normal file
|
@ -0,0 +1,4 @@
|
|||
[toolchain]
|
||||
channel = "nightly-2023-12-21"
|
||||
components = ["rust-analyzer", "rust-src"]
|
||||
profile = "default"
|
27
rust/rustfmt.toml
Normal file
27
rust/rustfmt.toml
Normal 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
9
rust/shell.nix
Normal 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
|
Loading…
Reference in a new issue