diff --git a/shaking-up-ghc.cabal b/shaking-up-ghc.cabal index 9c40f46419..1f7cfc1a53 100644 --- a/shaking-up-ghc.cabal +++ b/shaking-up-ghc.cabal @@ -51,7 +51,7 @@ executable ghc-shake , Rules.Generators.GhcSplit , Rules.Generators.GhcVersionH , Rules.Generators.VersionHs - , Rules.IntegerGmp + , Rules.Gmp , Rules.Libffi , Rules.Library , Rules.Oracles diff --git a/src/Main.hs b/src/Main.hs index 9f223a8852..63dbd7cfa2 100644 --- a/src/Main.hs +++ b/src/Main.hs @@ -7,7 +7,7 @@ import qualified Rules import qualified Rules.Cabal import qualified Rules.Config import qualified Rules.Generate -import qualified Rules.IntegerGmp +import qualified Rules.Gmp import qualified Rules.Libffi import qualified Rules.Oracles import qualified Rules.Perl @@ -22,7 +22,7 @@ main = shakeArgs options rules , Rules.Generate.generateRules , Rules.Perl.perlScriptRules , Rules.generateTargets - , Rules.IntegerGmp.integerGmpRules + , Rules.Gmp.gmpRules , Rules.Libffi.libffiRules , Rules.Oracles.oracleRules , Rules.packageRules ] diff --git a/src/Rules/Data.hs b/src/Rules/Data.hs index 4428b35911..5cd2e50e41 100644 --- a/src/Rules/Data.hs +++ b/src/Rules/Data.hs @@ -1,5 +1,7 @@ module Rules.Data (buildPackageData) where +import qualified System.Directory as IO + import Base import Expression import Extra (replace) @@ -20,8 +22,9 @@ buildPackageData rs target @ (PartialTarget stage pkg) = do let cabalFile = pkgCabalFile pkg configure = pkgPath pkg -/- "configure" dataFile = pkgDataFile stage pkg + oldPath = pkgPath pkg -/- targetDirectory stage pkg -- TODO: remove, #113 - dataFile %> \_ -> do + [dataFile, oldPath -/- "package-data.mk"] &%> \_ -> do -- The first thing we do with any package is make sure all generated -- dependencies are in place before proceeding. orderOnly $ generatedDependencies stage pkg @@ -37,15 +40,14 @@ buildPackageData rs target @ (PartialTarget stage pkg) = do orderOnly $ map (pkgDataFile stage) depPkgs -- TODO: get rid of this, see #113 - let oldPath = pkgPath pkg -/- targetDirectory stage pkg - inTreeMk = oldPath -/- takeFileName dataFile + let inTreeMk = oldPath -/- takeFileName dataFile need [cabalFile] buildWithResources [(resGhcCabal rs, 1)] $ fullTarget target GhcCabal [cabalFile] [inTreeMk] -- TODO: get rid of this, see #113 - copyFile inTreeMk dataFile + liftIO $ IO.copyFile inTreeMk dataFile autogenFiles <- getDirectoryFiles oldPath ["build/autogen/*"] createDirectory $ targetPath stage pkg -/- "build/autogen" forM_ autogenFiles $ \file -> do diff --git a/src/Rules/Generate.hs b/src/Rules/Generate.hs index 5dbf5dd4ea..4fd7da60ea 100644 --- a/src/Rules/Generate.hs +++ b/src/Rules/Generate.hs @@ -15,7 +15,7 @@ import Rules.Generators.GhcVersionH import Rules.Generators.VersionHs import Oracles.ModuleFiles import Rules.Actions -import Rules.IntegerGmp +import Rules.Gmp import Rules.Libffi import Rules.Resources (Resources) import Settings @@ -46,7 +46,7 @@ defaultDependencies :: [FilePath] defaultDependencies = concat [ includesDependencies , libffiDependencies - , integerGmpDependencies ] + , gmpDependencies ] ghcPrimDependencies :: Stage -> [FilePath] ghcPrimDependencies stage = ((targetPath stage ghcPrim -/- "build") -/-) <$> diff --git a/src/Rules/Gmp.hs b/src/Rules/Gmp.hs new file mode 100644 index 0000000000..b02fe365c9 --- /dev/null +++ b/src/Rules/Gmp.hs @@ -0,0 +1,134 @@ +module Rules.Gmp ( + gmpRules, gmpBuildPath, gmpObjects, gmpLibraryH, gmpDependencies + ) where + +import Base +import Expression +import GHC +import Oracles.Config.Setting +import Rules.Actions +import Settings.Packages.IntegerGmp +import Settings.User + +gmpBase :: FilePath +gmpBase = "libraries/integer-gmp/gmp" + +gmpTarget :: PartialTarget +gmpTarget = PartialTarget Stage0 integerGmp + +gmpObjects :: FilePath +gmpObjects = gmpBuildPath -/- "objs" + +gmpLibrary :: FilePath +gmpLibrary = gmpBuildPath -/- "libgmp.a" + +gmpLibraryInTreeH :: FilePath +gmpLibraryInTreeH = gmpBuildPath -/- "include/gmp.h" + +gmpLibraryH :: FilePath +gmpLibraryH = gmpBuildPath -/- "include/ghc-gmp.h" + +gmpLibraryFakeH :: FilePath +gmpLibraryFakeH = gmpBase -/- "ghc-gmp.h" + +gmpDependencies :: [FilePath] +gmpDependencies = [gmpLibraryH] + +gmpPatches :: [FilePath] +gmpPatches = (gmpBase -/-) <$> ["gmpsrc.patch", "tarball/gmp-5.0.4.patch"] + +-- TODO: See Libffi.hs about removing code duplication. +configureEnvironment :: Action [CmdOption] +configureEnvironment = do + sequence [ builderEnv "CC" $ Gcc Stage1 + , builderEnv "AR" Ar + , builderEnv "NM" Nm ] + where + builderEnv var builder = do + needBuilder False builder + path <- builderPath builder + return $ AddEnv var path + +configureArguments :: Action [String] +configureArguments = do + hostPlatform <- setting HostPlatform + buildPlatform <- setting BuildPlatform + return [ "--enable-shared=no" + , "--host=" ++ hostPlatform + , "--build=" ++ buildPlatform] + +-- TODO: we rebuild gmp every time. +gmpRules :: Rules () +gmpRules = do + + -- TODO: split into multiple rules + gmpLibraryH %> \_ -> do + when trackBuildSystem $ need [sourcePath -/- "Rules/Gmp.hs"] + + -- Do we need this step? + liftIO $ removeFiles gmpBuildPath ["//*"] + + -- Note: We use a tarball like gmp-4.2.4-nodoc.tar.bz2, which is + -- gmp-4.2.4.tar.bz2 repacked without the doc/ directory contents. + -- That's because the doc/ directory contents are under the GFDL, + -- which causes problems for Debian. + tarballs <- getDirectoryFiles "" [gmpBase -/- "tarball/gmp*.tar.bz2"] + when (length tarballs /= 1) $ + putError $ "gmpRules: exactly one tarball expected" + ++ "(found: " ++ show tarballs ++ ")." + + need tarballs + + createDirectory gmpBuildPath + build $ fullTarget gmpTarget Tar tarballs [gmpBuildPath] + + -- TODO: replace "patch" with PATCH_CMD + forM_ gmpPatches $ \src -> do + let patch = takeFileName src + patchPath = gmpBuildPath -/- patch + copyFile src patchPath + putBuild $ "| Apply " ++ patchPath + unit . quietly $ cmd Shell (EchoStdout False) [Cwd gmpBuildPath] "patch -p0 <" [patch] + + -- TODO: What's `chmod +x libraries/integer-gmp/gmp/ln` for? + + let filename = dropExtension . dropExtension . takeFileName $ head tarballs + suffix = "-nodoc-patched" + unless (suffix `isSuffixOf` filename) $ + putError $ "gmpRules: expected suffix " ++ suffix + ++ " (found: " ++ filename ++ ")." + let libName = take (length filename - length suffix) filename + libPath = gmpBuildPath -/- libName + + envs <- configureEnvironment + args <- configureArguments + runConfigure libPath envs args + + -- TODO: currently we configure integerGmp package twice -- optimise + runConfigure (pkgPath integerGmp) [] [] + + createDirectory $ takeDirectory gmpLibraryH + -- check whether we need to build in tree gmp + -- this is indicated by line "HaveFrameworkGMP = YES" in `config.mk` + configMk <- liftIO . readFile $ gmpBase -/- "config.mk" + if "HaveFrameworkGMP = YES" `isInfixOf` configMk + then do + putBuild "| GMP framework detected and will be used" + copyFile gmpLibraryFakeH gmpLibraryH + else do + putBuild "| No GMP framework detected; in tree GMP will be built" + runMake libPath ["MAKEFLAGS="] + + copyFile (libPath -/- "gmp.h") gmpLibraryInTreeH + copyFile (libPath -/- "gmp.h") gmpLibraryH + -- TODO: why copy library, can we move it instead? + copyFile (libPath -/- ".libs/libgmp.a") gmpLibrary + + createDirectory gmpObjects + build $ fullTarget gmpTarget Ar [gmpLibrary] [gmpObjects] + + runBuilder Ranlib [gmpLibrary] + + putSuccess "| Successfully built custom library 'integer-gmp'" + + -- gmpLibraryInTreeH %> \_ -> need [gmpLibraryH] diff --git a/src/Rules/IntegerGmp.hs b/src/Rules/IntegerGmp.hs deleted file mode 100644 index 31732bcc20..0000000000 --- a/src/Rules/IntegerGmp.hs +++ /dev/null @@ -1,137 +0,0 @@ -module Rules.IntegerGmp ( - integerGmpRules, integerGmpObjects, integerGmpLibraryH, integerGmpDependencies - ) where - -import Base -import Expression -import GHC -import Oracles.Config.Setting -import Rules.Actions -import Settings.User - --- TODO: move build artefacts to buildRootPath, see #113 -integerGmpBase :: FilePath -integerGmpBase = "libraries/integer-gmp/gmp" - -integerGmpBuild :: FilePath -integerGmpBuild = integerGmpBase -/- "gmpbuild" - -integerGmpObjects :: FilePath -integerGmpObjects = integerGmpBase -/- "objs" - -integerGmpLibrary :: FilePath -integerGmpLibrary = integerGmpBase -/- "libgmp.a" - -integerGmpLibraryInTreeH :: FilePath -integerGmpLibraryInTreeH = integerGmpBase -/- "gmp.h" - -integerGmpLibraryH :: FilePath -integerGmpLibraryH = pkgPath integerGmp -/- "include/ghc-gmp.h" - -integerGmpLibraryFakeH :: FilePath -integerGmpLibraryFakeH = integerGmpBase -/- "ghc-gmp.h" - -integerGmpDependencies :: [FilePath] -integerGmpDependencies = [integerGmpLibraryH] - --- relative to integerGmpBuild -integerGmpPatch :: FilePath -integerGmpPatch = ".." -/- "tarball" -/- "gmp-5.0.4.patch" - -target :: PartialTarget -target = PartialTarget Stage0 integerGmp - --- TODO: See Libffi.hs about removing code duplication. -configureEnvironment :: Action [CmdOption] -configureEnvironment = do - sequence [ builderEnv "CC" $ Gcc Stage1 - , builderEnv "AR" Ar - , builderEnv "NM" Nm ] - where - builderEnv var builder = do - needBuilder False builder - path <- builderPath builder - return $ AddEnv var path - -configureArguments :: Action [String] -configureArguments = do - hostPlatform <- setting HostPlatform - buildPlatform <- setting BuildPlatform - return [ "--enable-shared=no" - , "--host=" ++ hostPlatform - , "--build=" ++ buildPlatform] - --- TODO: we rebuild integer-gmp every time. -integerGmpRules :: Rules () -integerGmpRules = do - - -- TODO: split into multiple rules - integerGmpLibraryH %> \_ -> do - when trackBuildSystem $ need [sourcePath -/- "Rules/IntegerGmp.hs"] - - -- remove the old build folder, if it exists. - liftIO $ removeFiles integerGmpBuild ["//*"] - liftIO $ removeFiles (integerGmpObjects) ["//*"] - - -- unpack the gmp tarball. - -- Note: We use a tarball like gmp-4.2.4-nodoc.tar.bz2, which is - -- gmp-4.2.4.tar.bz2 repacked without the doc/ directory contents. - -- That's because the doc/ directory contents are under the GFDL, - -- which causes problems for Debian. - tarballs <- getDirectoryFiles "" [integerGmpBase -/- "tarball/gmp*.tar.bz2"] - when (length tarballs /= 1) $ - putError $ "integerGmpRules: exactly one tarball expected" - ++ "(found: " ++ show tarballs ++ ")." - - need tarballs - build $ fullTarget target Tar tarballs [integerGmpBase] - - -- move gmp- to gmpbuild - let filename = dropExtension . dropExtension . takeFileName $ head tarballs - suffix = "-nodoc-patched" - unless (suffix `isSuffixOf` filename) $ - putError $ "integerGmpRules: expected suffix " ++ suffix - ++ " (found: " ++ filename ++ ")." - let libname = take (length filename - length suffix) filename - moveDirectory (integerGmpBase -/- libname) integerGmpBuild - - -- apply patches - -- TODO: replace "patch" with PATCH_CMD - unit . quietly $ cmd Shell (EchoStdout False) [Cwd integerGmpBase] "patch -p0 < gmpsrc.patch" - putBuild $ "| Apply " ++ (integerGmpBase -/- "gmpsrc.patch") - unit . quietly $ cmd Shell (EchoStdout False) [Cwd integerGmpBuild] "patch -p1 < " [integerGmpPatch] - putBuild $ "| Apply " ++ (integerGmpBase -/- integerGmpPatch) - - -- TODO: What's `chmod +x libraries/integer-gmp/gmp/ln` for? - - envs <- configureEnvironment - args <- configureArguments - runConfigure integerGmpBuild envs args - - -- TODO: currently we configure integerGmp package twice -- optimise - runConfigure (pkgPath integerGmp) [] [] - - -- check whether we need to build in tree gmp - -- this is indicated by line "HaveFrameworkGMP = YES" in `config.mk` - configMk <- liftIO . readFile $ integerGmpBase -/- "config.mk" - if "HaveFrameworkGMP = YES" `isInfixOf` configMk - then do - putBuild "| GMP framework detected and will be used" - copyFile integerGmpLibraryFakeH integerGmpLibraryH - else do - putBuild "| No GMP framework detected; in tree GMP will be built" - runMake integerGmpBuild ["MAKEFLAGS="] - - copyFile (integerGmpBuild -/- "gmp.h") integerGmpLibraryInTreeH - copyFile (integerGmpBuild -/- "gmp.h") integerGmpLibraryH - -- TODO: why copy library, can we move it instead? - copyFile (integerGmpBuild -/- ".libs/libgmp.a") integerGmpLibrary - - createDirectory integerGmpObjects - build $ fullTarget target Ar [integerGmpLibrary] [integerGmpObjects] - - runBuilder Ranlib [integerGmpLibrary] - - putSuccess "| Successfully built custom library 'integer-gmp'" - - integerGmpLibraryInTreeH %> \_ -> need [integerGmpLibraryH] diff --git a/src/Rules/Libffi.hs b/src/Rules/Libffi.hs index 42bd4b1e28..854f8deb12 100644 --- a/src/Rules/Libffi.hs +++ b/src/Rules/Libffi.hs @@ -11,12 +11,17 @@ import Settings.Packages.Rts import Settings.TargetDirectory import Settings.User +-- TODO: this should be moved elsewhere rtsBuildPath :: FilePath rtsBuildPath = targetPath Stage1 rts -/- "build" +-- TODO: Why copy these include files in rts? Move to libffi! libffiDependencies :: [FilePath] libffiDependencies = (rtsBuildPath -/-) <$> [ "ffi.h", "ffitarget.h" ] +libffiTarget :: PartialTarget +libffiTarget = PartialTarget Stage0 libffi + libffiBuild :: FilePath libffiBuild = buildRootPath -/- "stage0/libffi" @@ -33,18 +38,15 @@ fixLibffiMakefile = unlines . map . replace "@INSTALL@" "$(subst ../install-sh,C:/msys/home/chEEtah/ghc/install-sh,@INSTALL@)" ) . lines -target :: PartialTarget -target = PartialTarget Stage0 libffi - -- TODO: remove code duplication (see Settings/Builders/GhcCabal.hs) configureEnvironment :: Action [CmdOption] configureEnvironment = do - cFlags <- interpretPartial target . fromDiffExpr $ mconcat + cFlags <- interpretPartial libffiTarget . fromDiffExpr $ mconcat [ cArgs , argStagedSettingList ConfCcArgs ] - ldFlags <- interpretPartial target $ fromDiffExpr ldArgs - sequence [ builderEnv "CC" $ Gcc Stage1 - , builderEnv "CXX" $ Gcc Stage1 + ldFlags <- interpretPartial libffiTarget $ fromDiffExpr ldArgs + sequence [ builderEnv "CC" $ Gcc Stage0 + , builderEnv "CXX" $ Gcc Stage0 , builderEnv "LD" Ld , builderEnv "AR" Ar , builderEnv "NM" Nm @@ -80,10 +82,12 @@ libffiRules = do ++ "(found: " ++ show tarballs ++ ")." need tarballs - build $ fullTarget target Tar tarballs ["libffi-tarballs"] - let libname = dropExtension . dropExtension . takeFileName $ head tarballs - moveDirectory ("libffi-tarballs" -/- libname) libffiBuild + + withTempDir $ \tmpDir -> do + let unifiedTmpDir = unifyPath tmpDir + build $ fullTarget libffiTarget Tar tarballs [unifiedTmpDir] + moveDirectory (unifiedTmpDir -/- libname) libffiBuild fixFile libffiMakefile fixLibffiMakefile diff --git a/src/Rules/Library.hs b/src/Rules/Library.hs index 788deb6577..cdf7ebb341 100644 --- a/src/Rules/Library.hs +++ b/src/Rules/Library.hs @@ -7,7 +7,7 @@ import Expression import GHC import Oracles import Rules.Actions -import Rules.IntegerGmp +import Rules.Gmp import Rules.Resources import Settings import qualified System.Directory as IO @@ -84,6 +84,6 @@ hSources target = do extraObjects :: PartialTarget -> Action [FilePath] extraObjects (PartialTarget _ pkg) | pkg == integerGmp = do - need [integerGmpLibraryH] - getDirectoryFiles "" [integerGmpObjects -/- "*.o"] + orderOnly [gmpLibraryH] -- TODO: move this dependency elsewhere, #113? + getDirectoryFiles "" [gmpObjects -/- "*.o"] | otherwise = return [] diff --git a/src/Settings/Packages/IntegerGmp.hs b/src/Settings/Packages/IntegerGmp.hs index c679bf3ac0..8b100b314e 100644 --- a/src/Settings/Packages/IntegerGmp.hs +++ b/src/Settings/Packages/IntegerGmp.hs @@ -1,9 +1,14 @@ -module Settings.Packages.IntegerGmp (integerGmpPackageArgs) where +module Settings.Packages.IntegerGmp (integerGmpPackageArgs, gmpBuildPath) where import Base import Expression import GHC (integerGmp) import Predicates (builder, builderGcc, package) +import Settings.User + +-- TODO: move elsewhere +gmpBuildPath :: FilePath +gmpBuildPath = buildRootPath -/- "stage0/gmp" -- TODO: move build artefacts to buildRootPath, see #113 -- TODO: Is this needed? @@ -11,13 +16,13 @@ import Predicates (builder, builderGcc, package) -- libraries/integer-gmp_CONFIGURE_OPTS += --with-gmp-framework-preferred -- endif integerGmpPackageArgs :: Args -integerGmpPackageArgs = package integerGmp ? - mconcat - [ builder GhcCabal ? mconcat - [ arg "--configure-option=--with-intree-gmp" - , appendSub "--configure-option=CFLAGS" includeGmp - , appendSub "--gcc-options" includeGmp ] - , builderGcc ? ( arg $ "-I" ++ pkgPath integerGmp -/- "gmp" ) - ] +integerGmpPackageArgs = package integerGmp ? do + let includeGmp = "-I" ++ gmpBuildPath -/- "include" + mconcat [ builder GhcCabal ? mconcat + [ arg "--configure-option=--with-intree-gmp" + , appendSub "--configure-option=CFLAGS" [includeGmp] + , appendSub "--gcc-options" [includeGmp] ] + + , builderGcc ? arg includeGmp ] where - includeGmp = ["-I" ++ pkgPath integerGmp -/- "gmp"] + diff --git a/src/Settings/TargetDirectory.hs b/src/Settings/TargetDirectory.hs index 1acf8ac506..6bbef72b21 100644 --- a/src/Settings/TargetDirectory.hs +++ b/src/Settings/TargetDirectory.hs @@ -7,7 +7,7 @@ import Base import Expression import Settings.User --- TODO: move to Settings.hs? +-- TODO: rename to Settings.Paths as part of #113 -- User can override the default target directory settings given below targetDirectory :: Stage -> Package -> FilePath