Use Cabal directly in place of ghc-cabal + make build root configurable (#531)
[hadrian.git] / src / Rules / Generate.hs
1 module Rules.Generate (
2 isGeneratedCmmFile, generatePackageCode, generateRules, copyRules,
3 includesDependencies, generatedDependencies
4 ) where
5
6 import Base
7 import Expression
8 import Flavour
9 import GHC.Packages
10 import Oracles.Flag
11 import Oracles.ModuleFiles
12 import Oracles.Setting
13 import Rules.Gmp
14 import Rules.Libffi
15 import Settings
16 import Settings.Packages.Rts
17 import Target
18 import Utilities
19
20 -- | Track this file to rebuild generated files whenever it changes.
21 trackGenerateHs :: Expr ()
22 trackGenerateHs = expr $ need [sourcePath -/- "Rules/Generate.hs"]
23
24 primopsSource :: FilePath
25 primopsSource = "compiler/prelude/primops.txt.pp"
26
27 primopsTxt :: Stage -> FilePath
28 primopsTxt stage = buildDir (vanillaContext stage compiler) -/- "primops.txt"
29
30 platformH :: Stage -> FilePath
31 platformH stage = buildDir (vanillaContext stage compiler) -/- "ghc_boot_platform.h"
32
33 isGeneratedCmmFile :: FilePath -> Bool
34 isGeneratedCmmFile file = takeBaseName file == "AutoApply"
35
36 includesDependencies :: [FilePath]
37 includesDependencies = fmap (generatedDir -/-)
38 [ "ghcautoconf.h"
39 , "ghcplatform.h"
40 , "ghcversion.h" ]
41
42 ghcPrimDependencies :: Expr [FilePath]
43 ghcPrimDependencies = do
44 stage <- getStage
45 path <- expr $ buildPath (vanillaContext stage ghcPrim)
46 return [path -/- "GHC/Prim.hs", path -/- "GHC/PrimopWrappers.hs"]
47
48 derivedConstantsDependencies :: [FilePath]
49 derivedConstantsDependencies = fmap (generatedDir -/-)
50 [ "DerivedConstants.h"
51 , "GHCConstantsHaskellExports.hs"
52 , "GHCConstantsHaskellType.hs"
53 , "GHCConstantsHaskellWrappers.hs" ]
54
55 compilerDependencies :: Expr [FilePath]
56 compilerDependencies = do
57 root <- getBuildRoot
58 stage <- getStage
59 isGmp <- (== integerGmp) <$> getIntegerPackage
60 ghcPath <- expr $ buildPath (vanillaContext stage compiler)
61 gmpPath <- expr gmpBuildPath
62 rtsPath <- expr rtsBuildPath
63 mconcat [ return [root -/- platformH stage]
64 , return ((root -/-) <$> includesDependencies)
65 , return ((root -/-) <$> derivedConstantsDependencies)
66 , notStage0 ? isGmp ? return [gmpPath -/- gmpLibraryH]
67 , notStage0 ? return ((rtsPath -/-) <$> libffiDependencies)
68 , return $ fmap (ghcPath -/-)
69 [ "primop-can-fail.hs-incl"
70 , "primop-code-size.hs-incl"
71 , "primop-commutable.hs-incl"
72 , "primop-data-decl.hs-incl"
73 , "primop-fixity.hs-incl"
74 , "primop-has-side-effects.hs-incl"
75 , "primop-list.hs-incl"
76 , "primop-out-of-line.hs-incl"
77 , "primop-primop-info.hs-incl"
78 , "primop-strictness.hs-incl"
79 , "primop-tag.hs-incl"
80 , "primop-vector-tycons.hs-incl"
81 , "primop-vector-tys-exports.hs-incl"
82 , "primop-vector-tys.hs-incl"
83 , "primop-vector-uniques.hs-incl" ] ]
84
85 generatedDependencies :: Expr [FilePath]
86 generatedDependencies = do
87 root <- getBuildRoot
88 rtsPath <- expr rtsBuildPath
89 mconcat [ package compiler ? compilerDependencies
90 , package ghcPrim ? ghcPrimDependencies
91 , package rts ? return (fmap (rtsPath -/-) libffiDependencies
92 ++ fmap (root -/-) includesDependencies
93 ++ fmap (root -/-) derivedConstantsDependencies)
94 , stage0 ? return (fmap (root -/-) includesDependencies) ]
95
96 generate :: FilePath -> Context -> Expr String -> Action ()
97 generate file context expr = do
98 contents <- interpretInContext context expr
99 writeFileChanged file contents
100 putSuccess $ "| Successfully generated " ++ file ++ "."
101
102 generatePackageCode :: Context -> Rules ()
103 generatePackageCode context@(Context stage pkg _) = do
104 root <- buildRootRules
105 let dir = buildDir context
106 generated f = (root -/- dir ++ "//*.hs") ?== f && not ("//autogen/*" ?== f)
107 go gen file = generate file context gen
108 generated ?> \file -> do
109 let unpack = fromMaybe . error $ "No generator for " ++ file ++ "."
110 (src, builder) <- unpack <$> findGenerator context file
111 need [src]
112 build $ target context builder [src] [file]
113 let boot = src -<.> "hs-boot"
114 whenM (doesFileExist boot) . copyFile boot $ file -<.> "hs-boot"
115
116 priority 2.0 $ do
117 when (pkg == compiler) $ do root <//> dir -/- "Config.hs" %> go generateConfigHs
118 root <//> dir -/- "*.hs-incl" %> genPrimopCode context
119 when (pkg == ghcPrim) $ do (root <//> dir -/- "GHC/Prim.hs") %> genPrimopCode context
120 (root <//> dir -/- "GHC/PrimopWrappers.hs") %> genPrimopCode context
121 when (pkg == ghcPkg) $ do root <//> dir -/- "Version.hs" %> go generateVersionHs
122
123 -- TODO: needing platformH is ugly and fragile
124 when (pkg == compiler) $ do
125 root -/- primopsTxt stage %> \file -> do
126 root <- buildRoot
127 need $ [ root -/- platformH stage
128 , primopsSource]
129 ++ fmap (root -/-) includesDependencies
130 build $ target context HsCpp [primopsSource] [file]
131
132 -- only generate this once! Until we have the include logic fixed.
133 -- See the note on `platformH`
134 when (stage == Stage0) $ do
135 root <//> "compiler/ghc_boot_platform.h" %> go generateGhcBootPlatformH
136 root <//> platformH stage %> go generateGhcBootPlatformH
137
138 when (pkg == rts) $ do
139 root <//> dir -/- "cmm/AutoApply.cmm" %> \file ->
140 build $ target context GenApply [] [file]
141
142 -- XXX: this should be fixed properly, e.g. generated here on demand.
143 (root <//> dir -/- "DerivedConstants.h") <~ (buildRoot <&> (-/- generatedDir))
144 (root <//> dir -/- "ghcautoconf.h") <~ (buildRoot <&> (-/- generatedDir))
145 (root <//> dir -/- "ghcplatform.h") <~ (buildRoot <&> (-/- generatedDir))
146 (root <//> dir -/- "ghcversion.h") <~ (buildRoot <&> (-/- generatedDir))
147 when (pkg == integerGmp) $ do
148 (root <//> dir -/- "ghc-gmp.h") <~ (buildRoot <&> (-/- "include"))
149 where
150 pattern <~ mdir = pattern %> \file -> do
151 dir <- mdir
152 copyFile (dir -/- takeFileName file) file
153
154 genPrimopCode :: Context -> FilePath -> Action ()
155 genPrimopCode context@(Context stage _pkg _) file = do
156 root <- buildRoot
157 need [root -/- primopsTxt stage]
158 build $ target context GenPrimopCode [root -/- primopsTxt stage] [file]
159
160 copyRules :: Rules ()
161 copyRules = do
162 root <- buildRootRules
163 forM_ [Stage0 ..] $ \stage -> do
164 let prefix = root -/- stageString stage -/- "lib"
165 (prefix -/- "ghc-usage.txt") <~ return "driver"
166 (prefix -/- "ghci-usage.txt" ) <~ return "driver"
167 (prefix -/- "llvm-targets") <~ return "."
168 (prefix -/- "platformConstants") <~ (buildRoot <&> (-/- generatedDir))
169 (prefix -/- "settings") <~ return "."
170 (prefix -/- "template-hsc.h") <~ return (pkgPath hsc2hs)
171 where
172 pattern <~ mdir = pattern %> \file -> do
173 dir <- mdir
174 copyFile (dir -/- takeFileName file) file
175
176 generateRules :: Rules ()
177 generateRules = do
178 root <- buildRootRules
179 priority 2.0 $ (root -/- generatedDir -/- "ghcautoconf.h") <~ generateGhcAutoconfH
180 priority 2.0 $ (root -/- generatedDir -/- "ghcplatform.h") <~ generateGhcPlatformH
181 priority 2.0 $ (root -/- generatedDir -/- "ghcversion.h") <~ generateGhcVersionH
182
183 forM_ [Stage0 ..] $ \stage ->
184 root -/- ghcSplitPath stage %> \path -> do
185 generate path emptyTarget generateGhcSplit
186 makeExecutable path
187
188 -- TODO: simplify, get rid of fake rts context
189 root -/- generatedDir ++ "//*" %> \file -> do
190 withTempDir $ \dir -> build $
191 target rtsContext DeriveConstants [] [file, dir]
192 where
193 file <~ gen = file %> \out -> generate out emptyTarget gen
194
195 -- TODO: Use the Types, Luke! (drop partial function)
196 -- We sometimes need to evaluate expressions that do not require knowing all
197 -- information about the context. In this case, we don't want to know anything.
198 emptyTarget :: Context
199 emptyTarget = vanillaContext (error "Rules.Generate.emptyTarget: unknown stage")
200 (error "Rules.Generate.emptyTarget: unknown package")
201
202 -- Generators
203
204 -- | Given a 'String' replace charaters '.' and '-' by underscores ('_') so that
205 -- the resulting 'String' is a valid C preprocessor identifier.
206 cppify :: String -> String
207 cppify = replaceEq '-' '_' . replaceEq '.' '_'
208
209 ghcSplitSource :: FilePath
210 ghcSplitSource = "driver/split/ghc-split.pl"
211
212 -- ref: rules/build-perl.mk
213 -- | Generate the @ghc-split@ Perl script.
214 generateGhcSplit :: Expr String
215 generateGhcSplit = do
216 trackGenerateHs
217 targetPlatform <- getSetting TargetPlatform
218 ghcEnableTNC <- expr $ yesNo <$> ghcEnableTablesNextToCode
219 perlPath <- getBuilderPath Perl
220 contents <- expr $ readFileLines ghcSplitSource
221 return . unlines $
222 [ "#!" ++ perlPath
223 , "my $TARGETPLATFORM = " ++ show targetPlatform ++ ";"
224 -- I don't see where the ghc-split tool uses TNC, but
225 -- it's in the build-perl macro.
226 , "my $TABLES_NEXT_TO_CODE = " ++ show ghcEnableTNC ++ ";"
227 ] ++ contents
228
229 -- | Generate @ghcplatform.h@ header.
230 generateGhcPlatformH :: Expr String
231 generateGhcPlatformH = do
232 trackGenerateHs
233 hostPlatform <- getSetting HostPlatform
234 hostArch <- getSetting HostArch
235 hostOs <- getSetting HostOs
236 hostVendor <- getSetting HostVendor
237 targetPlatform <- getSetting TargetPlatform
238 targetArch <- getSetting TargetArch
239 targetOs <- getSetting TargetOs
240 targetVendor <- getSetting TargetVendor
241 ghcUnreg <- expr $ flag GhcUnregisterised
242 return . unlines $
243 [ "#ifndef __GHCPLATFORM_H__"
244 , "#define __GHCPLATFORM_H__"
245 , ""
246 , "#define BuildPlatform_TYPE " ++ cppify hostPlatform
247 , "#define HostPlatform_TYPE " ++ cppify targetPlatform
248 , ""
249 , "#define " ++ cppify hostPlatform ++ "_BUILD 1"
250 , "#define " ++ cppify targetPlatform ++ "_HOST 1"
251 , ""
252 , "#define " ++ hostArch ++ "_BUILD_ARCH 1"
253 , "#define " ++ targetArch ++ "_HOST_ARCH 1"
254 , "#define BUILD_ARCH " ++ show hostArch
255 , "#define HOST_ARCH " ++ show targetArch
256 , ""
257 , "#define " ++ hostOs ++ "_BUILD_OS 1"
258 , "#define " ++ targetOs ++ "_HOST_OS 1"
259 , "#define BUILD_OS " ++ show hostOs
260 , "#define HOST_OS " ++ show targetOs
261 , ""
262 , "#define " ++ hostVendor ++ "_BUILD_VENDOR 1"
263 , "#define " ++ targetVendor ++ "_HOST_VENDOR 1"
264 , "#define BUILD_VENDOR " ++ show hostVendor
265 , "#define HOST_VENDOR " ++ show targetVendor
266 , ""
267 , "/* These TARGET macros are for backwards compatibility... DO NOT USE! */"
268 , "#define TargetPlatform_TYPE " ++ cppify targetPlatform
269 , "#define " ++ cppify targetPlatform ++ "_TARGET 1"
270 , "#define " ++ targetArch ++ "_TARGET_ARCH 1"
271 , "#define TARGET_ARCH " ++ show targetArch
272 , "#define " ++ targetOs ++ "_TARGET_OS 1"
273 , "#define TARGET_OS " ++ show targetOs
274 , "#define " ++ targetVendor ++ "_TARGET_VENDOR 1" ]
275 ++
276 [ "#define UnregisterisedCompiler 1" | ghcUnreg ]
277 ++
278 [ "\n#endif /* __GHCPLATFORM_H__ */" ]
279
280 -- | Generate @Config.hs@ files.
281 generateConfigHs :: Expr String
282 generateConfigHs = do
283 trackGenerateHs
284 cProjectName <- getSetting ProjectName
285 cProjectGitCommitId <- getSetting ProjectGitCommitId
286 cProjectVersion <- getSetting ProjectVersion
287 cProjectVersionInt <- getSetting ProjectVersionInt
288 cProjectPatchLevel <- getSetting ProjectPatchLevel
289 cProjectPatchLevel1 <- getSetting ProjectPatchLevel1
290 cProjectPatchLevel2 <- getSetting ProjectPatchLevel2
291 cBooterVersion <- getSetting GhcVersion
292 intLib <- getIntegerPackage
293 debugged <- ghcDebugged <$> expr flavour
294 let cIntegerLibraryType
295 | intLib == integerGmp = "IntegerGMP"
296 | intLib == integerSimple = "IntegerSimple"
297 | otherwise = error $ "Unknown integer library: " ++ pkgName intLib
298 cSupportsSplitObjs <- expr $ yesNo <$> supportsSplitObjects
299 cGhcWithInterpreter <- expr $ yesNo <$> ghcWithInterpreter
300 cGhcWithNativeCodeGen <- expr $ yesNo <$> ghcWithNativeCodeGen
301 cGhcWithSMP <- expr $ yesNo <$> ghcWithSMP
302 cGhcEnableTablesNextToCode <- expr $ yesNo <$> ghcEnableTablesNextToCode
303 cLeadingUnderscore <- expr $ yesNo <$> flag LeadingUnderscore
304 cGHC_UNLIT_PGM <- fmap takeFileName $ getBuilderPath Unlit
305 cLibFFI <- expr useLibFFIForAdjustors
306 rtsWays <- getRtsWays
307 cGhcRtsWithLibdw <- expr $ flag WithLibdw
308 let cGhcRTSWays = unwords $ map show rtsWays
309 return $ unlines
310 [ "{-# LANGUAGE CPP #-}"
311 , "module Config where"
312 , ""
313 , "import GhcPrelude"
314 , ""
315 , "#include \"ghc_boot_platform.h\""
316 , ""
317 , "data IntegerLibrary = IntegerGMP"
318 , " | IntegerSimple"
319 , " deriving Eq"
320 , ""
321 , "cBuildPlatformString :: String"
322 , "cBuildPlatformString = BuildPlatform_NAME"
323 , "cHostPlatformString :: String"
324 , "cHostPlatformString = HostPlatform_NAME"
325 , "cTargetPlatformString :: String"
326 , "cTargetPlatformString = TargetPlatform_NAME"
327 , ""
328 , "cProjectName :: String"
329 , "cProjectName = " ++ show cProjectName
330 , "cProjectGitCommitId :: String"
331 , "cProjectGitCommitId = " ++ show cProjectGitCommitId
332 , "cProjectVersion :: String"
333 , "cProjectVersion = " ++ show cProjectVersion
334 , "cProjectVersionInt :: String"
335 , "cProjectVersionInt = " ++ show cProjectVersionInt
336 , "cProjectPatchLevel :: String"
337 , "cProjectPatchLevel = " ++ show cProjectPatchLevel
338 , "cProjectPatchLevel1 :: String"
339 , "cProjectPatchLevel1 = " ++ show cProjectPatchLevel1
340 , "cProjectPatchLevel2 :: String"
341 , "cProjectPatchLevel2 = " ++ show cProjectPatchLevel2
342 , "cBooterVersion :: String"
343 , "cBooterVersion = " ++ show cBooterVersion
344 , "cStage :: String"
345 , "cStage = show (STAGE :: Int)"
346 , "cIntegerLibrary :: String"
347 , "cIntegerLibrary = " ++ show (pkgName intLib)
348 , "cIntegerLibraryType :: IntegerLibrary"
349 , "cIntegerLibraryType = " ++ cIntegerLibraryType
350 , "cSupportsSplitObjs :: String"
351 , "cSupportsSplitObjs = " ++ show cSupportsSplitObjs
352 , "cGhcWithInterpreter :: String"
353 , "cGhcWithInterpreter = " ++ show cGhcWithInterpreter
354 , "cGhcWithNativeCodeGen :: String"
355 , "cGhcWithNativeCodeGen = " ++ show cGhcWithNativeCodeGen
356 , "cGhcWithSMP :: String"
357 , "cGhcWithSMP = " ++ show cGhcWithSMP
358 , "cGhcRTSWays :: String"
359 , "cGhcRTSWays = " ++ show cGhcRTSWays
360 , "cGhcEnableTablesNextToCode :: String"
361 , "cGhcEnableTablesNextToCode = " ++ show cGhcEnableTablesNextToCode
362 , "cLeadingUnderscore :: String"
363 , "cLeadingUnderscore = " ++ show cLeadingUnderscore
364 , "cGHC_UNLIT_PGM :: String"
365 , "cGHC_UNLIT_PGM = " ++ show cGHC_UNLIT_PGM
366 , "cGHC_SPLIT_PGM :: String"
367 , "cGHC_SPLIT_PGM = " ++ show "ghc-split"
368 , "cLibFFI :: Bool"
369 , "cLibFFI = " ++ show cLibFFI
370 , "cGhcThreaded :: Bool"
371 , "cGhcThreaded = " ++ show (any (wayUnit Threaded) rtsWays)
372 , "cGhcDebugged :: Bool"
373 , "cGhcDebugged = " ++ show debugged
374 , "cGhcRtsWithLibdw :: Bool"
375 , "cGhcRtsWithLibdw = " ++ show cGhcRtsWithLibdw ]
376
377 -- | Generate @ghcautoconf.h@ header.
378 generateGhcAutoconfH :: Expr String
379 generateGhcAutoconfH = do
380 trackGenerateHs
381 configHContents <- expr $ map undefinePackage <$> readFileLines configH
382 tablesNextToCode <- expr ghcEnableTablesNextToCode
383 ghcUnreg <- expr $ flag GhcUnregisterised
384 ccLlvmBackend <- getSetting CcLlvmBackend
385 ccClangBackend <- getSetting CcClangBackend
386 return . unlines $
387 [ "#ifndef __GHCAUTOCONF_H__"
388 , "#define __GHCAUTOCONF_H__" ]
389 ++ configHContents ++
390 [ "\n#define TABLES_NEXT_TO_CODE 1" | tablesNextToCode && not ghcUnreg ]
391 ++
392 [ "\n#define llvm_CC_FLAVOR 1" | ccLlvmBackend == "1" ]
393 ++
394 [ "\n#define clang_CC_FLAVOR 1" | ccClangBackend == "1" ]
395 ++
396 [ "#endif /* __GHCAUTOCONF_H__ */" ]
397 where
398 undefinePackage s
399 | "#define PACKAGE_" `isPrefixOf` s
400 = "/* #undef " ++ takeWhile (/=' ') (drop 8 s) ++ " */"
401 | otherwise = s
402
403 -- | Generate @ghc_boot_platform.h@ headers.
404 generateGhcBootPlatformH :: Expr String
405 generateGhcBootPlatformH = do
406 trackGenerateHs
407 stage <- getStage
408 let chooseSetting x y = getSetting $ if stage == Stage0 then x else y
409 buildPlatform <- chooseSetting BuildPlatform HostPlatform
410 buildArch <- chooseSetting BuildArch HostArch
411 buildOs <- chooseSetting BuildOs HostOs
412 buildVendor <- chooseSetting BuildVendor HostVendor
413 hostPlatform <- chooseSetting HostPlatform TargetPlatform
414 hostArch <- chooseSetting HostArch TargetArch
415 hostOs <- chooseSetting HostOs TargetOs
416 hostVendor <- chooseSetting HostVendor TargetVendor
417 targetPlatform <- getSetting TargetPlatform
418 targetArch <- getSetting TargetArch
419 llvmTarget <- getSetting LlvmTarget
420 targetOs <- getSetting TargetOs
421 targetVendor <- getSetting TargetVendor
422 return $ unlines
423 [ "#ifndef __PLATFORM_H__"
424 , "#define __PLATFORM_H__"
425 , ""
426 , "#define BuildPlatform_NAME " ++ show buildPlatform
427 , "#define HostPlatform_NAME " ++ show hostPlatform
428 , "#define TargetPlatform_NAME " ++ show targetPlatform
429 , ""
430 , "#define " ++ cppify buildPlatform ++ "_BUILD 1"
431 , "#define " ++ cppify hostPlatform ++ "_HOST 1"
432 , "#define " ++ cppify targetPlatform ++ "_TARGET 1"
433 , ""
434 , "#define " ++ buildArch ++ "_BUILD_ARCH 1"
435 , "#define " ++ hostArch ++ "_HOST_ARCH 1"
436 , "#define " ++ targetArch ++ "_TARGET_ARCH 1"
437 , "#define BUILD_ARCH " ++ show buildArch
438 , "#define HOST_ARCH " ++ show hostArch
439 , "#define TARGET_ARCH " ++ show targetArch
440 , "#define LLVM_TARGET " ++ show llvmTarget
441 , ""
442 , "#define " ++ buildOs ++ "_BUILD_OS 1"
443 , "#define " ++ hostOs ++ "_HOST_OS 1"
444 , "#define " ++ targetOs ++ "_TARGET_OS 1"
445 , "#define BUILD_OS " ++ show buildOs
446 , "#define HOST_OS " ++ show hostOs
447 , "#define TARGET_OS " ++ show targetOs
448 , ""
449 , "#define " ++ buildVendor ++ "_BUILD_VENDOR 1"
450 , "#define " ++ hostVendor ++ "_HOST_VENDOR 1"
451 , "#define " ++ targetVendor ++ "_TARGET_VENDOR 1"
452 , "#define BUILD_VENDOR " ++ show buildVendor
453 , "#define HOST_VENDOR " ++ show hostVendor
454 , "#define TARGET_VENDOR " ++ show targetVendor
455 , ""
456 , "#endif /* __PLATFORM_H__ */" ]
457
458 -- | Generate @ghcversion.h@ header.
459 generateGhcVersionH :: Expr String
460 generateGhcVersionH = do
461 trackGenerateHs
462 version <- getSetting ProjectVersionInt
463 patchLevel1 <- getSetting ProjectPatchLevel1
464 patchLevel2 <- getSetting ProjectPatchLevel2
465 return . unlines $
466 [ "#ifndef __GHCVERSION_H__"
467 , "#define __GHCVERSION_H__"
468 , ""
469 , "#ifndef __GLASGOW_HASKELL__"
470 , "# define __GLASGOW_HASKELL__ " ++ version
471 , "#endif"
472 , ""]
473 ++
474 [ "#define __GLASGOW_HASKELL_PATCHLEVEL1__ " ++ patchLevel1 | patchLevel1 /= "" ]
475 ++
476 [ "#define __GLASGOW_HASKELL_PATCHLEVEL2__ " ++ patchLevel2 | patchLevel2 /= "" ]
477 ++
478 [ ""
479 , "#define MIN_VERSION_GLASGOW_HASKELL(ma,mi,pl1,pl2) (\\"
480 , " ((ma)*100+(mi)) < __GLASGOW_HASKELL__ || \\"
481 , " ((ma)*100+(mi)) == __GLASGOW_HASKELL__ \\"
482 , " && (pl1) < __GLASGOW_HASKELL_PATCHLEVEL1__ || \\"
483 , " ((ma)*100+(mi)) == __GLASGOW_HASKELL__ \\"
484 , " && (pl1) == __GLASGOW_HASKELL_PATCHLEVEL1__ \\"
485 , " && (pl2) <= __GLASGOW_HASKELL_PATCHLEVEL2__ )"
486 , ""
487 , "#endif /* __GHCVERSION_H__ */" ]
488
489 -- | Generate @Version.hs@ files.
490 generateVersionHs :: Expr String
491 generateVersionHs = do
492 trackGenerateHs
493 projectVersion <- getSetting ProjectVersion
494 targetOs <- getSetting TargetOs
495 targetArch <- getSetting TargetArch
496 return $ unlines
497 [ "module Version where"
498 , "version, targetOS, targetARCH :: String"
499 , "version = " ++ show projectVersion
500 , "targetOS = " ++ show targetOs
501 , "targetARCH = " ++ show targetArch ]