963bc4c5a052da7ae93416134e25b6b76dd74d1a
[ghc.git] / hadrian / src / Rules / Documentation.hs
1 module Rules.Documentation (
2 -- * Rules
3 buildPackageDocumentation, documentationRules,
4
5 -- * Utilities
6 haddockDependencies
7 ) where
8
9 import Hadrian.Haskell.Cabal
10 import Hadrian.Haskell.Cabal.Type
11
12 import Rules.Generate (ghcPrimDependencies)
13 import Base
14 import Context
15 import Expression (getContextData, interpretInContext, (?), package)
16 import Flavour
17 import Oracles.ModuleFiles
18 import Packages
19 import Settings
20 import Target
21 import Utilities
22
23 import Data.List (union)
24
25 docRoot :: FilePath
26 docRoot = "docs"
27
28 htmlRoot :: FilePath
29 htmlRoot = docRoot -/- "html"
30
31 pdfRoot :: FilePath
32 pdfRoot = docRoot -/- "pdfs"
33
34 archiveRoot :: FilePath
35 archiveRoot = docRoot -/- "archives"
36
37 haddockHtmlLib :: FilePath
38 haddockHtmlLib = htmlRoot -/- "haddock-bundle.min.js"
39
40 manPageBuildPath :: FilePath
41 manPageBuildPath = "docs/users_guide/build-man/ghc.1"
42
43 -- TODO: Get rid of this hack.
44 docContext :: Context
45 docContext = vanillaContext Stage2 (library "Documentation" "docs")
46
47 docPaths :: [FilePath]
48 docPaths = ["libraries", "users_guide", "Haddock"]
49
50 pathPdf :: FilePath -> FilePath
51 pathPdf path = pdfRoot -/- path <.> ".pdf"
52
53 pathIndex :: FilePath -> FilePath
54 pathIndex path = htmlRoot -/- path -/- "index.html"
55
56 pathArchive :: FilePath -> FilePath
57 pathArchive path = archiveRoot -/- path <.> "html.tar.xz"
58
59 -- TODO: Get rid of this hack.
60 pathPath :: FilePath -> FilePath
61 pathPath "users_guide" = "docs/users_guide"
62 pathPath "Haddock" = "utils/haddock/doc"
63 pathPath _ = ""
64
65 -- | Build all documentation
66 documentationRules :: Rules ()
67 documentationRules = do
68 buildDocumentationArchives
69 buildHtmlDocumentation
70 buildManPage
71 buildPdfDocumentation
72
73 -- a phony rule that runs Haddock for "Haskell Hierarchical Libraries" and
74 -- the "GHC-API"
75 "docs-haddock" ~> do
76 root <- buildRoot
77 need [ root -/- pathIndex "libraries" ]
78
79 -- a phony rule that runs Haddock, builds the User's guide, builds
80 -- Haddock's manual, and builds man pages
81 "docs" ~> do
82 root <- buildRoot
83 let html = htmlRoot -/- "index.html" -- also implies "docs-haddock"
84 archives = map pathArchive docPaths
85 pdfs = map pathPdf $ docPaths \\ ["libraries"]
86 need $ map (root -/-) $ [html] ++ archives ++ pdfs ++ [manPageBuildPath]
87
88 ------------------------------------- HTML -------------------------------------
89
90 -- | Build rules for HTML documentation.
91 buildHtmlDocumentation :: Rules ()
92 buildHtmlDocumentation = do
93 mapM_ buildSphinxHtml $ docPaths \\ ["libraries"]
94 buildLibraryDocumentation
95 root <- buildRootRules
96
97 root -/- htmlRoot -/- "index.html" %> \file -> do
98 need [root -/- haddockHtmlLib]
99 need $ map ((root -/-) . pathIndex) docPaths
100 copyFileUntracked "docs/index.html" file
101
102 -- | Compile a Sphinx ReStructured Text package to HTML.
103 buildSphinxHtml :: FilePath -> Rules ()
104 buildSphinxHtml path = do
105 root <- buildRootRules
106 root -/- htmlRoot -/- path -/- "index.html" %> \file -> do
107 need [root -/- haddockHtmlLib]
108 let dest = takeDirectory file
109 build $ target docContext (Sphinx Html) [pathPath path] [dest]
110
111 ------------------------------------ Haddock -----------------------------------
112
113 -- | Build the haddocks for GHC's libraries.
114 buildLibraryDocumentation :: Rules ()
115 buildLibraryDocumentation = do
116 root <- buildRootRules
117
118 -- Js and Css files for haddock output
119 root -/- haddockHtmlLib %> \_ ->
120 copyDirectory "utils/haddock/haddock-api/resources/html" (root -/- docRoot)
121
122 -- Building the "Haskell Hierarchical Libraries" index
123 root -/- htmlRoot -/- "libraries/index.html" %> \file -> do
124 need [ root -/- haddockHtmlLib
125 , "libraries/prologue.txt" ]
126
127 -- We want Haddocks for everything except `rts` to be built, but we
128 -- don't want the index to be polluted by stuff from `ghc`-the-library
129 -- (there will be a seperate top-level link to those Haddocks).
130 haddocks <- allHaddocks
131 let neededDocs = filter (\x -> takeFileName x /= "rts.haddock") haddocks
132 libDocs = filter (\x -> takeFileName x /= "ghc.haddock") neededDocs
133
134 need neededDocs
135 build $ target docContext (Haddock BuildIndex) libDocs [file]
136
137 allHaddocks :: Action [FilePath]
138 allHaddocks = do
139 pkgs <- stagePackages Stage1
140 sequence [ pkgHaddockFile $ vanillaContext Stage1 pkg
141 | pkg <- pkgs, isLibrary pkg ]
142
143 -- Note: this build rule creates plenty of files, not just the .haddock one.
144 -- All of them go into the 'docRoot' subdirectory. Pedantically tracking all
145 -- built files in the Shake database seems fragile and unnecessary.
146 buildPackageDocumentation :: Context -> Rules ()
147 buildPackageDocumentation context@Context {..} = when (stage == Stage1 && package /= rts) $ do
148 root <- buildRootRules
149
150 -- Per-package haddocks
151 root -/- htmlRoot -/- "libraries" -/- pkgName package -/- "haddock-prologue.txt" %> \file -> do
152 need [root -/- haddockHtmlLib]
153 -- This is how @ghc-cabal@ used to produces "haddock-prologue.txt" files.
154 syn <- pkgSynopsis package
155 desc <- pkgDescription package
156 let prologue = if null desc then syn else desc
157 liftIO $ writeFile file prologue
158
159 root -/- htmlRoot -/- "libraries" -/- pkgName package -/- pkgName package <.> "haddock" %> \file -> do
160 need [root -/- htmlRoot -/- "libraries" -/- pkgName package -/- "haddock-prologue.txt"]
161 haddocks <- haddockDependencies context
162
163 -- `ghc-prim` has a source file for 'GHC.Prim' which is generated just
164 -- for Haddock. We need to 'union' (instead of '++') to avoid passing
165 -- 'GHC.PrimopWrappers' (which unfortunately shows up in both
166 -- `generatedSrcs` and `vanillaSrcs`) to Haddock twice.
167 generatedSrcs <- interpretInContext context (Expression.package ghcPrim ? ghcPrimDependencies)
168 vanillaSrcs <- hsSources context
169 let srcs = vanillaSrcs `union` generatedSrcs
170
171 need $ srcs ++ haddocks ++ [root -/- haddockHtmlLib]
172
173 -- Build Haddock documentation
174 -- TODO: Pass the correct way from Rules via Context.
175 dynamicPrograms <- dynamicGhcPrograms =<< flavour
176 let haddockWay = if dynamicPrograms then dynamic else vanilla
177 build $ target (context {way = haddockWay}) (Haddock BuildPackage) srcs [file]
178
179 -------------------------------------- PDF -------------------------------------
180
181 -- | Build all PDF documentation
182 buildPdfDocumentation :: Rules ()
183 buildPdfDocumentation = mapM_ buildSphinxPdf docPaths
184
185 -- | Compile a Sphinx ReStructured Text package to LaTeX
186 buildSphinxPdf :: FilePath -> Rules ()
187 buildSphinxPdf path = do
188 root <- buildRootRules
189 root -/- pdfRoot -/- path <.> "pdf" %> \file -> do
190 need [root -/- haddockHtmlLib]
191 withTempDir $ \dir -> do
192 build $ target docContext (Sphinx Latex) [pathPath path] [dir]
193 build $ target docContext Xelatex [path <.> "tex"] [dir]
194 copyFileUntracked (dir -/- path <.> "pdf") file
195
196 ------------------------------------ Archive -----------------------------------
197
198 -- | Build documentation archives.
199 buildDocumentationArchives :: Rules ()
200 buildDocumentationArchives = mapM_ buildArchive docPaths
201
202 buildArchive :: FilePath -> Rules ()
203 buildArchive path = do
204 root <- buildRootRules
205 root -/- pathArchive path %> \file -> do
206 need [root -/- haddockHtmlLib]
207 root <- buildRoot
208 let src = root -/- pathIndex path
209 need [src]
210 build $ target docContext (Tar Create) [takeDirectory src] [file]
211
212 -- | Build the man page.
213 buildManPage :: Rules ()
214 buildManPage = do
215 root <- buildRootRules
216 root -/- manPageBuildPath %> \file -> do
217 need [root -/- haddockHtmlLib, "docs/users_guide/ghc.rst"]
218 withTempDir $ \dir -> do
219 build $ target docContext (Sphinx Man) ["docs/users_guide"] [dir]
220 copyFileUntracked (dir -/- "ghc.1") file
221
222 -- | Find the Haddock files for the dependencies of the current library.
223 haddockDependencies :: Context -> Action [FilePath]
224 haddockDependencies context = do
225 depNames <- interpretInContext context (getContextData depNames)
226 sequence [ pkgHaddockFile $ vanillaContext Stage1 depPkg
227 | Just depPkg <- map findPackageByName depNames, depPkg /= rts ]