pytrainer: unpin python 3.10
[NixPkgs.git] / pkgs / stdenv / adapters.nix
blobc5815d483bde1b1ccacaff617c9d687bd3e790dd
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     mkDerivationFromStdenv = withOldMkDerivation old (stdenv: mkDerivationSuper: args:
141     (mkDerivationSuper args).overrideAttrs (prevAttrs:
142       if prevAttrs ? env.NIX_CFLAGS_LINK then {
143         env = prevAttrs.env // {
144           NIX_CFLAGS_LINK = toString args.env.NIX_CFLAGS_LINK
145             + lib.optionalString (stdenv.cc.isGNU or false) " -static-libgcc";
146         };
147       } else {
148         NIX_CFLAGS_LINK = toString (prevAttrs.NIX_CFLAGS_LINK or "")
149           + lib.optionalString (stdenv.cc.isGNU or false) " -static-libgcc";
150       }));
151   });
153   # Puts all the other ones together
154   makeStatic = stdenv: lib.foldl (lib.flip lib.id) stdenv (
155     lib.optional stdenv.hostPlatform.isDarwin makeStaticDarwin
157     ++ [ makeStaticLibraries propagateBuildInputs ]
159     # Apple does not provide a static version of libSystem or crt0.o
160     # So we can’t build static binaries without extensive hacks.
161     ++ lib.optional (!stdenv.hostPlatform.isDarwin) makeStaticBinaries
162   );
165   /* Modify a stdenv so that all buildInputs are implicitly propagated to
166      consuming derivations
167   */
168   propagateBuildInputs = stdenv:
169     stdenv.override (old: {
170       mkDerivationFromStdenv = extendMkDerivationArgs old (args: {
171         propagatedBuildInputs = (args.propagatedBuildInputs or []) ++ (args.buildInputs or []);
172         buildInputs = [];
173       });
174     });
177   /* Modify a stdenv so that the specified attributes are added to
178      every derivation returned by its mkDerivation function.
180      Example:
181        stdenvNoOptimise =
182          addAttrsToDerivation
183            { env.NIX_CFLAGS_COMPILE = "-O0"; }
184            stdenv;
185   */
186   addAttrsToDerivation = extraAttrs: stdenv: stdenv.override (old: {
187     mkDerivationFromStdenv = extendMkDerivationArgs old (_: extraAttrs);
188   });
191   /* Use the trace output to report all processed derivations with their
192      license name.
193   */
194   traceDrvLicenses = stdenv:
195     stdenv.override (old: {
196       mkDerivationFromStdenv = overrideMkDerivationResult (pkg:
197         let
198           printDrvPath = val: let
199             drvPath = builtins.unsafeDiscardStringContext pkg.drvPath;
200             license = pkg.meta.license or null;
201           in
202             builtins.trace "@:drv:${toString drvPath}:${builtins.toString license}:@" val;
203         in pkg // {
204           outPath = printDrvPath pkg.outPath;
205           drvPath = printDrvPath pkg.drvPath;
206         });
207     });
210   /* Modify a stdenv so that it produces debug builds; that is,
211      binaries have debug info, and compiler optimisations are
212      disabled. */
213   keepDebugInfo = stdenv:
214     stdenv.override (old: {
215       mkDerivationFromStdenv = extendMkDerivationArgs old (args: {
216         dontStrip = true;
217         env = (args.env or {}) // { NIX_CFLAGS_COMPILE = toString (args.env.NIX_CFLAGS_COMPILE or "") + " -ggdb -Og"; };
218       });
219     });
222   /* Modify a stdenv so that it uses the Gold linker. */
223   useGoldLinker = stdenv:
224     stdenv.override (old: {
225       mkDerivationFromStdenv = extendMkDerivationArgs old (args: {
226         NIX_CFLAGS_LINK = toString (args.NIX_CFLAGS_LINK or "") + " -fuse-ld=gold";
227       });
228     });
230   /* Copy the libstdc++ from the model stdenv to the target stdenv.
231    *
232    * TODO(@connorbaker):
233    * This interface provides behavior which should be revisited prior to the
234    * release of 24.05. For a more detailed explanation and discussion, see
235    * https://github.com/NixOS/nixpkgs/issues/283517. */
236   useLibsFrom = modelStdenv: targetStdenv:
237     let
238       ccForLibs = modelStdenv.cc.cc;
239       /* NOTE(@connorbaker):
240        * This assumes targetStdenv.cc is a cc-wrapper. */
241       cc = targetStdenv.cc.override {
242         /* NOTE(originally by rrbutani):
243          * Normally the `useCcForLibs`/`gccForLibs` mechanism is used to get a
244          * clang based `cc` to use `libstdc++` (from gcc).
245          *
246          * Here we (ab)use it to use a `libstdc++` from a different `gcc` than our
247          * `cc`.
248          *
249          * Note that this does not inhibit our `cc`'s lib dir from being added to
250          * cflags/ldflags (see `cc_solib` in `cc-wrapper`) but this is okay: our
251          * `gccForLibs`'s paths should take precedence. */
252         useCcForLibs = true;
253         gccForLibs = ccForLibs;
254       };
255     in
256     overrideCC targetStdenv cc;
258   useMoldLinker = stdenv:
259     if stdenv.targetPlatform.isDarwin
260     then throw "Mold can't be used to emit Mach-O (Darwin) binaries"
261     else let
262       bintools = stdenv.cc.bintools.override {
263         extraBuildCommands = ''
264           wrap ${stdenv.cc.bintools.targetPrefix}ld.mold ${../build-support/bintools-wrapper/ld-wrapper.sh} ${pkgs.mold}/bin/ld.mold
265           wrap ${stdenv.cc.bintools.targetPrefix}ld ${../build-support/bintools-wrapper/ld-wrapper.sh} ${pkgs.mold}/bin/ld.mold
266         '';
267       };
268     in stdenv.override (old: {
269       allowedRequisites = null;
270       cc = stdenv.cc.override { inherit bintools; };
271       # gcc >12.1.0 supports '-fuse-ld=mold'
272       # the wrap ld above in bintools supports gcc <12.1.0 and shouldn't harm >12.1.0
273       # https://github.com/rui314/mold#how-to-use
274       } // lib.optionalAttrs (stdenv.cc.isClang || (stdenv.cc.isGNU && lib.versionAtLeast stdenv.cc.version "12")) {
275         mkDerivationFromStdenv = extendMkDerivationArgs old (args: {
276           NIX_CFLAGS_LINK = toString (args.NIX_CFLAGS_LINK or "") + " -fuse-ld=mold";
277         });
278       });
280   /* Modify a stdenv so that it builds binaries optimized specifically
281      for the machine they are built on.
283      WARNING: this breaks purity! */
284   impureUseNativeOptimizations = stdenv:
285     stdenv.override (old: {
286       mkDerivationFromStdenv = extendMkDerivationArgs old (args: {
287         env = (args.env or {}) // { NIX_CFLAGS_COMPILE = toString (args.env.NIX_CFLAGS_COMPILE or "") + " -march=native"; };
289         NIX_ENFORCE_NO_NATIVE = false;
291         preferLocalBuild = true;
292         allowSubstitutes = false;
293       });
294     });
297   /* Modify a stdenv so that it builds binaries with the specified list of
298      compilerFlags appended and passed to the compiler.
300      This example would recompile every derivation on the system with
301      -funroll-loops and -O3 passed to each gcc invocation.
303      Example:
304        nixpkgs.overlays = [
305          (self: super: {
306            stdenv = super.withCFlags [ "-funroll-loops" "-O3" ] super.stdenv;
307          })
308        ];
309   */
310   withCFlags = compilerFlags: stdenv:
311     stdenv.override (old: {
312       mkDerivationFromStdenv = extendMkDerivationArgs old (args: {
313         env = (args.env or {}) // { NIX_CFLAGS_COMPILE = toString (args.env.NIX_CFLAGS_COMPILE or "") + " ${toString compilerFlags}"; };
314       });
315     });
317   # Overriding the SDK changes the Darwin SDK used to build the package, which:
318   # * Ensures that the compiler and bintools have the correct Libsystem version; and
319   # * Replaces any SDK references with those in the SDK corresponding to the requested SDK version.
320   #
321   # `sdkVersion` can be any of the following:
322   # * A version string indicating the requested SDK version; or
323   # * An attrset consisting of either or both of the following fields: darwinSdkVersion and darwinMinVersion.
324   #
325   # Note: `overrideSDK` is deprecated. Add the versioned variants of `apple-sdk` to `buildInputs` change the SDK.
326   overrideSDK = pkgs.callPackage ./darwin/override-sdk.nix { inherit lib extendMkDerivationArgs; };
328   withDefaultHardeningFlags = defaultHardeningFlags: stdenv: let
329     bintools = let
330       bintools' = stdenv.cc.bintools;
331     in if bintools' ? override then (bintools'.override {
332       inherit defaultHardeningFlags;
333     }) else bintools';
334   in
335     stdenv.override (old: {
336       cc = if stdenv.cc == null then null else stdenv.cc.override {
337         inherit bintools;
338       };
339       allowedRequisites = lib.mapNullable (rs: rs ++ [ bintools ]) (stdenv.allowedRequisites or null);
340     });