Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: NixOS/nixpkgs
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: ac6599895725
Choose a base ref
...
head repository: NixOS/nixpkgs
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 07db0b248c4c
Choose a head ref
  • 4 commits
  • 5 files changed
  • 3 contributors

Commits on Jan 15, 2020

  1. Verified

    This commit was signed with the committer’s verified signature. The key has expired.
    iv-nn Ivann
    Copy the full SHA
    ba9066a View commit details

Commits on Jan 17, 2020

  1. shellFor: Refactor for consistency and cross

    This makes it work like work-on-multi from Reflex Platform. In
    particular, rather than making `.env` from `shellFor`, we make `.env`
    the primitive, and `shellFor` works by combining together the arguments
    of all the packages to `generic-builder` and taking the `.env` of the
    resulting mashup-package.
    
    There are 2 benefits of this:
    
    1. The dependency logic is deduplicated. generic builder just concatted
       lists, whereas all the envs until now would sieve apart haskell and
       system build inputs. Now, they both decide haskell vs system the same
       way: according to the argument list and without reflection.
       Consistency is good, especially because it mean that if the build
       works, the shell is more likely to work.
    
    2. Cross is handled better. For native builds, because the
       `ghcWithPackages` calls would shadow, we through both the regular
       component (lib, exe, test, bench) haskell deps and Setup.hs haskell
       deps in the same `ghcWithPackages` call. But for cross builds we use
       `buildPackages.ghcWithPackages` to get the setup deps. This ensures
       everything works correctly.
    jmininger authored and Ericson2314 committed Jan 17, 2020
    Copy the full SHA
    7d67db3 View commit details
  2. release.nix: Make hydra build all unit tests

    We have just a few, and these are regular jobs not must-pass. The tests
    that were must-pass are left as is.
    Ericson2314 committed Jan 17, 2020

    Verified

    This commit was signed with the committer’s verified signature. The key has expired.
    iv-nn Ivann
    Copy the full SHA
    cb46b97 View commit details
  3. Copy the full SHA
    07db0b2 View commit details
148 changes: 127 additions & 21 deletions pkgs/development/haskell-modules/generic-builder.nix
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{ stdenv, buildPackages, buildHaskellPackages, ghc
, jailbreak-cabal, hscolour, cpphs, nodejs, shellFor
, jailbreak-cabal, hscolour, cpphs, nodejs
, ghcWithHoogle, ghcWithPackages
}:

let
@@ -206,21 +207,28 @@ let
optionals doCheck testPkgconfigDepends ++ optionals doBenchmark benchmarkPkgconfigDepends;

depsBuildBuild = [ nativeGhc ];
nativeBuildInputs = [ ghc removeReferencesTo ] ++ optional (allPkgconfigDepends != []) pkgconfig ++
setupHaskellDepends ++
buildTools ++ libraryToolDepends ++ executableToolDepends ++
optionals doCheck testToolDepends ++
optionals doBenchmark benchmarkToolDepends;
collectedToolDepends =
buildTools ++ libraryToolDepends ++ executableToolDepends ++
optionals doCheck testToolDepends ++
optionals doBenchmark benchmarkToolDepends;
nativeBuildInputs =
[ ghc removeReferencesTo ] ++ optional (allPkgconfigDepends != []) pkgconfig ++
setupHaskellDepends ++ collectedToolDepends;
propagatedBuildInputs = buildDepends ++ libraryHaskellDepends ++ executableHaskellDepends ++ libraryFrameworkDepends;
otherBuildInputs = extraLibraries ++ librarySystemDepends ++ executableSystemDepends ++ executableFrameworkDepends ++
allPkgconfigDepends ++
optionals doCheck (testDepends ++ testHaskellDepends ++ testSystemDepends ++ testFrameworkDepends) ++
optionals doBenchmark (benchmarkDepends ++ benchmarkHaskellDepends ++ benchmarkSystemDepends ++ benchmarkFrameworkDepends);


allBuildInputs = propagatedBuildInputs ++ otherBuildInputs ++ depsBuildBuild ++ nativeBuildInputs;
isHaskellPartition =
stdenv.lib.partition isHaskellPkg allBuildInputs;
otherBuildInputsHaskell =
optionals doCheck (testDepends ++ testHaskellDepends) ++
optionals doBenchmark (benchmarkDepends ++ benchmarkHaskellDepends);
otherBuildInputsSystem =
extraLibraries ++ librarySystemDepends ++ executableSystemDepends ++ executableFrameworkDepends ++
allPkgconfigDepends ++
optionals doCheck (testSystemDepends ++ testFrameworkDepends) ++
optionals doBenchmark (benchmarkSystemDepends ++ benchmarkFrameworkDepends);
# TODO next rebuild just define as `otherBuildInputsHaskell ++ otherBuildInputsSystem`
otherBuildInputs =
extraLibraries ++ librarySystemDepends ++ executableSystemDepends ++ executableFrameworkDepends ++
allPkgconfigDepends ++
optionals doCheck (testDepends ++ testHaskellDepends ++ testSystemDepends ++ testFrameworkDepends) ++
optionals doBenchmark (benchmarkDepends ++ benchmarkHaskellDepends ++ benchmarkSystemDepends ++ benchmarkFrameworkDepends);

setupCommand = "./Setup";

@@ -462,17 +470,61 @@ stdenv.mkDerivation ({
runHook postInstall
'';

passthru = passthru // {
passthru = passthru // rec {

inherit pname version;

compiler = ghc;

# All this information is intended just for `shellFor`. It should be
# considered unstable and indeed we knew how to keep it private we would.
getCabalDeps = {
inherit
buildDepends
buildTools
executableFrameworkDepends
executableHaskellDepends
executablePkgconfigDepends
executableSystemDepends
executableToolDepends
extraLibraries
libraryFrameworkDepends
libraryHaskellDepends
libraryPkgconfigDepends
librarySystemDepends
libraryToolDepends
pkgconfigDepends
setupHaskellDepends
;
} // stdenv.lib.optionalAttrs doCheck {
inherit
testDepends
testFrameworkDepends
testHaskellDepends
testPkgconfigDepends
testSystemDepends
testToolDepends
;
} // stdenv.lib.optionalAttrs doBenchmark {
inherit
benchmarkDepends
benchmarkFrameworkDepends
benchmarkHaskellDepends
benchmarkPkgconfigDepends
benchmarkSystemDepends
benchmarkToolDepends
;
};

getBuildInputs = {
# Attributes for the old definition of `shellFor`. Should be removed but
# this predates the warning at the top of `getCabalDeps`.
getBuildInputs = rec {
inherit propagatedBuildInputs otherBuildInputs allPkgconfigDepends;
haskellBuildInputs = isHaskellPartition.right;
systemBuildInputs = isHaskellPartition.wrong;
isHaskellPartition = stdenv.lib.partition
isHaskellPkg
(propagatedBuildInputs ++ otherBuildInputs ++ depsBuildBuild ++ nativeBuildInputs);
};

isHaskellLibrary = isLibrary;
@@ -485,10 +537,64 @@ stdenv.mkDerivation ({
# TODO: fetch the self from the fixpoint instead
haddockDir = self: if doHaddock then "${docdir self.doc}/html" else null;

env = shellFor {
packages = p: [ drv ];
inherit shellHook;
};
# Creates a derivation containing all of the necessary dependencies for building the
# parent derivation. The attribute set that it takes as input can be viewed as:
#
# { withHoogle }
#
# The derivation that it builds contains no outpaths because it is meant for use
# as an environment
#
# # Example use
# # Creates a shell with all of the dependencies required to build the "hello" package,
# # and with python:
#
# > nix-shell -E 'with (import <nixpkgs> {}); \
# > haskell.packages.ghc865.hello.envFunc { buildInputs = [ python ]; }'
envFunc = { withHoogle ? false }:
let
name = "ghc-shell-for-${drv.name}";

withPackages = if withHoogle then ghcWithHoogle else ghcWithPackages;

# We use the `ghcWithPackages` function from `buildHaskellPackages` if we
# want a shell for the sake of cross compiling a package. In the native case
# we don't use this at all, and instead put the setupDepends in the main
# `ghcWithPackages`. This way we don't have two wrapper scripts called `ghc`
# shadowing each other on the PATH.
ghcEnvForBuild =
assert isCross;
buildHaskellPackages.ghcWithPackages (_: setupHaskellDepends);

ghcEnv = withPackages (_:
otherBuildInputsHaskell ++
propagatedBuildInputs ++
stdenv.lib.optionals (!isCross) setupHaskellDepends);

ghcCommandCaps = stdenv.lib.toUpper ghcCommand';
in stdenv.mkDerivation ({
inherit name shellHook;

depsBuildBuild = stdenv.lib.optional isCross ghcEnvForBuild;
nativeBuildInputs =
[ ghcEnv ] ++ optional (allPkgconfigDepends != []) pkgconfig ++
collectedToolDepends;
buildInputs =
otherBuildInputsSystem;
phases = ["installPhase"];
installPhase = "echo $nativeBuildInputs $buildInputs > $out";
LANG = "en_US.UTF-8";
LOCALE_ARCHIVE = stdenv.lib.optionalString (stdenv.hostPlatform.libc == "glibc") "${buildPackages.glibcLocales}/lib/locale/locale-archive";
"NIX_${ghcCommandCaps}" = "${ghcEnv}/bin/${ghcCommand}";
"NIX_${ghcCommandCaps}PKG" = "${ghcEnv}/bin/${ghcCommand}-pkg";
# TODO: is this still valid?
"NIX_${ghcCommandCaps}_DOCDIR" = "${ghcEnv}/share/doc/ghc/html";
"NIX_${ghcCommandCaps}_LIBDIR" = if ghc.isHaLVM or false
then "${ghcEnv}/lib/HaLVM-${ghc.version}"
else "${ghcEnv}/lib/${ghcCommand}-${ghc.version}";
});

env = envFunc { };

};

82 changes: 39 additions & 43 deletions pkgs/development/haskell-modules/make-package-set.nix
Original file line number Diff line number Diff line change
@@ -38,12 +38,12 @@ let
inherit (stdenv) buildPlatform hostPlatform;

inherit (stdenv.lib) fix' extends makeOverridable;
inherit (haskellLib) overrideCabal getBuildInputs;
inherit (haskellLib) overrideCabal;

mkDerivationImpl = pkgs.callPackage ./generic-builder.nix {
inherit stdenv;
nodejs = buildPackages.nodejs-slim;
inherit (self) buildHaskellPackages ghc shellFor;
inherit (self) buildHaskellPackages ghc ghcWithHoogle ghcWithPackages;
inherit (self.buildHaskellPackages) jailbreak-cabal;
hscolour = overrideCabal self.buildHaskellPackages.hscolour (drv: {
isLibrary = false;
@@ -258,6 +258,8 @@ in package-set { inherit pkgs stdenv callPackage; } self // {
# packages themselves. Using nix-shell on this derivation will
# give you an environment suitable for developing the listed
# packages with an incremental tool like cabal-install.
# In addition to the "packages" arg and "withHoogle" arg, anything that
# can be passed into stdenv.mkDerivation can be included in the input attrset
#
# # default.nix
# with import <nixpkgs> {};
@@ -268,9 +270,11 @@ in package-set { inherit pkgs stdenv callPackage; } self // {
# })
#
# # shell.nix
# let pkgs = import <nixpkgs> {} in
# (import ./.).shellFor {
# packages = p: [p.frontend p.backend p.common];
# withHoogle = true;
# buildInputs = [ pkgs.python ];
# }
#
# -- cabal.project
@@ -280,49 +284,41 @@ in package-set { inherit pkgs stdenv callPackage; } self // {
# common/
#
# bash$ nix-shell --run "cabal new-build all"
# bash$ nix-shell --run "python"
shellFor = { packages, withHoogle ? false, ... } @ args:
let
selected = packages self;

packageInputs = map getBuildInputs selected;

name = if pkgs.lib.length selected == 1
then "ghc-shell-for-${(pkgs.lib.head selected).name}"
else "ghc-shell-for-packages";

# If `packages = [ a b ]` and `a` depends on `b`, don't build `b`,
# because cabal will end up ignoring that built version, assuming
# new-style commands.
haskellInputs = pkgs.lib.filter
(input: pkgs.lib.all (p: input.outPath != p.outPath) selected)
(pkgs.lib.concatMap (p: p.haskellBuildInputs) packageInputs);
systemInputs = pkgs.lib.concatMap (p: p.systemBuildInputs) packageInputs;

withPackages = if withHoogle then self.ghcWithHoogle else self.ghcWithPackages;
ghcEnv = withPackages (p: haskellInputs);
nativeBuildInputs = pkgs.lib.concatMap (p: p.nativeBuildInputs) selected;

ghcCommand' = if ghc.isGhcjs or false then "ghcjs" else "ghc";
ghcCommand = "${ghc.targetPrefix}${ghcCommand'}";
ghcCommandCaps= pkgs.lib.toUpper ghcCommand';

mkDrvArgs = builtins.removeAttrs args ["packages" "withHoogle"];
in pkgs.stdenv.mkDerivation (mkDrvArgs // {
name = mkDrvArgs.name or name;

buildInputs = systemInputs ++ mkDrvArgs.buildInputs or [];
nativeBuildInputs = [ ghcEnv ] ++ nativeBuildInputs ++ mkDrvArgs.nativeBuildInputs or [];
phases = ["installPhase"];
installPhase = "echo $nativeBuildInputs $buildInputs > $out";
LANG = "en_US.UTF-8";
LOCALE_ARCHIVE = pkgs.lib.optionalString (stdenv.hostPlatform.libc == "glibc") "${buildPackages.glibcLocales}/lib/locale/locale-archive";
"NIX_${ghcCommandCaps}" = "${ghcEnv}/bin/${ghcCommand}";
"NIX_${ghcCommandCaps}PKG" = "${ghcEnv}/bin/${ghcCommand}-pkg";
# TODO: is this still valid?
"NIX_${ghcCommandCaps}_DOCDIR" = "${ghcEnv}/share/doc/ghc/html";
"NIX_${ghcCommandCaps}_LIBDIR" = if ghc.isHaLVM or false
then "${ghcEnv}/lib/HaLVM-${ghc.version}"
else "${ghcEnv}/lib/${ghcCommand}-${ghc.version}";
combinedPackageFor = packages:
let
selected = packages self;

pname = if pkgs.lib.length selected == 1
then (pkgs.lib.head selected).name
else "packages";

# If `packages = [ a b ]` and `a` depends on `b`, don't build `b`,
# because cabal will end up ignoring that built version, assuming
# new-style commands.
combinedPackages = pkgs.lib.filter
(input: pkgs.lib.all (p: input.outPath or null != p.outPath) selected);

# Returns an attrset containing a combined list packages' inputs for each
# stage of the build process
packageInputs = pkgs.lib.zipAttrsWith
(_: pkgs.lib.concatMap combinedPackages)
(map (p: p.getCabalDeps) selected);

genericBuilderArgs = {
inherit pname;
version = "0";
license = null;
} // packageInputs;

in self.mkDerivation genericBuilderArgs;

envFuncArgs = builtins.removeAttrs args [ "packages" ];
in (combinedPackageFor packages).env.overrideAttrs (old: envFuncArgs // {
nativeBuildInputs = old.nativeBuildInputs ++ envFuncArgs.nativeBuildInputs or [];
buildInputs = old.buildInputs ++ envFuncArgs.buildInputs or [];
});

ghc = ghc // {
2 changes: 2 additions & 0 deletions pkgs/test/default.nix
Original file line number Diff line number Diff line change
@@ -26,6 +26,8 @@ with pkgs;
cc-wrapper-libcxx-9 = callPackage ./cc-wrapper { stdenv = llvmPackages_9.libcxxStdenv; };
stdenv-inputs = callPackage ./stdenv-inputs { };

haskell-shellFor = callPackage ./haskell-shellFor { };

cc-multilib-gcc = callPackage ./cc-wrapper/multilib.nix { stdenv = gccMultiStdenv; };
cc-multilib-clang = callPackage ./cc-wrapper/multilib.nix { stdenv = clangMultiStdenv; };

24 changes: 24 additions & 0 deletions pkgs/test/haskell-shellFor/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{ stdenv, haskellPackages, cabal-install }:

haskellPackages.shellFor {
packages = p: [ p.database-id-class p.constraints-extras ];
nativeBuildInputs = [ cabal-install ];
phases = [ "unpackPhase" "buildPhase" "installPhase" ];
unpackPhase = ''
sourceRoot=$(pwd)/scratch
mkdir -p "$sourceRoot"
cd "$sourceRoot"
tar -xf ${haskellPackages.database-id-class.src}
tar -xf ${haskellPackages.constraints-extras.src}
cp ${builtins.toFile "cabal.project" "packages: database-id-class* constraints-extras*"} cabal.project
'';
buildPhase = ''
export HOME=$(mktemp -d)
mkdir -p $HOME/.cabal
touch $HOME/.cabal/config
cabal v2-build --offline --verbose database-id-class constraints-extras --ghc-options="-O0 -j$NIX_BUILD_CORES"
'';
installPhase = ''
touch $out
'';
}
2 changes: 2 additions & 0 deletions pkgs/top-level/release.nix
Original file line number Diff line number Diff line change
@@ -191,6 +191,8 @@ let
haskellPackages = packagePlatforms pkgs.haskellPackages;
idrisPackages = packagePlatforms pkgs.idrisPackages;

tests = packagePlatforms pkgs.tests;

# Language packages disabled in https://github.com/NixOS/nixpkgs/commit/ccd1029f58a3bb9eca32d81bf3f33cb4be25cc66

#emacsPackages = packagePlatforms pkgs.emacsPackages;