summaryrefslogtreecommitdiff
path: root/hadrian/src/Rules
diff options
context:
space:
mode:
authorAlp Mestanogullari <alp@well-typed.com>2018-11-27 13:17:53 +0100
committerAlp Mestanogullari <alpmestan@gmail.com>2018-11-27 13:18:44 +0100
commit8f52ab9223544b756010a7a92ea52fffdf1d1c71 (patch)
tree6ac142ece5cd3d448ee1606ce8444b4b99761b25 /hadrian/src/Rules
parent984b75de7082689ebcc6e9d17b37f2c9b3702f71 (diff)
downloadhaskell-8f52ab9223544b756010a7a92ea52fffdf1d1c71.tar.gz
Hadrian: improve bindist rule
As outlined in #15925, hadrian bindists had not made a clear choice with respect to relocatable GHCs and wrapper scripts. This commit implements the policy described in the ticket. That is: - the bindists ship {bin, lib} as they are, modulo the addition of haddock from stage2/bin - we now _always_ generate wrapper scripts for all the programs that are in the bindist's bin/ directory The idea being that anyone on Linux/Windows/OS X can just unpack the binary distribution anywhere and start using bin/ghc, while the installation process systematicaly generates wrapper scripts. Test Plan: hadrian/build.sh binary-dist ; cd _build/bindist/ghc-X.Y.Z-arch/; configure --prefix=/tmp/foo && make install Reviewers: snowleopard, bgamari, angerman Reviewed By: snowleopard, bgamari, angerman Subscribers: rwbarton, carter GHC Trac Issues: #15925 Differential Revision: https://phabricator.haskell.org/D5371
Diffstat (limited to 'hadrian/src/Rules')
-rw-r--r--hadrian/src/Rules/BinaryDist.hs149
1 files changed, 111 insertions, 38 deletions
diff --git a/hadrian/src/Rules/BinaryDist.hs b/hadrian/src/Rules/BinaryDist.hs
index 667fbf1454..9cf442c3f5 100644
--- a/hadrian/src/Rules/BinaryDist.hs
+++ b/hadrian/src/Rules/BinaryDist.hs
@@ -10,6 +10,84 @@ import Settings
import Target
import Utilities
+{-
+Note [Binary distributions]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Hadrian produces binary distributions under:
+ <build root>/bindist/ghc-<X>.<Y>.<Z>-<arch>-<os>.tar.xz
+
+It is generated by creating an archive from:
+ <build root>/bindist/ghc-<X>.<Y>.<Z>-<arch>-<os>/
+
+It does so by following the steps below.
+
+- make sure we have a complete stage 2 compiler + haddock
+
+- copy the bin and lib directories of the compiler we built:
+ <build root>/stage1/{bin, lib}
+ to
+ <build root>/bindist/ghc-<X>.<Y>.<Z>-<arch>-<os>/{bin, lib}
+
+- copy the generated docs (user guide, haddocks, etc):
+ <build root>/docs/
+ to
+ <build root>/bindist/ghc-<X>.<Y>.<Z>-<arch>-<os>/docs/
+
+- copy haddock (built by our stage2 compiler):
+ <build root>/stage2/bin/haddock
+ to
+ <build root>/bindist/ghc-<X>.<Y>.<Z>-<arch>-<os>/bin/haddock
+
+- use autoreconf to generate a `configure` script from
+ aclocal.m4 and distrib/configure.ac, that we move to:
+ <build root>/bindist/ghc-<X>.<Y>.<Z>-<arch>-<os>/configure
+
+- write a (fixed) Makefile capable of supporting 'make install' to:
+ <build root>/bindist/ghc-<X>.<Y>.<Z>-<arch>-<os>/Makefile
+
+- write some (fixed) supporting bash code for the wrapper scripts to:
+ <build root>/bindist/ghc-<X>.<Y>.<Z>-<arch>-<os>/wrappers/<program>
+
+ where <program> is the name of the executable that the bash file will
+ help wrapping.
+
+- copy supporting configure/make related files
+ (see @bindistInstallFiles@) to:
+ <build root>/bindist/ghc-<X>.<Y>.<Z>-<arch>-<os>/<file>
+
+- create a .tar.xz archive of the directory:
+ <build root>/bindist/ghc-<X>.<Y>.<Z>-<arch>-<os>/
+ at
+ <build root>/bindist/ghc-<X>.<Y>.<Z>-<arch>-<os>.tar.xz
+
+
+Note [Wrapper scripts and binary distributions]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Users of Linux, FreeBSD, Windows and OS X can unpack a
+binary distribution produced by hadrian for their arch
+and OS and start using @bin/ghc@, @bin/ghc-pkg@ and so on
+right away, without even having to configure or install
+the distribution. They would then be using the real executables
+directly, not through wrapper scripts.
+
+This works because GHCs produced by hadrian on those systems
+are relocatable. This means that you can copy the @bin@ and @lib@
+dirs anywhere and GHC will keep working, as long as both
+directories sit next to each other. (This is achieved by having
+GHC look up its $libdir relatively to where the GHC executable
+resides.)
+
+It is however still possible (and simple) to install a GHC
+distribution that uses wrapper scripts. From the unpacked archive,
+you can simply do:
+
+ ./configure --prefix=<path> [... other configure options ...]
+ make install
+
+-}
+
bindistRules :: Rules ()
bindistRules = do
root <- buildRootRules
@@ -17,6 +95,7 @@ bindistRules = do
-- We 'need' all binaries and libraries
targets <- mapM pkgTarget =<< stagePackages Stage1
need targets
+
version <- setting ProjectVersion
targetPlatform <- setting TargetPlatformFull
cabalHostOs <- cabalOsString <$> setting BuildOs
@@ -36,9 +115,13 @@ bindistRules = do
copyDirectory (ghcBuildDir -/- "bin") bindistFilesDir
copyDirectory (ghcBuildDir -/- "lib") bindistFilesDir
copyDirectory (rtsIncludeDir) bindistFilesDir
- {- TODO: Should we ship docs?
need ["docs"]
- copyDirectory (root -/- "docs") bindistFilesDir -}
+ copyDirectory (root -/- "docs") bindistFilesDir
+
+ -- We copy the binary (<build root>/stage2/bin/haddock) to
+ -- the bindist's bindir (<build root>/bindist/ghc-.../bin/).
+ haddockPath <- programPath (vanillaContext Stage2 haddock)
+ copyFile haddockPath (bindistFilesDir -/- "bin" -/- "haddock")
-- We then 'need' all the files necessary to configure and install
-- (as in, './configure [...] && make install') this build on some
@@ -88,9 +171,8 @@ bindistRules = do
fixup f | f `elem` ["INSTALL", "README"] = "distrib" -/- f
| otherwise = f
--- TODO: This list is surely incomplete -- fix this.
-- | A list of files that allow us to support a simple
--- @./configure [--prefix=PATH] && make install@ workflow.
+-- @./configure [...] && make install@ workflow.
bindistInstallFiles :: [FilePath]
bindistInstallFiles =
[ "config.sub", "config.guess", "install-sh", "mk" -/- "config.mk.in"
@@ -123,7 +205,7 @@ bindistMakefile = unlines
, "\t@echo 'Run \"make install\" to install'"
, "\t@false"
, ""
- , "#------------------------------------------------------------------------------"
+ , "#-----------------------------------------------------------------------"
, "# INSTALL RULES"
, ""
, "# Hacky function to check equality of two strings"
@@ -139,12 +221,11 @@ bindistMakefile = unlines
, "# $6 = Library Directory"
, "# $7 = Docs Directory"
, "# $8 = Includes Directory"
- , "# We are installing wrappers to programs by searching corresponding wrappers."
- , "# If wrapper is not found, we are attaching the common wrapper to it "
- , "# This implementation is a bit hacky and depends on consistency of program"
- , "# names. For hadrian build this will work as programs have a consistent "
- , "# naming procefure. This file is tested on Linux(Ubuntu)"
- , "# TODO : Check implementation in other distributions"
+ , "# We are installing wrappers to programs by searching corresponding"
+ , "# wrappers. If wrapper is not found, we are attaching the common wrapper"
+ , "# to it. This implementation is a bit hacky and depends on consistency"
+ , "# of program names. For hadrian build this will work as programs have a"
+ , "# consistent naming procedure."
, "\trm -f $2"
, "\t$(CREATE_SCRIPT) $2"
, "\t@echo \"#!$(SHELL)\" >> $2"
@@ -162,40 +243,29 @@ bindistMakefile = unlines
, ""
, "# QUESTION : should we use shell commands?"
, ""
- , "# Due to the fact that package database is configured relatively"
- , "# We do not change the relative paths of executables and libraries"
- , "# But instead use wrapper scripts whenever necessary"
- , "LIBPARENT = $(shell dirname $(libdir))"
- , "GHCBINDIR = \"$(LIBPARENT)/bin\""
, ""
, ".PHONY: install"
- , "install: install_bin install_lib install_includes"
- , ""
- , "# Check if we need to install docs"
- , "ifeq \"DOCS\" \"YES\""
- , "install: install_docs"
- , "endif"
+ , "install: install_lib install_bin install_includes"
+ , "install: install_docs install_wrappers install_ghci"
, ""
- , "# If the relative path of binaries and libraries are altered, we will need to"
- , "# install additional wrapper scripts at bindir."
- , "ifneq \"$(LIBPARENT)/bin\" \"$(bindir)\""
- , "install: install_wrappers"
- , "endif"
+ , "ActualBinsDir=${ghclibdir}/bin"
+ , "WrapperBinsDir=${bindir}"
, ""
, "# We need to install binaries relative to libraries."
, "BINARIES = $(wildcard ./bin/*)"
, "install_bin:"
- , "\t@echo \"Copying Binaries to $(GHCBINDIR)\""
- , "\t$(INSTALL_DIR) \"$(GHCBINDIR)\""
+ , "\t@echo \"Copying binaries to $(ActualBinsDir)\""
+ , "\t$(INSTALL_DIR) \"$(ActualBinsDir)\""
, "\tfor i in $(BINARIES); do \\"
- , "\t\tcp -R $$i \"$(GHCBINDIR)\"; \\"
+ , "\t\tcp -R $$i \"$(ActualBinsDir)\"; \\"
, "\tdone"
+ , ""
+ , "install_ghci:"
, "\t@echo \"Copying and installing ghci\""
- , "\trm -f $(GHCBINDIR)/dir"
- , "\t$(CREATE_SCRIPT) $(GHCBINDIR)/ghci"
- , "\t@echo \"#!$(SHELL)\" >> $(GHCBINDIR)/ghci"
- , "\tcat wrappers/ghci-script >> $(GHCBINDIR)/ghci"
- , "\t$(EXECUTABLE_FILE) $(GHCBINDIR)/ghci"
+ , "\t$(CREATE_SCRIPT) $(WrapperBinsDir)/ghci"
+ , "\t@echo \"#!$(SHELL)\" >> $(WrapperBinsDir)/ghci"
+ , "\tcat wrappers/ghci-script >> $(WrapperBinsDir)/ghci"
+ , "\t$(EXECUTABLE_FILE) $(WrapperBinsDir)/ghci"
, ""
, "LIBRARIES = $(wildcard ./lib/*)"
, "install_lib:"
@@ -224,12 +294,15 @@ bindistMakefile = unlines
, "BINARY_NAMES=$(shell ls ./bin/)"
, "install_wrappers:"
, "\t@echo \"Installing Wrapper scripts\""
- , "\t$(INSTALL_DIR) \"$(bindir)\""
+ , "\t$(INSTALL_DIR) \"$(WrapperBinsDir)\""
, "\t$(foreach p, $(BINARY_NAMES),\\"
- , "\t\t$(call installscript,$p,$(bindir)/$p,$(bindir),$(GHCBINDIR),$(GHCBINDIR)/$p,$(libdir),$(docdir),$(includedir)))"
+ , "\t\t$(call installscript,$p,$(WrapperBinsDir)/$p," ++
+ "$(WrapperBinsDir),$(ActualBinsDir),$(ActualBinsDir)/$p," ++
+ "$(libdir),$(docdir),$(includedir)))"
, ""
, "# END INSTALL"
- , "# -----------------------------------------------------------------------------" ]
+ , "# ----------------------------------------------------------------------"
+ ]
wrapper :: FilePath -> String
wrapper "ghc" = ghcWrapper