-
Notifications
You must be signed in to change notification settings - Fork 161
Expand file tree
/
Copy pathflake.nix
More file actions
279 lines (261 loc) · 11.4 KB
/
flake.nix
File metadata and controls
279 lines (261 loc) · 11.4 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
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
{
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
inputs.nixpkgs-mozilla.url = "github:mozilla/nixpkgs-mozilla/master";
outputs = { self, nixpkgs, nixpkgs-mozilla, ... } @ inputs:
rec {
overlays.fix-rust = self: super: {
# Work around the nixpkgs-mozilla equivalent of
# https://github.com/NixOS/nixpkgs/issues/278508 and an
# incompatibility between nixpkgs-mozilla and makeRustPlatform
rustChannelOf = args: let
orig = super.rustChannelOf args;
patchRustPkg = pkg: (pkg.overrideAttrs (oA: {
buildCommand = (builtins.replaceStrings
[ "rustc,rustdoc" ]
[ "rustc,rustdoc,clippy-driver,cargo-clippy,miri,cargo-miri" ]
oA.buildCommand) + (let
wrapperPath = self.path + "/pkgs/build-support/bintools-wrapper/ld-wrapper.sh";
baseOut = self.clangStdenv.cc.bintools.out;
getStdenvAttrs = drv: (drv.overrideAttrs (oA: {
passthru.origAttrs = oA;
})).origAttrs;
baseEnv = (getStdenvAttrs self.clangStdenv.cc.bintools).env;
baseSubstitutedWrapper = self.replaceVars wrapperPath
{
inherit (baseEnv)
shell coreutils_bin suffixSalt mktemp rm;
use_response_file_by_default = "0";
prog = null;
out = null;
};
in ''
# work around a bug in the overlay
${oA.postInstall}
# copy over helper scripts that the wrapper needs
(cd "${baseOut}"; find . -type f \( -name '*.sh' -or -name '*.bash' \) -print0) | while read -d $'\0' script; do
mkdir -p "$out/$(dirname "$script")"
substitute "${baseOut}/$script" "$out/$script" --replace-quiet "${baseOut}" "$out"
done
# TODO: Work out how to make this work with cross builds
ldlld="$out/lib/rustlib/${self.clangStdenv.targetPlatform.config}/bin/gcc-ld/ld.lld";
if [ -e "$ldlld" ]; then
export prog="$(readlink -f "$ldlld")"
rm "$ldlld"
substitute ${baseSubstitutedWrapper} "$ldlld" --subst-var "out" --subst-var "prog"
chmod +x "$ldlld"
fi
'');
})) // {
targetPlatforms = [ "x86_64-linux" ];
badTargetPlatforms = [ ];
};
overrideRustPkg = pkg: self.lib.makeOverridable (origArgs:
patchRustPkg (pkg.override origArgs)
) {};
in builtins.mapAttrs (_: overrideRustPkg) orig;
};
gcroots =
let gcrootForShell = pkg: pkg // derivation (pkg.drvAttrs // {
origArgs = pkg.drvAttrs.args;
# assume the builder is bash for now (it always is for
# stdenv, which is the only thing that we will encounter
# in this flake).
args = [ "-c" "declare > $out" ];
});
in {
shells.default = gcrootForShell devShells.x86_64-linux.default;
};
devShells.x86_64-linux.default =
let pkgs = import nixpkgs {
system = "x86_64-linux";
overlays = [ (import (nixpkgs-mozilla + "/rust-overlay.nix")) overlays.fix-rust ];
};
in with pkgs; let
customisedRustChannelOf = args:
lib.flip builtins.mapAttrs (rustChannelOf args) (_: pkg: pkg.override {
targets = [
"x86_64-unknown-linux-gnu"
"x86_64-pc-windows-msvc" "x86_64-unknown-none"
"wasm32-wasip1" "wasm32-wasip2" "wasm32-unknown-unknown"
"i686-unknown-linux-gnu"
];
extensions = [ "rust-src" ] ++ (if args.channel == "nightly" then [ "miri-preview" ] else []);
});
# Hyperlight needs a variety of toolchains, since we use Nightly
# for rustfmt and old toolchains to verify MSRV
toolchains = lib.mapAttrs (_: customisedRustChannelOf) {
stable = {
date = "2025-12-11";
channel = "stable";
sha256 = "sha256-sqSWJDUxc+zaz1nBWMAJKTAGBuGWP25GCftIOlCEAtA=";
};
nightly = {
date = "2026-01-19";
channel = "nightly";
sha256 = "sha256-Ye65U/qzilPLte800N5oxFOY96shgG8bST8dbrF6Qh0=";
};
"1.89" = {
date = "2025-08-07";
channel = "stable";
sha256 = "sha256-+9FmLhAOezBZCOziO0Qct1NOrfpjNsXxc/8I0c7BdKE=";
};
};
rust-platform = makeRustPlatform {
cargo = toolchains.stable.rust;
rustc = toolchains.stable.rust;
};
manifests = [
"Cargo.toml"
"src/tests/rust_guests/dummyguest/Cargo.toml"
"src/tests/rust_guests/simpleguest/Cargo.toml"
"src/tests/rust_guests/witguest/Cargo.toml"
];
manifestDeps = builtins.map (manifest:
let lockPath = builtins.replaceStrings [ "toml" ] [ "lock" ] manifest; in
let lockFile = ./${lockPath}; in
rust-platform.importCargoLock { inherit lockFile; }) manifests;
# when building a guest with cargo-hyperlight, or when
# building a miri sysroot for the main workspace, we need to
# include any crates.io dependencies of the standard library
# (e.g. rustc-literal-escaper)
stdlibLocks = lib.mapAttrsToList (_: toolchain:
"${toolchain.rust}/lib/rustlib/src/rust/library/Cargo.lock"
) toolchains;
stdlibDeps = builtins.map (lockFile:
rust-platform.importCargoLock { inherit lockFile; }) stdlibLocks;
deps = pkgs.symlinkJoin {
name = "cargo-deps";
paths = stdlibDeps ++ manifestDeps;
};
# Script snippet, used in the cargo/rustc wrappers below,
# which creates a number of .cargo/config.toml files in
# order to allow using Nix-fetched dependencies (this must
# be done for the guests, as well as for the main
# workspace). Ideally, we would just use environment
# variables or the --config option to Cargo, but
# unfortunately that tends not to play well with subcommands
# like `cargo clippy` and `cargo hyperlight` (see
# https://github.com/rust-lang/cargo/issues/11031).
materialiseDeps = let
sortedManifests = lib.lists.sort (p: q: p > q) manifests;
matchClause = path: '' */${path}) root="''${manifest%${path}}" ;;'';
matchClauses = lib.strings.concatStringsSep "\n"
(builtins.map matchClause sortedManifests);
in ''
base_cargo() {
PATH="$base/bin:$PATH" "$base/bin/cargo" "$@"
}
manifest=$(base_cargo locate-project --message-format plain --workspace)
case "$manifest" in
${matchClauses}
esac
if [ -f ''${root}/flake.nix ]; then
mkdir -p $root/$.cargo
cat >$root/.cargo/config.toml <<EOF
[source.crates-io]
replace-with = "vendored-sources"
[source.vendored-sources]
directory = "${deps}"
EOF
sed -i '/# vendor dependency configuration generated by nix/{N;d;}' $root/.git/info/exclude
printf "# vendor dependency configuration generated by nix\n%s\n" "/.cargo" >> $root/.git/info/exclude
fi
# libgit2-sys copies a vendored git2 into the target/
# directory somewhere. In certain, rare, cases,
# libgit2-sys is rebuilt in the same incremental dep
# directory as it was before, and then this copy fails,
# because the files, copied from the nix store, already
# exist and do not have w permission. Hack around this
# issue by making any existing libgit2-sys vendored git2
# files writable before a build can be run
find "$(base_cargo metadata --format-version 1 | jq -r '.target_directory')" -path '*/build/libgit2-sys-*/out/include' -print0 | xargs -r -0 chmod u+w -R
'';
# Hyperlight scripts use cargo in a bunch of ways that don't
# make sense for Nix cargo, including the `rustup +toolchain`
# syntax to use a specific toolchain and `cargo install`, so we
# build wrappers for rustc and cargo that enable this. The
# scripts also use `rustup toolchain install` in some cases, in
# order to work in CI, so we provide a fake rustup that does
# nothing as well.
rustup-like-wrapper = name: pkgs.writeShellScriptBin name
(let
clause = name: toolchain:
"+${name}) base=\"${toolchain.rust}\"; shift 1; ;;";
clauses = lib.strings.concatStringsSep "\n"
(lib.mapAttrsToList clause toolchains);
in ''
base="${toolchains.stable.rust}"
${materialiseDeps}
case "$1" in
${clauses}
install) exit 0; ;;
esac
export PATH="$base/bin:$PATH"
exec "$base/bin/${name}" "$@"
'');
fake-rustup = pkgs.symlinkJoin {
name = "fake-rustup";
paths = [
(pkgs.writeShellScriptBin "rustup" "")
(rustup-like-wrapper "rustc")
(rustup-like-wrapper "cargo")
];
};
buildRustPackageClang = rust-platform.buildRustPackage.override { stdenv = clangStdenv; };
cargo-hyperlight = buildRustPackageClang rec {
pname = "cargo-hyperlight";
version = "0.1.5";
src = fetchFromGitHub {
owner = "hyperlight-dev";
repo = "cargo-hyperlight";
tag = "v${version}";
hash = "sha256-xq4/c69N0wG/I8WOYVloo0J0JqoSIKiWWtECdSKrsxo=";
};
cargoHash = "sha256-muiMVrK1TydQiMitihfo7xYidqUIIQ+Hw3BIeo5rLFw=";
};
in (buildRustPackageClang (mkDerivationAttrs: {
pname = "hyperlight";
version = "0.0.0";
src = lib.cleanSource ./.;
cargoDeps = deps;
nativeBuildInputs = [
azure-cli
just
dotnet-sdk_9
llvmPackages_18.llvm
gh
lld
valgrind
pkg-config
ffmpeg
mkvtoolnix
wasm-tools
jq
jaq
gdb
zlib
cargo-hyperlight
typos
flatbuffers
cargo-fuzz
];
buildInputs = [
pango
cairo
openssl
];
auditable = false;
LIBCLANG_PATH = "${pkgs.llvmPackages_18.libclang.lib}/lib";
# Use unwrapped clang for compiling guests
HYPERLIGHT_GUEST_clang = "${clang.cc}/bin/clang";
RUST_NIGHTLY = "${toolchains.nightly.rust}";
# Set this through shellHook rather than nativeBuildInputs to be
# really sure that it overrides the real cargo.
postHook = ''
export PATH="${fake-rustup}/bin:$PATH"
'';
})).overrideAttrs(oA: {
hardeningDisable = [ "all" ];
});
};
}