diff --git a/pkgs/development/compilers/ghc/createGhcWrapper/default.nix b/pkgs/development/compilers/ghc/createGhcWrapper/default.nix new file mode 100644 index 000000000000..5eeb4d431908 --- /dev/null +++ b/pkgs/development/compilers/ghc/createGhcWrapper/default.nix @@ -0,0 +1,25 @@ +args: with args; + +stdenv.mkDerivation { + inherit suffix name ghc ; + + buildInputs = libraries ++ [ghcPkgUtil]; + + phases="installPhase"; + + installPhase=" + ensureDir \$out/bin + if test -n \"\$ghcPackagedLibs\"; then + g=:\$(echo \$ghc/lib/ghc-*/package.conf) + fi + + for a in ghc ghci ghc-pkg; do + app=$(ls -al $ghc/bin/$a | sed -n 's%.*-> \\(.*\\)%\\1%p'); +cat > \"\$out/bin/\$a$suffix\" << EOF +#!`type -f sh | gawk '{ print $3; }'` +GHC_PACKAGE_PATH=\${GHC_PACKAGE_PATH}\${g} \$ghc/bin/$app \"\\\$@\" +EOF + chmod +x \"\$out/bin/\$a$suffix\" + done +"; +} diff --git a/pkgs/development/compilers/ghcs/default.nix b/pkgs/development/compilers/ghcs/default.nix new file mode 100644 index 000000000000..c3a46968880d --- /dev/null +++ b/pkgs/development/compilers/ghcs/default.nix @@ -0,0 +1,168 @@ +{ ghcPkgUtil, gnum4, perl, ghcboot, stdenv, fetchurl, recurseIntoAttrs, gmp, readline, lib } : rec { + + /* What's in here? + Goal: really pure GHC. This means put every library into its each package.conf + and add all together using GHC_PACKAGE_PATH + + First I've tried separating the build of ghc from it's lib. It hase been to painful. I've failed. + Now there is splitpackagedb.hs which just takes the installed package.conf + and creates a new package db file for each contained package. + + The final attribute set looks similar to this: + ghc, core_libs and extra_libraries will then be used to build all the ohter packages availible on hackege.. + (There is much left to be done) + + ghcAndLibraries = { + ghc68 = { + ghc = { + src = "The compiler source" + extra_src = "source of extra libraries" + version = "GHC version as string" + } + + core_libs = [ libs distributed the ghc core (see libraries/core-packages ]; + extra_libraries = [ libraries contained extra_src ]; + }; + + ghc66 = { + roughly the same + }; + } + + */ + + # creates a nix package out of the single package.conf files created when after installing ghc (see splitpackagedb.hs) + packageByPackageDB = otherPkg : name : packageconfpath : propagatedBuildInputs : stdenv.mkDerivation { + inherit name otherPkg propagatedBuildInputs; + phases = "buildPhase fixupPhase"; + buildInputs = [ghcPkgUtil]; + buildPhase = "setupHookRegisteringPackageDatabase \"$otherPkg/${packageconfpath}\" + "; + }; + + # used to automatically get dependencies ( used for core_libs ) + # TODO use kind of state and evaluate deps of a dep only once + resolveDeps = ghc : libs : + let attrs = __listToAttrs libs; in + rec { + # using undocumented feature that attribute can contain hyphens when using listToAttrs + # You should be able to get the attribute values using __getAttr + result = __listToAttrs (map ( l : lib.av l.name ( + packageByPackageDB ghc l.name + ("lib/ghc-${ghc.version}/${l.name}.conf") + (map (n: __getAttr n result) l.deps) + ) ) libs ); + }.result; + + + + #this only works for ghc-6.8 right now + ghcAndLibraries = { version, src /* , core_libraries, extra_libraries */ + , extra_src }: + recurseIntoAttrs ( rec { + inherit src extra_src version; + + ghc = stdenv.mkDerivation { + name = "ghc-"+version; + inherit src ghcboot gmp version; + + buildInputs = [readline perl gnum4 gmp]; + + preConfigure = " + chmod u+x rts/gmp/configure + # still requires a hack for ncurses + sed -i \"s|^\(library-dirs.*$\)|\1 \\\"$ncurses/lib\\\"|\" libraries/readline/package.conf.in + "; + + splitpackagedb = ./splitpackagedb.hs; + + configurePhase = "./configure" + +" --prefix=\$out " + +" --with-ghc=\$ghcboot/bin/ghc" + +" --with-gmp-libraries=$gmp/lib" + +" --with-readline-libraries=\"$readline/lib\""; + + # now read the main package.conf and create a single package db file for each of them + # Also create setup hook. + + # note : I don't know yet wether it's a good idea to have RUNGHC.. It's faster + # but you can't pass packages, can you? + postInstall = " + cp \$splitpackagedb splitpackagedb.hs + \$out/bin/ghc-\$version --make -o splitpackagedb splitpackagedb.hs; + ./splitpackagedb \$out/lib/ghc-\$version/package.conf \$out/lib/ghc-\$version + + if test -x \$out/bin/runghc; then + RUNHGHC=\$out/bin/runghc # > ghc-6.7/8 ? + else + RUNHGHC=\$out/bin/runhaskell # ghc-6.6 and prior + fi + + ensureDir \$out/nix-support + sh=\$out/nix-support/setup-hook + echo \"RUNHGHC=\$RUNHGHC\" >> \$sh + + "; + }; + + # 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" ];} + ]; + + + + extra_libs = []; + + #all_libs = core_libs ++ extra_libs; + + } ); + + ghc68 = ghcAndLibraries { + version = "6.8.0.20071004"; + 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.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-6.8.20070912-src-extralibs.tar.bz2; + #sha256 = "0py7d9nh3lkhjxr3yb3n9345d0hmzq79bi40al5rcr3sb84rnp9r"; + }; + + # this will change because of dependency hell :) + #core_libraries = [ "Cabal" /* "Win32" */ "array" "base" "bytestring" "containers" + #"directory" "doc" "filepath" "haskell98" "hpc" "old-locale" "old-time" + #"packedstring" "pretty" "process" "random" "readline" "stamp" + #"template-haskell" "unix" ]; + + #extra_libraries = [ "ALUT" "GLUT" "HGL" "HUnit" "ObjectIO" "OpenAL" "OpenGL" "QuickCheck" "X11" + #"arrows" "cgi" "fgl" "haskell-src" "html" "mtl" "network" "parallel" "parsec" + #"regex-base" "regex-compat" "regex-posix" "stm" "time" "xhtm" ]; + + }; +} + diff --git a/pkgs/development/compilers/ghcs/splitpackagedb.hs b/pkgs/development/compilers/ghcs/splitpackagedb.hs new file mode 100644 index 000000000000..0f7ceb0d4019 --- /dev/null +++ b/pkgs/development/compilers/ghcs/splitpackagedb.hs @@ -0,0 +1,25 @@ +{-# OPTIONS_GHC -fglasgow-exts #-} +module Main where +import Distribution.InstalledPackageInfo (InstalledPackageInfo (..)) +import Distribution.Package (showPackageId) +import System.FilePath +import System.Environment + +usage = unlines [ + " in outDir" + , "reads package db appname" + , "and creates a package database for each contained package in outDir" + , "" + , "The purpose is to be able to control availible packages to ensure purity in nix." + , "Separating each package from the auomated ghc build process is to painful (for me)" + ] + +main = do + args <- getArgs + case args of + [inFile, outDir] -> do + (packagedb :: [InstalledPackageInfo] ) <- fmap read $ readFile inFile + mapM_ (\pi -> let fn = outDir (showPackageId $ package pi) ++ ".conf" + in writeFile fn (show [pi]) + ) packagedb + _ -> putStrLn usage diff --git a/pkgs/development/libraries/haskell/generic/ghcPkgUtil.sh b/pkgs/development/libraries/haskell/generic/ghcPkgUtil.sh index e265195b321f..5760372888ec 100644 --- a/pkgs/development/libraries/haskell/generic/ghcPkgUtil.sh +++ b/pkgs/development/libraries/haskell/generic/ghcPkgUtil.sh @@ -16,7 +16,11 @@ # if not already contained setupHookRegisteringPackageDatabase(){ ensureDir $out/nix-support; - local pkgdb=$out/nix-support/package.conf + if test -n "$1"; then + local pkgdb=$1 + else + local pkgdb=$out/nix-support/package.conf + fi cat >> $out/nix-support/setup-hook << EOF echo \$GHC_PACKAGE_PATH | grep -l $pkgdb &> /dev/null || \ @@ -28,6 +32,6 @@ EOF createEmptyPackageDatabaseAndSetupHook(){ ensureDir $out/nix-support; PACKAGE_DB=$out/nix-support/package.conf; - echo '[]' > $PACKAGE_DB"; + echo '[]' > "$PACKAGE_DB"; setupHookRegisteringPackageDatabase } diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index c586475cc054..853c917524bf 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -240,6 +240,7 @@ rec { } else defaultStdenv; + stdenvUsingSetupNew2 = overrideSetup stdenv ../stdenv/generic/setup-new-2.sh; ### BUILD SUPPORT @@ -926,6 +927,49 @@ rec { profiledCompiler = true; }); + # This new ghc stuff is under heavy development and might change ! + + # usage: see ghcPkgUtil.sh - use setup-new2 because of PATH_DELIMITER + ghcPkgUtil = runCommand "ghcPkgUtil-internal" + { ghcPkgUtil = ../development/libraries/haskell/generic/ghcPkgUtil.sh; } + "mkdir -p $out/nix-support; cp $ghcPkgUtil \$out/nix-support/setup-hook;"; + + ghcsAndLibs = recurseIntoAttrs (import ../development/compilers/ghcs { + inherit ghcboot fetchurl recurseIntoAttrs perl gnum4 gmp readline; + inherit ghcPkgUtil; + stdenv = stdenvUsingSetupNew2; + lib = lib_unstable; + }); + + # creates ghc-X-wl wich adds the passed libraries to the env var GHC_PACKAGE_PATH + createGhcWrapper = { ghcPackagedLibs ? false, ghc, libraries, name, suffix ? "ghc_wrapper_${ghc.name}" } : + import ../development/compilers/ghc/createGhcWrapper { + inherit ghcPackagedLibs ghc name suffix libraries ghcPkgUtil; + stdenv = stdenvUsingSetupNew2; + }; + + # 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 + ghcLibraryWrapper68 = + 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" + ]; + # (flatten ghcsAndLibs.ghc68.core_libs); + inherit ghc; + }; + # ghc66boot = import ../development/compilers/ghc-6.6-boot { # inherit fetchurl stdenv perl readline; # m4 = gnum4; @@ -2322,11 +2366,6 @@ rec { ### DEVELOPMENT / LIBRARIES / HASKELL - # usage: see ghcPkgUtil.sh - use setup-new2 because of PATH_DELIMITER - ghcPkgUtil = runCommand "ghcPkgUtil-internal" - { ghcPkgUtil = ../development/libraries/haskell/generic/ghcPkgUtil.sh; } - "mkdir -p $out/nix-support; cp $ghcPkgUtil \$out/nix-support/setup-hook;"; - uulib64 = import ../development/libraries/haskell/uulib { # !!! remove? inherit stdenv fetchurl ghc;