Commit 360d7404 authored by Ben Gamari's avatar Ben Gamari 🐢

Squashed 'hadrian/' changes from fa3771fe..4499b294

4499b294 Follow GHC changes
8fd68186 Add ways to build hadrian using nix
e5c7a29c Do not depend on the in-tree filepath library
9dd7ad2a Fix dependencies
49718439 Bring mtl dependency back
6c5f5c9b Minor clean up of Hadrian dependencies
9aff81d4 Fix Windows build
fa95caa8 Unbreak `cabal new-build`

git-subtree-dir: hadrian
git-subtree-split: 4499b294
parent c1fcd9b3
......@@ -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].
......
#!/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/.." \
"$@"
packages: ./
../libraries/Cabal/Cabal/
../libraries/filepath/
../libraries/text/
../libraries/hpc/
../libraries/parsec/
../libraries/text/
......@@ -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
......
# 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 ];
}
......@@ -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
......
......@@ -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))
......
......@@ -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)
......
......@@ -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]
......
......@@ -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"]
......
......@@ -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]
......
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment