From 22c7d08b6abae3f31f340629f1aa0d68cc7be5a0 Mon Sep 17 00:00:00 2001 From: Marc Weber Date: Tue, 22 Jan 2008 14:34:23 +0000 Subject: [PATCH] proposal cabal ghc builder + dep tracking using GHC_PACKAGE_PATH (untested - not yet working) svn path=/nixpkgs/trunk/; revision=10245 --- pkgs/development/compilers/ghcs/default.nix | 56 ++++---- pkgs/top-level/all-packages.nix | 41 ++++-- pkgs/top-level/builder-defs.nix | 137 +++++++++++++++++--- 3 files changed, 181 insertions(+), 53 deletions(-) diff --git a/pkgs/development/compilers/ghcs/default.nix b/pkgs/development/compilers/ghcs/default.nix index eae967fad4b..b4e14c9921d 100644 --- a/pkgs/development/compilers/ghcs/default.nix +++ b/pkgs/development/compilers/ghcs/default.nix @@ -80,6 +80,7 @@ +" --prefix=\$out " +" --with-ghc=\$ghcboot/bin/ghc" +" --with-gmp-libraries=$gmp/lib" + +" --with-gmp-includes=${gmp}/include" +" --with-readline-libraries=\"$readline/lib\""; # now read the main package.conf and create a single package db file for each of them @@ -107,26 +108,26 @@ # Why this effort? If you want to use pretty-0.9 you can do this now without cabal choosing the 1.0 version hassle core_libs = resolveDeps ghc - [ { name = "Cabal-1.2.0"; deps = ["base-2.1" "pretty-1.0" "old-locale-1.0" "old-time-1.0" "directory-1.0" "unix-2.0" "process-1.0" "array-0.1" "containers-0.1" "rts-1.0" "filepath-1.0"];} # - { name = "array-0.1"; deps = ["base-2.1"];} - { name = "base-2.1"; deps = [];} # - { name = "bytestring-0.9"; deps = [ "base-2.1" "array-0.1" ];} - { name = "containers-0.1"; deps = [ "base-2.1" "array-0.1" ];} - { name = "directory-1.0"; deps = [ "base-2.1" "old-locale-1.0" "old-time-1.0" "filepath-1.0"];} - { name = "filepath-1.0"; deps = [ "base-2.1" ];} # - { name = "ghc-6.8.0.20071004"; deps = [ "base-2.1" "old-locale-1.0" "old-time-1.0" "filepath-1.0" "directory-1.0" "array-0.1" "containers-0.1" "hpc-0.5" "bytestring-0.9" "pretty-1.0" "packedstring-0.1" "template-haskell-0.1" "unix-2.0" "process-1.0" "readline-1.0" "Cabal-1.2.0" "random-1.0" "haskell98-1.0"];} - { name = "haskell98-1.0"; deps = [ "base-2.1" "old-locale-1.0" "old-time-1.0" "filepath-1.0" "directory-1.0" "random-1.0" "unix-2.0" "process-1.0" "array-0.1"];} - { name = "hpc-0.5"; deps = [ "base-2.1" "old-locale-1.0" "old-time-1.0" "filepath-1.0" "directory-1.0" "array-0.1" "containers-0.1"]; } - { name = "old-locale-1.0"; deps = [ "base-2.1"];} - { name = "old-time-1.0"; deps = [ "base-2.1" "old-locale-1.0" ];} - { name = "packedstring-0.1"; deps = [ "base-2.1" "array-0.1" ];} - { name = "pretty-1.0"; deps = [ "base-2.1" ];} - { name = "process-1.0"; deps = [ "base-2.1" "old-locale-1.0" "old-time-1.0" "filepath-1.0" "directory-1.0" "unix-2.0"];} - { name = "random-1.0"; deps = [ "base-2.1" "old-locale-1.0" "old-time-1.0"];} - { name = "readline-1.0"; deps = [ "base-2.1" "old-locale-1.0" "old-time-1.0" "filepath-1.0" "directory-1.0" "unix-2.0" "process-1.0" ];} - { name = "rts-1.0"; deps = [ "base-2.1" ];} # - { name = "template-haskell-0.1"; deps = [ "base-2.1" "pretty-1.0" "array-0.1" "packedstring-0.1" "containers-0.1" ];} - { name = "unix-2.0"; deps = [ "base-2.1" "old-locale-1.0" "old-time-1.0" "filepath-1.0" "directory-1.0" ];} + [ { name = "Cabal-1.2.3.0"; deps = ["base-3.0.1.0" "pretty-1.0.0.0" "old-locale-1.0.0.0" "old-time-1.0.0.0" "directory-1.0.0.0" "unix-2.3.0.0" "process-1.0.0.0" "array-0.1.0.0" "containers-0.1.0.1" "rts-1.0" "filepath-1.1.0.0"];} # + { name = "array-0.1.0.0"; deps = ["base-3.0.1.0"];} + { name = "base-3.0.1.0"; deps = [];} # + { name = "bytestring-0.9.0.1"; deps = [ "base-3.0.1.0" "array-0.1.0.0" ];} + { name = "containers-0.1.0.1"; deps = [ "base-3.0.1.0" "array-0.1.0.0" ];} + { name = "directory-1.0.0.0"; deps = [ "base-3.0.1.0" "old-locale-1.0.0.0" "old-time-1.0.0.0" "filepath-1.1.0.0"];} + { name = "filepath-1.1.0.0"; deps = [ "base-3.0.1.0" ];} # + { name = "ghc-${version}"; deps = [ "base-3.0.1.0" "old-locale-1.0.0.0" "old-time-1.0.0.0" "filepath-1.1.0.0" "directory-1.0.0.0" "array-0.1.0.0" "containers-0.1.0.1" "hpc-0.5.0.0" "bytestring-0.9.0.1" "pretty-1.0.0.0" "packedstring-0.1.0.0" "template-haskell-2.2.0.0" "unix-2.3.0.0" "process-1.0.0.0" "readline-1.0.1.0" "Cabal-1.2.3.0" "random-1.0.0.0" "haskell98-1.0.1.0"];} + { name = "haskell98-1.0.1.0"; deps = [ "base-3.0.1.0" "old-locale-1.0.0.0" "old-time-1.0.0.0" "filepath-1.1.0.0" "directory-1.0.0.0" "random-1.0.0.0" "unix-2.3.0.0" "process-1.0.0.0" "array-0.1.0.0"];} + { name = "hpc-0.5.0.0"; deps = [ "base-3.0.1.0" "old-locale-1.0.0.0" "old-time-1.0.0.0" "filepath-1.1.0.0" "directory-1.0.0.0" "array-0.1.0.0" "containers-0.1.0.1"]; } + { name = "old-locale-1.0.0.0"; deps = [ "base-3.0.1.0"];} + { name = "old-time-1.0.0.0"; deps = [ "base-3.0.1.0" "old-locale-1.0.0.0" ];} + { name = "packedstring-0.1.0.0"; deps = [ "base-3.0.1.0" "array-0.1.0.0" ];} + { name = "pretty-1.0.0.0"; deps = [ "base-3.0.1.0" ];} + { name = "process-1.0.0.0"; deps = [ "base-3.0.1.0" "old-locale-1.0.0.0" "old-time-1.0.0.0" "filepath-1.1.0.0" "directory-1.0.0.0" "unix-2.3.0.0"];} + { name = "random-1.0.0.0"; deps = [ "base-3.0.1.0" "old-locale-1.0.0.0" "old-time-1.0.0.0"];} + { name = "readline-1.0.1.0"; deps = [ "base-3.0.1.0" "old-locale-1.0.0.0" "old-time-1.0.0.0" "filepath-1.1.0.0" "directory-1.0.0.0" "unix-2.3.0.0" "process-1.0.0.0" ];} + { name = "rts-1.0"; deps = [ "base-3.0.1.0" ];} # + { name = "template-haskell-2.2.0.0"; deps = [ "base-3.0.1.0" "pretty-1.0.0.0" "array-0.1.0.0" "packedstring-0.1.0.0" "containers-0.1.0.1" ];} + { name = "unix-2.3.0.0"; deps = [ "base-3.0.1.0" "old-locale-1.0.0.0" "old-time-1.0.0.0" "filepath-1.1.0.0" "directory-1.0.0.0" ];} ]; @@ -137,18 +138,20 @@ } ); - ghc68 = ghcAndLibraries { - version = "6.8.0.20071004"; + ghc68 = ghcAndLibraries rec { + version = "6.8.2"; src = fetchurl { - url = http://www.haskell.org/ghc/dist/stable/dist/ghc-6.8.0.20071004-src.tar.bz2; - sha256 = "1yyl7sxykmvkiwfxkfzpqa6cmgw19phkyjcdv99ml22j16wli63l"; + #url = http://www.haskell.org/ghc/dist/stable/dist/ghc-6.8.0.20071004-src.tar.bz2; + #sha256 = "1yyl7sxykmvkiwfxkfzpqa6cmgw19phkyjcdv99ml22j16wli63l"; + url = "http://www.haskell.org/ghc/dist/stable/dist/ghc-${version}-src.tar.bz2"; + md5 = "745c6b7d4370610244419cbfec4b2f84"; #url = http://www.haskell.org/ghc/dist/stable/dist/ghc-6.8.20070912-src.tar.bz2; #sha256 = "1b1gvi7hc7sc0fkh29qvzzd5lgnlvdv3ayiak4mkfnzkahvmq85s"; }; extra_src = fetchurl { - url = http://www.haskell.org/ghc/dist/stable/dist/ghc-6.8.0.20071004-src-extralibs.tar.bz2; - sha256 = "0vjx4vb2xhv5v2wj74ii3gpjim7x9wj0m87zglqlhc8xn31pmrd2"; + url = "http://www.haskell.org/ghc/dist/stable/dist/ghc-${version}-src-extralibs.tar.bz2"; + sha256 = "044mpbzpkbxcnqhjnrnmjs00mr85057d123rrlz2vch795lxbkcn"; #url = http://www.haskell.org/ghc/dist/stable/dist/ghc-6.8.20070912-src-extralibs.tar.bz2; #sha256 = "0py7d9nh3lkhjxr3yb3n9345d0hmzq79bi40al5rcr3sb84rnp9r"; }; @@ -165,4 +168,3 @@ }; } - diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index 8230083875c..92b2ecefbc6 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -1006,6 +1006,7 @@ rec { # This new ghc stuff is under heavy development and might change ! # usage: see ghcPkgUtil.sh - use setup-new2 because of PATH_DELIMITER + # depreceated -> use functions defined in builderDefs ghcPkgUtil = runCommand "ghcPkgUtil-internal" { ghcPkgUtil = ../development/libraries/haskell/generic/ghcPkgUtil.sh; } "mkdir -p $out/nix-support; cp $ghcPkgUtil \$out/nix-support/setup-hook;"; @@ -1025,6 +1026,22 @@ rec { stdenv = stdenvUsingSetupNew2; }; + # this will change in the future + ghc68_extra_libs = + ghc : let + deriv = name : goSrcDir : deps : + let bd = builderDefs { + goSrcDir = "ghc-*/libraries"; + src = ghc.extra_src; + } null; in + stdenv.mkDerivation rec { + inherit name; + builder = bd.writeScript (name + "-builder") + (bd.textClosure [builderDefs.haskellBuilderDefs]); + }; + # using nvs to be able to use mtl-1.1.0.0 as name + in lib.nvs "mtl-1.1.0.0" (deriv "mtl-1.1.0.0" "libraries/mtl" [ (__getAttr "base-3.0.1.0" ghc.core_libs) ]); + # the wrappers basically does one thing: It defines GHC_PACKAGE_PATH before calling ghc{i,-pkg} # So you can have different wrappers with different library combinations # So installing ghc libraries isn't done by nix-env -i package but by adding the lib to the libraries list below @@ -1032,17 +1049,19 @@ rec { let ghc = ghcsAndLibs.ghc68.ghc; in createGhcWrapper rec { ghcPackagedLibs = true; - name = "ghc68_wrapper"; - suffix = "68wrapper"; - libraries = map ( a : __getAttr a ghcsAndLibs.ghc68.core_libs ) - [ "old-locale-1.0" "old-time-1.0" "filepath-1.0" "directory-1.0" "array-0.1" "containers-0.1" - "hpc-0.5" "bytestring-0.9" "pretty-1.0" "packedstring-0.1" "template-haskell-0.1" - "unix-2.0" "process-1.0" "readline-1.0" "Cabal-1.2.0" "random-1.0" "haskell98-1.0" "ghc-6.8.0.20071004" - "array-0.1" "bytestring-0.9" "containers-0.1" "directory-1.0" "filepath-1.0" - "ghc-6.8.0.20071004" "haskell98-1.0" "hpc-0.5" "old-locale-1.0" "old-time-1.0" - "packedstring-0.1" "pretty-1.0" "process-1.0" "random-1.0" - "readline-1.0" "rts-1.0" "template-haskell-0.1" "unix-2.0" - ]; + name = "ghc${ghc.version}_wrapper"; + suffix = "${ghc.version}wrapper"; + libraries = map ( a : __getAttr a ghcsAndLibs.ghc68.core_libs ) [ + "old-locale-1.0.0.0" "old-time-1.0.0.0" "filepath-1.1.0.0" "directory-1.0.0.0" "array-0.1.0.0" "containers-0.1.0.1" + "hpc-0.5.0.0" "bytestring-0.9.0.1" "pretty-1.0.0.0" "packedstring-0.1.0.0" "template-haskell-2.2.0.0" + "unix-2.3.0.0" "process-1.0.0.0" "readline-1.0.1.0" "Cabal-1.2.3.0" "random-1.0.0.0" "haskell98-1.0.1.0" "ghc-${ghc.version}" + "array-0.1.0.0" "bytestring-0.9.0.1" "containers-0.1.0.1" "directory-1.0.0.0" "filepath-1.1.0.0" + "ghc-${ghc.version}" "haskell98-1.0.1.0" "hpc-0.5.0.0" "old-locale-1.0.0.0" "old-time-1.0.0.0" + "packedstring-0.1.0.0" "pretty-1.0.0.0" "process-1.0.0.0" "random-1.0.0.0" + "readline-1.0.1.0" "rts-1.0" "unix-2.3.0.0" "base-3.0.1.0" + ] ++ map ( a : __getAttr a (ghc68_extra_libs ghcsAndLibs.ghc68 ) ) [ + "mtl-1.1.0.0" + ]; # (flatten ghcsAndLibs.ghc68.core_libs); inherit ghc; }; diff --git a/pkgs/top-level/builder-defs.nix b/pkgs/top-level/builder-defs.nix index a2b132ee365..9e35a36b2ef 100644 --- a/pkgs/top-level/builder-defs.nix +++ b/pkgs/top-level/builder-defs.nix @@ -1,3 +1,39 @@ +# see dep-strings.nix as well +/* +questions: + + add some comments? + + why is prefix used in doConfigure ? shouldn't that be out? + + don't think toSrcDir should cd to the directory. + I'd prefer cd `toSrcDir xx.tar.gz` + Then you can use it to unpack files + + suggestion: + deps before text? why? + It's kind of documentation and much less lines most of the time ? + + remove noDepEntry, FullDepEntry, PackEntry all together and use { ... } ? + you only have to remember two words: text and deps which isn't hard + using noDepEntry FullDepEntry PackEntry you'll have to remember 3 words and argument order + You just have to learn it once.. ? + + no way to override steps ? + + separate settings from dep entries + (eg patchFlags / forceShare, patches) to get a better overview ? ) + + envAdderInner: What about a small example? It took quite some time to understand how to use it + eg envAdderInner "" "A" "B" "C" "D" null results in + echo export A="$A:B"; + echo export C="$C:D"; + does'nt handle the env has been empty don't add delimiter case + + +*/ + + args: with args; with stringsWithDeps; with lib; (rec { @@ -18,6 +54,7 @@ args: with args; with stringsWithDeps; with lib; # Last block - for single files!! It should be always after .tar.* else if (hasSuffixHack ".bz2" s) then "plain-bz2" + else if (hasSuffixHack ".zip" s) || (hasSuffixHack ".ZIP" s) then "zip" else (abort "unknown archive type : ${s}")); defAddToSearchPath = FullDepEntry (" @@ -40,7 +77,7 @@ args: with args; with stringsWithDeps; with lib; { addToSearchPathWithCustomDelimiter \"\${PATH_DELIMITER}\" \"\$@\" } - ") ["defNest"]; + ") [defNest]; defNest = noDepEntry (" nestingLevel=0 @@ -95,7 +132,7 @@ args: with args; with stringsWithDeps; with lib; prefix=${if args ? prefix then (toString args.prefix) else "\$out"} " - else "")) ["defNest" "defAddToSearchPath"]; + else "")) [defNest defAddToSearchPath]; addInputs = FullDepEntry (" # Recursively find all build inputs. @@ -115,6 +152,12 @@ args: with args; with stringsWithDeps; with lib; if test -f \$pkg/nix-support/setup-hook; then source \$pkg/nix-support/setup-hook fi + + if test -f \$pkg/nix-support/propagated-build-inputs; then + for i in \$(cat \$pkg/nix-support/propagated-build-inputs); do + findInputs \$i + done + fi } pkgs=\"\" @@ -161,7 +204,7 @@ args: with args; with stringsWithDeps; with lib; fi PATH=\$_PATH\${_PATH:+:}\$PATH - ") ["minInit"]; + ") [minInit]; defEnsureDir = FullDepEntry (" # Ensure that the given directories exists. @@ -171,7 +214,7 @@ args: with args; with stringsWithDeps; with lib; if ! test -x \"\$dir\"; then mkdir -p \"\$dir\"; fi done } - ") ["minInit"]; + ") [minInit]; toSrcDir = s : FullDepEntry ((if (archiveType s) == "tar" then " tar xvf '${s}' @@ -200,11 +243,11 @@ args: with args; with stringsWithDeps; with lib; cd \$(basename ${s} .bz2) " else (abort "unknown archive type : ${s}"))+ (if args ? goSrcDir then args.goSrcDir else "") - ) ["minInit"]; + ) [minInit]; doConfigure = FullDepEntry (" ./configure --prefix=\"\$prefix\" ${toString configureFlags} - ") ["minInit" "addInputs" "doUnpack"]; + ") [minInit addInputs doUnpack]; doAutotools = FullDepEntry (" mkdir -p config @@ -214,21 +257,21 @@ args: with args; with stringsWithDeps; with lib; autoheader || true; automake --add-missing --copy autoconf - ")["minInit" "addInputs" "doUnpack"]; + ")[minInit addInputs doUnpack]; doMake = FullDepEntry (" make ${toString makeFlags} - ") ["minInit" "addInputs" "doUnpack"]; + ") [minInit addInputs doUnpack]; doUnpack = toSrcDir (toString src); installPythonPackage = FullDepEntry (" python setup.py install --prefix=\"\$prefix\" - ") ["minInit" "addInputs" "doUnpack"]; + ") [minInit addInputs doUnpack]; doMakeInstall = FullDepEntry (" make ${toString (getAttr ["makeFlags"] "" args)} "+ - "${toString (getAttr ["installFlags"] "" args)} install") ["doMake"]; + "${toString (getAttr ["installFlags"] "" args)} install") [doMake]; doForceShare = FullDepEntry (" ensureDir \"\$prefix/share\" @@ -238,7 +281,7 @@ args: with args; with stringsWithDeps; with lib; ln -sv share/\$d \"\$prefix\" fi; done; - ") ["minInit" "defEnsureDir"]; + ") [minInit defEnsureDir]; doDump = n: noDepEntry "echo Dump number ${n}; set"; @@ -250,7 +293,7 @@ args: with args; with stringsWithDeps; with lib; doPatch = FullDepEntry (concatStringsSep ";" (map toPatchCommand patches) - ) ["minInit" "doUnpack"]; + ) [minInit doUnpack]; envAdderInner = s: x: if x==null then s else y: a: envAdderInner (s+"echo export ${x}='\"'\"\$${x}:${y}\";'\"'\n") a; @@ -268,12 +311,12 @@ args: with args; with stringsWithDeps; with lib; (${envAdderList env} echo '\"'\"${cmd}-orig\"'\"' '\"'\\\$@'\"' \n) > \"${cmd}\""; - doWrap = cmd: FullDepEntry (wrapEnv cmd (getAttr ["wrappedEnv"] [] args)) ["minInit"]; + doWrap = cmd: FullDepEntry (wrapEnv cmd (getAttr ["wrappedEnv"] [] args)) [minInit]; doPropagate = FullDepEntry (" ensureDir \$out/nix-support echo '${toString (getAttr ["propagatedBuildInputs"] [] args)}' >\$out/nix-support/propagated-build-inputs - ") ["minInit" "defEnsureDir"]; + ") [minInit defEnsureDir]; /*debug = x:(__trace x x); debugX = x:(__trace (__toXML x) x);*/ @@ -283,7 +326,7 @@ args: with args; with stringsWithDeps; with lib; replaceScripts = l:(concatStringsSep "\n" (pairMap replaceInScript l)); doReplaceScripts = FullDepEntry (replaceScripts (getAttr ["shellReplacements"] [] args)) [minInit]; makeNest = x:(if x==defNest.text then x else "startNest\n" + x + "\nstopNest\n"); - textClosure = textClosureMapOveridable makeNest; + textClosure = textClosureMap makeNest; inherit noDepEntry FullDepEntry PackEntry; @@ -317,4 +360,68 @@ args: with args; with stringsWithDeps; with lib; surroundWithCommands = x : before : after : {deps=x.deps; text = before + "\n" + x.text + "\n" + after ;}; + + # some haskell stuff - untested! + # -------------------------------------------------------- + # creates a setup hook + # adding the package database + # nix-support/package.conf to GHC_PACKAGE_PATH + # if not already contained + # using nix-support because user does'nt want to have it in it's + # nix-profile I think? + defSetupHookRegisteringPackageDatabase = noDepEntry ( + "\nsetupHookRegisteringPackageDatabase(){" + + "\n ensureDir $out/nix-support;" + + "\n if test -n \"$1\"; then" + + "\n local pkgdb=$1" + + "\n else" + + "\n local pkgdb=$out/nix-support/package.conf" + + "\n fi" + + "\n cat >> $out/nix-support/setup-hook << EOF" + + "\n " + + "\n echo \$GHC_PACKAGE_PATH | grep -l $pkgdb &> /dev/null || \" "+ + "\n export GHC_PACKAGE_PATH=\$GHC_PACKAGE_PATH\${GHC_PACKAGE_PATH:+$PATH_DELIMITER}$pkgdb;" + + "\nEOF" + + "\n}"); + + # Either rungghc or compile setup.hs + # / which one is better ? runghc had some trouble with ghc-6.6.1 + defineCabalSetupCmd = noDepEntry " + CABAL_SETUP=\"runghc setup.hs\" + "; + + # create an empty package database in which the new library can be registered. + defCreateEmptyPackageDatabaseAndSetupHook = FullDepEntry " + createEmptyPackageDatabaseAndSetupHook(){ + ensureDir $out/nix-support; + PACKAGE_DB=$out/nix-support/package.conf; + echo '[]' > \"$PACKAGE_DB\"; + setupHookRegisteringPackageDatabase + }" [defSetupHookRegisteringPackageDatabase]; + + # Cabal does only support --user ($HOME/.ghc/** ) and --global (/nix/store/*-ghc/lib/...) + # But we need kind of --custom=my-package-db + # by accident cabal does support using multiple databases passed by GHC_PACKAGE_PATH + # + # Options: + # 1) create a local package db containing all dependencies + # 2) create a single db file for each package merging them using GHC_PACKAGE_PATH=db1:db2 + # (no trailing : which would mean add global and user db) + # I prefer 2) (Marc Weber) so the most convinient way is + # using ./setup copy to install + # and ./setup register --gen-script to install to our local database + # after replacing /usr/lib etc with our pure $out path + defCabalBuild = FullDepEntry + (if (args ? subdir) then "cd ${args.subdir}" else "")+ " + createEmptyPackageDatabaseAndSetupHook + ghc --make setup.hs -o setup + \$CABAL_SETUP configure + \$CABAL_SETUP build + \$CABAL_SETUP copy --dest-dir=\$out + \$CABAL_SETUP register --gen-script + sed -e 's=/usr/local/lib=\$out=g' \\ + -i register.sh + GHC_PACKAGE_PATH=\$PACKAGE_DB ./register.sh + " [defCreateEmptyPackageDatabaseAndSetupHook defineCabalSetupCmd]; + }) // args