1{
2 lib,
3 pkgs,
4 src,
5 officialRelease,
6 maintainers,
7 teams,
8 version,
9}:
10
11scope:
12
13let
14 inherit (scope)
15 callPackage
16 ;
17 inherit
18 (scope.callPackage (
19 { stdenv }:
20 {
21 inherit stdenv;
22 }
23 ) { })
24 stdenv
25 ;
26 inherit (pkgs.buildPackages)
27 meson
28 ninja
29 pkg-config
30 ;
31
32 root = ../.;
33
34 # Indirection for Nixpkgs to override when package.nix files are vendored
35 filesetToSource = lib.fileset.toSource;
36
37 /**
38 Given a set of layers, create a mkDerivation-like function
39 */
40 mkPackageBuilder =
41 exts: userFn: stdenv.mkDerivation (lib.extends (lib.composeManyExtensions exts) userFn);
42
43 setVersionLayer = finalAttrs: prevAttrs: {
44 preConfigure =
45 prevAttrs.preConfigure or ""
46 +
47 # Update the repo-global .version file.
48 # Symlink ./.version points there, but by default only workDir is writable.
49 ''
50 chmod u+w ./.version
51 echo ${finalAttrs.version} > ./.version
52 '';
53 };
54
55 localSourceLayer =
56 finalAttrs: prevAttrs:
57 let
58 workDirPath =
59 # Ideally we'd pick finalAttrs.workDir, but for now `mkDerivation` has
60 # the requirement that everything except passthru and meta must be
61 # serialized by mkDerivation, which doesn't work for this.
62 prevAttrs.workDir;
63
64 workDirSubpath = lib.path.removePrefix root workDirPath;
65 sources =
66 assert prevAttrs.fileset._type == "fileset";
67 prevAttrs.fileset;
68 src = lib.fileset.toSource {
69 fileset = sources;
70 inherit root;
71 };
72
73 in
74 {
75 sourceRoot = "${src.name}/" + workDirSubpath;
76 inherit src;
77
78 # Clear what `derivation` can't/shouldn't serialize; see prevAttrs.workDir.
79 fileset = null;
80 workDir = null;
81 };
82
83 resolveRelPath = p: lib.path.removePrefix root p;
84
85 makeFetchedSourceLayer =
86 finalScope: finalAttrs: prevAttrs:
87 let
88 workDirPath =
89 # Ideally we'd pick finalAttrs.workDir, but for now `mkDerivation` has
90 # the requirement that everything except passthru and meta must be
91 # serialized by mkDerivation, which doesn't work for this.
92 prevAttrs.workDir;
93
94 workDirSubpath = resolveRelPath workDirPath;
95
96 in
97 {
98 sourceRoot = "${finalScope.patchedSrc.name}/" + workDirSubpath;
99 src = finalScope.patchedSrc;
100 version =
101 let
102 n = lib.length finalScope.patches;
103 in
104 if n == 0 then prevAttrs.version else prevAttrs.version + "+${toString n}";
105
106 # Clear what `derivation` can't/shouldn't serialize; see prevAttrs.workDir.
107 fileset = null;
108 workDir = null;
109 };
110
111 mesonLayer = finalAttrs: prevAttrs: {
112 # NOTE:
113 # As of https://github.com/NixOS/nixpkgs/blob/8baf8241cea0c7b30e0b8ae73474cb3de83c1a30/pkgs/by-name/me/meson/setup-hook.sh#L26,
114 # `mesonBuildType` defaults to `plain` if not specified. We want our Nix-built binaries to be optimized by default.
115 # More on build types here: https://mesonbuild.com/Builtin-options.html#details-for-buildtype.
116 mesonBuildType = "release";
117 # NOTE:
118 # Users who are debugging Nix builds are expected to set the environment variable `mesonBuildType`, per the
119 # guidance in https://github.com/NixOS/nix/blob/8a3fc27f1b63a08ac983ee46435a56cf49ebaf4a/doc/manual/source/development/debugging.md?plain=1#L10.
120 # For this reason, we don't want to refer to `finalAttrs.mesonBuildType` here, but rather use the environment variable.
121 preConfigure =
122 prevAttrs.preConfigure or ""
123 +
124 lib.optionalString
125 (
126 !stdenv.hostPlatform.isWindows
127 # build failure
128 && !stdenv.hostPlatform.isStatic
129 # LTO breaks exception handling on x86-64-darwin.
130 && stdenv.system != "x86_64-darwin"
131 )
132 ''
133 case "$mesonBuildType" in
134 release|minsize) appendToVar mesonFlags "-Db_lto=true" ;;
135 *) appendToVar mesonFlags "-Db_lto=false" ;;
136 esac
137 '';
138 nativeBuildInputs = [
139 meson
140 ninja
141 ]
142 ++ prevAttrs.nativeBuildInputs or [ ];
143 mesonCheckFlags = prevAttrs.mesonCheckFlags or [ ] ++ [
144 "--print-errorlogs"
145 ];
146 };
147
148 mesonBuildLayer = finalAttrs: prevAttrs: {
149 nativeBuildInputs = prevAttrs.nativeBuildInputs or [ ] ++ [
150 pkg-config
151 ];
152 separateDebugInfo = !stdenv.hostPlatform.isStatic;
153 hardeningDisable = lib.optional stdenv.hostPlatform.isStatic "pie";
154 env =
155 prevAttrs.env or { }
156 // lib.optionalAttrs (
157 stdenv.isLinux
158 && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux")
159 && !(stdenv.system == "loongarch64-linux")
160 && !(stdenv.hostPlatform.useLLVM or false)
161 ) { LDFLAGS = "-fuse-ld=gold"; };
162 };
163
164 mesonLibraryLayer = finalAttrs: prevAttrs: {
165 outputs = prevAttrs.outputs or [ "out" ] ++ [ "dev" ];
166 };
167
168 # Work around weird `--as-needed` linker behavior with BSD, see
169 # https://github.com/mesonbuild/meson/issues/3593
170 bsdNoLinkAsNeeded =
171 finalAttrs: prevAttrs:
172 lib.optionalAttrs stdenv.hostPlatform.isBSD {
173 mesonFlags = [ (lib.mesonBool "b_asneeded" false) ] ++ prevAttrs.mesonFlags or [ ];
174 };
175
176 nixDefaultsLayer = finalAttrs: prevAttrs: {
177 strictDeps = prevAttrs.strictDeps or true;
178 enableParallelBuilding = true;
179 pos = builtins.unsafeGetAttrPos "pname" prevAttrs;
180 meta = prevAttrs.meta or { } // {
181 homepage = prevAttrs.meta.homepage or "https://nixos.org/nix";
182 longDescription =
183 prevAttrs.longDescription or ''
184 Nix is a powerful package manager for mainly Linux and other Unix systems that
185 makes package management reliable and reproducible. It provides atomic
186 upgrades and rollbacks, side-by-side installation of multiple versions of
187 a package, multi-user package management and easy setup of build
188 environments.
189 '';
190 license = prevAttrs.meta.license or lib.licenses.lgpl21Plus;
191 maintainers = prevAttrs.meta.maintainers or [ ] ++ scope.maintainers;
192 teams = prevAttrs.meta.teams or [ ] ++ scope.teams;
193 platforms = prevAttrs.meta.platforms or (lib.platforms.unix ++ lib.platforms.windows);
194 };
195 };
196
197 /**
198 Append patches to the source layer.
199 */
200 appendPatches =
201 scope: patches:
202 scope.overrideScope (
203 finalScope: prevScope: {
204 patches = prevScope.patches ++ patches;
205 }
206 );
207
208 whenAtLeast = v: thing: if lib.versionAtLeast version v then thing else null;
209
210in
211
212# This becomes the pkgs.nixComponents attribute set
213{
214 inherit version;
215 inherit maintainers;
216 inherit teams;
217
218 inherit filesetToSource;
219
220 /**
221 A user-provided extension function to apply to each component derivation.
222 */
223 mesonComponentOverrides = finalAttrs: prevAttrs: { };
224
225 /**
226 An overridable derivation layer for handling the sources.
227 */
228 sourceLayer = localSourceLayer;
229
230 /**
231 Resolve a path value to either itself or a path in the `src`, depending
232 whether `overrideSource` was called.
233 */
234 resolvePath = p: p;
235
236 /**
237 Apply an extension function (i.e. overlay-shaped) to all component derivations.
238
239 Single argument: the extension function to apply (finalAttrs: prevAttrs: { ... })
240 */
241 overrideAllMesonComponents =
242 f:
243 scope.overrideScope (
244 finalScope: prevScope: {
245 mesonComponentOverrides = lib.composeExtensions scope.mesonComponentOverrides f;
246 }
247 );
248
249 /**
250 Provide an alternate source. This allows the expressions to be vendored without copying the sources,
251 but it does make the build non-granular; all components will use a complete source.
252
253 Filesets in the packaging expressions will be ignored.
254
255 Single argument: the source to use.
256
257 See also `appendPatches`
258 */
259 overrideSource =
260 src:
261 scope.overrideScope (
262 finalScope: prevScope: {
263 sourceLayer = makeFetchedSourceLayer finalScope;
264 /**
265 Unpatched source for the build of Nix. Packaging expressions will be ignored.
266 */
267 src = src;
268 /**
269 Patches for the whole Nix source. Changes to packaging expressions will be ignored.
270 */
271 patches = [ ];
272 /**
273 Fetched and patched source to be used in component derivations.
274 */
275 patchedSrc =
276 if finalScope.patches == [ ] then
277 src
278 else
279 pkgs.buildPackages.srcOnly (
280 pkgs.buildPackages.stdenvNoCC.mkDerivation {
281 name = "${finalScope.src.name or "nix-source"}-patched";
282 inherit (finalScope) src patches;
283 }
284 );
285
286 resolvePath = p: finalScope.patchedSrc + "/${resolveRelPath p}";
287 filesetToSource = { root, fileset }: finalScope.resolvePath root;
288
289 appendPatches = appendPatches finalScope;
290 }
291 );
292
293 /**
294 Append patches to be applied to the whole Nix source.
295 This affects all components.
296
297 Changes to the packaging expressions will be ignored.
298
299 Single argument: list of patches to apply
300
301 See also `overrideSource`
302 */
303 appendPatches =
304 patches:
305 # switch to "fetched" source first, so that patches apply to the whole tree.
306 (scope.overrideSource "${./..}").appendPatches patches;
307
308 mkMesonDerivation = mkPackageBuilder [
309 nixDefaultsLayer
310 scope.sourceLayer
311 setVersionLayer
312 mesonLayer
313 scope.mesonComponentOverrides
314 ];
315 mkMesonExecutable = mkPackageBuilder [
316 nixDefaultsLayer
317 bsdNoLinkAsNeeded
318 scope.sourceLayer
319 setVersionLayer
320 mesonLayer
321 mesonBuildLayer
322 scope.mesonComponentOverrides
323 ];
324 mkMesonLibrary = mkPackageBuilder [
325 nixDefaultsLayer
326 bsdNoLinkAsNeeded
327 scope.sourceLayer
328 mesonLayer
329 setVersionLayer
330 mesonBuildLayer
331 mesonLibraryLayer
332 scope.mesonComponentOverrides
333 ];
334
335 nix-util = callPackage ../src/libutil/package.nix { };
336 nix-util-c = callPackage ../src/libutil-c/package.nix { };
337 nix-util-test-support = callPackage ../src/libutil-test-support/package.nix { };
338 nix-util-tests = callPackage ../src/libutil-tests/package.nix { };
339
340 nix-store = callPackage ../src/libstore/package.nix { };
341 nix-store-c = callPackage ../src/libstore-c/package.nix { };
342 nix-store-test-support = callPackage ../src/libstore-test-support/package.nix { };
343 nix-store-tests = callPackage ../src/libstore-tests/package.nix { };
344
345 nix-fetchers = callPackage ../src/libfetchers/package.nix { };
346 ${whenAtLeast "2.29pre" "nix-fetchers-c"} = callPackage ../src/libfetchers-c/package.nix { };
347 nix-fetchers-tests = callPackage ../src/libfetchers-tests/package.nix { };
348
349 nix-expr = callPackage ../src/libexpr/package.nix { };
350 nix-expr-c = callPackage ../src/libexpr-c/package.nix { };
351 nix-expr-test-support = callPackage ../src/libexpr-test-support/package.nix { };
352 nix-expr-tests = callPackage ../src/libexpr-tests/package.nix { };
353
354 nix-flake = callPackage ../src/libflake/package.nix { };
355 nix-flake-c = callPackage ../src/libflake-c/package.nix { };
356 nix-flake-tests = callPackage ../src/libflake-tests/package.nix { };
357
358 nix-main = callPackage ../src/libmain/package.nix { };
359 nix-main-c = callPackage ../src/libmain-c/package.nix { };
360
361 nix-cmd = callPackage ../src/libcmd/package.nix { };
362
363 nix-cli = callPackage ../src/nix/package.nix { };
364
365 nix-functional-tests = callPackage ../tests/functional/package.nix { };
366
367 nix-manual = callPackage ../doc/manual/package.nix { };
368 nix-internal-api-docs = callPackage ../src/internal-api-docs/package.nix { };
369 nix-external-api-docs = callPackage ../src/external-api-docs/package.nix { };
370
371 nix-perl-bindings = callPackage ../src/perl/package.nix { };
372
373 nix-everything = callPackage ../packaging/everything.nix { } // {
374 # Note: no `passthru.overrideAllMesonComponents` etc
375 # This would propagate into `nix.overrideAttrs f`, but then discard
376 # `f` when `.overrideAllMesonComponents` is used.
377 # Both "methods" should be views on the same fixpoint overriding mechanism
378 # for that to work. For now, we intentionally don't support the broken
379 # two-fixpoint solution.
380 /**
381 Apply an extension function (i.e. overlay-shaped) to all component derivations, and return the nix package.
382
383 Single argument: the extension function to apply (finalAttrs: prevAttrs: { ... })
384 */
385 overrideAllMesonComponents = f: (scope.overrideAllMesonComponents f).nix-everything;
386
387 /**
388 Append patches to be applied to the whole Nix source.
389 This affects all components.
390
391 Changes to the packaging expressions will be ignored.
392
393 Single argument: list of patches to apply
394
395 See also `overrideSource`
396 */
397 appendPatches = ps: (scope.appendPatches ps).nix-everything;
398
399 /**
400 Provide an alternate source. This allows the expressions to be vendored without copying the sources,
401 but it does make the build non-granular; all components will use a complete source.
402
403 Filesets in the packaging expressions will be ignored.
404
405 Single argument: the source to use.
406
407 See also `appendPatches`
408 */
409 overrideSource = src: (scope.overrideSource src).nix-everything;
410
411 /**
412 Override any internals of the Nix package set.
413
414 Single argument: the extension function to apply to the package set (finalScope: prevScope: { ... })
415
416 Example:
417 ```
418 overrideScope (finalScope: prevScope: { aws-sdk-cpp = null; })
419 ```
420 */
421 overrideScope = f: (scope.overrideScope f).nix-everything;
422
423 };
424}