c3d84d15ce
This removes the need for hacks like stdenv.regenerate. It also ensures that overrideGCC is now stackable (so ‘stdenv = useGoldLinker clangStdenv’ works).
364 lines
13 KiB
Nix
364 lines
13 KiB
Nix
/* This file contains various functions that take a stdenv and return
|
|
a new stdenv with different behaviour, e.g. using a different C
|
|
compiler. */
|
|
|
|
pkgs:
|
|
|
|
rec {
|
|
|
|
|
|
# Override the compiler in stdenv for specific packages.
|
|
overrideGCC = stdenv: gcc: stdenv.override { inherit gcc; };
|
|
|
|
|
|
# Add some arbitrary packages to buildInputs for specific packages.
|
|
# Used to override packages in stdenv like Make. Should not be used
|
|
# for other dependencies.
|
|
overrideInStdenv = stdenv: pkgs:
|
|
stdenv.override (prev: { extraBuildInputs = prev.extraBuildInputs or [] ++ pkgs; });
|
|
|
|
|
|
# Override the setup script of stdenv. Useful for testing new
|
|
# versions of the setup script without causing a rebuild of
|
|
# everything.
|
|
#
|
|
# Example:
|
|
# randomPkg = import ../bla { ...
|
|
# stdenv = overrideSetup stdenv ../stdenv/generic/setup-latest.sh;
|
|
# };
|
|
overrideSetup = stdenv: setupScript: stdenv.override { inherit setupScript; };
|
|
|
|
|
|
# Return a modified stdenv that uses dietlibc to create small
|
|
# statically linked binaries.
|
|
useDietLibC = stdenv: stdenv //
|
|
{ mkDerivation = args: stdenv.mkDerivation (args // {
|
|
NIX_CFLAGS_LINK = "-static";
|
|
|
|
# libcompat.a contains some commonly used functions.
|
|
NIX_LDFLAGS = "-lcompat";
|
|
|
|
# These are added *after* the command-line flags, so we'll
|
|
# always optimise for size.
|
|
NIX_CFLAGS_COMPILE =
|
|
args.NIX_CFLAGS_COMPILE or ""
|
|
+ " -Os -s -D_BSD_SOURCE=1";
|
|
|
|
configureFlags =
|
|
args.configureFlags or ""
|
|
+ " --disable-shared"; # brrr...
|
|
|
|
NIX_GCC = import ../build-support/gcc-wrapper {
|
|
inherit stdenv;
|
|
libc = pkgs.dietlibc;
|
|
inherit (stdenv.gcc) gcc binutils nativeTools nativePrefix;
|
|
nativeLibc = false;
|
|
};
|
|
});
|
|
isDietLibC = true;
|
|
};
|
|
|
|
|
|
# Return a modified stdenv that uses klibc to create small
|
|
# statically linked binaries.
|
|
useKlibc = stdenv: klibc: stdenv //
|
|
{ mkDerivation = args: stdenv.mkDerivation (args // {
|
|
NIX_CFLAGS_LINK = "-static";
|
|
|
|
# These are added *after* the command-line flags, so we'll
|
|
# always optimise for size.
|
|
NIX_CFLAGS_COMPILE =
|
|
args.NIX_CFLAGS_COMPILE or "" + " -Os -s";
|
|
|
|
configureFlags =
|
|
args.configureFlags or "" + " --disable-shared"; # brrr...
|
|
|
|
NIX_GCC = pkgs.runCommand "klibc-wrapper" {} ''
|
|
mkdir -p $out/bin
|
|
ln -s ${klibc}/bin/klcc $out/bin/gcc
|
|
ln -s ${klibc}/bin/klcc $out/bin/cc
|
|
mkdir -p $out/nix-support
|
|
echo 'PATH=$PATH:${stdenv.gcc.binutils}/bin' > $out/nix-support/setup-hook
|
|
'';
|
|
});
|
|
isKlibc = true;
|
|
isStatic = true;
|
|
};
|
|
|
|
|
|
# Return a modified stdenv that tries to build statically linked
|
|
# binaries.
|
|
makeStaticBinaries = stdenv: stdenv //
|
|
{ mkDerivation = args: stdenv.mkDerivation (args // {
|
|
NIX_CFLAGS_LINK = "-static";
|
|
configureFlags =
|
|
toString args.configureFlags or ""
|
|
+ " --disable-shared"; # brrr...
|
|
});
|
|
isStatic = true;
|
|
};
|
|
|
|
|
|
# Return a modified stdenv that builds static libraries instead of
|
|
# shared libraries.
|
|
makeStaticLibraries = stdenv: stdenv //
|
|
{ mkDerivation = args: stdenv.mkDerivation (args // {
|
|
dontDisableStatic = true;
|
|
configureFlags =
|
|
toString args.configureFlags or ""
|
|
+ " --enable-static --disable-shared";
|
|
});
|
|
};
|
|
|
|
|
|
# Return a modified stdenv that adds a cross compiler to the
|
|
# builds.
|
|
makeStdenvCross = stdenv: cross: binutilsCross: gccCross: stdenv //
|
|
{ mkDerivation = {name ? "", buildInputs ? [], nativeBuildInputs ? [],
|
|
propagatedBuildInputs ? [], propagatedNativeBuildInputs ? [],
|
|
selfNativeBuildInput ? false, ...}@args: let
|
|
|
|
# *BuildInputs exists temporarily as another name for
|
|
# *HostInputs.
|
|
|
|
# In nixpkgs, sometimes 'null' gets in as a buildInputs element,
|
|
# and we handle that through isAttrs.
|
|
getNativeDrv = drv: drv.nativeDrv or drv;
|
|
getCrossDrv = drv: drv.crossDrv or drv;
|
|
nativeBuildInputsDrvs = map getNativeDrv nativeBuildInputs;
|
|
buildInputsDrvs = map getCrossDrv buildInputs;
|
|
buildInputsDrvsAsBuildInputs = map getNativeDrv buildInputs;
|
|
propagatedBuildInputsDrvs = map getCrossDrv propagatedBuildInputs;
|
|
propagatedNativeBuildInputsDrvs = map getNativeDrv propagatedNativeBuildInputs;
|
|
|
|
# The base stdenv already knows that nativeBuildInputs and
|
|
# buildInputs should be built with the usual gcc-wrapper
|
|
# And the same for propagatedBuildInputs.
|
|
nativeDrv = stdenv.mkDerivation args;
|
|
|
|
# Temporary expression until the cross_renaming, to handle the
|
|
# case of pkgconfig given as buildInput, but to be used as
|
|
# nativeBuildInput.
|
|
hostAsNativeDrv = drv:
|
|
builtins.unsafeDiscardStringContext drv.nativeDrv.drvPath
|
|
== builtins.unsafeDiscardStringContext drv.crossDrv.drvPath;
|
|
buildInputsNotNull = stdenv.lib.filter
|
|
(drv: builtins.isAttrs drv && drv ? nativeDrv) buildInputs;
|
|
nativeInputsFromBuildInputs = stdenv.lib.filter hostAsNativeDrv buildInputsNotNull;
|
|
|
|
# We should overwrite the input attributes in crossDrv, to overwrite
|
|
# the defaults for only-native builds in the base stdenv
|
|
crossDrv = if cross == null then nativeDrv else
|
|
stdenv.mkDerivation (args // {
|
|
name = name + "-" + cross.config;
|
|
nativeBuildInputs = nativeBuildInputsDrvs
|
|
++ nativeInputsFromBuildInputs
|
|
++ [ gccCross binutilsCross ] ++
|
|
stdenv.lib.optional selfNativeBuildInput nativeDrv;
|
|
|
|
# Cross-linking dynamic libraries, every buildInput should
|
|
# be propagated because ld needs the -rpath-link to find
|
|
# any library needed to link the program dynamically at
|
|
# loader time. ld(1) explains it.
|
|
buildInputs = [];
|
|
propagatedBuildInputs = propagatedBuildInputsDrvs ++ buildInputsDrvs;
|
|
propagatedNativeBuildInputs = propagatedNativeBuildInputsDrvs;
|
|
|
|
crossConfig = cross.config;
|
|
} // args.crossAttrs or {});
|
|
in nativeDrv // {
|
|
inherit crossDrv nativeDrv;
|
|
};
|
|
} // {
|
|
inherit cross gccCross binutilsCross;
|
|
};
|
|
|
|
|
|
/* Modify a stdenv so that the specified attributes are added to
|
|
every derivation returned by its mkDerivation function.
|
|
|
|
Example:
|
|
stdenvNoOptimise =
|
|
addAttrsToDerivation
|
|
{ NIX_CFLAGS_COMPILE = "-O0"; }
|
|
stdenv;
|
|
*/
|
|
addAttrsToDerivation = extraAttrs: stdenv: stdenv //
|
|
{ mkDerivation = args: stdenv.mkDerivation (args // extraAttrs); };
|
|
|
|
|
|
/* Return a modified stdenv that performs the build under $out/.build
|
|
instead of in $TMPDIR. Thus, the sources are kept available.
|
|
This is useful for things like debugging or generation of
|
|
dynamic analysis reports. */
|
|
keepBuildTree = stdenv:
|
|
addAttrsToDerivation
|
|
{ prePhases = "moveBuildDir";
|
|
|
|
moveBuildDir =
|
|
''
|
|
mkdir -p $out/.build
|
|
cd $out/.build
|
|
'';
|
|
} stdenv;
|
|
|
|
|
|
cleanupBuildTree = stdenv:
|
|
addAttrsToDerivation
|
|
{ postPhases = "cleanupBuildDir";
|
|
|
|
# Get rid of everything that isn't a gcno file or a C source
|
|
# file. This also includes the gcda files; we're not
|
|
# interested in coverage resulting from the package's own test
|
|
# suite. Also strip the `.tmp_' prefix from gcno files. (The
|
|
# Linux kernel creates these.)
|
|
cleanupBuildDir =
|
|
''
|
|
find $out/.build/ -type f -a ! \
|
|
\( -name "*.c" -o -name "*.h" -o -name "*.gcno" \) \
|
|
| xargs rm -f --
|
|
|
|
for i in $(find $out/.build/ -name ".tmp_*.gcno"); do
|
|
mv "$i" "$(echo $i | sed s/.tmp_//)"
|
|
done
|
|
'';
|
|
} stdenv;
|
|
|
|
|
|
/* Return a modified stdenv that builds packages with GCC's coverage
|
|
instrumentation. The coverage note files (*.gcno) are stored in
|
|
$out/.build, along with the source code of the package, to enable
|
|
programs like lcov to produce pretty-printed reports.
|
|
*/
|
|
addCoverageInstrumentation = stdenv:
|
|
addAttrsToDerivation
|
|
{
|
|
postUnpack =
|
|
''
|
|
# This is an uberhack to prevent libtool from removing gcno
|
|
# files. This has been fixed in libtool, but there are
|
|
# packages out there with old ltmain.sh scripts.
|
|
# See http://www.mail-archive.com/libtool@gnu.org/msg10725.html
|
|
for i in $(find -name ltmain.sh); do
|
|
substituteInPlace $i --replace '*.$objext)' '*.$objext | *.gcno)'
|
|
done
|
|
|
|
export NIX_CFLAGS_COMPILE="$NIX_CFLAGS_COMPILE -O0 --coverage"
|
|
'';
|
|
}
|
|
|
|
# Object files instrumented with coverage analysis write
|
|
# runtime coverage data to <path>/<object>.gcda, where <path>
|
|
# is the location where gcc originally created the object
|
|
# file. That would be /tmp/nix-build-<something>, which will
|
|
# be long gone by the time we run the program. Furthermore,
|
|
# the <object>.gcno files created at compile time are also
|
|
# written there. And to make nice coverage reports with lcov,
|
|
# we need the source code. So we have to use the
|
|
# `keepBuildTree' adapter as well.
|
|
(cleanupBuildTree (keepBuildTree stdenv));
|
|
|
|
|
|
/* Replace the meta.maintainers field of a derivation. This is useful
|
|
when you want to fork to update some packages without disturbing other
|
|
developers.
|
|
|
|
e.g.: in all-packages.nix:
|
|
|
|
# remove all maintainers.
|
|
defaultStdenv = replaceMaintainersField allStdenvs.stdenv pkgs [];
|
|
*/
|
|
replaceMaintainersField = stdenv: pkgs: maintainers: stdenv //
|
|
{ mkDerivation = args:
|
|
stdenv.lib.recursiveUpdate
|
|
(stdenv.mkDerivation args)
|
|
{ meta.maintainers = maintainers; };
|
|
};
|
|
|
|
|
|
/* Use the trace output to report all processed derivations with their
|
|
license name.
|
|
*/
|
|
traceDrvLicenses = stdenv: stdenv //
|
|
{ mkDerivation = args:
|
|
let
|
|
pkg = stdenv.mkDerivation args;
|
|
printDrvPath = val: let
|
|
drvPath = builtins.unsafeDiscardStringContext pkg.drvPath;
|
|
license = pkg.meta.license or null;
|
|
in
|
|
builtins.trace "@:drv:${toString drvPath}:${builtins.toString license}:@" val;
|
|
in pkg // {
|
|
outPath = printDrvPath pkg.outPath;
|
|
drvPath = printDrvPath pkg.drvPath;
|
|
};
|
|
};
|
|
|
|
|
|
/* Abort if the license predicate is not verified for a derivation
|
|
declared with mkDerivation.
|
|
|
|
One possible predicate to avoid all non-free packages can be achieved
|
|
with the following function:
|
|
|
|
isFree = license: with builtins;
|
|
if isNull license then true
|
|
else if isList license then lib.all isFree license
|
|
else license != "non-free" && license != "unfree";
|
|
|
|
This adapter can be defined on the defaultStdenv definition. You can
|
|
use it by patching the all-packages.nix file or by using the override
|
|
feature of ~/.nixpkgs/config.nix .
|
|
*/
|
|
validateLicenses = licensePred: stdenv: stdenv //
|
|
{ mkDerivation = args:
|
|
let
|
|
pkg = stdenv.mkDerivation args;
|
|
drv = builtins.unsafeDiscardStringContext pkg.drvPath;
|
|
license =
|
|
pkg.meta.license or
|
|
# Fixed-output derivations such as source tarballs usually
|
|
# don't have licensing information, but that's OK.
|
|
(pkg.outputHash or
|
|
(builtins.trace
|
|
"warning: ${drv} lacks licensing information" null));
|
|
|
|
validate = arg:
|
|
if licensePred license then arg
|
|
else abort ''
|
|
while building ${drv}:
|
|
license `${builtins.toString license}' does not pass the predicate.
|
|
'';
|
|
|
|
in pkg // {
|
|
outPath = validate pkg.outPath;
|
|
drvPath = validate pkg.drvPath;
|
|
};
|
|
};
|
|
|
|
|
|
/* Modify a stdenv so that it produces debug builds; that is,
|
|
binaries have debug info, and compiler optimisations are
|
|
disabled. */
|
|
keepDebugInfo = stdenv: stdenv //
|
|
{ mkDerivation = args: stdenv.mkDerivation (args // {
|
|
dontStrip = true;
|
|
NIX_CFLAGS_COMPILE = toString (args.NIX_CFLAGS_COMPILE or "") + " -g -O0";
|
|
});
|
|
};
|
|
|
|
|
|
/* Modify a stdenv so that it used the Gold linker. */
|
|
useGoldLinker = stdenv:
|
|
let
|
|
binutils = stdenv.gcc.binutils;
|
|
binutils' = pkgs.runCommand "${binutils.name}-gold" { }
|
|
''
|
|
mkdir -p $out/bin
|
|
ln -s ${binutils}/bin/* $out/bin/
|
|
ln -sfn ${binutils}/bin/ld.gold $out/bin/ld
|
|
''; # */
|
|
in overrideGCC stdenv (stdenv.gcc.override { binutils = binutils'; });
|
|
|
|
}
|