summaryrefslogtreecommitdiff
path: root/hadrian/src/Rules/PackageData.hs
blob: 2442b03de346e0b37dd0e37e5b7e0a746139fb91 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
module Rules.PackageData (buildPackageData) where

import Base
import Context
import Expression
import Oracles.Setting
import Rules.Generate
import Settings.Packages.Rts
import Target
import Utilities

-- | Build @package-data.mk@ by using ghc-cabal utility to process .cabal files.
buildPackageData :: Context -> Rules ()
buildPackageData context@Context {..} = do
    let dir       = "//" ++ contextDir context
        cabalFile = unsafePkgCabalFile package -- TODO: improve
        configure = pkgPath package -/- "configure"
    -- TODO: Get rid of hardcoded file paths.
    [dir -/- "package-data.mk", dir -/- "setup-config"] &%> \[mk, setupConfig] -> do
        -- Make sure all generated dependencies are in place before proceeding.
        orderOnly =<< interpretInContext context generatedDependencies

        -- GhcCabal may run the configure script, so we depend on it.
        whenM (doesFileExist $ configure <.> "ac") $ need [configure]

        -- Before we configure a package its dependencies need to be registered.
        need =<< mapM pkgConfFile =<< contextDependencies context

        need [cabalFile]
        build $ target context GhcCabal [cabalFile] [mk, setupConfig]
        postProcessPackageData context mk

    -- TODO: Get rid of hardcoded file paths.
    dir -/- "inplace-pkg-config" %> \conf -> do
        path     <- buildPath context
        dataFile <- pkgDataFile context
        need [dataFile] -- ghc-cabal builds inplace package configuration file
        if package == rts
        then do
            genPath <- buildRoot <&> (-/- generatedDir)
            rtsPath <- rtsBuildPath
            need [rtsConfIn]
            build $ target context HsCpp [rtsConfIn] [conf]
            fixFile conf $ unlines
                         . map
                         ( replace "\"\"" ""
                         . replace "rts/dist/build" rtsPath
                         . replace "includes/dist-derivedconstants/header" genPath )
                         . lines
        else
            fixFile conf $ unlines . map (replace (path </> "build") path) . lines

    priority 2.0 $ when (nonCabalContext context) $ dir -/- "package-data.mk" %>
        generatePackageData context

generatePackageData :: Context -> FilePath -> Action ()
generatePackageData context@Context {..} file = do
    orderOnly =<< interpretInContext context generatedDependencies
    asmSrcs <- packageAsmSources package
    cSrcs   <- packageCSources   package
    cmmSrcs <- packageCmmSources package
    genPath <- buildRoot <&> (-/- generatedDir)
    writeFileChanged file . unlines $
        [ "S_SRCS = "   ++ unwords asmSrcs                                  ] ++
        [ "C_SRCS = "   ++ unwords cSrcs                                    ] ++
        [ "CMM_SRCS = " ++ unwords cmmSrcs                                  ] ++
        [ "DEP_EXTRA_LIBS = m"                 | package == hp2ps           ] ++
        [ "CC_OPTS = -I" ++ genPath            | package `elem` [hp2ps, rts]] ++
        [ "MODULES = Main"                     | package == ghcCabal        ] ++
        [ "HS_SRC_DIRS = ."                    | package == ghcCabal        ]
    putSuccess $ "| Successfully generated " ++ file

packageCSources :: Package -> Action [FilePath]
packageCSources pkg
    | pkg /= rts = getDirectoryFiles (pkgPath pkg) ["*.c"]
    | otherwise  = do
        windows <- windowsHost
        rtsPath <- rtsBuildPath
        sources <- fmap (map unifyPath) . getDirectoryFiles (pkgPath pkg) .
            map (-/- "*.c") $ [ ".", "hooks", "sm", "eventlog", "linker" ] ++
                              [ if windows then "win32" else "posix"     ]
        return $ sources ++ [ rtsPath -/- "c/sm/Evac_thr.c" ]
                         ++ [ rtsPath -/- "c/sm/Scav_thr.c" ]

packageAsmSources :: Package -> Action [FilePath]
packageAsmSources pkg
    | pkg /= rts = return []
    | otherwise  = do
        buildAdjustor   <- anyTargetArch ["i386", "powerpc", "powerpc64"]
        buildStgCRunAsm <- anyTargetArch ["powerpc64le"]
        return $ [ "AdjustorAsm.S" | buildAdjustor   ]
              ++ [ "StgCRunAsm.S"  | buildStgCRunAsm ]

packageCmmSources :: Package -> Action [FilePath]
packageCmmSources pkg
    | pkg /= rts = return []
    | otherwise  = do
        rtsPath <- rtsBuildPath
        sources <- getDirectoryFiles (pkgPath pkg) ["*.cmm"]
        return $ sources ++ [ rtsPath -/- "cmm/AutoApply.cmm" ]

-- Prepare a given 'packaga-data.mk' file for parsing by readConfigFile:
-- 1) Drop lines containing '$'. For example, get rid of
-- @libraries/Win32_dist-install_CMM_SRCS  := $(addprefix cbits/,$(notdir ...@
-- and replace it with a tracked call to getDirectoryFiles.
-- 2) Drop path prefixes to individual settings.
-- For example, @libraries/deepseq/dist-install_VERSION = 1.4.0.0@
-- is replaced by @VERSION = 1.4.0.0@.
-- Reason: Shake's built-in makefile parser doesn't recognise slashes
-- TODO (izgzhen): should fix DEP_LIB_REL_DIRS_SEARCHPATH
postProcessPackageData :: Context -> FilePath -> Action ()
postProcessPackageData context@Context {..} file = do
    top     <- topDirectory
    cmmSrcs <- getDirectoryFiles (pkgPath package) ["cbits/*.cmm"]
    path    <- buildPath context
    let len = length (pkgPath package) + length (top -/- path) + 2
    fixFile file $ unlines
                 . (++ ["CMM_SRCS = " ++ unwords (map unifyPath cmmSrcs) ])
                 . map (drop len) . filter ('$' `notElem`) . lines