1{
2 lib,
3 suffix ? "",
4 version,
5 src,
6 # For Lix versions >= 2.92, Rust sources are in the Lix repository root.
7 cargoDeps ? null,
8 # For previous versions, Rust sources are only in a subdirectory for
9 # `lix-doc`.
10 docCargoDeps ? null,
11 patches ? [ ],
12 knownVulnerabilities ? [ ],
13}@args:
14
15assert lib.assertMsg (
16 lib.versionOlder version "2.92" -> docCargoDeps != null
17) "`lix-doc` `cargoDeps` must be set for Lix < 2.92";
18assert lib.assertMsg (
19 lib.versionAtLeast version "2.92" -> cargoDeps != null
20) "`cargoDeps` must be set for Lix ≥ 2.92";
21
22{
23 stdenv,
24 meson,
25 bison,
26 boehmgc,
27 boost,
28 brotli,
29 busybox-sandbox-shell,
30 bzip2,
31 callPackage,
32 capnproto,
33 cargo,
34 curl,
35 cmake,
36 doxygen,
37 editline,
38 flex,
39 git,
40 gtest,
41 jq,
42 lib,
43 libarchive,
44 libcpuid,
45 libsodium,
46 libsystemtap,
47 llvmPackages,
48 lowdown,
49 lowdown-unsandboxed,
50 lsof,
51 mercurial,
52 mdbook,
53 mdbook-linkcheck,
54 nlohmann_json,
55 ninja,
56 openssl,
57 rustc,
58 toml11,
59 pegtl,
60 python3,
61 pkg-config,
62 rapidcheck,
63 sqlite,
64 systemtap-sdt,
65 util-linuxMinimal,
66 removeReferencesTo,
67 xz,
68 yq,
69 nixosTests,
70 rustPlatform,
71 # Only used for versions before 2.92.
72 lix-doc ? callPackage ./doc {
73 inherit src;
74 version = "${version}${suffix}";
75 cargoDeps = docCargoDeps;
76 },
77
78 enableDocumentation ? stdenv.hostPlatform == stdenv.buildPlatform,
79 enableStatic ? stdenv.hostPlatform.isStatic,
80 enableStrictLLVMChecks ? true,
81 withAWS ? !enableStatic && (stdenv.hostPlatform.isLinux || stdenv.hostPlatform.isDarwin),
82 aws-sdk-cpp,
83 # FIXME support Darwin once https://github.com/NixOS/nixpkgs/pull/392918 lands
84 withDtrace ?
85 lib.meta.availableOn stdenv.hostPlatform libsystemtap
86 && lib.meta.availableOn stdenv.buildPlatform systemtap-sdt,
87 # RISC-V support in progress https://github.com/seccomp/libseccomp/pull/50
88 withLibseccomp ? lib.meta.availableOn stdenv.hostPlatform libseccomp,
89 libseccomp,
90 pastaFod ? lib.meta.availableOn stdenv.hostPlatform passt,
91 passt,
92
93 confDir,
94 stateDir,
95 storeDir,
96}:
97let
98 isLLVMOnly = lib.versionAtLeast version "2.92";
99 hasExternalLixDoc = lib.versionOlder version "2.92";
100 isLegacyParser = lib.versionOlder version "2.91";
101 hasDtraceSupport = lib.versionAtLeast version "2.93";
102 parseToYAML = lib.versionAtLeast version "2.93";
103in
104# gcc miscompiles coroutines at least until 13.2, possibly longer
105# do not remove this check unless you are sure you (or your users) will not report bugs to Lix upstream about GCC miscompilations.
106assert lib.assertMsg (enableStrictLLVMChecks && isLLVMOnly -> stdenv.cc.isClang)
107 "Lix upstream strongly discourage the usage of GCC to compile Lix as there's known miscompilations in important places. If you are a compiler developer, please get in touch with us.";
108stdenv.mkDerivation (finalAttrs: {
109 pname = "lix";
110
111 version = "${version}${suffix}";
112 VERSION_SUFFIX = suffix;
113
114 inherit src patches;
115
116 outputs = [
117 "out"
118 "dev"
119 ]
120 ++ lib.optionals enableDocumentation [
121 "man"
122 "doc"
123 "devdoc"
124 ];
125
126 strictDeps = true;
127 disallowedReferences = lib.optionals isLLVMOnly [
128 # We don't want the Clang.
129 stdenv.cc.cc
130 # We don't want the underlying GCC neither!
131 stdenv.cc.cc.stdenv.cc.cc
132 ];
133 __structuredAttrs = true;
134
135 # We only include CMake so that Meson can locate toml11, which only ships CMake dependency metadata.
136 dontUseCmakeConfigure = true;
137
138 nativeBuildInputs = [
139 # python3.withPackages does not splice properly, see https://github.com/NixOS/nixpkgs/issues/305858
140 (python3.pythonOnBuildForHost.withPackages (p: [
141 p.pytest
142 p.pytest-xdist
143 p.python-frontmatter
144 p.toml
145 ]))
146 pkg-config
147 flex
148 jq
149 meson
150 ninja
151 cmake
152 python3
153 # Required for libstd++ assertions that leaks inside of the final binary.
154 removeReferencesTo
155
156 # Tests
157 git
158 mercurial
159 jq
160 lsof
161 ]
162 ++ lib.optionals isLLVMOnly [
163 rustc
164 cargo
165 rustPlatform.cargoSetupHook
166 ]
167 ++ lib.optionals isLegacyParser [ bison ]
168 ++ lib.optionals enableDocumentation [
169 (lib.getBin lowdown-unsandboxed)
170 mdbook
171 mdbook-linkcheck
172 doxygen
173 ]
174 ++ lib.optionals (hasDtraceSupport && withDtrace) [ systemtap-sdt ]
175 ++ lib.optionals pastaFod [ passt ]
176 ++ lib.optionals parseToYAML [ yq ]
177 ++ lib.optionals stdenv.hostPlatform.isLinux [ util-linuxMinimal ];
178
179 buildInputs = [
180 boost
181 brotli
182 bzip2
183 curl
184 capnproto
185 editline
186 libsodium
187 openssl
188 sqlite
189 xz
190 gtest
191 libarchive
192 lowdown
193 rapidcheck
194 toml11
195 ]
196 ++ lib.optionals hasExternalLixDoc [ lix-doc ]
197 ++ lib.optionals (!isLegacyParser) [ pegtl ]
198 # NOTE(Raito): I'd have expected that the LLVM packaging would inject the
199 # libunwind library path directly in the wrappers, but it does inject
200 # -lunwind without injecting the library path...
201 ++ lib.optionals stdenv.hostPlatform.isStatic [ llvmPackages.libunwind ]
202 ++ lib.optionals (stdenv.hostPlatform.isx86_64) [ libcpuid ]
203 ++ lib.optionals withLibseccomp [ libseccomp ]
204 ++ lib.optionals withAWS [ aws-sdk-cpp ]
205 ++ lib.optionals (hasDtraceSupport && withDtrace) [ libsystemtap ];
206
207 inherit cargoDeps;
208
209 env = {
210 # Meson allows referencing a /usr/share/cargo/registry shaped thing for subproject sources.
211 # Turns out the Nix-generated Cargo dependencies are named the same as they
212 # would be in a Cargo registry cache.
213 MESON_PACKAGE_CACHE_DIR =
214 if finalAttrs.cargoDeps != null then
215 finalAttrs.cargoDeps
216 else
217 "lix: no `MESON_PACKAGE_CACHE_DIR`, set `cargoDeps`";
218 };
219
220 propagatedBuildInputs = [
221 boehmgc
222 nlohmann_json
223 ];
224
225 postPatch = ''
226 patchShebangs --build tests doc/manual
227 '';
228
229 preConfigure =
230 # Copy libboost_context so we don't get all of Boost in our closure.
231 # https://github.com/NixOS/nixpkgs/issues/45462
232 lib.optionalString (!enableStatic) ''
233 mkdir -p $out/lib
234 cp -pd ${boost}/lib/{libboost_context*,libboost_thread*,libboost_system*} $out/lib
235 rm -f $out/lib/*.a
236 ${lib.optionalString stdenv.hostPlatform.isLinux ''
237 chmod u+w $out/lib/*.so.*
238 patchelf --set-rpath $out/lib:${lib.getLib stdenv.cc.cc}/lib $out/lib/libboost_thread.so.*
239 ''}
240 ${lib.optionalString stdenv.hostPlatform.isDarwin ''
241 for LIB in $out/lib/*.dylib; do
242 chmod u+w $LIB
243 install_name_tool -id $LIB $LIB
244 install_name_tool -delete_rpath ${boost}/lib/ $LIB || true
245 done
246 install_name_tool -change ${boost}/lib/libboost_system.dylib $out/lib/libboost_system.dylib $out/lib/libboost_thread.dylib
247 ''}
248 '';
249
250 # -O3 seems to anger a gcc bug and provide no performance benefit.
251 # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114360
252 # We use -O2 upstream https://gerrit.lix.systems/c/lix/+/554
253 mesonBuildType = "debugoptimized";
254
255 mesonFlags = [
256 # Enable LTO, since it improves eval performance a fair amount
257 # LTO is disabled on:
258 # - static builds (strange linkage errors)
259 # - darwin builds (install test failures. see fj#568 & fj#832)
260 (lib.mesonBool "b_lto" (
261 !stdenv.hostPlatform.isStatic && !stdenv.hostPlatform.isDarwin && (isLLVMOnly || stdenv.cc.isGNU)
262 ))
263 (lib.mesonEnable "gc" true)
264 (lib.mesonBool "enable-tests" true)
265 (lib.mesonBool "enable-docs" enableDocumentation)
266 (lib.mesonEnable "internal-api-docs" enableDocumentation)
267 (lib.mesonBool "enable-embedded-sandbox-shell" (
268 stdenv.hostPlatform.isLinux && stdenv.hostPlatform.isStatic
269 ))
270 (lib.mesonEnable "seccomp-sandboxing" withLibseccomp)
271
272 (lib.mesonOption "store-dir" storeDir)
273 (lib.mesonOption "state-dir" stateDir)
274 (lib.mesonOption "sysconfdir" confDir)
275 ]
276 ++ lib.optionals hasDtraceSupport [
277 (lib.mesonEnable "dtrace-probes" withDtrace)
278 ]
279 ++ lib.optionals stdenv.hostPlatform.isLinux [
280 (lib.mesonOption "sandbox-shell" "${busybox-sandbox-shell}/bin/busybox")
281 ];
282
283 ninjaFlags = [ "-v" ];
284
285 postInstall =
286 lib.optionalString enableDocumentation ''
287 mkdir -p $doc/nix-support
288 echo "doc manual $doc/share/doc/nix/manual" >> $doc/nix-support/hydra-build-products
289
290 mkdir -p $devdoc/nix-support
291 echo "devdoc internal-api $devdoc/share/doc/nix/internal-api" >> $devdoc/nix-support/hydra-build-products
292 ''
293 + lib.optionalString (!hasExternalLixDoc) ''
294 # We do not need static archives.
295 # FIXME(Raito): why are they getting installed _at all_ ?
296 rm $out/lib/liblix_doc.a
297 ''
298 + lib.optionalString stdenv.hostPlatform.isStatic ''
299 mkdir -p $out/nix-support
300 echo "file binary-dist $out/bin/nix" >> $out/nix-support/hydra-build-products
301 ''
302 + lib.optionalString stdenv.hostPlatform.isDarwin ''
303 for lib in liblixutil.dylib liblixexpr.dylib; do
304 install_name_tool \
305 -change "${lib.getLib boost}/lib/libboost_context.dylib" \
306 "$out/lib/libboost_context.dylib" \
307 "$out/lib/$lib"
308 done
309 ''
310 + ''
311 # Drop all references to libstd++ include files due to `__FILE__` leaking in libstd++ assertions.
312 find "$out" -type f -exec remove-references-to -t ${stdenv.cc.cc.stdenv.cc.cc} '{}' +
313 '';
314
315 # This needs to run after _multioutDocs moves the docs to $doc
316 postFixup = lib.optionalString enableDocumentation ''
317 mkdir -p $devdoc/share/doc/nix
318 mv $doc/share/doc/nix/internal-api $devdoc/share/doc/nix
319 '';
320
321 doCheck = true;
322 mesonCheckFlags = [
323 "--suite=check"
324 "--print-errorlogs"
325 ];
326 checkInputs = [
327 gtest
328 rapidcheck
329 ];
330
331 doInstallCheck = true;
332 mesonInstallCheckFlags = [
333 "--suite=installcheck"
334 "--print-errorlogs"
335 ];
336
337 preInstallCheck = lib.optionalString stdenv.hostPlatform.isDarwin ''
338 # socket path becomes too long otherwise
339 export TMPDIR=$NIX_BUILD_TOP
340 # Prevent crashes in libcurl due to invoking Objective-C `+initialize` methods after `fork`.
341 # See http://sealiesoftware.com/blog/archive/2017/6/5/Objective-C_and_fork_in_macOS_1013.html.
342 export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES
343 '';
344
345 installCheckPhase = ''
346 runHook preInstallCheck
347 flagsArray=($mesonInstallCheckFlags "''${mesonInstallCheckFlagsArray[@]}")
348 meson test --no-rebuild "''${flagsArray[@]}"
349 runHook postInstallCheck
350 '';
351 hardeningDisable = [
352 "shadowstack"
353 # strictoverflow is disabled because we trap on signed overflow instead
354 "strictoverflow"
355 ]
356 # fortify breaks the build with lto and musl for some reason
357 ++ lib.optional stdenv.hostPlatform.isMusl "fortify";
358
359 # hardeningEnable = lib.optionals (!stdenv.hostPlatform.isDarwin) [ "pie" ];
360 separateDebugInfo = stdenv.hostPlatform.isLinux && !enableStatic;
361 enableParallelBuilding = true;
362
363 # Used by (1) test which has dynamic port assignment.
364 __darwinAllowLocalNetworking = true;
365
366 passthru = {
367 inherit aws-sdk-cpp boehmgc;
368 tests = {
369 misc = nixosTests.nix-misc.default.passthru.override { nixPackage = finalAttrs.finalPackage; };
370 installer = nixosTests.installer.simple.override { selectNixPackage = _: finalAttrs.finalPackage; };
371 };
372 };
373
374 # point 'nix edit' and ofborg at the file that defines the attribute,
375 # not this common file.
376 pos = builtins.unsafeGetAttrPos "version" args;
377 meta = {
378 description = "Powerful package manager that makes package management reliable and reproducible";
379 longDescription = ''
380 Lix (a fork of Nix) is a powerful package manager for Linux and other Unix systems that
381 makes package management reliable and reproducible. It provides atomic
382 upgrades and rollbacks, side-by-side installation of multiple versions of
383 a package, multi-user package management and easy setup of build
384 environments.
385 '';
386 homepage = "https://lix.systems";
387 license = lib.licenses.lgpl21Plus;
388 teams = [ lib.teams.lix ];
389 platforms = lib.platforms.unix;
390 outputsToInstall = [ "out" ] ++ lib.optional enableDocumentation "man";
391 mainProgram = "nix";
392 inherit knownVulnerabilities;
393 };
394})