-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathflake.nix
More file actions
226 lines (218 loc) · 7.79 KB
/
flake.nix
File metadata and controls
226 lines (218 loc) · 7.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
rust-overlay.url = "github:oxalica/rust-overlay";
rust-overlay.inputs.nixpkgs.follows = "nixpkgs";
systems.url = "github:nix-systems/default";
};
outputs =
inputs:
let
inherit (inputs.nixpkgs.lib) recursiveUpdate;
# Optional function or just `f`
ofunc =
f: x: y:
if (builtins.isFunction f) then (f x y) else (f);
# This file is laid out a bit backwards for readability's sake.
# This is the final output, it's going to be a nice output of all the
# packages, with the devshell and overlays merged into one output.
# outs is how we get the final output, where all the packages are joined
# and then a default overlay and devshell is created with all of the
# requirements for each package.
# merge :: [attrSet] -> attrSet
rust-flakes =
output-list: builtins.removeAttrs (builtins.foldl' mergeOutputs { } output-list) [ "all-deps" ];
# Merges two of the rust-flakes into a single output. It's not suitable to
# use directly yet. Use `merge` instead.
mergeOutputs =
left: right:
let
# Defaults from the left and right that we need
# Overlays
lo = left.overlays.default or { };
ro = right.overlays.default or { };
# Dependencies
ld = left.all-deps or [ ];
rd = right.all-deps or [ ];
# Packages
lp = left.packages or { };
rp = right.packages or { };
overlay-all = (final: prev: (ofunc lo final prev) // (ofunc ro final prev));
all-deps = f: p: (ofunc ld f p) ++ (ofunc rd f p);
in
{
inherit all-deps;
packages = recursiveUpdate lp rp;
overlays.default = overlay-all;
devShells = forEachSupportedSystem overlay-all (
{ pkgs }:
{
default = pkgs.mkShell {
# Join all the deps together
packages = [
pkgs.rustToolchain-dev'
]
++ (all-deps pkgs pkgs);
};
}
);
};
forEachSupportedSystem =
overlay: f:
inputs.nixpkgs.lib.genAttrs (import inputs.systems) (
system:
f {
pkgs = import inputs.nixpkgs {
inherit system;
overlays = [
inputs.rust-overlay.overlays.default
overlay
];
};
}
);
rust-flake =
{
# The root of your rust crate
root,
repo-root ? root,
# Use the workspace instead of the normal package.* info
workspace ? false,
# Extra files to include in the source
extra-files ? [ ],
# Extra files to _exclude_ in the source
exclude-files ? [ ],
# The `deps-*` variables should be functions that take a package set as
# a variable.
# Dependencies required only for the build (`nativeBuildInputs`)
deps-build ? [ ],
# Runtime dependencies (`buildInputs`)
deps-run ? [ ],
# Development dependencies (for the devShells)
deps-dev ? [ ],
# Will also create a default output.
is-default ? true,
# Specify an alternate toolchain file (useful for sub-crates)
toolchain ? repo-root + /rust-toolchain.toml,
toolchain-overrides ? { },
dev-overrides ? {
extensions = [
"rust-src"
"rust-analyzer"
];
},
pkg-overrides ? { },
...
}@rustArgs:
let
## Be careful editing anything below here. ##
# Stores a nix object from the Cargo.toml file
cargoToml =
let
c = builtins.fromTOML (builtins.readFile (root + /Cargo.toml));
in
if workspace then c.workspace else c;
pname = rustArgs.name-override or cargoToml.package.name;
name = pname;
# Easy way to get just the rust source stuff that we care about without
# rebuilding when non-code stuff changes
inherit (inputs.nixpkgs.lib.fileset)
toSource
intersection
unions
difference
maybeMissing
;
rustSrc = toSource {
inherit root;
fileset = (
intersection root (
difference (unions (
[
(maybeMissing (root + /Cargo.toml))
(maybeMissing (root + /Cargo.lock))
(maybeMissing (root + /src))
]
++ (map maybeMissing extra-files)
)) (unions exclude-files)
)
);
};
# Creates an overlay using rust-overlay and adds this package to it
pkg-overlay = (
final: prev: {
# Add an override for the toolchain and platform
# Uses the `foo'` notation because otherwise the recursion is nasty.
# Split into two different toolchains, one with stuff for development,
# and the other only containing the base toolchain.
rustToolchain' = (prev.rust-bin.fromRustupToolchainFile toolchain).override (
ofunc toolchain-overrides final prev
);
rustToolchain-dev' = final.rustToolchain'.override (
(ofunc toolchain-overrides final prev) // (ofunc dev-overrides final prev)
);
rustPlatform' = final.makeRustPlatform {
cargo = final.rustToolchain';
rustc = final.rustToolchain';
};
"${name}" = (
final.rustPlatform'.buildRustPackage (
{
inherit pname;
version = cargoToml.package.version;
src = rustSrc;
cargoLock.lockFile = root + /Cargo.lock;
meta = (
{
homepage = cargoToml.package.repository or "https://example.com";
mainProgram = name;
}
// {
description = (cargoToml.package.description or "default description");
}
);
}
// (
if (ofunc deps-build final prev) != [ ] then
{
nativeBuildInputs = ofunc deps-build final prev;
}
else
{ }
)
// (
if (ofunc deps-run final prev) != [ ] then
{
buildInputs = ofunc deps-run final prev;
}
else
{ }
)
// (ofunc pkg-overrides final prev)
)
);
}
);
final-outputs = final-name: {
# `nix run` works with the package now that it has mainProgram set
packages = forEachSupportedSystem pkg-overlay (
{ pkgs }:
{
"${final-name}" = pkgs.${name};
}
);
# Allow using this in other flakes as an overlay easily
overlays = {
default = pkg-overlay;
};
all-deps = f: p: (ofunc deps-build f p) ++ (ofunc deps-run f p) ++ (ofunc deps-dev f p);
};
in
final-outputs (if is-default then "default" else name);
in
{
lib = {
inherit rust-flake rust-flakes;
};
};
}