3db64ee64815c51e127d0a9184d93ab8025fe818
[ghc.git] / hadrian / src / Rules / BinaryDist.hs
1 module Rules.BinaryDist where
2
3 import Hadrian.Haskell.Cabal
4
5 import Context
6 import Expression
7 import Oracles.Setting
8 import Packages
9 import Settings
10 import Target
11 import Utilities
12
13 {-
14 Note [Binary distributions]
15 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
16
17 Hadrian produces binary distributions under:
18 <build root>/bindist/ghc-<X>.<Y>.<Z>-<arch>-<os>.tar.xz
19
20 It is generated by creating an archive from:
21 <build root>/bindist/ghc-<X>.<Y>.<Z>-<arch>-<os>/
22
23 It does so by following the steps below.
24
25 - make sure we have a complete stage 2 compiler + haddock
26
27 - copy the bin and lib directories of the compiler we built:
28 <build root>/stage1/{bin, lib}
29 to
30 <build root>/bindist/ghc-<X>.<Y>.<Z>-<arch>-<os>/{bin, lib}
31
32 - copy the generated docs (user guide, haddocks, etc):
33 <build root>/docs/
34 to
35 <build root>/bindist/ghc-<X>.<Y>.<Z>-<arch>-<os>/docs/
36
37 - copy haddock (built by our stage2 compiler):
38 <build root>/stage2/bin/haddock
39 to
40 <build root>/bindist/ghc-<X>.<Y>.<Z>-<arch>-<os>/bin/haddock
41
42 - use autoreconf to generate a `configure` script from
43 aclocal.m4 and distrib/configure.ac, that we move to:
44 <build root>/bindist/ghc-<X>.<Y>.<Z>-<arch>-<os>/configure
45
46 - write a (fixed) Makefile capable of supporting 'make install' to:
47 <build root>/bindist/ghc-<X>.<Y>.<Z>-<arch>-<os>/Makefile
48
49 - write some (fixed) supporting bash code for the wrapper scripts to:
50 <build root>/bindist/ghc-<X>.<Y>.<Z>-<arch>-<os>/wrappers/<program>
51
52 where <program> is the name of the executable that the bash file will
53 help wrapping.
54
55 - copy supporting configure/make related files
56 (see @bindistInstallFiles@) to:
57 <build root>/bindist/ghc-<X>.<Y>.<Z>-<arch>-<os>/<file>
58
59 - create a .tar.xz archive of the directory:
60 <build root>/bindist/ghc-<X>.<Y>.<Z>-<arch>-<os>/
61 at
62 <build root>/bindist/ghc-<X>.<Y>.<Z>-<arch>-<os>.tar.xz
63
64
65 Note [Wrapper scripts and binary distributions]
66 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
67
68 Users of Linux, FreeBSD, Windows and OS X can unpack a
69 binary distribution produced by hadrian for their arch
70 and OS and start using @bin/ghc@, @bin/ghc-pkg@ and so on
71 right away, without even having to configure or install
72 the distribution. They would then be using the real executables
73 directly, not through wrapper scripts.
74
75 This works because GHCs produced by hadrian on those systems
76 are relocatable. This means that you can copy the @bin@ and @lib@
77 dirs anywhere and GHC will keep working, as long as both
78 directories sit next to each other. (This is achieved by having
79 GHC look up its $libdir relatively to where the GHC executable
80 resides.)
81
82 It is however still possible (and simple) to install a GHC
83 distribution that uses wrapper scripts. From the unpacked archive,
84 you can simply do:
85
86 ./configure --prefix=<path> [... other configure options ...]
87 make install
88
89 In order to support @bin@ and @lib@ directories that don't sit next to each
90 other, the install script:
91 * installs programs into @LIBDIR/ghc-VERSION/bin@
92 * installs libraries into @LIBDIR/ghc-VERSION/lib@
93 * installs the wrappers scripts into @BINDIR@ directory
94
95 -}
96
97 bindistRules :: Rules ()
98 bindistRules = do
99 root <- buildRootRules
100 phony "binary-dist-dir" $ do
101 -- We 'need' all binaries and libraries
102 targets <- mapM pkgTarget =<< stagePackages Stage1
103 need targets
104
105 version <- setting ProjectVersion
106 targetPlatform <- setting TargetPlatformFull
107 distDir <- Context.distDir Stage1
108 rtsDir <- pkgIdentifier rts
109 windows <- windowsHost
110
111 let ghcBuildDir = root -/- stageString Stage1
112 bindistFilesDir = root -/- "bindist" -/- ghcVersionPretty
113 ghcVersionPretty = "ghc-" ++ version ++ "-" ++ targetPlatform
114 rtsIncludeDir = ghcBuildDir -/- "lib" -/- distDir -/- rtsDir
115 -/- "include"
116
117 -- We create the bindist directory at <root>/bindist/ghc-X.Y.Z-platform/
118 -- and populate it with Stage2 build results
119 createDirectory bindistFilesDir
120 copyDirectory (ghcBuildDir -/- "bin") bindistFilesDir
121 copyDirectory (ghcBuildDir -/- "lib") bindistFilesDir
122 copyDirectory (rtsIncludeDir) bindistFilesDir
123 need ["docs"]
124 -- TODO: we should only embed the docs that have been generated
125 -- depending on the current settings (flavours' "ghcDocs" field and
126 -- "--docs=.." command-line flag)
127 -- Currently we embed the "docs" directory if it exists but it may
128 -- contain outdated or even invalid data.
129 whenM (doesDirectoryExist (root -/- "docs")) $ do
130 copyDirectory (root -/- "docs") bindistFilesDir
131 when windows $ do
132 copyDirectory (root -/- "mingw") bindistFilesDir
133 -- we use that opportunity to delete the .stamp file that we use
134 -- as a proxy for the whole mingw toolchain, there's no point in
135 -- shipping it
136 removeFile (bindistFilesDir -/- mingwStamp)
137
138 -- We copy the binary (<build root>/stage1/bin/haddock) to
139 -- the bindist's bindir (<build root>/bindist/ghc-.../bin/).
140 haddockPath <- programPath (vanillaContext Stage1 haddock)
141 copyFile haddockPath (bindistFilesDir -/- "bin" -/- "haddock")
142
143 -- We then 'need' all the files necessary to configure and install
144 -- (as in, './configure [...] && make install') this build on some
145 -- other machine.
146 need $ map (bindistFilesDir -/-)
147 (["configure", "Makefile"] ++ bindistInstallFiles)
148 need $ map ((bindistFilesDir -/- "wrappers") -/-) ["check-api-annotations"
149 , "check-ppr", "ghc", "ghc-iserv", "ghc-pkg"
150 , "ghci-script", "haddock", "hpc", "hp2ps", "hsc2hs"
151 , "runghc"]
152
153
154 phony "binary-dist" $ do
155
156 need ["binary-dist-dir"]
157
158 version <- setting ProjectVersion
159 targetPlatform <- setting TargetPlatformFull
160
161 let ghcVersionPretty = "ghc-" ++ version ++ "-" ++ targetPlatform
162
163 -- Finally, we create the archive <root>/bindist/ghc-X.Y.Z-platform.tar.xz
164 tarPath <- builderPath (Tar Create)
165 cmd [Cwd $ root -/- "bindist"] tarPath
166 [ "-c", "--xz", "-f"
167 , ghcVersionPretty <.> "tar.xz"
168 , ghcVersionPretty ]
169
170 -- Prepare binary distribution configure script
171 -- (generated under <ghc root>/distrib/configure by 'autoreconf')
172 root -/- "bindist" -/- "ghc-*" -/- "configure" %> \configurePath -> do
173 ghcRoot <- topDirectory
174 copyFile (ghcRoot -/- "aclocal.m4") (ghcRoot -/- "distrib" -/- "aclocal.m4")
175 buildWithCmdOptions [] $
176 target (vanillaContext Stage1 ghc) (Autoreconf $ ghcRoot -/- "distrib") [] []
177 -- We clean after ourselves, moving the configure script we generated in
178 -- our bindist dir
179 removeFile (ghcRoot -/- "distrib" -/- "aclocal.m4")
180 moveFile (ghcRoot -/- "distrib" -/- "configure") configurePath
181
182 -- Generate the Makefile that enables the "make install" part
183 root -/- "bindist" -/- "ghc-*" -/- "Makefile" %> \makefilePath ->
184 writeFile' makefilePath bindistMakefile
185
186 root -/- "bindist" -/- "ghc-*" -/- "wrappers/*" %> \wrapperPath ->
187 writeFile' wrapperPath $ wrapper (takeFileName wrapperPath)
188
189 -- Copy various configure-related files needed for a working
190 -- './configure [...] && make install' workflow
191 -- (see the list of files needed in the 'binary-dist' rule above, before
192 -- creating the archive).
193 forM_ bindistInstallFiles $ \file ->
194 root -/- "bindist" -/- "ghc-*" -/- file %> \dest -> do
195 ghcRoot <- topDirectory
196 copyFile (ghcRoot -/- fixup file) dest
197
198 where
199 fixup f | f `elem` ["INSTALL", "README"] = "distrib" -/- f
200 | otherwise = f
201
202 -- | A list of files that allow us to support a simple
203 -- @./configure [...] && make install@ workflow.
204 bindistInstallFiles :: [FilePath]
205 bindistInstallFiles =
206 [ "config.sub", "config.guess", "install-sh", "mk" -/- "config.mk.in"
207 , "mk" -/- "install.mk.in", "mk" -/- "project.mk", "settings.in", "README"
208 , "INSTALL" ]
209
210 -- | This auxiliary function gives us a top-level 'Filepath' that we can 'need'
211 -- for all libraries and programs that are needed for a complete build.
212 -- For libraries, it returns the path to the @.conf@ file in the package
213 -- database. For programs, it returns the path to the compiled executable.
214 pkgTarget :: Package -> Action FilePath
215 pkgTarget pkg
216 | isLibrary pkg = pkgConfFile (vanillaContext Stage1 pkg)
217 | otherwise = programPath =<< programContext Stage1 pkg
218
219 -- TODO: Augment this Makefile to match the various parameters that the current
220 -- bindist scripts support.
221 -- | A trivial Makefile that only takes @$prefix@ into account, and not e.g
222 -- @$datadir@ (for docs) and other variables, yet.
223 bindistMakefile :: String
224 bindistMakefile = unlines
225 [ "MAKEFLAGS += --no-builtin-rules"
226 , ".SUFFIXES:"
227 , ""
228 , "include mk/install.mk"
229 , "include mk/config.mk"
230 , ""
231 , ".PHONY: default"
232 , "default:"
233 , "\t@echo 'Run \"make install\" to install'"
234 , "\t@false"
235 , ""
236 , "#-----------------------------------------------------------------------"
237 , "# INSTALL RULES"
238 , ""
239 , "# Hacky function to check equality of two strings"
240 , "# TODO : find if a better function exists"
241 , "eq=$(and $(findstring $(1),$(2)),$(findstring $(2),$(1)))"
242 , ""
243 , "define installscript"
244 , "# $1 = package name"
245 , "# $2 = wrapper path"
246 , "# $3 = bindir"
247 , "# $4 = ghcbindir"
248 , "# $5 = Executable binary path"
249 , "# $6 = Library Directory"
250 , "# $7 = Docs Directory"
251 , "# $8 = Includes Directory"
252 , "# We are installing wrappers to programs by searching corresponding"
253 , "# wrappers. If wrapper is not found, we are attaching the common wrapper"
254 , "# to it. This implementation is a bit hacky and depends on consistency"
255 , "# of program names. For hadrian build this will work as programs have a"
256 , "# consistent naming procedure."
257 , "\trm -f '$2'"
258 , "\t$(CREATE_SCRIPT) '$2'"
259 , "\t@echo \"#!$(SHELL)\" >> '$2'"
260 , "\t@echo \"exedir=\\\"$4\\\"\" >> '$2'"
261 , "\t@echo \"exeprog=\\\"$1\\\"\" >> '$2'"
262 , "\t@echo \"executablename=\\\"$5\\\"\" >> '$2'"
263 , "\t@echo \"bindir=\\\"$3\\\"\" >> '$2'"
264 , "\t@echo \"libdir=\\\"$6\\\"\" >> '$2'"
265 , "\t@echo \"docdir=\\\"$7\\\"\" >> '$2'"
266 , "\t@echo \"includedir=\\\"$8\\\"\" >> '$2'"
267 , "\t@echo \"\" >> '$2'"
268 , "\tcat wrappers/$1 >> '$2'"
269 , "\t$(EXECUTABLE_FILE) '$2' ;"
270 , "endef"
271 , ""
272 , "# Hacky function to patch up the 'haddock-interfaces' and 'haddock-html'"
273 , "# fields in the package .conf files"
274 , "define patchpackageconf"
275 , "# $1 = package name (ex: 'bytestring')"
276 , "# $2 = path to .conf file"
277 , "# $3 = Docs Directory"
278 , "\tcat '$2' | sed 's|haddock-interfaces.*|haddock-interfaces: $3/html/libraries/$1/$1.haddock|' \\"
279 , "\t | sed 's|haddock-html.*|haddock-html: $3/html/libraries/$1|' \\"
280 , "\t > '$2.copy'"
281 , "\tmv '$2.copy' '$2'"
282 , "endef"
283 , ""
284 , "# QUESTION : should we use shell commands?"
285 , ""
286 , ""
287 , ".PHONY: install"
288 , "install: install_lib install_bin install_includes"
289 , "install: install_docs install_wrappers install_ghci"
290 , "install: install_mingw update_package_db"
291 , ""
292 , "ActualBinsDir=${ghclibdir}/bin"
293 , "ActualLibsDir=${ghclibdir}/lib"
294 , "WrapperBinsDir=${bindir}"
295 , ""
296 , "# We need to install binaries relative to libraries."
297 , "BINARIES = $(wildcard ./bin/*)"
298 , "install_bin:"
299 , "\t@echo \"Copying binaries to $(ActualBinsDir)\""
300 , "\t$(INSTALL_DIR) \"$(ActualBinsDir)\""
301 , "\tfor i in $(BINARIES); do \\"
302 , "\t\tcp -R $$i \"$(ActualBinsDir)\"; \\"
303 , "\tdone"
304 , ""
305 , "install_ghci:"
306 , "\t@echo \"Installing ghci wrapper\""
307 , "\t@echo \"#!$(SHELL)\" > '$(WrapperBinsDir)/ghci'"
308 , "\tcat wrappers/ghci-script >> '$(WrapperBinsDir)/ghci'"
309 , "\t$(EXECUTABLE_FILE) '$(WrapperBinsDir)/ghci'"
310 , ""
311 , "LIBRARIES = $(wildcard ./lib/*)"
312 , "install_lib:"
313 , "\t@echo \"Copying libraries to $(ActualLibsDir)\""
314 , "\t$(INSTALL_DIR) \"$(ActualLibsDir)\""
315 , "\tfor i in $(LIBRARIES); do \\"
316 , "\t\tcp -R $$i \"$(ActualLibsDir)/\"; \\"
317 , "\tdone"
318 , ""
319 , "INCLUDES = $(wildcard ./include/*)"
320 , "install_includes:"
321 , "\t@echo \"Copying libraries to $(includedir)\""
322 , "\t$(INSTALL_DIR) \"$(includedir)\""
323 , "\tfor i in $(INCLUDES); do \\"
324 , "\t\tcp -R $$i \"$(includedir)/\"; \\"
325 , "\tdone"
326 , ""
327 , "DOCS = $(wildcard ./docs/*)"
328 , "install_docs:"
329 , "\t@echo \"Copying libraries to $(docdir)\""
330 , "\t$(INSTALL_DIR) \"$(docdir)\""
331 , "\tfor i in $(DOCS); do \\"
332 , "\t\tcp -R $$i \"$(docdir)/\"; \\"
333 , "\tdone"
334 , ""
335 , "BINARY_NAMES=$(shell ls ./wrappers/)"
336 , "install_wrappers:"
337 , "\t@echo \"Installing Wrapper scripts\""
338 , "\t$(INSTALL_DIR) \"$(WrapperBinsDir)\""
339 , "\t$(foreach p, $(BINARY_NAMES),\\"
340 , "\t\t$(call installscript,$p,$(WrapperBinsDir)/$p," ++
341 "$(WrapperBinsDir),$(ActualBinsDir),$(ActualBinsDir)/$p," ++
342 "$(ActualLibsDir),$(docdir),$(includedir)))"
343 , "\trm -f '$(WrapperBinsDir)/ghci-script'" -- FIXME: we shouldn't generate it in the first place
344 , ""
345 , "PKG_CONFS = $(wildcard $(ActualLibsDir)/package.conf.d/*)"
346 , "update_package_db:"
347 , "\t@echo \"Updating the package DB\""
348 , "\t$(foreach p, $(PKG_CONFS),\\"
349 , "\t\t$(call patchpackageconf," ++
350 "$(shell echo $(notdir $p) | sed 's/-\\([0-9]*[0-9]\\.\\)*conf//g')," ++
351 "$p,$(docdir)))"
352 , "\t'$(WrapperBinsDir)/ghc-pkg' recache"
353 , ""
354 , "# The 'foreach' that copies the mingw directory will only trigger a copy"
355 , "# when the wildcard matches, therefore only on Windows."
356 , "MINGW = $(wildcard ./mingw)"
357 , "install_mingw:"
358 , "\t@echo \"Installing MingGW\""
359 , "\t$(INSTALL_DIR) \"$(prefix)/mingw\""
360 , "\t$(foreach d, $(MINGW),\\"
361 , "\t\tcp -R ./mingw \"$(prefix)\")"
362 , "# END INSTALL"
363 , "# ----------------------------------------------------------------------"
364 ]
365
366 wrapper :: FilePath -> String
367 wrapper "ghc" = ghcWrapper
368 wrapper "ghc-pkg" = ghcPkgWrapper
369 wrapper "ghci-script" = ghciScriptWrapper
370 wrapper "haddock" = haddockWrapper
371 wrapper "hsc2hs" = hsc2hsWrapper
372 wrapper "runghc" = runGhcWrapper
373 wrapper _ = commonWrapper
374
375 -- | Wrapper scripts for different programs. Common is default wrapper.
376
377 ghcWrapper :: String
378 ghcWrapper = "exec \"$executablename\" -B\"$libdir\" ${1+\"$@\"}\n"
379
380 ghcPkgWrapper :: String
381 ghcPkgWrapper = unlines
382 [ "PKGCONF=\"$libdir/package.conf.d\""
383 , "exec \"$executablename\" --global-package-db \"$PKGCONF\" ${1+\"$@\"}" ]
384
385 haddockWrapper :: String
386 haddockWrapper = "exec \"$executablename\" -B\"$libdir\" -l\"$libdir\" ${1+\"$@\"}\n"
387
388 commonWrapper :: String
389 commonWrapper = "exec \"$executablename\" ${1+\"$@\"}\n"
390
391 hsc2hsWrapper :: String
392 hsc2hsWrapper = unlines
393 [ "HSC2HS_EXTRA=\"--cflag=-fno-stack-protector --lflag=-fuse-ld=gold\""
394 , "tflag=\"--template=$libdir/template-hsc.h\""
395 , "Iflag=\"-I$includedir/\""
396 , "for arg do"
397 , " case \"$arg\" in"
398 , "# On OS X, we need to specify -m32 or -m64 in order to get gcc to"
399 , "# build binaries for the right target. We do that by putting it in"
400 , "# HSC2HS_EXTRA. When cabal runs hsc2hs, it passes a flag saying which"
401 , "# gcc to use, so if we set HSC2HS_EXTRA= then we don't get binaries"
402 , "# for the right platform. So for now we just don't set HSC2HS_EXTRA="
403 , "# but we probably want to revisit how this works in the future."
404 , "# -c*) HSC2HS_EXTRA=;;"
405 , "# --cc=*) HSC2HS_EXTRA=;;"
406 , " -t*) tflag=;;"
407 , " --template=*) tflag=;;"
408 , " --) break;;"
409 , " esac"
410 , "done"
411 , "exec \"$executablename\" ${tflag:+\"$tflag\"} $HSC2HS_EXTRA ${1+\"$@\"} \"$Iflag\"" ]
412
413 runGhcWrapper :: String
414 runGhcWrapper = "exec \"$executablename\" -f \"$exedir/ghc\" ${1+\"$@\"}\n"
415
416 -- | We need to ship ghci executable, which basically just calls ghc with
417 -- | --interactive flag.
418 ghciScriptWrapper :: String
419 ghciScriptWrapper = unlines
420 [ "DIR=`dirname \"$0\"`"
421 , "executable=\"$DIR/ghc\""
422 , "exec $executable --interactive \"$@\"" ]
423
424 -- | When not on Windows, we want to ship the 3 flavours of the iserv program
425 -- in binary distributions. This isn't easily achievable by just asking for
426 -- the package to be built, since here we're generating 3 different
427 -- executables out of just one package, so we need to specify all 3 contexts
428 -- explicitly and 'need' the result of building them.
429 needIservBins :: Action ()
430 needIservBins = do
431 windows <- windowsHost
432 when (not windows) $ do
433 rtsways <- interpretInContext (vanillaContext Stage1 ghc) getRtsWays
434 need =<< traverse programPath
435 [ Context Stage1 iserv w
436 | w <- [vanilla, profiling, dynamic]
437 , w `elem` rtsways
438 ]