summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md4
-rwxr-xr-xbuild.nix.sh35
-rw-r--r--cabal.project3
-rw-r--r--hadrian.cabal10
-rw-r--r--shell.nix61
-rw-r--r--src/Rules/Compile.hs2
-rw-r--r--src/Rules/Dependencies.hs4
-rw-r--r--src/Rules/Program.hs3
-rw-r--r--src/Settings/Builders/Ghc.hs8
-rw-r--r--src/Settings/Packages/GhcCabal.hs5
-rw-r--r--src/Utilities.hs30
-rw-r--r--stack.yaml7
12 files changed, 135 insertions, 37 deletions
diff --git a/README.md b/README.md
index 916edc21a1..d188a4a054 100644
--- a/README.md
+++ b/README.md
@@ -41,8 +41,8 @@ Notes:
on Cabal sandboxes (`build.cabal.*`), Stack (`build.stack.*`) or the global package database
(`build.global-db.*`). Also see [instructions for building GHC on Windows using Stack][windows-build].
-* Hadrian is written in Haskell and depends on the following packages:
-`ansi-terminal extra mtl quickcheck shake`.
+* Hadrian is written in Haskell and depends on `shake` (plus a few packages that `shake` depends on),
+`ansi-terminal`, `mtl`, `quickcheck`, and GHC core libraries.
* If you have never built GHC before, start with the [preparation guide][ghc-preparation].
diff --git a/build.nix.sh b/build.nix.sh
new file mode 100755
index 0000000000..4b03ea8418
--- /dev/null
+++ b/build.nix.sh
@@ -0,0 +1,35 @@
+#!/usr/bin/env nix-shell
+#! nix-shell -i bash shell.nix
+
+# This script sets up the build environment by invoking nix-shell shell.nix
+# and then runs the hadrian executable.
+
+function rl {
+ TARGET_FILE="$1"
+
+ cd "$(dirname "$TARGET_FILE")"
+ TARGET_FILE="$(basename "$TARGET_FILE")"
+
+ # Iterate down a (possible) chain of symlinks
+ while [ -L "$TARGET_FILE" ]
+ do
+ TARGET_FILE="$(readlink "$TARGET_FILE")"
+ cd "$(dirname "$TARGET_FILE")"
+ TARGET_FILE="$(basename "$TARGET_FILE")"
+ done
+
+ # Compute the canonicalized name by finding the physical path
+ # for the directory we're in and appending the target file.
+ PHYS_DIR="$(pwd -P)"
+ RESULT="$PHYS_DIR/$TARGET_FILE"
+ echo "$RESULT"
+}
+
+absoluteRoot="$(dirname "$(rl "$0")")"
+echo $absoluteRoot
+cd "$absoluteRoot"
+
+hadrian \
+ --lint \
+ --directory="$absoluteRoot/.." \
+ "$@"
diff --git a/cabal.project b/cabal.project
index 317094fb74..0d2b509daa 100644
--- a/cabal.project
+++ b/cabal.project
@@ -1,6 +1,5 @@
packages: ./
../libraries/Cabal/Cabal/
- ../libraries/filepath/
- ../libraries/text/
../libraries/hpc/
../libraries/parsec/
+ ../libraries/text/
diff --git a/hadrian.cabal b/hadrian.cabal
index 389f5530c1..9c170bcd16 100644
--- a/hadrian.cabal
+++ b/hadrian.cabal
@@ -116,17 +116,17 @@ executable hadrian
, TupleSections
other-extensions: MultiParamTypeClasses
, TypeFamilies
- build-depends: base >= 4.8 && < 5
+ build-depends: base >= 4.8 && < 5
, ansi-terminal == 0.6.*
, Cabal >= 2.0.0.2 && < 2.2
, containers == 0.5.*
- , directory >= 1.2 && < 1.4
+ , directory >= 1.2 && < 1.4
, extra >= 1.4.7
, mtl == 2.2.*
- , QuickCheck >= 2.6 && < 2.10
+ , QuickCheck >= 2.6 && < 2.10
, shake == 0.16.*
- , transformers >= 0.4 && < 0.6
- , unordered-containers == 0.2.*
+ , transformers >= 0.4 && < 0.6
+ , unordered-containers >= 0.2.1 && < 0.3
build-tools: alex >= 3.1
, happy >= 1.19.4
ghc-options: -Wall
diff --git a/shell.nix b/shell.nix
new file mode 100644
index 0000000000..e9a5ecc88e
--- /dev/null
+++ b/shell.nix
@@ -0,0 +1,61 @@
+# Invoking nix-shell sets up an environment where we can build ghc
+# by only invoking hadrian.
+
+
+{ nixpkgs ? import <nixpkgs> {} }:
+
+let
+ haskellPackages = nixpkgs.haskell.packages.ghc821;
+
+ removeBuild = path: type:
+ let baseName = baseNameOf (toString path);
+ in
+ ! (baseName == "_build"
+ || baseName == "dist"
+ || baseName == "dist-newstyle"
+ || baseName == ".stack-work"
+ || baseName == "config.log"
+ || baseName == "config.status"
+ || nixpkgs.lib.hasSuffix ".sh" baseName
+ || !(nixpkgs.lib.cleanSourceFilter path type)) ;
+
+ filterSrc = path: builtins.filterSource removeBuild path;
+
+
+ hadrianPackages = nixpkgs.haskell.packages.ghc821.override {
+ overrides = self: super: let
+ localPackage = name: path: self.callCabal2nix name (filterSrc path) {};
+ in {
+ hadrian = localPackage "hadrian" ./. ;
+ shake = self.callHackage "shake" "0.16" {};
+ Cabal = localPackage "Cabal" ./../libraries/Cabal/Cabal ;
+ filepath = localPackage "filepath" ./../libraries/filepath ;
+ text = localPackage "text" ./../libraries/text ;
+ hpc = localPackage"hpc" ./../libraries/hpc ;
+ parsec = localPackage "parsec" ./../libraries/parsec ;
+ HUnit = nixpkgs.haskell.lib.dontCheck (self.callHackage "HUnit" "1.3.1.2" {});
+ process = localPackage "process" ./../libraries/process ;
+ directory = localPackage "directory" ./../libraries/directory ;
+ }; };
+
+in
+
+ nixpkgs.stdenv.mkDerivation {
+ name = "ghc-dev";
+ buildInputs = [
+ hadrianPackages.hadrian
+ nixpkgs.haskell.compiler.ghc821
+ haskellPackages.alex
+ haskellPackages.happy
+ nixpkgs.python3
+ nixpkgs.git
+ nixpkgs.autoconf
+ nixpkgs.automake
+ nixpkgs.perl
+ nixpkgs.gcc
+ nixpkgs.python3Packages.sphinx
+ nixpkgs.ncurses
+ nixpkgs.m4
+ nixpkgs.gmp
+ nixpkgs.file ];
+ }
diff --git a/src/Rules/Compile.hs b/src/Rules/Compile.hs
index a4b1278660..b7f3bc8447 100644
--- a/src/Rules/Compile.hs
+++ b/src/Rules/Compile.hs
@@ -22,8 +22,6 @@ compilePackage rs context@Context {..} = do
path <- buildPath context
(src, deps) <- lookupDependencies (path -/- ".dependencies") obj
need $ src : deps
- when (isLibrary package) $ need =<< return <$> pkgConfFile context
- needLibrary =<< contextDependencies context
buildWithResources rs $ target context (Ghc CompileHs stage) [src] [obj]
priority 2.0 $ do
diff --git a/src/Rules/Dependencies.hs b/src/Rules/Dependencies.hs
index f27ef0d912..f9d17e93d8 100644
--- a/src/Rules/Dependencies.hs
+++ b/src/Rules/Dependencies.hs
@@ -19,11 +19,11 @@ buildPackageDependencies rs context@Context {..} =
orderOnly =<< interpretInContext context generatedDependencies
let mk = deps <.> "mk"
if null srcs
- then writeFileChanged mk ""
+ then writeFile' mk ""
else buildWithResources rs $
target context (Ghc FindHsDependencies stage) srcs [mk]
removeFile $ mk <.> "bak"
- mkDeps <- readFile' mk
+ mkDeps <- liftIO $ readFile mk
writeFileChanged deps . unlines
. map (\(src, deps) -> unwords $ src : deps)
. map (bimap unifyPath (map unifyPath))
diff --git a/src/Rules/Program.hs b/src/Rules/Program.hs
index ba4dab0442..dca177f879 100644
--- a/src/Rules/Program.hs
+++ b/src/Rules/Program.hs
@@ -92,7 +92,6 @@ buildWrapper context@Context {..} wrapper wrapperPath wrapped = do
putSuccess $ "| Successfully created wrapper for " ++
quote (pkgName package) ++ " (" ++ show stage ++ ")."
--- TODO: Get rid of the Paths_hsc2hs.o hack.
buildBinary :: [(Resource, Int)] -> FilePath -> Context -> Action ()
buildBinary rs bin context@Context {..} = do
binDeps <- if stage == Stage0 && package == ghcCabal
@@ -107,8 +106,6 @@ buildBinary rs bin context@Context {..} = do
cObjs <- mapM (objectPath context) cSrcs
hsObjs <- hsObjects context
return $ cObjs ++ hsObjs
- ++ [ path -/- "Paths_hsc2hs.o" | package == hsc2hs ]
- ++ [ path -/- "Paths_haddock.o" | package == haddock ]
need binDeps
buildWithResources rs $ target context (Ghc LinkHs stage) binDeps [bin]
synopsis <- traverse pkgSynopsis (pkgCabalFile package)
diff --git a/src/Settings/Builders/Ghc.hs b/src/Settings/Builders/Ghc.hs
index a975e7e799..af78b74637 100644
--- a/src/Settings/Builders/Ghc.hs
+++ b/src/Settings/Builders/Ghc.hs
@@ -87,10 +87,10 @@ haddockGhcArgs = mconcat [ commonGhcArgs, getPkgDataList HsArgs ]
-- Used in ghcBuilderArgs, ghcCBuilderArgs, ghcMBuilderArgs and haddockGhcArgs.
commonGhcArgs :: Args
commonGhcArgs = do
- way <- getWay
- path <- getBuildPath
- pkg <- getPackage
- when (isLibrary pkg) $ do
+ way <- getWay
+ path <- getBuildPath
+ pkg <- getPackage
+ when (pkg == rts) $ do
context <- getContext
conf <- expr $ pkgConfFile context
expr $ need [conf]
diff --git a/src/Settings/Packages/GhcCabal.hs b/src/Settings/Packages/GhcCabal.hs
index 0e915b3ea6..c88617b97f 100644
--- a/src/Settings/Packages/GhcCabal.hs
+++ b/src/Settings/Packages/GhcCabal.hs
@@ -8,10 +8,11 @@ import Utilities
ghcCabalPackageArgs :: Args
ghcCabalPackageArgs = stage0 ? package ghcCabal ? builder Ghc ? do
- cabalDeps <- expr $ stage1Dependencies cabal
+ cabalDeps <- expr $ stage1Dependencies cabal
+ let bootDeps = cabalDeps \\ [integerGmp, integerSimple, mtl, parsec, text]
cabalVersion <- expr $ pkgVersion (unsafePkgCabalFile cabal) -- TODO: improve
mconcat
- [ pure [ "-package " ++ pkgName pkg | pkg <- cabalDeps \\ [parsec, mtl] ]
+ [ pure [ "-package " ++ pkgName pkg | pkg <- bootDeps ]
, arg "--make"
, arg "-j"
, pure ["-Wall", "-fno-warn-unused-imports", "-fno-warn-warnings-deprecations"]
diff --git a/src/Utilities.hs b/src/Utilities.hs
index 3c61daecfd..fc898c35b9 100644
--- a/src/Utilities.hs
+++ b/src/Utilities.hs
@@ -24,21 +24,29 @@ buildWithResources rs target = H.buildWithResources rs target getArgs
buildWithCmdOptions :: [CmdOption] -> Target -> Action ()
buildWithCmdOptions opts target = H.buildWithCmdOptions opts target getArgs
--- | Given a 'Context' this 'Action' look up the package dependencies and wrap
+-- TODO: Cache the computation.
+-- | Given a 'Context' this 'Action' looks up the package dependencies and wraps
-- the results in appropriate contexts. The only subtlety here is that we never
-- depend on packages built in 'Stage2' or later, therefore the stage of the
-- resulting dependencies is bounded from above at 'Stage1'. To compute package
--- dependencies we scan package @.cabal@ files, see 'pkgDependencies' defined
--- in "Hadrian.Haskell.Cabal".
+-- dependencies we transitively scan @.cabal@ files using 'pkgDependencies'
+-- defined in "Hadrian.Haskell.Cabal".
contextDependencies :: Context -> Action [Context]
-contextDependencies Context {..} = case pkgCabalFile package of
- Nothing -> return [] -- Non-Cabal packages have no dependencies.
- Just cabalFile -> do
- let depStage = min stage Stage1
- depContext = \pkg -> Context depStage pkg way
- deps <- pkgDependencies cabalFile
- pkgs <- sort <$> stagePackages depStage
- return . map depContext $ intersectOrd (compare . pkgName) pkgs deps
+contextDependencies Context {..} = do
+ depPkgs <- go [package]
+ return [ Context depStage pkg way | pkg <- depPkgs, pkg /= package ]
+ where
+ depStage = min stage Stage1
+ go pkgs = do
+ deps <- concatMapM step pkgs
+ let newPkgs = nubOrd $ sort (deps ++ pkgs)
+ if pkgs == newPkgs then return pkgs else go newPkgs
+ step pkg = case pkgCabalFile pkg of
+ Nothing -> return [] -- Non-Cabal packages have no dependencies.
+ Just cabalFile -> do
+ deps <- pkgDependencies cabalFile
+ active <- sort <$> stagePackages depStage
+ return $ intersectOrd (compare . pkgName) active deps
-- | Lookup dependencies of a 'Package' in the vanilla Stage1 context.
stage1Dependencies :: Package -> Action [Package]
diff --git a/stack.yaml b/stack.yaml
index a1b7413474..1d3f6e3b38 100644
--- a/stack.yaml
+++ b/stack.yaml
@@ -7,10 +7,9 @@ resolver: lts-9.0
packages:
- '.'
- '../libraries/Cabal/Cabal'
-- '../libraries/filepath/'
-- '../libraries/text/'
-- '../libraries/hpc/'
-- '../libraries/parsec/'
+- '../libraries/hpc'
+- '../libraries/parsec'
+- '../libraries/text'
extra-deps:
- shake-0.16