Skip to content

Commit

Permalink
Merge pull request NixOS#27209 from nc6/nc/haskell-multiple-out
Browse files Browse the repository at this point in the history
Enable multiple outputs for haskell packages.
  • Loading branch information
peti committed Sep 5, 2017
2 parents 7f8ff02 + eb99d3a commit dfb0f25
Show file tree
Hide file tree
Showing 14 changed files with 167 additions and 36 deletions.
2 changes: 1 addition & 1 deletion pkgs/development/compilers/ghc/7.10.2.nix
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ stdenv.mkDerivation rec {
sha256 = "1x8m4rp2v7ydnrz6z9g8x7z3x3d3pxhv2pixy7i7hkbqbdsp7kal";
};

buildInputs = [ ghc perl libxml2 libxslt docbook_xsl docbook_xml_dtd_45 docbook_xml_dtd_42 hscolour ];
buildInputs = [ ghc perl libxml2 libxslt docbook_xsl docbook_xml_dtd_45 docbook_xml_dtd_42 (stdenv.lib.getBin hscolour) ];

patches = [ ./relocation.patch ];

Expand Down
2 changes: 1 addition & 1 deletion pkgs/development/compilers/ghc/7.10.3.nix
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ stdenv.mkDerivation rec {
./relocation.patch
];

buildInputs = [ ghc perl libxml2 libxslt docbook_xsl docbook_xml_dtd_45 docbook_xml_dtd_42 hscolour ];
buildInputs = [ ghc perl libxml2 libxslt docbook_xsl docbook_xml_dtd_45 docbook_xml_dtd_42 (stdenv.lib.getBin hscolour) ];

enableParallelBuilding = true;

Expand Down
2 changes: 1 addition & 1 deletion pkgs/development/compilers/ghc/8.0.1.nix
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ stdenv.mkDerivation rec {
(fetchFilteredPatch { url = https://git.haskell.org/ghc.git/patch/2f8cd14fe909a377b3e084a4f2ded83a0e6d44dd; sha256 = "06zvlgcf50ab58bw6yw3krn45dsmhg4cmlz4nqff8k4z1f1bj01v"; })
] ++ stdenv.lib.optional stdenv.isLinux ./ghc-no-madv-free.patch;

buildInputs = [ ghc perl hscolour sphinx];
buildInputs = [ ghc perl (stdenv.lib.getBin hscolour) sphinx];

enableParallelBuilding = true;

Expand Down
2 changes: 1 addition & 1 deletion pkgs/development/compilers/ghc/8.0.2.nix
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ stdenv.mkDerivation rec {
++ stdenv.lib.optional stdenv.isLinux ./ghc-no-madv-free.patch
++ stdenv.lib.optional stdenv.isDarwin ./ghc-8.0.2-no-cpp-warnings.patch;

buildInputs = [ ghc perl hscolour sphinx ];
buildInputs = [ ghc perl (stdenv.lib.getBin hscolour) sphinx ];

enableParallelBuilding = true;

Expand Down
2 changes: 1 addition & 1 deletion pkgs/development/compilers/ghc/8.2.1.nix
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ let
inherit (bootPkgs) ghc;
version = "8.2.1";
preReleaseName = "ghc-8.2.1";
commonBuildInputs = [ alex autoconf automake ghc happy hscolour perl python3 sphinx ];
commonBuildInputs = [ (stdenv.lib.getBin alex) autoconf automake ghc (stdenv.lib.getBin happy) (stdenv.lib.getBin hscolour) perl python3 sphinx ];
commonPreConfigure = ''
sed -i -e 's|-isysroot /Developer/SDKs/MacOSX10.5.sdk||' configure
'' + stdenv.lib.optionalString (!stdenv.isDarwin) ''
Expand Down
2 changes: 1 addition & 1 deletion pkgs/development/compilers/ghc/head.nix
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
let
inherit (bootPkgs) ghc;

commonBuildInputs = [ ghc perl autoconf automake happy alex python3 ];
commonBuildInputs = [ ghc perl autoconf automake (stdenv.lib.getBin happy) (stdenv.lib.getBin alex) python3 ];

rev = "14457cf6a50f708eecece8f286f08687791d51f7";

Expand Down
2 changes: 1 addition & 1 deletion pkgs/development/compilers/ghcjs/base.nix
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ in mkDerivation (rec {
lens optparse-applicative parallel safe shelly split
stringsearch syb system-fileio system-filepath tar terminfo text-binary
unordered-containers vector wl-pprint-text yaml
alex happy git gnumake autoconf automake libtool patch gmp
(stdenv.lib.getBin alex) (stdenv.lib.getBin happy) git gnumake autoconf automake libtool patch gmp
base16-bytestring cryptohash executable-path haddock-api
transformers-compat QuickCheck haddock hspec xhtml
regex-posix libiconv
Expand Down
4 changes: 2 additions & 2 deletions pkgs/development/compilers/halvm/2.4.0.nix
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ stdenv.mkDerivation rec {
sed -ie 's|ld |${binutils}/bin/ld |g' src/scripts/ldkernel.in
'';
configureFlags = stdenv.lib.optional (!enableIntegerSimple) [ "--enable-gmp" ];
propagatedNativeBuildInputs = [ alex happy ];
propagatedNativeBuildInputs = [ (stdenv.lib.getBin alex) (stdenv.lib.getBin happy) ];
buildInputs =
let haskellPkgs = [ alex happy bootPkgs.hscolour bootPkgs.cabal-install bootPkgs.haddock bootPkgs.hpc
let haskellPkgs = [ (stdenv.lib.getBin alex) (stdenv.lib.getBin happy) (stdenv.lib.getBin bootPkgs.hscolour) bootPkgs.cabal-install bootPkgs.haddock bootPkgs.hpc
]; in [ bootPkgs.ghc
automake perl git binutils
autoconf xen zlib ncurses.dev
Expand Down
5 changes: 5 additions & 0 deletions pkgs/development/haskell-modules/configuration-common.nix
Original file line number Diff line number Diff line change
Expand Up @@ -862,6 +862,7 @@ self: super: {
# Don't install internal mkReadme tool.
hastache = overrideCabal super.hastache (drv: {
doCheck = false;
enableSeparateBinOutput = false;
postInstall = "rm $out/bin/mkReadme && rmdir $out/bin";
});

Expand Down Expand Up @@ -899,4 +900,8 @@ self: super: {
sha256 = "1vss7b99zrhw3r29krl1b60r4qk0m2mpwmrz8q8zdxrh33hb8pd7";
});

# Has extra data files which are referred to from the binary output,
# creating a store reference cycle. Putting data in separate output
# solves the problem.
happy = overrideCabal super.happy (drv: { enableSeparateDataOutput = true; });
}
47 changes: 46 additions & 1 deletion pkgs/development/haskell-modules/configuration-nix.nix
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,10 @@ self: super: builtins.intersectAttrs super {

# wxc supports wxGTX >= 3.0, but our current default version points to 2.8.
# http://hydra.cryp.to/build/1331287/log/raw
wxc = (addBuildDepend super.wxc self.split).override { wxGTK = pkgs.wxGTK30; };
wxc = (overrideCabal super.wxc (drv: {
buildDepends = (drv.buildDepends or []) ++ [self.split];
postInstall = "cp -v dist/build/libwxc.so.0.92.3.0 $lib/lib/libwxc.so";
})).override { wxGTK = pkgs.wxGTK30; };
wxcore = super.wxcore.override { wxGTK = pkgs.wxGTK30; };

# Test suite wants to connect to $DISPLAY.
Expand Down Expand Up @@ -489,4 +492,46 @@ self: super: builtins.intersectAttrs super {
# Without this override, the builds lacks pkg-config.
opencv-extra = addPkgconfigDepend super.opencv-extra (pkgs.opencv3.override { enableContrib = true; });

# Alex has some weird files in /usr/share that create a cyclic ref with
# its bin dir.
alex = hasNoBinOutput super.alex;

# Disable separate bin outputs for these specific packages that break with it.
H = hasNoBinOutput super.H;
cryptol = hasNoBinOutput super.cryptol;
sproxy = hasNoBinOutput super.sproxy;
sproxy2 = hasNoBinOutput super.sproxy2;
sproxy-web = hasNoBinOutput super.sproxy-web;
juandelacosa = hasNoBinOutput super.juandelacosa;
mywatch = hasNoBinOutput super.mywatch;
sugarhaskell = hasNoBinOutput super.sugarhaskell;
zerobin = hasNoBinOutput super.zerobin;

git-annex = overrideCabal super.git-annex (drv: {
enableSeparateBinOutput = false;
enableSeparateEtcOutput = false;
});

# Override a number of packages with specific references to $out in their
# derivations
stack = overrideCabal super.stack (drv: {
postInstall = ''
exe=$bin/bin/stack
mkdir -p $bin/share/bash-completion/completions
$exe --bash-completion-script $exe >$bin/share/bash-completion/completions/stack
'';
});
Agda = overrideCabal super.Agda (drv: {
postInstall = ''
files=("$out/share/"*"-ghc-"*"/Agda-"*"/lib/prim/Agda/"{Primitive.agda,Builtin"/"*.agda})
for f in "''${files[@]}" ; do
$bin/bin/agda $f
done
for f in "''${files[@]}" ; do
$bin/bin/agda -c --no-main $f
done
$bin/bin/agda-mode compile
'';
});

}
118 changes: 97 additions & 21 deletions pkgs/development/haskell-modules/generic-builder.nix
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ let isCross = (ghc.cross or null) != null; in
, hardeningDisable ? lib.optional (ghc.isHaLVM or false) "all"
, enableSeparateDataOutput ? false
, enableSeparateDocOutput ? doHaddock
, enableSeparateBinOutput ? isExecutable
, outputsToInstall ? []
, enableSeparateLibOutput ? true
, enableSeparateEtcOutput ? (stdenv.lib.versionOlder "7.7" ghc.version)
} @ args:

assert editedCabalFile != null -> revision != null;
Expand All @@ -79,9 +83,6 @@ let
then "package-db"
else "package-conf";

# the target dir for haddock documentation
docdir = docoutput: docoutput + "/share/doc";

newCabalFileUrl = "http://hackage.haskell.org/package/${pname}-${version}/revision/${revision}.cabal";
newCabalFile = fetchurl {
url = newCabalFileUrl;
Expand All @@ -95,6 +96,13 @@ let
'';

hasActiveLibrary = isLibrary && (enableStaticLibraries || enableSharedLibraries || enableLibraryProfiling);
hasLibOutput = enableSeparateLibOutput && hasActiveLibrary;
libDir = if hasLibOutput then "$lib/lib/${ghc.name}" else "$out/lib/${ghc.name}";
binDir = if enableSeparateBinOutput then "$bin/bin" else "$out/bin";
libexecDir = if enableSeparateBinOutput then "$libexec/bin" else "$out/libexec";
etcDir = if enableSeparateEtcOutput then "$etc/etc" else "$out/etc";
docDir = if enableSeparateDocOutput then "$doc/share/doc" else "$out/share/doc";
dataDir = if enableSeparateDataOutput then "$data/share/${ghc.name}" else "$out/share/${ghc.name}";

# We cannot enable -j<n> parallelism for libraries because GHC is far more
# likely to generate a non-determistic library ID in that case. Further
Expand All @@ -113,12 +121,20 @@ let
stdenv.lib.optionalString isCross (" " + stdenv.lib.concatStringsSep " " crossCabalFlags);

defaultConfigureFlags = [
"--verbose" "--prefix=$out" "--libdir=\\$prefix/lib/\\$compiler" "--libsubdir=\\$pkgid"
(optionalString enableSeparateDataOutput "--datadir=$data/share/${ghc.name}")
(optionalString enableSeparateDocOutput "--docdir=${docdir "$doc"}")
"--verbose" "--prefix=$out"
# Binary directory has to be $bin/bin instead of just $bin: this
# is so that the package is added to the PATH when it's used as a
# build input. Sadly mkDerivation won't add inputs that don't have
# bin subdirectory.
"--bindir=${binDir}"
"--libdir=${libDir}" "--libsubdir=\\$pkgid"
"--libexecdir=${libexecDir}"
(optionalString (enableSeparateEtcOutput) "--sysconfdir=${etcDir}") # Old versions of cabal don't support this flag.
"--datadir=${dataDir}"
"--docdir=${docDir}"
"--with-gcc=$CC" # Clang won't work without that extra information.
"--package-db=$packageConfDir"
(optionalString (enableSharedExecutables && stdenv.isLinux) "--ghc-option=-optl=-Wl,-rpath=$out/lib/${ghc.name}/${pname}-${version}")
(optionalString (enableSharedExecutables && stdenv.isLinux) "--ghc-option=-optl=-Wl,-rpath=${libDir}/${pname}-${version}")
(optionalString (enableSharedExecutables && stdenv.isDarwin) "--ghc-option=-optl=-Wl,-headerpad_max_install_names")
(optionalString enableParallelBuilding "--ghc-option=-j$NIX_BUILD_CORES")
(optionalString useCpphs "--with-cpphs=${cpphs}/bin/cpphs --ghc-options=-cpp --ghc-options=-pgmP${cpphs}/bin/cpphs --ghc-options=-optP--cpp")
Expand Down Expand Up @@ -152,7 +168,8 @@ let
allPkgconfigDepends = pkgconfigDepends ++ libraryPkgconfigDepends ++ executablePkgconfigDepends ++
optionals doCheck testPkgconfigDepends ++ optionals withBenchmarkDepends benchmarkPkgconfigDepends;

nativeBuildInputs = buildTools ++ libraryToolDepends ++ executableToolDepends ++ [ removeReferencesTo ];
nativeBuildInputs = map stdenv.lib.getBin
(buildTools ++ libraryToolDepends ++ executableToolDepends ++ [ removeReferencesTo ]);
propagatedBuildInputs = buildDepends ++ libraryHaskellDepends ++ executableHaskellDepends;
otherBuildInputs = setupHaskellDepends ++ extraLibraries ++ librarySystemDepends ++ executableSystemDepends ++
optionals (allPkgconfigDepends != []) ([pkgconfig] ++ allPkgconfigDepends) ++
Expand Down Expand Up @@ -181,7 +198,15 @@ assert allPkgconfigDepends != [] -> pkgconfig != null;
stdenv.mkDerivation ({
name = "${pname}-${version}";

outputs = if (args ? outputs) then args.outputs else ([ "out" ] ++ (optional enableSeparateDataOutput "data") ++ (optional enableSeparateDocOutput "doc"));
outputs = if (args ? outputs) then args.outputs else
( (optional enableSeparateBinOutput "bin")
++ (optional enableSeparateBinOutput "libexec")
++ [ "out" ]
++ (optional enableSeparateDataOutput "data")
++ (optional enableSeparateDocOutput "doc")
++ (optional enableSeparateEtcOutput "etc")
++ (optional hasLibOutput "lib")
);
setOutputFlags = false;

pos = builtins.unsafeGetAttrPos "pname" args;
Expand All @@ -205,15 +230,15 @@ stdenv.mkDerivation ({

postPatch = optionalString jailbreak ''
echo "Run jailbreak-cabal to lift version restrictions on build inputs."
${jailbreak-cabal}/bin/jailbreak-cabal ${pname}.cabal
${stdenv.lib.getBin jailbreak-cabal}/bin/jailbreak-cabal ${pname}.cabal
'' + postPatch;

setupCompilerEnvironmentPhase = ''
runHook preSetupCompilerEnvironment
echo "Build with ${ghc}."
export PATH="${ghc}/bin:$PATH"
${optionalString (hasActiveLibrary && hyperlinkSource) "export PATH=${hscolour}/bin:$PATH"}
${optionalString (hasActiveLibrary && hyperlinkSource) "export PATH=${stdenv.lib.getBin hscolour}/bin:$PATH"}
packageConfDir="$TMPDIR/package.conf.d"
mkdir -p $packageConfDir
Expand All @@ -240,7 +265,7 @@ stdenv.mkDerivation ({
#
# Create a local directory with symlinks of the *.dylib (macOS shared
# libraries) from all the dependencies.
local dynamicLinksDir="$out/lib/links"
local dynamicLinksDir="${libDir}/links"
mkdir -p $dynamicLinksDir
for d in $(grep dynamic-library-dirs "$packageConfDir/"*|awk '{print $2}'); do
ln -s "$d/"*.dylib $dynamicLinksDir
Expand Down Expand Up @@ -312,15 +337,15 @@ stdenv.mkDerivation ({
${if !hasActiveLibrary then "${setupCommand} install" else ''
${setupCommand} copy
local packageConfDir="$out/lib/${ghc.name}/package.conf.d"
local packageConfDir="${libDir}/package.conf.d"
local packageConfFile="$packageConfDir/${pname}-${version}.conf"
mkdir -p "$packageConfDir"
${setupCommand} register --gen-pkg-config=$packageConfFile
local pkgId=$( ${gnused}/bin/sed -n -e 's|^id: ||p' $packageConfFile )
mv $packageConfFile $packageConfDir/$pkgId.conf
''}
${optionalString isGhcjs ''
for exeDir in "$out/bin/"*.jsexe; do
for exeDir in "${binDir}/"*.jsexe; do
exe="''${exeDir%.jsexe}"
printWords '#!${nodejs}/bin/node' > "$exe"
cat "$exeDir/all.js" >> "$exe"
Expand All @@ -329,18 +354,68 @@ stdenv.mkDerivation ({
''}
${optionalString doCoverage "mkdir -p $out/share && cp -r dist/hpc $out/share"}
${optionalString (enableSharedExecutables && isExecutable && !isGhcjs && stdenv.isDarwin && stdenv.lib.versionOlder ghc.version "7.10") ''
for exe in "$out/bin/"* ; do
install_name_tool -add_rpath "$out/lib/ghc-${ghc.version}/${pname}-${version}" "$exe"
for exe in "${binDir}/"* ; do
install_name_tool -add_rpath "${libDir}/${pname}-${version}" "$exe"
done
''}
${optionalString enableSeparateDocOutput ''
for x in ${docdir "$doc"}/html/src/*.html; do
remove-references-to -t $out $x
# Remove references back to $out but also back to $lib if we have
# docs. $lib is needed as it stores path to haddock interfaces in the
# conf file which creates a cycle if docs refer back to library
# path.
mkdir -p ${docDir}
for x in ${docDir}/html/src/*.html; do
remove-references-to -t $out -t ${libDir} -t ${binDir} ${optionalString enableSeparateDataOutput "-t $data"} $x
done
mkdir -p $doc
''}
${optionalString enableSeparateDataOutput "mkdir -p $data"}
${optionalString hasLibOutput ''
# Even if we don't have binary output for the package, things like
# Paths files will embed paths to bin/libexec directories in themselves
# which results in .lib <-> $out cyclic store reference. We
# therefore patch out the paths from separate library if we don't have
# separate bin output too.
#
# If we _do_ have separate bin and lib outputs, we may still be in
# trouble in case of shared executables: executable contains path to
# .lib, .lib contains path (through Paths) to .bin and we have a
# cycle.
#
# Lastly we have to deal with references from .lib back into
# $out/share if we're not splitting out data directory.
#
# It may happen that we have hasLibOutput set but the library
# directory was not created: this happens in the case that library
# section is not exposing any modules. See "fail" package for an
# example where no modules are exposed for GHC >= 8.0.
if [ -d ${libDir} ]; then
find ${libDir} -type f -exec \
remove-references-to -t ${binDir} -t ${libexecDir} "{}" \;
fi
''}
${optionalString (hasLibOutput && ! enableSeparateDocOutput) ''
# If we don't have separate docs, we have to patch out the ref to
# docs in package conf. This will likely break Haddock
# cross-package links but is necessary to break store cycle…
find ${libDir}/ -type f -name '*.conf' -exec \
remove-references-to -t ${docDir} "{}" \;
''}
${optionalString (hasLibOutput && ! enableSeparateDataOutput) ''
# Just like for doc output path in $out potentially landing in
# *.conf, we have to also remove the data directory so that it
# doesn't appear under data-dir field creating a cycle.
find ${libDir}/ -type f -exec echo Removing ${dataDir} refs from "{}" \;
find ${libDir}/ -type f -exec \
remove-references-to -t ${dataDir} "{}" \;
''}
${optionalString enableSeparateDataOutput "mkdir -p ${dataDir}"}
${optionalString enableSeparateBinOutput "mkdir -p ${binDir} ${libexecDir}"}
${optionalString enableSeparateEtcOutput "mkdir -p ${etcDir}"}
runHook postInstall
'';
Expand All @@ -357,7 +432,7 @@ stdenv.mkDerivation ({
# the directory containing the haddock documentation.
# `null' if no haddock documentation was built.
# TODO: fetch the self from the fixpoint instead
haddockDir = self: if doHaddock then "${docdir self.doc}/html" else null;
haddockDir = self: if doHaddock then "${docDir}/html" else null;

env = stdenv.mkDerivation {
name = "interactive-${pname}-${version}-environment";
Expand Down Expand Up @@ -386,6 +461,7 @@ stdenv.mkDerivation ({
// optionalAttrs (description != "") { inherit description; }
// optionalAttrs (maintainers != []) { inherit maintainers; }
// optionalAttrs (hydraPlatforms != platforms) { inherit hydraPlatforms; }
// optionalAttrs (outputsToInstall != []) { inherit outputsToInstall; }
;

}
Expand Down
4 changes: 4 additions & 0 deletions pkgs/development/haskell-modules/lib.nix
Original file line number Diff line number Diff line change
Expand Up @@ -142,4 +142,8 @@ rec {
overrideSrc = drv: { src, version ? drv.version }:
overrideCabal drv (_: { inherit src version; editedCabalFile = null; });

hasNoBinOutput = drv: overrideCabal drv (drv: { enableSeparateBinOutput = false; });

installOutputs = drv: outputs: overrideCabal drv
(drv: { outputsToInstall = outputs; });
}
1 change: 1 addition & 0 deletions pkgs/development/haskell-modules/make-package-set.nix
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ let
isLibrary = false;
doHaddock = false;
hyperlinkSource = false; # Avoid depending on hscolour for this build.
enableSeparateEtcOutput = false; # The flag to support this is missing in old versions of cabal.
postFixup = "rm -rf $out/lib $out/share $out/nix-support";
});
cpphs = overrideCabal (self.cpphs.overrideScope (self: super: {
Expand Down

0 comments on commit dfb0f25

Please sign in to comment.