ghc.mk: Use the same conditional install logic from unlit
[hsc2hs.git] / Flags.hs
1
2 module Flags where
3
4 import System.Console.GetOpt
5
6 data Mode
7 = Help
8 | Version
9 | UseConfig (ConfigM Maybe)
10
11 newtype Id a = Id { fromId :: a }
12 type Config = ConfigM Id
13
14 data ConfigM m = Config {
15 cmTemplate :: m FilePath,
16 cmCompiler :: m FilePath,
17 cmLinker :: m FilePath,
18 cKeepFiles :: Bool,
19 cNoCompile :: Bool,
20 cCrossCompile :: Bool,
21 cCrossSafe :: Bool,
22 cColumn :: Bool,
23 cVerbose :: Bool,
24 cFlags :: [Flag]
25 }
26
27 cTemplate :: ConfigM Id -> FilePath
28 cTemplate c = fromId $ cmTemplate c
29
30 cCompiler :: ConfigM Id -> FilePath
31 cCompiler c = fromId $ cmCompiler c
32
33 cLinker :: ConfigM Id -> FilePath
34 cLinker c = fromId $ cmLinker c
35
36 emptyMode :: Mode
37 emptyMode = UseConfig $ Config {
38 cmTemplate = Nothing,
39 cmCompiler = Nothing,
40 cmLinker = Nothing,
41 cKeepFiles = False,
42 cNoCompile = False,
43 cCrossCompile = False,
44 cCrossSafe = False,
45 cColumn = False,
46 cVerbose = False,
47 cFlags = []
48 }
49
50 data Flag
51 = CompFlag String
52 | LinkFlag String
53 | Include String
54 | Define String (Maybe String)
55 | Output String
56 deriving Show
57
58 options :: [OptDescr (Mode -> Mode)]
59 options = [
60 Option ['o'] ["output"] (ReqArg (addFlag . Output) "FILE")
61 "name of main output file",
62 Option ['t'] ["template"] (ReqArg (withConfig . setTemplate) "FILE")
63 "template file",
64 Option ['c'] ["cc"] (ReqArg (withConfig . setCompiler) "PROG")
65 "C compiler to use",
66 Option ['l'] ["ld"] (ReqArg (withConfig . setLinker) "PROG")
67 "linker to use",
68 Option ['C'] ["cflag"] (ReqArg (addFlag . CompFlag) "FLAG")
69 "flag to pass to the C compiler",
70 Option ['I'] [] (ReqArg (addFlag . CompFlag . ("-I"++)) "DIR")
71 "passed to the C compiler",
72 Option ['L'] ["lflag"] (ReqArg (addFlag . LinkFlag) "FLAG")
73 "flag to pass to the linker",
74 Option ['i'] ["include"] (ReqArg (addFlag . include) "FILE")
75 "as if placed in the source",
76 Option ['D'] ["define"] (ReqArg (addFlag . define) "NAME[=VALUE]")
77 "as if placed in the source",
78 Option [] ["no-compile"] (NoArg (withConfig $ setNoCompile True))
79 "stop after writing *_hsc_make.c",
80 Option ['x'] ["cross-compile"] (NoArg (withConfig $ setCrossCompile True))
81 "activate cross-compilation mode",
82 Option [] ["cross-safe"] (NoArg (withConfig $ setCrossSafe True))
83 "restrict .hsc directives to those supported by --cross-compile",
84 Option ['k'] ["keep-files"] (NoArg (withConfig $ setKeepFiles True))
85 "do not remove temporary files",
86 Option [] ["column"] (NoArg (withConfig $ setColumn True))
87 "annotate output with COLUMN pragmas (requires GHC 8.2)",
88 Option ['v'] ["verbose"] (NoArg (withConfig $ setVerbose True))
89 "dump commands to stderr",
90 Option ['?'] ["help"] (NoArg (setMode Help))
91 "display this help and exit",
92 Option ['V'] ["version"] (NoArg (setMode Version))
93 "output version information and exit" ]
94
95 addFlag :: Flag -> Mode -> Mode
96 addFlag f (UseConfig c) = UseConfig $ c { cFlags = f : cFlags c }
97 addFlag _ mode = mode
98
99 setMode :: Mode -> Mode -> Mode
100 setMode Help _ = Help
101 setMode _ Help = Help
102 setMode Version _ = Version
103 setMode (UseConfig {}) _ = error "setMode: UseConfig: Can't happen"
104
105 withConfig :: (ConfigM Maybe -> ConfigM Maybe) -> Mode -> Mode
106 withConfig f (UseConfig c) = UseConfig $ f c
107 withConfig _ m = m
108
109 setTemplate :: FilePath -> ConfigM Maybe -> ConfigM Maybe
110 setTemplate fp c = c { cmTemplate = Just fp }
111
112 setCompiler :: FilePath -> ConfigM Maybe -> ConfigM Maybe
113 setCompiler fp c = c { cmCompiler = Just fp }
114
115 setLinker :: FilePath -> ConfigM Maybe -> ConfigM Maybe
116 setLinker fp c = c { cmLinker = Just fp }
117
118 setKeepFiles :: Bool -> ConfigM Maybe -> ConfigM Maybe
119 setKeepFiles b c = c { cKeepFiles = b }
120
121 setNoCompile :: Bool -> ConfigM Maybe -> ConfigM Maybe
122 setNoCompile b c = c { cNoCompile = b }
123
124 setCrossCompile :: Bool -> ConfigM Maybe -> ConfigM Maybe
125 setCrossCompile b c = c { cCrossCompile = b }
126
127 setCrossSafe :: Bool -> ConfigM Maybe -> ConfigM Maybe
128 setCrossSafe b c = c { cCrossSafe = b }
129
130 setColumn :: Bool -> ConfigM Maybe -> ConfigM Maybe
131 setColumn b c = c { cColumn = b }
132
133 setVerbose :: Bool -> ConfigM Maybe -> ConfigM Maybe
134 setVerbose v c = c { cVerbose = v }
135
136 include :: String -> Flag
137 include s@('\"':_) = Include s
138 include s@('<' :_) = Include s
139 include s = Include ("\""++s++"\"")
140
141 define :: String -> Flag
142 define s = case break (== '=') s of
143 (name, []) -> Define name Nothing
144 (name, _:value) -> Define name (Just value)
145