From 1df37abdd53217709c859125a6e2bfc771b77b5c Mon Sep 17 00:00:00 2001 From: Alp Mestanogullari Date: Fri, 23 Mar 2018 12:22:27 +0100 Subject: [PATCH 1/4] Preliminary bindist rule For now, we only ship `/{bin, lib}` and the few make build system related files that are needed to support a simple ``` ./configure [--prefix=PATH] && make install ``` workflow. The current binary distributions of GHC support a wider range of parameters, but I figured it would be a good thing to start with this and enhance it as we all see fit and perhaps using feedback from GHC HQ (@bgamari in particular) and bindist users. --- cfg/system.config.in | 1 + hadrian.cabal | 1 + src/Builder.hs | 4 ++ src/Builder.hs-boot | 1 + src/Rules.hs | 6 ++- src/Rules/Bindist.hs | 121 +++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 132 insertions(+), 2 deletions(-) create mode 100644 src/Rules/Bindist.hs diff --git a/cfg/system.config.in b/cfg/system.config.in index c983ae4a50..72bef125c6 100644 --- a/cfg/system.config.in +++ b/cfg/system.config.in @@ -7,6 +7,7 @@ alex = @AlexCmd@ ar = @ArCmd@ +autoreconf = autoreconf cc = @CC@ happy = @HappyCmd@ hs-cpp = @HaskellCPPCmd@ diff --git a/hadrian.cabal b/hadrian.cabal index 486148fc72..3f68d20978 100644 --- a/hadrian.cabal +++ b/hadrian.cabal @@ -51,6 +51,7 @@ executable hadrian , Oracles.Setting , Oracles.ModuleFiles , Rules + , Rules.Bindist , Rules.Clean , Rules.Compile , Rules.Configure diff --git a/src/Builder.hs b/src/Builder.hs index 8ce2aeae5c..a5fb8c3e49 100644 --- a/src/Builder.hs +++ b/src/Builder.hs @@ -88,6 +88,7 @@ instance NFData HaddockMode -- @GhcPkg Stage1@ is the one built in Stage0. data Builder = Alex | Ar ArMode Stage + | Autoreconf FilePath | DeriveConstants | Cc CcMode Stage | Configure FilePath @@ -173,6 +174,7 @@ instance H.Builder Builder where runtimeDependencies :: Builder -> Action [FilePath] runtimeDependencies = \case + Autoreconf dir -> return [dir -/- "configure.ac"] Configure dir -> return [dir -/- "configure"] Ghc _ Stage0 -> return [] @@ -231,6 +233,7 @@ instance H.Builder Builder where Ar Unpack _ -> cmd echo [Cwd output] [path] buildArgs + Autoreconf dir -> cmd echo [Cwd dir] [path] buildArgs Configure dir -> do -- Inject /bin/bash into `libtool`, instead of /bin/sh, -- otherwise Windows breaks. TODO: Figure out why. @@ -282,6 +285,7 @@ systemBuilderPath builder = case builder of Alex -> fromKey "alex" Ar _ Stage0 -> fromKey "system-ar" Ar _ _ -> fromKey "ar" + Autoreconf _ -> fromKey "autoreconf" Cc _ Stage0 -> fromKey "system-cc" Cc _ _ -> fromKey "cc" -- We can't ask configure for the path to configure! diff --git a/src/Builder.hs-boot b/src/Builder.hs-boot index e8eed47ef4..727b923044 100644 --- a/src/Builder.hs-boot +++ b/src/Builder.hs-boot @@ -13,6 +13,7 @@ data HaddockMode = BuildPackage | BuildIndex data Builder = Alex | Ar ArMode Stage + | Autoreconf FilePath | DeriveConstants | Cc CcMode Stage | Configure FilePath diff --git a/src/Rules.hs b/src/Rules.hs index 982d24969a..7fbb850da3 100644 --- a/src/Rules.hs +++ b/src/Rules.hs @@ -8,15 +8,16 @@ import qualified Hadrian.Oracles.TextFile import Expression import GHC import qualified Oracles.ModuleFiles +import qualified Rules.Bindist import qualified Rules.Compile -import qualified Rules.PackageData +import qualified Rules.Configure import qualified Rules.Dependencies import qualified Rules.Documentation import qualified Rules.Generate -import qualified Rules.Configure import qualified Rules.Gmp import qualified Rules.Libffi import qualified Rules.Library +import qualified Rules.PackageData import qualified Rules.Program import qualified Rules.Register import Settings @@ -122,6 +123,7 @@ packageRules = do buildRules :: Rules () buildRules = do + Rules.Bindist.bindistRules Rules.Configure.configureRules Rules.Generate.copyRules Rules.Generate.generateRules diff --git a/src/Rules/Bindist.hs b/src/Rules/Bindist.hs new file mode 100644 index 0000000000..f848d5819b --- /dev/null +++ b/src/Rules/Bindist.hs @@ -0,0 +1,121 @@ +module Rules.Bindist where + +import Expression +import GHC +import Oracles.Setting +import Settings +import Target +import Utilities + +bindistRules :: Rules () +bindistRules = do + root <- buildRootRules + phony "binary-dist" $ do + -- We 'need' all binaries and libraries + targets <- mapM pkgTarget =<< stagePackages Stage1 + need targets + + version <- setting ProjectVersion + targetPlatform <- setting TargetPlatformFull + + let ghcBuildDir = root -/- stageString Stage1 + bindistFilesDir = root -/- "bindist" -/- ghcVersionPretty + ghcVersionPretty = "ghc-" ++ version ++ "-" ++ targetPlatform + + -- we create the bindist directory at /bindist/ghc-X.Y.Z-platform/ + -- and populate it with a stage2 build + createDirectory bindistFilesDir + copyDirectory (ghcBuildDir -/- "bin") bindistFilesDir + copyDirectory (ghcBuildDir -/- "lib") bindistFilesDir + {- SHOULD WE SHIP DOCS? + need ["docs"] + copyDirectory (root -/- "docs") bindistFilesDir + -} + + -- we then 'need' all the files necessary to configure and install + -- (as in, './configure [...] && make install') this build on some + -- other machine. + need $ map (bindistFilesDir -/-) + (["configure", "Makefile"] ++ bindistInstallFiles) + + -- finally, we create the archive, at + -- /bindist/ghc-X.Y.Z-platform.tar.xz + command [Cwd $ root -/- "bindist"] "tar" + [ "-c", "--xz", "-f" + , ghcVersionPretty <.> "tar.xz" + , ghcVersionPretty + ] + + -- prepare binary distribution configure script + -- (generated under /distrib/configure by 'autoreconf') + root -/- "bindist" -/- "ghc-*" -/- "configure" %> \configurePath -> do + ghcRoot <- topDirectory + copyFile (ghcRoot -/- "aclocal.m4") (ghcRoot -/- "distrib" -/- "aclocal.m4") + buildWithCmdOptions [] $ + target (vanillaContext Stage1 ghc) (Autoreconf $ ghcRoot -/- "distrib") [] [] + -- we clean after ourselves, moving the configure script we generated in + -- our bindist dir + removeFile (ghcRoot -/- "distrib" -/- "aclocal.m4") + moveFile (ghcRoot -/- "distrib" -/- "configure") configurePath + + -- generate the Makefile that enables the "make install" part + root -/- "bindist" -/- "ghc-*" -/- "Makefile" %> \makefilePath -> + writeFile' makefilePath bindistMakefile + + -- copy over the various configure-related files needed for a working + -- './configure [...] && make install' workflow + -- (see the list of files needed in the 'binary-dist' rule above, before + -- creating the archive). + forM_ bindistInstallFiles $ \file -> + root -/- "bindist" -/- "ghc-*" -/- file %> \dest -> do + ghcRoot <- topDirectory + copyFile (ghcRoot -/- fixup file) dest + + where fixup f + | f `elem` ["INSTALL", "README"] = "distrib" -/- f + | otherwise = f + +-- | A list of files that allow us to support a simple +-- @./configure [--prefix=PATH] && make install@ workflow. +-- +-- NOTE: the list surely is incomplete +bindistInstallFiles :: [FilePath] +bindistInstallFiles = + [ "config.sub", "config.guess", "install-sh" + , "mk" -/- "config.mk.in", "mk" -/- "install.mk.in" + , "settings.in", "README", "INSTALL" + ] + +-- | Auxiliary function that gives us a 'Filepath' we can 'need' for +-- all libraries and programs that are needed for a complete build. +-- +-- For libraries, it returns the path to the .conf file in the package db. +-- For executables, it returns the path to the compiled executable. +pkgTarget :: Package -> Action FilePath +pkgTarget pkg + | isLibrary pkg = pkgConfFile (Context Stage1 pkg $ read "v") + | otherwise = programPath =<< programContext Stage1 pkg + +-- TODO: augment this makefile to match the various parameters that +-- the current bindist scripts support. +-- | A trivial makefile that only takes @$prefix@ into account, +-- and not e.g @$datadir@ (for docs) and other variables, yet. +bindistMakefile :: String +bindistMakefile = unlines + [ "MAKEFLAGS += --no-builtin-rules" + , ".SUFFIXES:" + , "" + , "include mk/install.mk" + , "" + , ".PHONY: default" + , "default:" + , "\t@echo 'Run \"make install\" to install'" + , "\t@false" + , "" + , ".PHONY: install" + , "install:" + , "\tmkdir -p $(prefix)" + , "\tcp settings lib/settings" + , "\tcp -R bin $(prefix)/" + , "\tcp -R lib $(prefix)/" + ] From 32efe2f1407dce1243f44e833dc349349b3048f9 Mon Sep 17 00:00:00 2001 From: Alp Mestanogullari Date: Tue, 3 Apr 2018 18:00:24 +0200 Subject: [PATCH 2/4] document binary distribution rule in README --- README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/README.md b/README.md index 620d405627..2f40165317 100644 --- a/README.md +++ b/README.md @@ -127,6 +127,17 @@ are currently not supported. To build a GHC source distribution tarball, run `build sdist-ghc`. +#### Binary distribution + +To build a GHC binary distribution, run `build binary-dist`. The resulting +tarball contains just enough to support the + +``` sh +$ ./configure [--prefix=PATH] && make install +``` + +workflow, for now. + #### Testing * `build validate` runs GHC tests by simply executing `make fast` in `testsuite/tests` From b51c28ca2607cff3a55a97494b2e3bf1973d9899 Mon Sep 17 00:00:00 2001 From: Alp Mestanogullari Date: Tue, 3 Apr 2018 18:14:52 +0200 Subject: [PATCH 3/4] sdist-ghc -> source-dist, Rules.Bindist -> Rules.BinaryDist --- README.md | 2 +- hadrian.cabal | 2 +- src/Rules.hs | 4 +- src/Rules/Bindist.hs | 121 ---------------------------------------- src/Rules/SourceDist.hs | 2 +- 5 files changed, 5 insertions(+), 126 deletions(-) delete mode 100644 src/Rules/Bindist.hs diff --git a/README.md b/README.md index 2f40165317..2509dae430 100644 --- a/README.md +++ b/README.md @@ -125,7 +125,7 @@ are currently not supported. #### Source distribution -To build a GHC source distribution tarball, run `build sdist-ghc`. +To build a GHC source distribution tarball, run `build source-dist`. #### Binary distribution diff --git a/hadrian.cabal b/hadrian.cabal index 3f68d20978..ca339fbf7c 100644 --- a/hadrian.cabal +++ b/hadrian.cabal @@ -51,7 +51,7 @@ executable hadrian , Oracles.Setting , Oracles.ModuleFiles , Rules - , Rules.Bindist + , Rules.BinaryDist , Rules.Clean , Rules.Compile , Rules.Configure diff --git a/src/Rules.hs b/src/Rules.hs index 7fbb850da3..100720f3cc 100644 --- a/src/Rules.hs +++ b/src/Rules.hs @@ -8,7 +8,7 @@ import qualified Hadrian.Oracles.TextFile import Expression import GHC import qualified Oracles.ModuleFiles -import qualified Rules.Bindist +import qualified Rules.BinaryDist import qualified Rules.Compile import qualified Rules.Configure import qualified Rules.Dependencies @@ -123,7 +123,7 @@ packageRules = do buildRules :: Rules () buildRules = do - Rules.Bindist.bindistRules + Rules.BinaryDist.bindistRules Rules.Configure.configureRules Rules.Generate.copyRules Rules.Generate.generateRules diff --git a/src/Rules/Bindist.hs b/src/Rules/Bindist.hs deleted file mode 100644 index f848d5819b..0000000000 --- a/src/Rules/Bindist.hs +++ /dev/null @@ -1,121 +0,0 @@ -module Rules.Bindist where - -import Expression -import GHC -import Oracles.Setting -import Settings -import Target -import Utilities - -bindistRules :: Rules () -bindistRules = do - root <- buildRootRules - phony "binary-dist" $ do - -- We 'need' all binaries and libraries - targets <- mapM pkgTarget =<< stagePackages Stage1 - need targets - - version <- setting ProjectVersion - targetPlatform <- setting TargetPlatformFull - - let ghcBuildDir = root -/- stageString Stage1 - bindistFilesDir = root -/- "bindist" -/- ghcVersionPretty - ghcVersionPretty = "ghc-" ++ version ++ "-" ++ targetPlatform - - -- we create the bindist directory at /bindist/ghc-X.Y.Z-platform/ - -- and populate it with a stage2 build - createDirectory bindistFilesDir - copyDirectory (ghcBuildDir -/- "bin") bindistFilesDir - copyDirectory (ghcBuildDir -/- "lib") bindistFilesDir - {- SHOULD WE SHIP DOCS? - need ["docs"] - copyDirectory (root -/- "docs") bindistFilesDir - -} - - -- we then 'need' all the files necessary to configure and install - -- (as in, './configure [...] && make install') this build on some - -- other machine. - need $ map (bindistFilesDir -/-) - (["configure", "Makefile"] ++ bindistInstallFiles) - - -- finally, we create the archive, at - -- /bindist/ghc-X.Y.Z-platform.tar.xz - command [Cwd $ root -/- "bindist"] "tar" - [ "-c", "--xz", "-f" - , ghcVersionPretty <.> "tar.xz" - , ghcVersionPretty - ] - - -- prepare binary distribution configure script - -- (generated under /distrib/configure by 'autoreconf') - root -/- "bindist" -/- "ghc-*" -/- "configure" %> \configurePath -> do - ghcRoot <- topDirectory - copyFile (ghcRoot -/- "aclocal.m4") (ghcRoot -/- "distrib" -/- "aclocal.m4") - buildWithCmdOptions [] $ - target (vanillaContext Stage1 ghc) (Autoreconf $ ghcRoot -/- "distrib") [] [] - -- we clean after ourselves, moving the configure script we generated in - -- our bindist dir - removeFile (ghcRoot -/- "distrib" -/- "aclocal.m4") - moveFile (ghcRoot -/- "distrib" -/- "configure") configurePath - - -- generate the Makefile that enables the "make install" part - root -/- "bindist" -/- "ghc-*" -/- "Makefile" %> \makefilePath -> - writeFile' makefilePath bindistMakefile - - -- copy over the various configure-related files needed for a working - -- './configure [...] && make install' workflow - -- (see the list of files needed in the 'binary-dist' rule above, before - -- creating the archive). - forM_ bindistInstallFiles $ \file -> - root -/- "bindist" -/- "ghc-*" -/- file %> \dest -> do - ghcRoot <- topDirectory - copyFile (ghcRoot -/- fixup file) dest - - where fixup f - | f `elem` ["INSTALL", "README"] = "distrib" -/- f - | otherwise = f - --- | A list of files that allow us to support a simple --- @./configure [--prefix=PATH] && make install@ workflow. --- --- NOTE: the list surely is incomplete -bindistInstallFiles :: [FilePath] -bindistInstallFiles = - [ "config.sub", "config.guess", "install-sh" - , "mk" -/- "config.mk.in", "mk" -/- "install.mk.in" - , "settings.in", "README", "INSTALL" - ] - --- | Auxiliary function that gives us a 'Filepath' we can 'need' for --- all libraries and programs that are needed for a complete build. --- --- For libraries, it returns the path to the .conf file in the package db. --- For executables, it returns the path to the compiled executable. -pkgTarget :: Package -> Action FilePath -pkgTarget pkg - | isLibrary pkg = pkgConfFile (Context Stage1 pkg $ read "v") - | otherwise = programPath =<< programContext Stage1 pkg - --- TODO: augment this makefile to match the various parameters that --- the current bindist scripts support. --- | A trivial makefile that only takes @$prefix@ into account, --- and not e.g @$datadir@ (for docs) and other variables, yet. -bindistMakefile :: String -bindistMakefile = unlines - [ "MAKEFLAGS += --no-builtin-rules" - , ".SUFFIXES:" - , "" - , "include mk/install.mk" - , "" - , ".PHONY: default" - , "default:" - , "\t@echo 'Run \"make install\" to install'" - , "\t@false" - , "" - , ".PHONY: install" - , "install:" - , "\tmkdir -p $(prefix)" - , "\tcp settings lib/settings" - , "\tcp -R bin $(prefix)/" - , "\tcp -R lib $(prefix)/" - ] diff --git a/src/Rules/SourceDist.hs b/src/Rules/SourceDist.hs index 6ef79294a1..8bec3f3b26 100644 --- a/src/Rules/SourceDist.hs +++ b/src/Rules/SourceDist.hs @@ -9,7 +9,7 @@ import Rules.Clean sourceDistRules :: Rules () sourceDistRules = do - "sdist-ghc" ~> do + "source-dist" ~> do -- We clean the source tree first. -- See https://github.com/snowleopard/hadrian/issues/384. -- TODO: Do we still need to clean the tree? From cd79333b7f1b7a52a8aea1175559083f848c5747 Mon Sep 17 00:00:00 2001 From: Alp Mestanogullari Date: Tue, 3 Apr 2018 19:54:34 +0200 Subject: [PATCH 4/4] add missing src/Rules/BinaryDist.hs --- src/Rules/BinaryDist.hs | 121 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 src/Rules/BinaryDist.hs diff --git a/src/Rules/BinaryDist.hs b/src/Rules/BinaryDist.hs new file mode 100644 index 0000000000..db7362254b --- /dev/null +++ b/src/Rules/BinaryDist.hs @@ -0,0 +1,121 @@ +module Rules.BinaryDist where + +import Expression +import GHC +import Oracles.Setting +import Settings +import Target +import Utilities + +bindistRules :: Rules () +bindistRules = do + root <- buildRootRules + phony "binary-dist" $ do + -- We 'need' all binaries and libraries + targets <- mapM pkgTarget =<< stagePackages Stage1 + need targets + + version <- setting ProjectVersion + targetPlatform <- setting TargetPlatformFull + + let ghcBuildDir = root -/- stageString Stage1 + bindistFilesDir = root -/- "bindist" -/- ghcVersionPretty + ghcVersionPretty = "ghc-" ++ version ++ "-" ++ targetPlatform + + -- we create the bindist directory at /bindist/ghc-X.Y.Z-platform/ + -- and populate it with a stage2 build + createDirectory bindistFilesDir + copyDirectory (ghcBuildDir -/- "bin") bindistFilesDir + copyDirectory (ghcBuildDir -/- "lib") bindistFilesDir + {- SHOULD WE SHIP DOCS? + need ["docs"] + copyDirectory (root -/- "docs") bindistFilesDir + -} + + -- we then 'need' all the files necessary to configure and install + -- (as in, './configure [...] && make install') this build on some + -- other machine. + need $ map (bindistFilesDir -/-) + (["configure", "Makefile"] ++ bindistInstallFiles) + + -- finally, we create the archive, at + -- /bindist/ghc-X.Y.Z-platform.tar.xz + command [Cwd $ root -/- "bindist"] "tar" + [ "-c", "--xz", "-f" + , ghcVersionPretty <.> "tar.xz" + , ghcVersionPretty + ] + + -- prepare binary distribution configure script + -- (generated under /distrib/configure by 'autoreconf') + root -/- "bindist" -/- "ghc-*" -/- "configure" %> \configurePath -> do + ghcRoot <- topDirectory + copyFile (ghcRoot -/- "aclocal.m4") (ghcRoot -/- "distrib" -/- "aclocal.m4") + buildWithCmdOptions [] $ + target (vanillaContext Stage1 ghc) (Autoreconf $ ghcRoot -/- "distrib") [] [] + -- we clean after ourselves, moving the configure script we generated in + -- our bindist dir + removeFile (ghcRoot -/- "distrib" -/- "aclocal.m4") + moveFile (ghcRoot -/- "distrib" -/- "configure") configurePath + + -- generate the Makefile that enables the "make install" part + root -/- "bindist" -/- "ghc-*" -/- "Makefile" %> \makefilePath -> + writeFile' makefilePath bindistMakefile + + -- copy over the various configure-related files needed for a working + -- './configure [...] && make install' workflow + -- (see the list of files needed in the 'binary-dist' rule above, before + -- creating the archive). + forM_ bindistInstallFiles $ \file -> + root -/- "bindist" -/- "ghc-*" -/- file %> \dest -> do + ghcRoot <- topDirectory + copyFile (ghcRoot -/- fixup file) dest + + where fixup f + | f `elem` ["INSTALL", "README"] = "distrib" -/- f + | otherwise = f + +-- | A list of files that allow us to support a simple +-- @./configure [--prefix=PATH] && make install@ workflow. +-- +-- NOTE: the list surely is incomplete +bindistInstallFiles :: [FilePath] +bindistInstallFiles = + [ "config.sub", "config.guess", "install-sh" + , "mk" -/- "config.mk.in", "mk" -/- "install.mk.in" + , "settings.in", "README", "INSTALL" + ] + +-- | Auxiliary function that gives us a 'Filepath' we can 'need' for +-- all libraries and programs that are needed for a complete build. +-- +-- For libraries, it returns the path to the .conf file in the package db. +-- For executables, it returns the path to the compiled executable. +pkgTarget :: Package -> Action FilePath +pkgTarget pkg + | isLibrary pkg = pkgConfFile (Context Stage1 pkg $ read "v") + | otherwise = programPath =<< programContext Stage1 pkg + +-- TODO: augment this makefile to match the various parameters that +-- the current bindist scripts support. +-- | A trivial makefile that only takes @$prefix@ into account, +-- and not e.g @$datadir@ (for docs) and other variables, yet. +bindistMakefile :: String +bindistMakefile = unlines + [ "MAKEFLAGS += --no-builtin-rules" + , ".SUFFIXES:" + , "" + , "include mk/install.mk" + , "" + , ".PHONY: default" + , "default:" + , "\t@echo 'Run \"make install\" to install'" + , "\t@false" + , "" + , ".PHONY: install" + , "install:" + , "\tmkdir -p $(prefix)" + , "\tcp settings lib/settings" + , "\tcp -R bin $(prefix)/" + , "\tcp -R lib $(prefix)/" + ]