46ae5b5bd0dda1114a871b83d0224298156df7e5
[ghc.git] / hadrian / src / Oracles / Setting.hs
1 module Oracles.Setting (
2 configFile, Setting (..), SettingList (..), setting, settingList, getSetting,
3 getSettingList, anyTargetPlatform, anyTargetOs, anyTargetArch, anyHostOs,
4 ghcWithInterpreter, ghcEnableTablesNextToCode, useLibFFIForAdjustors,
5 ghcCanonVersion, cmdLineLengthLimit, iosHost, osxHost, windowsHost,
6 hostSupportsRPaths, topDirectory, libsuf, ghcVersionStage
7 ) where
8
9 import Hadrian.Expression
10 import Hadrian.Oracles.TextFile
11 import Hadrian.Oracles.Path
12
13 import Base
14
15 -- | Each 'Setting' comes from the file @hadrian/cfg/system.config@, generated
16 -- by the @configure@ script from the input file @hadrian/cfg/system.config.in@.
17 -- For example, the line
18 --
19 -- > target-os = mingw32
20 --
21 -- sets the value of the setting 'TargetOs'. The action 'setting' 'TargetOs'
22 -- looks up the value of the setting and returns the string @"mingw32"@,
23 -- tracking the result in the Shake database.
24 data Setting = BuildArch
25 | BuildOs
26 | BuildPlatform
27 | BuildVendor
28 | CcClangBackend
29 | CcLlvmBackend
30 | CursesLibDir
31 | DynamicExtension
32 | FfiIncludeDir
33 | FfiLibDir
34 | GhcMajorVersion
35 | GhcMinorVersion
36 | GhcPatchLevel
37 | GhcVersion
38 | GhcSourcePath
39 | GmpIncludeDir
40 | GmpLibDir
41 | HostArch
42 | HostOs
43 | HostPlatform
44 | HostVendor
45 | IconvIncludeDir
46 | IconvLibDir
47 | LlvmTarget
48 | ProjectGitCommitId
49 | ProjectName
50 | ProjectVersion
51 | ProjectVersionInt
52 | ProjectPatchLevel
53 | ProjectPatchLevel1
54 | ProjectPatchLevel2
55 | SystemGhc
56 | TargetArch
57 | TargetOs
58 | TargetPlatform
59 | TargetPlatformFull
60 | TargetVendor
61
62 -- TODO: Reduce the variety of similar flags (e.g. CPP and non-CPP versions).
63 -- | Each 'SettingList' comes from the file @hadrian/cfg/system.config@,
64 -- generated by the @configure@ script from the input file
65 -- @hadrian/cfg/system.config.in@. For example, the line
66 --
67 -- > hs-cpp-args = -E -undef -traditional
68 --
69 -- sets the value of 'HsCppArgs'. The action 'settingList' 'HsCppArgs' looks up
70 -- the value of the setting and returns the list of strings
71 -- @["-E", "-undef", "-traditional"]@, tracking the result in the Shake database.
72 data SettingList = ConfCcArgs Stage
73 | ConfCppArgs Stage
74 | ConfGccLinkerArgs Stage
75 | ConfLdLinkerArgs Stage
76 | HsCppArgs
77
78 -- | Look up the value of a 'Setting' in @cfg/system.config@, tracking the
79 -- result.
80 setting :: Setting -> Action String
81 setting key = lookupValueOrError configFile $ case key of
82 BuildArch -> "build-arch"
83 BuildOs -> "build-os"
84 BuildPlatform -> "build-platform"
85 BuildVendor -> "build-vendor"
86 CcClangBackend -> "cc-clang-backend"
87 CcLlvmBackend -> "cc-llvm-backend"
88 CursesLibDir -> "curses-lib-dir"
89 DynamicExtension -> "dynamic-extension"
90 FfiIncludeDir -> "ffi-include-dir"
91 FfiLibDir -> "ffi-lib-dir"
92 GhcMajorVersion -> "ghc-major-version"
93 GhcMinorVersion -> "ghc-minor-version"
94 GhcPatchLevel -> "ghc-patch-level"
95 GhcVersion -> "ghc-version"
96 GhcSourcePath -> "ghc-source-path"
97 GmpIncludeDir -> "gmp-include-dir"
98 GmpLibDir -> "gmp-lib-dir"
99 HostArch -> "host-arch"
100 HostOs -> "host-os"
101 HostPlatform -> "host-platform"
102 HostVendor -> "host-vendor"
103 IconvIncludeDir -> "iconv-include-dir"
104 IconvLibDir -> "iconv-lib-dir"
105 LlvmTarget -> "llvm-target"
106 ProjectGitCommitId -> "project-git-commit-id"
107 ProjectName -> "project-name"
108 ProjectVersion -> "project-version"
109 ProjectVersionInt -> "project-version-int"
110 ProjectPatchLevel -> "project-patch-level"
111 ProjectPatchLevel1 -> "project-patch-level1"
112 ProjectPatchLevel2 -> "project-patch-level2"
113 SystemGhc -> "system-ghc"
114 TargetArch -> "target-arch"
115 TargetOs -> "target-os"
116 TargetPlatform -> "target-platform"
117 TargetPlatformFull -> "target-platform-full"
118 TargetVendor -> "target-vendor"
119
120 -- | Look up the value of a 'SettingList' in @cfg/system.config@, tracking the
121 -- result.
122 settingList :: SettingList -> Action [String]
123 settingList key = fmap words $ lookupValueOrError configFile $ case key of
124 ConfCcArgs stage -> "conf-cc-args-" ++ stageString stage
125 ConfCppArgs stage -> "conf-cpp-args-" ++ stageString stage
126 ConfGccLinkerArgs stage -> "conf-gcc-linker-args-" ++ stageString stage
127 ConfLdLinkerArgs stage -> "conf-ld-linker-args-" ++ stageString stage
128 HsCppArgs -> "hs-cpp-args"
129
130 -- | An expression that looks up the value of a 'Setting' in @cfg/system.config@,
131 -- tracking the result.
132 getSetting :: Setting -> Expr c b String
133 getSetting = expr . setting
134
135 -- | An expression that looks up the value of a 'SettingList' in
136 -- @cfg/system.config@, tracking the result.
137 getSettingList :: SettingList -> Args c b
138 getSettingList = expr . settingList
139
140 -- | Check whether the value of a 'Setting' matches one of the given strings.
141 matchSetting :: Setting -> [String] -> Action Bool
142 matchSetting key values = (`elem` values) <$> setting key
143
144 -- | Check whether the target platform setting matches one of the given strings.
145 anyTargetPlatform :: [String] -> Action Bool
146 anyTargetPlatform = matchSetting TargetPlatformFull
147
148 -- | Check whether the target OS setting matches one of the given strings.
149 anyTargetOs :: [String] -> Action Bool
150 anyTargetOs = matchSetting TargetOs
151
152 -- | Check whether the target architecture setting matches one of the given
153 -- strings.
154 anyTargetArch :: [String] -> Action Bool
155 anyTargetArch = matchSetting TargetArch
156
157 -- | Check whether the host OS setting matches one of the given strings.
158 anyHostOs :: [String] -> Action Bool
159 anyHostOs = matchSetting HostOs
160
161 -- | Check whether the host OS setting is set to @"ios"@.
162 iosHost :: Action Bool
163 iosHost = anyHostOs ["ios"]
164
165 -- | Check whether the host OS setting is set to @"darwin"@.
166 osxHost :: Action Bool
167 osxHost = anyHostOs ["darwin"]
168
169 -- | Check whether the host OS supports the @-rpath@ linker option when
170 -- using dynamic linking.
171 --
172 -- TODO: Windows supports lazy binding (but GHC doesn't currently support
173 -- dynamic way on Windows anyways).
174 hostSupportsRPaths :: Action Bool
175 hostSupportsRPaths = anyHostOs ["linux", "darwin", "freebsd"]
176
177 -- | Check whether the host OS setting is set to @"mingw32"@ or @"cygwin32"@.
178 windowsHost :: Action Bool
179 windowsHost = anyHostOs ["mingw32", "cygwin32"]
180
181 -- | Check whether the target supports GHCi.
182 ghcWithInterpreter :: Action Bool
183 ghcWithInterpreter = do
184 goodOs <- anyTargetOs [ "mingw32", "cygwin32", "linux", "solaris2"
185 , "freebsd", "dragonfly", "netbsd", "openbsd"
186 , "darwin", "kfreebsdgnu" ]
187 goodArch <- anyTargetArch [ "i386", "x86_64", "powerpc", "sparc"
188 , "sparc64", "arm" ]
189 return $ goodOs && goodArch
190
191 -- | Check whether the target architecture supports placing info tables next to
192 -- code. See: https://gitlab.haskell.org/ghc/ghc/wikis/commentary/rts/storage/heap-objects#tables_next_to_code.
193 ghcEnableTablesNextToCode :: Action Bool
194 ghcEnableTablesNextToCode = notM $ anyTargetArch ["ia64", "powerpc64", "powerpc64le"]
195
196 -- | Check to use @libffi@ for adjustors.
197 useLibFFIForAdjustors :: Action Bool
198 useLibFFIForAdjustors = notM $ anyTargetArch ["i386", "x86_64"]
199
200 -- | Canonicalised GHC version number, used for integer version comparisons. We
201 -- expand 'GhcMinorVersion' to two digits by adding a leading zero if necessary.
202 ghcCanonVersion :: Action String
203 ghcCanonVersion = do
204 ghcMajorVersion <- setting GhcMajorVersion
205 ghcMinorVersion <- setting GhcMinorVersion
206 let leadingZero = [ '0' | length ghcMinorVersion == 1 ]
207 return $ ghcMajorVersion ++ leadingZero ++ ghcMinorVersion
208
209 -- | Path to the GHC source tree.
210 topDirectory :: Action FilePath
211 topDirectory = fixAbsolutePathOnWindows =<< setting GhcSourcePath
212
213 ghcVersionStage :: Stage -> Action String
214 ghcVersionStage Stage0 = setting GhcVersion
215 ghcVersionStage _ = setting ProjectVersion
216
217 -- | The file suffix used for libraries of a given build 'Way'. For example,
218 -- @_p.a@ corresponds to a static profiled library, and @-ghc7.11.20141222.so@
219 -- is a dynamic vanilly library. Why do we need GHC version number in the
220 -- dynamic suffix? Here is a possible reason: dynamic libraries are placed in a
221 -- single giant directory in the load path of the dynamic linker, and hence we
222 -- must distinguish different versions of GHC. In contrast, static libraries
223 -- live in their own per-package directory and hence do not need a unique
224 -- filename. We also need to respect the system's dynamic extension, e.g. @.dll@
225 -- or @.so@.
226 libsuf :: Stage -> Way -> Action String
227 libsuf st way
228 | not (wayUnit Dynamic way) = return (waySuffix way ++ ".a") -- e.g., _p.a
229 | otherwise = do
230 extension <- setting DynamicExtension -- e.g., .dll or .so
231 version <- ghcVersionStage st -- e.g. 8.4.4 or 8.9.xxxx
232 let suffix = waySuffix (removeWayUnit Dynamic way)
233 return (suffix ++ "-ghc" ++ version ++ extension)