Build against GHC 7.10.3 (#621)

... as requested by @jneira so that Dhall will continue to work as a
dependency of Eta, which is built using GHC 7.10.3

This adds CI support for testing the build against GHC 7.10.3 and also
fixes issues building against that GHC version that were caught in the process
This commit is contained in:
Gabriel Gonzalez 2018-10-05 20:51:18 -07:00 committed by GitHub
parent fedfa8e41e
commit f3a372c99a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 291 additions and 93 deletions

View File

@ -1,3 +1,4 @@
{-# LANGUAGE CPP #-}
{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE OverloadedStrings #-}
module Main where module Main where
@ -5,6 +6,7 @@ module Main where
import Control.Monad (forM) import Control.Monad (forM)
import Criterion.Main (defaultMain, bgroup, bench, whnf, nfIO) import Criterion.Main (defaultMain, bgroup, bench, whnf, nfIO)
import Data.Map (Map, foldrWithKey, singleton, unions) import Data.Map (Map, foldrWithKey, singleton, unions)
import Data.Monoid ((<>))
import System.Directory import System.Directory
@ -16,6 +18,23 @@ import qualified Data.Text.IO as TIO
import qualified Dhall.Binary import qualified Dhall.Binary
import qualified Dhall.Parser as Dhall import qualified Dhall.Parser as Dhall
#if MIN_VERSION_directory(1,2,3)
#else
import Control.Exception (bracket)
withCurrentDirectory :: FilePath -- ^ Directory to execute in
-> IO a -- ^ Action to be executed
-> IO a
withCurrentDirectory dir action =
bracket getCurrentDirectory setCurrentDirectory $ \ _ -> do
setCurrentDirectory dir
action
listDirectory :: FilePath -> IO [FilePath]
listDirectory path = filter f <$> getDirectoryContents path
where f filename = filename /= "." && filename /= ".."
#endif
type PreludeFiles = Map FilePath T.Text type PreludeFiles = Map FilePath T.Text
loadPreludeFiles :: IO PreludeFiles loadPreludeFiles :: IO PreludeFiles

View File

@ -1,3 +1,5 @@
{ compiler ? "ghc843" }:
let let
fetchNixpkgs = import ./nix/fetchNixpkgs.nix; fetchNixpkgs = import ./nix/fetchNixpkgs.nix;
@ -20,56 +22,71 @@ let
in in
pkgsNew.callPackage (import ./nix/dhall-sdist.nix src) { }; pkgsNew.callPackage (import ./nix/dhall-sdist.nix src) { };
haskellPackages = pkgsOld.haskellPackages.override (old: { haskell = pkgsOld.haskell // {
overrides = packages = pkgsOld.haskell.packages // {
let "${compiler}" = pkgsOld.haskell.packages."${compiler}".override (old: {
extension = overrides =
haskellPackagesNew: haskellPackagesOld: { let
dhall = failOnAllWarnings = drv:
pkgsNew.haskell.lib.overrideCabal # GHC 7.10.3 incorrectly detects non-exhaustive pattern
(pkgsNew.haskell.lib.doCoverage # matches
(pkgsNew.haskell.lib.failOnAllWarnings if compiler == "ghc7103"
(haskellPackagesNew.callCabal2nix then drv
"dhall" else pkgsNew.haskell.lib.failOnAllWarnings drv;
pkgsNew.dhall-sdist
{ } extension =
haskellPackagesNew: haskellPackagesOld: {
dhall =
pkgsNew.haskell.lib.overrideCabal
(pkgsNew.haskell.lib.doCoverage
(failOnAllWarnings
(haskellPackagesNew.callCabal2nix
"dhall"
pkgsNew.dhall-sdist
{ }
)
)
) )
) (old: {
) postInstall = (old.postInstall or "") + ''
(old: { ${pkgsNew.coreutils}/bin/mkdir --parents $out/nix-support
postInstall = (old.postInstall or "") + '' ${pkgsNew.coreutils}/bin/ln --symbolic $out/share/hpc/vanilla/html/dhall-* "$out/share/hpc/vanilla/html/dhall"
${pkgsNew.coreutils}/bin/mkdir --parents $out/nix-support ${pkgsNew.coreutils}/bin/echo "report coverage $out/share/hpc/vanilla/html/dhall/hpc_index.html" >> $out/nix-support/hydra-build-products
${pkgsNew.coreutils}/bin/ln --symbolic $out/share/hpc/vanilla/html/dhall-* "$out/share/hpc/vanilla/html/dhall" '';
${pkgsNew.coreutils}/bin/echo "report coverage $out/share/hpc/vanilla/html/dhall/hpc_index.html" >> $out/nix-support/hydra-build-products }
''; );
}
);
prettyprinter = # https://github.com/well-typed/cborg/issues/172
pkgsNew.haskell.lib.dontCheck haskellPackagesOld.prettyprinter; serialise =
pkgsNew.haskell.lib.dontCheck
haskellPackagesOld.serialise;
serialise = prettyprinter =
pkgsNew.haskell.lib.dontCheck haskellPackagesOld.serialise; pkgsNew.haskell.lib.dontCheck
}; haskellPackagesOld.prettyprinter;
};
in in
pkgsNew.lib.fold pkgsNew.lib.fold
pkgsNew.lib.composeExtensions pkgsNew.lib.composeExtensions
(old.overrides or (_: _: {})) (old.overrides or (_: _: {}))
[ (pkgsNew.haskell.lib.packagesFromDirectory { directory = ./nix; }) [ (pkgsNew.haskell.lib.packagesFromDirectory { directory = ./nix; })
extension extension
]; ];
} }
); );
};
};
}; };
overlayDynamic = pkgsNew: pkgsOld: { overlayCabal2nix = pkgsNew: pkgsOld: {
haskellPackages = pkgsOld.haskellPackages.override (old: { haskellPackages = pkgsOld.haskellPackages.override (old: {
overrides = overrides =
let let
extension = extension =
haskellPackagesNew: haskellPackagesOld: { haskellPackagesNew: haskellPackagesOld: {
# `cabal2nix` requires a newer version of `hpack`
hpack = hpack =
haskellPackagesOld.hpack_0_29_6; haskellPackagesOld.hpack_0_29_6;
}; };
@ -82,6 +99,79 @@ let
); );
}; };
overlayGHC7103 = pkgsNew: pkgsOld: {
haskell = pkgsOld.haskell // {
packages = pkgsOld.haskell.packages // {
"${compiler}" = pkgsOld.haskell.packages."${compiler}".override (old: {
overrides =
let
extension =
haskellPackagesNew: haskellPackagesOld: {
# Most of these fixes are due to certain dependencies being
# hidden behind a conditional compiler version directive, so
# they aren't included by default in the default Hackage
# package set (which was generated for `ghc-8.4.3`)
base-compat-batteries =
pkgsNew.haskell.lib.addBuildDepends
haskellPackagesOld.base-compat-batteries
[ haskellPackagesNew.bifunctors
haskellPackagesNew.fail
];
cborg =
pkgsNew.haskell.lib.addBuildDepends
haskellPackagesOld.cborg
[ haskellPackagesNew.fail
haskellPackagesNew.semigroups
];
dhall =
pkgsNew.haskell.lib.addBuildDepends
haskellPackagesOld.dhall
[ haskellPackagesNew.doctest
haskellPackagesNew.mockery
];
megaparsec =
pkgsNew.haskell.lib.addBuildDepend
haskellPackagesOld.megaparsec
haskellPackagesNew.fail;
generic-deriving =
pkgsNew.haskell.lib.dontCheck
haskellPackagesOld.generic-deriving;
prettyprinter =
pkgsNew.haskell.lib.addBuildDepend
haskellPackagesOld.prettyprinter
haskellPackagesNew.semigroups;
transformers-compat =
pkgsNew.haskell.lib.addBuildDepend
haskellPackagesOld.transformers-compat
haskellPackagesNew.generic-deriving;
# For some reason, `Cabal-1.22.5` does not respect the
# `buildable: False` directive for the executable section
# even when configured with `-f -cli`. Fixing this requires
# patching out the executable section of `wcwidth` in order
# to avoid pulling in some extra dependencies which cause a
# a dependency cycle.
wcwidth =
pkgsNew.haskell.lib.appendPatch
haskellPackagesOld.wcwidth ./nix/wcwidth.patch;
};
in
pkgsNew.lib.composeExtensions
(old.overrides or (_: _: {}))
extension;
}
);
};
};
};
nixpkgs = fetchNixpkgs { nixpkgs = fetchNixpkgs {
rev = "1d4de0d552ae9aa66a5b8dee5fb0650a4372d148"; rev = "1d4de0d552ae9aa66a5b8dee5fb0650a4372d148";
@ -92,7 +182,9 @@ let
pkgs = import nixpkgs { pkgs = import nixpkgs {
config = {}; config = {};
overlays = [ overlayShared overlayDynamic ]; overlays =
[ overlayShared overlayCabal2nix ]
++ (if compiler == "ghc7103" then [ overlayGHC7103 ] else []);
}; };
overlayStaticLinux = pkgsNew: pkgsOld: { overlayStaticLinux = pkgsNew: pkgsOld: {
@ -115,12 +207,12 @@ let
useFixedCabal = drv: pkgsNew.haskell.lib.overrideCabal drv (old: { useFixedCabal = drv: pkgsNew.haskell.lib.overrideCabal drv (old: {
setupHaskellDepends = setupHaskellDepends =
(old.setupHaskellDepends or []) ++ [ (old.setupHaskellDepends or []) ++ [
pkgsNew.haskellPackages.Cabal_patched pkgsNew.haskell.packages."${compiler}".Cabal_patched
]; ];
libraryHaskellDepends = libraryHaskellDepends =
(old.libraryHaskellDepends or []) ++ [ (old.libraryHaskellDepends or []) ++ [
pkgsNew.haskellPackages.Cabal_patched pkgsNew.haskell.packages."${compiler}".Cabal_patched
]; ];
} }
); );
@ -140,28 +232,30 @@ let
"--extra-lib-dirs=${pkgsNew.ncurses.override { enableStatic = true; }}/lib" "--extra-lib-dirs=${pkgsNew.ncurses.override { enableStatic = true; }}/lib"
]; ];
}; };
packages = pkgsOld.haskell.packages // {
"${compiler}" = pkgsOld.haskell.packages."${compiler}".override (old: {
overrides =
let
extension =
haskellPackagesNew: haskellPackagesOld: {
Cabal_patched =
haskellPackagesNew.callCabal2nix
"Cabal"
pkgsNew.Cabal_patched_Cabal_subdir
{ };
dhall = pkgsNew.haskell.lib.statify haskellPackagesOld.dhall;
};
in
pkgsNew.lib.composeExtensions
(old.overrides or (_: _: {}))
extension;
}
);
};
}; };
haskellPackages = pkgsOld.haskellPackages.override (old: {
overrides =
let
extension =
haskellPackagesNew: haskellPackagesOld: {
Cabal_patched =
pkgsNew.haskellPackages.callCabal2nix
"Cabal"
pkgsNew.Cabal_patched_Cabal_subdir
{ };
dhall = pkgsNew.haskell.lib.statify haskellPackagesOld.dhall;
};
in
pkgsNew.lib.composeExtensions
(old.overrides or (_: _: {}))
extension;
}
);
}; };
nixpkgsStaticLinux = fetchNixpkgs { nixpkgsStaticLinux = fetchNixpkgs {
@ -190,7 +284,7 @@ in
tarball = tarball =
pkgsStaticLinux.releaseTools.binaryTarball rec { pkgsStaticLinux.releaseTools.binaryTarball rec {
src = pkgsStaticLinux.pkgsMusl.haskellPackages.dhall; src = pkgsStaticLinux.pkgsMusl.haskell.packages."${compiler}".dhall;
installPhase = '' installPhase = ''
releaseName=${src.name} releaseName=${src.name}
@ -198,17 +292,9 @@ in
''; '';
}; };
inherit (pkgs.haskellPackages) dhall; inherit (pkgs.haskell.packages."${compiler}") dhall;
all = pkgs.releaseTools.aggregate inherit (pkgs.releaseTools) aggregate;
{ name = "dhall";
constituents = [ shell = (pkgs.haskell.lib.doBenchmark pkgs.haskell.packages."${compiler}".dhall).env;
dhall
tarball
pwd
];
};
shell = (pkgs.haskell.lib.doBenchmark pkgs.haskellPackages.dhall).env;
} }

View File

@ -179,11 +179,11 @@ Library
contravariant < 1.6 , contravariant < 1.6 ,
cryptonite >= 0.23 && < 1.0 , cryptonite >= 0.23 && < 1.0 ,
Diff >= 0.2 && < 0.4 , Diff >= 0.2 && < 0.4 ,
directory >= 1.2.7.1 && < 1.4 , directory >= 1.2.2.0 && < 1.4 ,
exceptions >= 0.8.3 && < 0.11, exceptions >= 0.8.3 && < 0.11,
filepath >= 1.4 && < 1.5 , filepath >= 1.4 && < 1.5 ,
hashable < 1.3 , hashable < 1.3 ,
haskeline >= 0.7.3.0 && < 0.8 , haskeline >= 0.7.2.1 && < 0.8 ,
insert-ordered-containers >= 0.2.1.0 && < 0.3 , insert-ordered-containers >= 0.2.1.0 && < 0.3 ,
lens-family-core >= 1.0.0 && < 1.3 , lens-family-core >= 1.0.0 && < 1.3 ,
megaparsec >= 7.0.0 && < 7.1 , megaparsec >= 7.0.0 && < 7.1 ,
@ -291,11 +291,16 @@ Test-Suite doctest
GHC-Options: -Wall GHC-Options: -Wall
Build-Depends: Build-Depends:
base , base ,
directory >= 1.2.2.0 && < 1.4 , directory ,
filepath < 1.5 , filepath < 1.5 ,
mockery < 0.4 , mockery < 0.4 ,
doctest >= 0.7.0 && < 0.17 doctest >= 0.7.0 && < 0.17
Default-Language: Haskell2010 Default-Language: Haskell2010
-- `doctest` doesn't work with `MIN_VERSION` macros before GHC 8
--
-- See: https://ghc.haskell.org/trac/ghc/ticket/10970
if impl(ghc < 8.0)
Buildable: False
Benchmark dhall-parser Benchmark dhall-parser
Type: exitcode-stdio-1.0 Type: exitcode-stdio-1.0
@ -307,7 +312,7 @@ Benchmark dhall-parser
containers >= 0.5.0.0 && < 0.7, containers >= 0.5.0.0 && < 0.7,
criterion >= 1.1 && < 1.6, criterion >= 1.1 && < 1.6,
dhall , dhall ,
directory >= 1.2.7.1 && < 1.4, directory ,
serialise , serialise ,
text >= 0.11.1.0 && < 1.3 text >= 0.11.1.0 && < 1.3
Default-Language: Haskell2010 Default-Language: Haskell2010

12
nix/basement.nix Normal file
View File

@ -0,0 +1,12 @@
{ mkDerivation, base, ghc-prim, stdenv }:
mkDerivation {
pname = "basement";
version = "0.0.6";
sha256 = "9ca23b940006d8c6a7bc9c07c4ef1bf5ddb47ce82d384c5f341996e22cb95ff7";
revision = "1";
editedCabalFile = "0jlj6jy1fsh5xc3z1finjxsq838n3v7qz4zv344l37s1w9z8pwlf";
libraryHaskellDepends = [ base ghc-prim ];
homepage = "https://github.com/haskell-foundation/foundation";
description = "Foundation scrap box of array & string";
license = stdenv.lib.licenses.bsd3;
}

12
nix/foundation.nix Normal file
View File

@ -0,0 +1,12 @@
{ mkDerivation, base, basement, gauge, ghc-prim, stdenv }:
mkDerivation {
pname = "foundation";
version = "0.0.19";
sha256 = "b83bd852f1bc2f7a39fe02ce673580483cb3264ce10dd8768ee4dcf49a2b6f14";
libraryHaskellDepends = [ base basement ghc-prim ];
testHaskellDepends = [ base basement ];
benchmarkHaskellDepends = [ base basement gauge ];
homepage = "https://github.com/haskell-foundation/foundation";
description = "Alternative prelude with batteries and no dependencies";
license = stdenv.lib.licenses.bsd3;
}

9
nix/lens-family-core.nix Normal file
View File

@ -0,0 +1,9 @@
{ mkDerivation, base, containers, stdenv, transformers }:
mkDerivation {
pname = "lens-family-core";
version = "1.2.1";
sha256 = "95e3b9876a6cdcc6865bfad22e04af41430c7a9a6bc96e9a25a2a35a841d19a4";
libraryHaskellDepends = [ base containers transformers ];
description = "Haskell 98 Lens Families";
license = stdenv.lib.licenses.bsd3;
}

29
nix/wcwidth.patch Normal file
View File

@ -0,0 +1,29 @@
diff -Naur wcwidth-0.0.2.before/wcwidth.cabal wcwidth-0.0.2.after/wcwidth.cabal
--- wcwidth-0.0.2.before/wcwidth.cabal 2011-04-03 21:19:59.000000000 -0700
+++ wcwidth-0.0.2.after/wcwidth.cabal 2018-10-04 11:34:55.000000000 -0700
@@ -35,25 +35,3 @@
extensions : StandaloneDeriving
ForeignFunctionInterface
OverloadedStrings
-
-
-executable wcwidth-tools
- main-is : WCWidthTableaux.hs
- if flag(cli)
- buildable : True
- else
- buildable : False
- if flag(split-base)
- build-depends : base >= 4 && < 5
- else
- build-depends : base < 4
- build-depends : containers
- , bytestring
- , setlocale >= 0.0.3
- , utf8-string >= 0.3
- , attoparsec >= 0.8.5
- extensions : StandaloneDeriving
- ForeignFunctionInterface
- OverloadedStrings
-
-

View File

@ -1,10 +1,21 @@
let let
default = (import ./default.nix); default_7_10_3 = import ./default.nix { compiler = "ghc7103"; };
default_8_4_3 = import ./default.nix { compiler = "ghc843"; };
in in
{ dhall = default.all; { dhall = default_8_4_3.aggregate
{ name = "dhall";
inherit (default) tarball; constituents = [
default_7_10_3.dhall
default_8_4_3.dhall
default_8_4_3.tarball
default_8_4_3.pwd
];
};
coverage = default.dhall; "coverage" = default_8_4_3.dhall;
inherit (default_8_4_3) tarball;
} }

View File

@ -1 +1 @@
(import ./default.nix).shell (import ./default.nix {}).shell

View File

@ -129,7 +129,6 @@ module Dhall.Import (
import Control.Applicative (Alternative(..)) import Control.Applicative (Alternative(..))
import Codec.CBOR.Term (Term) import Codec.CBOR.Term (Term)
import Control.Applicative (empty)
import Control.Exception (Exception, SomeException, throwIO, toException) import Control.Exception (Exception, SomeException, throwIO, toException)
import Control.Monad (guard) import Control.Monad (guard)
import Control.Monad.Catch (throwM, MonadCatch(catch), catches, Handler(..)) import Control.Monad.Catch (throwM, MonadCatch(catch), catches, Handler(..))
@ -470,7 +469,7 @@ exprFromImport here@(Import {..}) = do
result <- Maybe.runMaybeT $ do result <- Maybe.runMaybeT $ do
Just expectedHash <- return hash Just expectedHash <- return hash
cacheFile <- getCacheFile expectedHash cacheFile <- getCacheFile expectedHash
True <- liftIO (Directory.doesPathExist cacheFile) True <- liftIO (Directory.doesFileExist cacheFile)
bytesStrict <- liftIO (Data.ByteString.readFile cacheFile) bytesStrict <- liftIO (Data.ByteString.readFile cacheFile)
@ -564,7 +563,7 @@ getCacheFile hash = do
liftIO (Directory.setPermissions directory private) liftIO (Directory.setPermissions directory private)
cacheDirectory <- liftIO $ Directory.getXdgDirectory Directory.XdgCache "" cacheDirectory <- getCacheDirectory
assertDirectory cacheDirectory assertDirectory cacheDirectory
@ -576,6 +575,23 @@ getCacheFile hash = do
return cacheFile return cacheFile
getCacheDirectory :: MonadIO io => io FilePath
#if MIN_VERSION_directory(1,2,3)
getCacheDirectory = liftIO (Directory.getXdgDirectory Directory.XdgCache "")
#else
getCacheDirectory = liftIO $ do
maybeXDGCacheHome <- System.Environment.lookupEnv "XDG_CACHE_HOME"
case maybeXDGCacheHome of
Nothing -> do
homeDirectory <- Directory.getHomeDirectory
return (homeDirectory </> ".cache")
Just xdgCacheHome -> do
return xdgCacheHome
#endif
exprFromUncachedImport :: Import -> StateT (Status IO) IO (Expr Src Import) exprFromUncachedImport :: Import -> StateT (Status IO) IO (Expr Src Import)
exprFromUncachedImport (Import {..}) = do exprFromUncachedImport (Import {..}) = do
let ImportHashed {..} = importHashed let ImportHashed {..} = importHashed

View File

@ -1,7 +1,6 @@
{-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeApplications #-}
module Regression where module Regression where
@ -52,7 +51,7 @@ data Foo = Foo Integer Bool | Bar Bool Bool Bool | Baz Integer Integer
unnamedFields :: TestTree unnamedFields :: TestTree
unnamedFields = Test.Tasty.HUnit.testCase "Unnamed Fields" (do unnamedFields = Test.Tasty.HUnit.testCase "Unnamed Fields" (do
let ty = Dhall.auto @Foo let ty = Dhall.auto :: Dhall.Type Foo
Test.Tasty.HUnit.assertEqual "Good type" (Dhall.expected ty) (Dhall.Core.Union ( Test.Tasty.HUnit.assertEqual "Good type" (Dhall.expected ty) (Dhall.Core.Union (
Data.HashMap.Strict.InsOrd.fromList [ Data.HashMap.Strict.InsOrd.fromList [
("Bar",Dhall.Core.Record (Data.HashMap.Strict.InsOrd.fromList [ ("Bar",Dhall.Core.Record (Data.HashMap.Strict.InsOrd.fromList [
@ -62,14 +61,14 @@ unnamedFields = Test.Tasty.HUnit.testCase "Unnamed Fields" (do
,("Foo",Dhall.Core.Record (Data.HashMap.Strict.InsOrd.fromList [ ,("Foo",Dhall.Core.Record (Data.HashMap.Strict.InsOrd.fromList [
("_1",Dhall.Core.Integer),("_2",Dhall.Core.Bool)]))])) ("_1",Dhall.Core.Integer),("_2",Dhall.Core.Bool)]))]))
let inj = Dhall.inject @Foo let inj = Dhall.inject :: Dhall.InputType Foo
Test.Tasty.HUnit.assertEqual "Good Inject" (Dhall.declared inj) (Dhall.expected ty) Test.Tasty.HUnit.assertEqual "Good Inject" (Dhall.declared inj) (Dhall.expected ty)
let tu_ty = Dhall.auto @(Integer, Bool) let tu_ty = Dhall.auto :: Dhall.Type (Integer, Bool)
Test.Tasty.HUnit.assertEqual "Auto Tuple" (Dhall.expected tu_ty) (Dhall.Core.Record ( Test.Tasty.HUnit.assertEqual "Auto Tuple" (Dhall.expected tu_ty) (Dhall.Core.Record (
Data.HashMap.Strict.InsOrd.fromList [ ("_1",Dhall.Core.Integer),("_2",Dhall.Core.Bool) ])) Data.HashMap.Strict.InsOrd.fromList [ ("_1",Dhall.Core.Integer),("_2",Dhall.Core.Bool) ]))
let tu_in = Dhall.inject @(Integer, Bool) let tu_in = Dhall.inject :: Dhall.InputType (Integer, Bool)
Test.Tasty.HUnit.assertEqual "Inj. Tuple" (Dhall.declared tu_in) (Dhall.expected tu_ty) Test.Tasty.HUnit.assertEqual "Inj. Tuple" (Dhall.declared tu_in) (Dhall.expected tu_ty)
return () ) return () )