python312Packages.vdf: avoid using pname for src.repo
[NixPkgs.git] / pkgs / stdenv / adapters.nix
blob4289bcaeb991848df1079ca1c98f9ea9c184eeb0
1 /* This file contains various functions that take a stdenv and return
2    a new stdenv with different behaviour, e.g. using a different C
3    compiler. */
5 { lib, pkgs, config }:
7 let
8   # N.B. Keep in sync with default arg for stdenv/generic.
9   defaultMkDerivationFromStdenv = stdenv: (import ./generic/make-derivation.nix { inherit lib config; } stdenv).mkDerivation;
11   # Low level function to help with overriding `mkDerivationFromStdenv`. One
12   # gives it the old stdenv arguments and a "continuation" function, and
13   # underneath the final stdenv argument it yields to the continuation to do
14   # whatever it wants with old `mkDerivation` (old `mkDerivationFromStdenv`
15   # applied to the *new, final* stdenv) provided for convenience.
16   withOldMkDerivation = stdenvSuperArgs: k: stdenvSelf: let
17     mkDerivationFromStdenv-super = stdenvSuperArgs.mkDerivationFromStdenv or defaultMkDerivationFromStdenv;
18     mkDerivationSuper = mkDerivationFromStdenv-super stdenvSelf;
19   in
20     k stdenvSelf mkDerivationSuper;
22   # Wrap the original `mkDerivation` providing extra args to it.
23   extendMkDerivationArgs = old: f: withOldMkDerivation old (_: mkDerivationSuper: args:
24     (mkDerivationSuper args).overrideAttrs f);
26   # Wrap the original `mkDerivation` transforming the result.
27   overrideMkDerivationResult = old: f: withOldMkDerivation old (_: mkDerivationSuper: args:
28     f (mkDerivationSuper args));
31 rec {
34   # Override the compiler in stdenv for specific packages.
35   overrideCC = stdenv: cc: stdenv.override {
36     allowedRequisites = null;
37     cc = cc;
38     hasCC = cc != null;
39   };
42   # Add some arbitrary packages to buildInputs for specific packages.
43   # Used to override packages in stdenv like Make.  Should not be used
44   # for other dependencies.
45   overrideInStdenv = stdenv: pkgs:
46     stdenv.override (prev: { allowedRequisites = null; extraBuildInputs = (prev.extraBuildInputs or []) ++ pkgs; });
49   # Override the libc++ dynamic library used in the stdenv to use the one from the platform’s
50   # default stdenv. This allows building packages and linking dependencies with different
51   # compiler versions while still using the same libc++ implementation for compatibility.
52   #
53   # Note that this adapter still uses the headers from the new stdenv’s libc++. This is necessary
54   # because older compilers may not be able to parse the headers from the default stdenv’s libc++.
55   overrideLibcxx = stdenv:
56     assert stdenv.cc.libcxx != null;
57     assert pkgs.stdenv.cc.libcxx != null;
58     # only unified libcxx / libcxxabi stdenv's are supported
59     assert lib.versionAtLeast pkgs.stdenv.cc.libcxx.version "12";
60     assert lib.versionAtLeast stdenv.cc.libcxx.version "12";
61     let
62       llvmLibcxxVersion = lib.getVersion llvmLibcxx;
64       stdenvLibcxx = pkgs.stdenv.cc.libcxx;
65       llvmLibcxx = stdenv.cc.libcxx;
67       libcxx = pkgs.runCommand "${stdenvLibcxx.name}-${llvmLibcxxVersion}" {
68         outputs = [ "out" "dev" ];
69         isLLVM = true;
70       } ''
71         mkdir -p "$dev/nix-support"
72         ln -s '${stdenvLibcxx}' "$out"
73         echo '${stdenvLibcxx}' > "$dev/nix-support/propagated-build-inputs"
74         ln -s '${lib.getDev llvmLibcxx}/include' "$dev/include"
75       '';
76     in
77     overrideCC stdenv (stdenv.cc.override {
78       inherit libcxx;
79       extraPackages = [
80         pkgs.buildPackages.targetPackages."llvmPackages_${lib.versions.major llvmLibcxxVersion}".compiler-rt
81       ];
82     });
84   # Override the setup script of stdenv.  Useful for testing new
85   # versions of the setup script without causing a rebuild of
86   # everything.
87   #
88   # Example:
89   #   randomPkg = import ../bla { ...
90   #     stdenv = overrideSetup stdenv ../stdenv/generic/setup-latest.sh;
91   #   };
92   overrideSetup = stdenv: setupScript: stdenv.override { inherit setupScript; };
95   # Return a modified stdenv that tries to build statically linked
96   # binaries.
97   makeStaticBinaries = stdenv0:
98     stdenv0.override (old: {
99       mkDerivationFromStdenv = withOldMkDerivation old (stdenv: mkDerivationSuper: args:
100       if stdenv.hostPlatform.isDarwin
101       then throw "Cannot build fully static binaries on Darwin/macOS"
102       else (mkDerivationSuper args).overrideAttrs (args: if args ? env.NIX_CFLAGS_LINK then {
103         env = args.env // {
104           NIX_CFLAGS_LINK = toString args.env.NIX_CFLAGS_LINK + " -static";
105         };
106       } else {
107         NIX_CFLAGS_LINK = toString (args.NIX_CFLAGS_LINK or "") + " -static";
108       } // lib.optionalAttrs (!(args.dontAddStaticConfigureFlags or false)) {
109         configureFlags = (args.configureFlags or []) ++ [
110           "--disable-shared" # brrr...
111         ];
112         cmakeFlags = (args.cmakeFlags or []) ++ ["-DCMAKE_SKIP_INSTALL_RPATH=On"];
113       }));
114     } // lib.optionalAttrs (stdenv0.hostPlatform.libc == "glibc") {
115       extraBuildInputs = (old.extraBuildInputs or []) ++ [
116         pkgs.glibc.static
117       ];
118     });
121   # Return a modified stdenv that builds static libraries instead of
122   # shared libraries.
123   makeStaticLibraries = stdenv:
124     stdenv.override (old: {
125       mkDerivationFromStdenv = extendMkDerivationArgs old (args: {
126         dontDisableStatic = true;
127       } // lib.optionalAttrs (!(args.dontAddStaticConfigureFlags or false)) {
128         configureFlags = (args.configureFlags or []) ++ [
129           "--enable-static"
130           "--disable-shared"
131         ];
132         cmakeFlags = (args.cmakeFlags or []) ++ [ "-DBUILD_SHARED_LIBS:BOOL=OFF" ];
133         mesonFlags = (args.mesonFlags or []) ++ [ "-Ddefault_library=static" ];
134       });
135     });
137   # Best effort static binaries. Will still be linked to libSystem,
138   # but more portable than Nix store binaries.
139   makeStaticDarwin = stdenv: stdenv.override (old: {
140     # extraBuildInputs are dropped in cross.nix, but darwin still needs them
141     extraBuildInputs = [ pkgs.buildPackages.darwin.CF ];
142     mkDerivationFromStdenv = withOldMkDerivation old (stdenv: mkDerivationSuper: args:
143     (mkDerivationSuper args).overrideAttrs (prevAttrs: {
144       NIX_CFLAGS_LINK = toString (prevAttrs.NIX_CFLAGS_LINK or "")
145         + lib.optionalString (stdenv.cc.isGNU or false) " -static-libgcc";
146       nativeBuildInputs = (prevAttrs.nativeBuildInputs or [])
147         ++ lib.optionals stdenv.hasCC [
148           (pkgs.buildPackages.makeSetupHook {
149             name = "darwin-portable-libSystem-hook";
150             substitutions = {
151               libsystem = "${stdenv.cc.libc}/lib/libSystem.B.dylib";
152               targetPrefix = stdenv.cc.bintools.targetPrefix;
153             };
154           } ./darwin/portable-libsystem.sh)
155         ];
156     }));
157   });
159   # Puts all the other ones together
160   makeStatic = stdenv: lib.foldl (lib.flip lib.id) stdenv (
161     lib.optional stdenv.hostPlatform.isDarwin makeStaticDarwin
163     ++ [ makeStaticLibraries propagateBuildInputs ]
165     # Apple does not provide a static version of libSystem or crt0.o
166     # So we can’t build static binaries without extensive hacks.
167     ++ lib.optional (!stdenv.hostPlatform.isDarwin) makeStaticBinaries
168   );
171   /* Modify a stdenv so that all buildInputs are implicitly propagated to
172      consuming derivations
173   */
174   propagateBuildInputs = stdenv:
175     stdenv.override (old: {
176       mkDerivationFromStdenv = extendMkDerivationArgs old (args: {
177         propagatedBuildInputs = (args.propagatedBuildInputs or []) ++ (args.buildInputs or []);
178         buildInputs = [];
179       });
180     });
183   /* Modify a stdenv so that the specified attributes are added to
184      every derivation returned by its mkDerivation function.
186      Example:
187        stdenvNoOptimise =
188          addAttrsToDerivation
189            { env.NIX_CFLAGS_COMPILE = "-O0"; }
190            stdenv;
191   */
192   addAttrsToDerivation = extraAttrs: stdenv: stdenv.override (old: {
193     mkDerivationFromStdenv = extendMkDerivationArgs old (_: extraAttrs);
194   });
197   /* Use the trace output to report all processed derivations with their
198      license name.
199   */
200   traceDrvLicenses = stdenv:
201     stdenv.override (old: {
202       mkDerivationFromStdenv = overrideMkDerivationResult (pkg:
203         let
204           printDrvPath = val: let
205             drvPath = builtins.unsafeDiscardStringContext pkg.drvPath;
206             license = pkg.meta.license or null;
207           in
208             builtins.trace "@:drv:${toString drvPath}:${builtins.toString license}:@" val;
209         in pkg // {
210           outPath = printDrvPath pkg.outPath;
211           drvPath = printDrvPath pkg.drvPath;
212         });
213     });
216   /* Modify a stdenv so that it produces debug builds; that is,
217      binaries have debug info, and compiler optimisations are
218      disabled. */
219   keepDebugInfo = stdenv:
220     stdenv.override (old: {
221       mkDerivationFromStdenv = extendMkDerivationArgs old (args: {
222         dontStrip = true;
223         env = (args.env or {}) // { NIX_CFLAGS_COMPILE = toString (args.env.NIX_CFLAGS_COMPILE or "") + " -ggdb -Og"; };
224       });
225     });
228   /* Modify a stdenv so that it uses the Gold linker. */
229   useGoldLinker = stdenv:
230     stdenv.override (old: {
231       mkDerivationFromStdenv = extendMkDerivationArgs old (args: {
232         NIX_CFLAGS_LINK = toString (args.NIX_CFLAGS_LINK or "") + " -fuse-ld=gold";
233       });
234     });
236   /* Copy the libstdc++ from the model stdenv to the target stdenv.
237    *
238    * TODO(@connorbaker):
239    * This interface provides behavior which should be revisited prior to the
240    * release of 24.05. For a more detailed explanation and discussion, see
241    * https://github.com/NixOS/nixpkgs/issues/283517. */
242   useLibsFrom = modelStdenv: targetStdenv:
243     let
244       ccForLibs = modelStdenv.cc.cc;
245       /* NOTE(@connorbaker):
246        * This assumes targetStdenv.cc is a cc-wrapper. */
247       cc = targetStdenv.cc.override {
248         /* NOTE(originally by rrbutani):
249          * Normally the `useCcForLibs`/`gccForLibs` mechanism is used to get a
250          * clang based `cc` to use `libstdc++` (from gcc).
251          *
252          * Here we (ab)use it to use a `libstdc++` from a different `gcc` than our
253          * `cc`.
254          *
255          * Note that this does not inhibit our `cc`'s lib dir from being added to
256          * cflags/ldflags (see `cc_solib` in `cc-wrapper`) but this is okay: our
257          * `gccForLibs`'s paths should take precedence. */
258         useCcForLibs = true;
259         gccForLibs = ccForLibs;
260       };
261     in
262     overrideCC targetStdenv cc;
264   useMoldLinker = stdenv:
265     if stdenv.targetPlatform.isDarwin
266     then throw "Mold can't be used to emit Mach-O (Darwin) binaries"
267     else let
268       bintools = stdenv.cc.bintools.override {
269         extraBuildCommands = ''
270           wrap ${stdenv.cc.bintools.targetPrefix}ld.mold ${../build-support/bintools-wrapper/ld-wrapper.sh} ${pkgs.mold}/bin/ld.mold
271           wrap ${stdenv.cc.bintools.targetPrefix}ld ${../build-support/bintools-wrapper/ld-wrapper.sh} ${pkgs.mold}/bin/ld.mold
272         '';
273       };
274     in stdenv.override (old: {
275       allowedRequisites = null;
276       cc = stdenv.cc.override { inherit bintools; };
277       # gcc >12.1.0 supports '-fuse-ld=mold'
278       # the wrap ld above in bintools supports gcc <12.1.0 and shouldn't harm >12.1.0
279       # https://github.com/rui314/mold#how-to-use
280       } // lib.optionalAttrs (stdenv.cc.isClang || (stdenv.cc.isGNU && lib.versionAtLeast stdenv.cc.version "12")) {
281         mkDerivationFromStdenv = extendMkDerivationArgs old (args: {
282           NIX_CFLAGS_LINK = toString (args.NIX_CFLAGS_LINK or "") + " -fuse-ld=mold";
283         });
284       });
286   /* Modify a stdenv so that it builds binaries optimized specifically
287      for the machine they are built on.
289      WARNING: this breaks purity! */
290   impureUseNativeOptimizations = stdenv:
291     stdenv.override (old: {
292       mkDerivationFromStdenv = extendMkDerivationArgs old (args: {
293         env = (args.env or {}) // { NIX_CFLAGS_COMPILE = toString (args.env.NIX_CFLAGS_COMPILE or "") + " -march=native"; };
295         NIX_ENFORCE_NO_NATIVE = false;
297         preferLocalBuild = true;
298         allowSubstitutes = false;
299       });
300     });
303   /* Modify a stdenv so that it builds binaries with the specified list of
304      compilerFlags appended and passed to the compiler.
306      This example would recompile every derivation on the system with
307      -funroll-loops and -O3 passed to each gcc invocation.
309      Example:
310        nixpkgs.overlays = [
311          (self: super: {
312            stdenv = super.withCFlags [ "-funroll-loops" "-O3" ] super.stdenv;
313          })
314        ];
315   */
316   withCFlags = compilerFlags: stdenv:
317     stdenv.override (old: {
318       mkDerivationFromStdenv = extendMkDerivationArgs old (args: {
319         env = (args.env or {}) // { NIX_CFLAGS_COMPILE = toString (args.env.NIX_CFLAGS_COMPILE or "") + " ${toString compilerFlags}"; };
320       });
321     });
323   # Overriding the SDK changes the Darwin SDK used to build the package, which:
324   # * Ensures that the compiler and bintools have the correct Libsystem version; and
325   # * Replaces any SDK references with those in the SDK corresponding to the requested SDK version.
326   #
327   # `sdkVersion` can be any of the following:
328   # * A version string indicating the requested SDK version; or
329   # * An attrset consisting of either or both of the following fields: darwinSdkVersion and darwinMinVersion.
330   overrideSDK = import ./darwin/override-sdk.nix {
331     inherit lib extendMkDerivationArgs;
332     inherit (pkgs)
333       stdenvNoCC
334       pkgsBuildBuild
335       pkgsBuildHost
336       pkgsBuildTarget
337       pkgsHostHost
338       pkgsHostTarget
339       pkgsTargetTarget;
340   };
342   withDefaultHardeningFlags = defaultHardeningFlags: stdenv: let
343     bintools = let
344       bintools' = stdenv.cc.bintools;
345     in if bintools' ? override then (bintools'.override {
346       inherit defaultHardeningFlags;
347     }) else bintools';
348   in
349     stdenv.override (old: {
350       cc = if stdenv.cc == null then null else stdenv.cc.override {
351         inherit bintools;
352       };
353       allowedRequisites = lib.mapNullable (rs: rs ++ [ bintools ]) (stdenv.allowedRequisites or null);
354     });