Merge branch 'arrakis'
[barrelfish] / hake / RuleDefs.hs
1 -------------------------------------------------------------------------
2 -- Copyright (c) 2007-2011, 2012 ETH Zurich.
3 -- All rights reserved.
4 --
5 -- This file is distributed under the terms in the attached LICENSE file.
6 -- If you do not find this file, copies can be found by writing to:-
7 -- ETH Zurich D-INFK CAB F.78, Universitaetstr 6, CH-8092 Zurich. 
8 -- Attn: Systems Group.
9 --
10 -- Basic Hake rule definitions and combinators
11 --
12 --------------------------------------------------------------------------
13
14 module RuleDefs where
15 import Data.List (intersect, isSuffixOf, union, (\\), nub, sortBy, elemIndex)
16 import Path
17 import qualified X86_64
18 import qualified K1om
19 import qualified X86_32
20 import qualified SCC
21 import qualified ARMv5
22 import qualified ARM11MP
23 import qualified XScale
24 import qualified ARMv7
25 import qualified ARMv7_M
26 import qualified ARMv8
27 import HakeTypes
28 import qualified Args
29 import qualified Config
30
31 import Debug.Trace
32 -- enable debug spew
33 -- should we move this to Config.hs? -AB
34 debugFlag = False
35
36 --
37 -- Is a token to be displayed in a rule?
38 --
39 inRule :: RuleToken -> Bool
40 inRule (Dep _ _ _) = False
41 inRule (PreDep _ _ _) = False
42 inRule (Target _ _) = False
43 inRule _ = True
44
45 --
46 -- Look for a set of files: this is called using the "find" combinator
47 --
48 withSuffix :: [String] -> String -> String -> [String]
49 withSuffix af tf arg =
50     [ basename f | f <- af, f `isInSameDirAs` tf, isSuffixOf arg f ]
51 withSuffices :: [String] -> String -> [String] -> [String]
52 withSuffices af tf args =
53     concat [ withSuffix af tf arg | arg <- args ]
54
55 --
56 -- Find files with a given suffix in a given dir
57 --
58 inDir :: [String] -> String -> String -> String -> [String]
59 inDir af tf dir suffix =
60     -- Dummy is here so that we can find files in the same dir :-/
61     let subdir = (if head dir == '/' then absdir else reldir) ./. "dummy"
62         absdir = if head tf == '/' then dir else '.':dir
63         reldir = (dirname tf) ./. dir
64         files = withSuffix af subdir suffix
65     in
66         [ dir ./. f | f <- files ]
67
68 cInDir :: [String] -> String -> String -> [String]
69 cInDir af tf dir = inDir af tf dir ".c"
70 cxxInDir :: [String] -> String -> String -> [String]
71 cxxInDir af tf dir = (inDir af tf dir ".cpp") ++ (inDir af tf dir ".cc")
72 sInDir :: [String] -> String -> String -> [String]
73 sInDir af tf dir = inDir af tf dir ".S"
74
75 -------------------------------------------------------------------------
76 --
77 -- Architecture specific definitions
78 --
79 -------------------------------------------------------------------------
80
81 options :: String -> Options
82 options "x86_64" = X86_64.options
83 options "k1om" = K1om.options
84 options "x86_32" = X86_32.options
85 options "scc" = SCC.options
86 options "armv5" = ARMv5.options
87 options "arm11mp" = ARM11MP.options
88 options "xscale" = XScale.options
89 options "armv7" = ARMv7.options
90 options "armv7-m" = ARMv7_M.options
91 options "armv8" = ARMv8.options
92
93 kernelCFlags "x86_64" = X86_64.kernelCFlags
94 kernelCFlags "k1om" = K1om.kernelCFlags
95 kernelCFlags "x86_32" = X86_32.kernelCFlags
96 kernelCFlags "scc" = SCC.kernelCFlags
97 kernelCFlags "armv5" = ARMv5.kernelCFlags
98 kernelCFlags "arm11mp" = ARM11MP.kernelCFlags
99 kernelCFlags "xscale" = XScale.kernelCFlags
100 kernelCFlags "armv7" = ARMv7.kernelCFlags
101 kernelCFlags "armv7-m" = ARMv7_M.kernelCFlags
102 kernelCFlags "armv8" = ARMv8.kernelCFlags
103
104 kernelLdFlags "x86_64" = X86_64.kernelLdFlags
105 kernelLdFlags "k1om" = K1om.kernelLdFlags
106 kernelLdFlags "x86_32" = X86_32.kernelLdFlags
107 kernelLdFlags "scc" = SCC.kernelLdFlags
108 kernelLdFlags "armv5" = ARMv5.kernelLdFlags
109 kernelLdFlags "arm11mp" = ARM11MP.kernelLdFlags
110 kernelLdFlags "xscale" = XScale.kernelLdFlags
111 kernelLdFlags "armv7" = ARMv7.kernelLdFlags
112 kernelLdFlags "armv7-m" = ARMv7_M.kernelLdFlags
113 kernelLdFlags "armv8" = ARMv8.kernelLdFlags
114
115 archFamily :: String -> String
116 archFamily arch = optArchFamily (options arch)
117
118 -------------------------------------------------------------------------
119 --
120 -- Options for compiling the kernel, which is special
121 --
122 -------------------------------------------------------------------------
123
124 kernelOptIncludes :: String -> [ RuleToken ]
125 kernelOptIncludes arch
126     | arch == "k1om"  = K1om.kernelOptIncludes
127     | otherwise = [ ]
128
129 kernelIncludes arch = [ NoDep BuildTree arch f | f <- [
130                     "/include" ]]
131                  ++
132                  [ NoDep SrcTree "src" f | f <- [
133                     "/kernel/include/arch" ./. arch,
134                     "/kernel/include/arch" ./. archFamily arch,
135                     "/kernel/include",
136                     "/include",
137                     "/include/arch" ./. archFamily arch,
138                     Config.libcInc,
139                     "/include/c",
140                     "/include/target" ./. archFamily arch]]
141                  ++ kernelOptIncludes arch
142
143 kernelOptions arch = Options {
144             optArch = arch,
145             optArchFamily = archFamily arch,
146             optFlags = kernelCFlags arch,
147             optCxxFlags = [],
148             optDefines = (optDefines (options arch)) ++ [ Str "-DIN_KERNEL",
149                 Str ("-DCONFIG_SCHEDULER_" ++ (show Config.scheduler)),
150                 Str ("-DCONFIG_TIMESLICE=" ++ (show Config.timeslice)) ],
151             optIncludes = kernelIncludes arch,
152             optDependencies =
153                 [ Dep InstallTree arch "/include/errors/errno.h",
154                   Dep InstallTree arch "/include/barrelfish_kpi/capbits.h",
155                   Dep InstallTree arch "/include/asmoffsets.h",
156                   Dep InstallTree arch "/include/trace_definitions/trace_defs.h" ],
157             optLdFlags = kernelLdFlags arch,
158             optLdCxxFlags = [],
159             optLibs = [],
160             optCxxLibs = [],
161             optSuffix = [],
162             optInterconnectDrivers = [],
163             optFlounderBackends = [],
164             extraFlags = [],
165             extraCxxFlags = [],
166             extraDefines = [],
167             extraIncludes = [],
168             extraDependencies = [],
169             extraLdFlags = []
170           }
171
172
173 -------------------------------------------------------------------------
174 --
175 -- IMPORTANT: This section contains extraction of functions from the
176 -- relevant architecture module.  The names and types should be
177 -- exactly the same as in the architecture.hs file.  This section
178 -- should not contain any logic; ony architecture extraction.
179 --
180 --------------------------------------------------------------------------
181
182 --
183 -- First, the default C compiler for an architecture
184 --
185 cCompiler :: Options -> String -> String -> String -> [ RuleToken ]
186 cCompiler opts phase src obj
187     | optArch opts == "x86_64"  = X86_64.cCompiler opts phase src obj
188     | optArch opts == "k1om"    = K1om.cCompiler opts phase src obj
189     | optArch opts == "x86_32"  = X86_32.cCompiler opts phase src obj
190     | optArch opts == "scc"     = SCC.cCompiler opts phase src obj
191     | optArch opts == "armv5"   = ARMv5.cCompiler opts phase src obj
192     | optArch opts == "arm11mp" = ARM11MP.cCompiler opts phase src obj
193     | optArch opts == "xscale" = XScale.cCompiler opts phase src obj
194     | optArch opts == "armv7" = ARMv7.cCompiler opts phase src obj
195     | optArch opts == "armv7-m" = ARMv7_M.cCompiler opts phase src obj
196     | optArch opts == "armv8" = ARMv8.cCompiler opts phase src obj
197     | otherwise = [ ErrorMsg ("no C compiler for " ++ (optArch opts)) ]
198
199 cPreprocessor :: Options -> String -> String -> String -> [ RuleToken ]
200 cPreprocessor opts phase src obj
201     | otherwise = [ ErrorMsg ("no C preprocessor for " ++ (optArch opts)) ]
202
203 --
204 -- C++ compiler, where supported
205 --
206 cxxCompiler :: Options -> String -> String -> String -> [ RuleToken ]
207 cxxCompiler opts phase src obj
208     | optArch opts == "x86_64"  = X86_64.cxxCompiler opts phase src obj
209     | optArch opts == "k1om"  = K1om.cxxCompiler opts phase src obj
210     | otherwise = [ ErrorMsg ("no C++ compiler for " ++ (optArch opts)) ]
211
212
213 --
214 -- makeDepend step; note that obj can be whatever the intended output is
215 --
216 makeDepend :: Options -> String -> String -> String -> String -> [ RuleToken ]
217 makeDepend opts phase src obj depfile
218     | optArch opts == "x86_64" =
219         X86_64.makeDepend opts phase src obj depfile
220     | optArch opts == "k1om" =
221         K1om.makeDepend opts phase src obj depfile
222     | optArch opts == "x86_32" =
223         X86_32.makeDepend opts phase src obj depfile
224     | optArch opts == "scc" =
225         SCC.makeDepend opts phase src obj depfile
226     | optArch opts == "armv5" =
227         ARMv5.makeDepend opts phase src obj depfile
228     | optArch opts == "arm11mp" =
229         ARM11MP.makeDepend opts phase src obj depfile
230     | optArch opts == "xscale" =
231         XScale.makeDepend opts phase src obj depfile
232     | optArch opts == "armv7" = 
233         ARMv7.makeDepend opts phase src obj depfile
234     | optArch opts == "armv7-m" = 
235         ARMv7_M.makeDepend opts phase src obj depfile
236     | optArch opts == "armv8" = 
237         ARMv8.makeDepend opts phase src obj depfile
238     | otherwise = [ ErrorMsg ("no dependency generator for " ++ (optArch opts)) ]
239
240 makeCxxDepend :: Options -> String -> String -> String -> String -> [ RuleToken ]
241 makeCxxDepend opts phase src obj depfile
242     | optArch opts == "x86_64" =
243         X86_64.makeCxxDepend opts phase src obj depfile
244     | optArch opts == "k1om" =
245         K1om.makeCxxDepend opts phase src obj depfile        
246     | otherwise = [ ErrorMsg ("no C++ dependency generator for " ++ (optArch opts)) ]
247
248 cToAssembler :: Options -> String -> String -> String -> String -> [ RuleToken ]
249 cToAssembler opts phase src afile objdepfile
250     | optArch opts == "x86_64"  = X86_64.cToAssembler opts phase src afile objdepfile
251     | optArch opts == "k1om"  = K1om.cToAssembler opts phase src afile objdepfile
252     | optArch opts == "x86_32"  = X86_32.cToAssembler opts phase src afile objdepfile
253     | optArch opts == "scc"     = SCC.cToAssembler opts phase src afile objdepfile
254     | optArch opts == "armv5"   = ARMv5.cToAssembler opts phase src afile objdepfile
255     | optArch opts == "arm11mp" = ARM11MP.cToAssembler opts phase src afile objdepfile
256     | optArch opts == "xscale" = XScale.cToAssembler opts phase src afile objdepfile
257     | optArch opts == "armv7" = ARMv7.cToAssembler opts phase src afile objdepfile
258     | optArch opts == "armv7-m" = ARMv7_M.cToAssembler opts phase src afile objdepfile
259     | optArch opts == "armv8" = ARMv8.cToAssembler opts phase src afile objdepfile
260     | otherwise = [ ErrorMsg ("no C compiler for " ++ (optArch opts)) ]
261
262 --
263 -- Assemble an assembly language file
264 --
265 assembler :: Options -> String -> String -> [ RuleToken ]
266 assembler opts src obj
267     | optArch opts == "x86_64"  = X86_64.assembler opts src obj
268     | optArch opts == "k1om"  = K1om.assembler opts src obj
269     | optArch opts == "x86_32"  = X86_32.assembler opts src obj
270     | optArch opts == "scc"     = SCC.assembler opts src obj
271     | optArch opts == "armv5"   = ARMv5.assembler opts src obj
272     | optArch opts == "arm11mp" = ARM11MP.assembler opts src obj
273     | optArch opts == "xscale" = XScale.assembler opts src obj
274     | optArch opts == "armv7" = ARMv7.assembler opts src obj
275     | optArch opts == "armv7-m" = ARMv7_M.assembler opts src obj
276     | optArch opts == "armv8" = ARMv8.assembler opts src obj
277     | otherwise = [ ErrorMsg ("no assembler for " ++ (optArch opts)) ]
278
279 archive :: Options -> [String] -> [String] -> String -> String -> [ RuleToken ]
280 archive opts objs libs name libname
281     | optArch opts == "x86_64"  = X86_64.archive opts objs libs name libname
282     | optArch opts == "k1om"  = K1om.archive opts objs libs name libname
283     | optArch opts == "x86_32"  = X86_32.archive opts objs libs name libname
284     | optArch opts == "scc"     = SCC.archive opts objs libs name libname
285     | optArch opts == "armv5"     = ARMv5.archive opts objs libs name libname
286     | optArch opts == "arm11mp" = ARM11MP.archive opts objs libs name libname
287     | optArch opts == "xscale" = XScale.archive opts objs libs name libname
288     | optArch opts == "armv7" = ARMv7.archive opts objs libs name libname
289     | optArch opts == "armv7-m" = ARMv7_M.archive opts objs libs name libname
290     | optArch opts == "armv8" = ARMv8.archive opts objs libs name libname
291     | otherwise = [ ErrorMsg ("Can't build a library for " ++ (optArch opts)) ]
292
293 linker :: Options -> [String] -> [String] -> String -> [RuleToken]
294 linker opts objs libs bin
295     | optArch opts == "x86_64" = X86_64.linker opts objs libs bin
296     | optArch opts == "k1om" = K1om.linker opts objs libs bin
297     | optArch opts == "x86_32" = X86_32.linker opts objs libs bin
298     | optArch opts == "scc"    = SCC.linker opts objs libs bin
299     | optArch opts == "armv5"  = ARMv5.linker opts objs libs bin
300     | optArch opts == "arm11mp" = ARM11MP.linker opts objs libs bin
301     | optArch opts == "xscale" = XScale.linker opts objs libs bin
302     | optArch opts == "armv7" = ARMv7.linker opts objs libs bin
303     | optArch opts == "armv7-m" = ARMv7_M.linker opts objs libs bin
304     | optArch opts == "armv8" = ARMv8.linker opts objs libs bin
305     | otherwise = [ ErrorMsg ("Can't link executables for " ++ (optArch opts)) ]
306
307 cxxlinker :: Options -> [String] -> [String] -> String -> [RuleToken]
308 cxxlinker opts objs libs bin
309     | optArch opts == "x86_64" = X86_64.cxxlinker opts objs libs bin
310     | optArch opts == "k1om" = K1om.cxxlinker opts objs libs bin
311     | otherwise = [ ErrorMsg ("Can't link C++ executables for " ++ (optArch opts)) ]
312
313 --
314 -- The C compiler for compiling things on the host
315 --
316 nativeCCompiler :: String
317 nativeCCompiler = "$(CC)"
318
319 -------------------------------------------------------------------------
320 --
321 -- Functions to create useful filenames
322 --
323
324 dependFilePath :: String -> String
325 dependFilePath obj = obj ++ ".depend"
326
327 objectFilePath :: Options -> String -> String
328 objectFilePath opts src = (optSuffix opts) ./. ((removeSuffix src) ++ ".o")
329
330 generatedObjectFilePath :: Options -> String -> String
331 generatedObjectFilePath opts src = (removeSuffix src) ++ ".o"
332
333 preprocessedFilePath :: Options -> String -> String
334 preprocessedFilePath opts src = (optSuffix opts) ./. ((removeSuffix src) ++ ".i")
335
336 -- Standard convention is that human generated assembler is .S, machine generated is .s
337 assemblerFilePath :: Options -> String -> String
338 assemblerFilePath opts src = (optSuffix opts) ./. ((removeSuffix src) ++ ".s")
339
340
341 -------------------------------------------------------------------------
342 --
343 -- Functions with logic to start doing things
344 --
345
346 --
347 -- Create C file dependencies
348 --
349
350 -- Since this is where we know what the depfile is called it is here that we also
351 -- decide to include it.  This stops many different places below trying to
352 -- guess what the depfile is called
353 --
354 makeDependArchSub :: Options -> String -> String -> String -> String -> [ RuleToken ]
355 makeDependArchSub opts phase src objfile depfile =
356    [ Str ("@echo Generating $@"), NL ] ++
357      makeDepend opts phase src objfile depfile
358
359 makeDependArch :: Options -> String -> String -> String -> String -> HRule
360 makeDependArch opts phase src objfile depfile =
361     Rules [ Rule (makeDependArchSub opts phase src objfile depfile),
362             Include (Out (optArch opts) depfile)
363           ]
364
365 -- Make depend for a standard object file
366 makeDependObj :: Options -> String -> String -> HRule
367 makeDependObj opts phase src =
368     let objfile = (objectFilePath opts src)
369     in
370       makeDependArch opts phase src objfile (dependFilePath objfile)
371
372 -- Make depend for a C++ object file
373 makeDependCxxArchSub :: Options -> String -> String -> String -> String -> [ RuleToken ]
374 makeDependCxxArchSub opts phase src objfile depfile =
375    [ Str ("@echo Generating $@"), NL ] ++
376      makeCxxDepend opts phase src objfile depfile
377
378 makeDependCxxArch :: Options -> String -> String -> String -> String -> HRule
379 makeDependCxxArch opts phase src objfile depfile =
380     Rules [ Rule (makeDependCxxArchSub opts phase src objfile depfile),
381             Include (Out (optArch opts) depfile)
382           ]
383
384 makeDependCxxObj :: Options -> String -> String -> HRule
385 makeDependCxxObj opts phase src =
386     let objfile = (objectFilePath opts src)
387     in
388       makeDependCxxArch opts phase src objfile (dependFilePath objfile)
389
390 -- Make depend for an assembler output
391 makeDependAssembler :: Options -> String -> String -> HRule
392 makeDependAssembler opts phase src =
393     let objfile = (assemblerFilePath opts src)
394     in
395       makeDependArch opts phase src objfile (dependFilePath objfile)
396
397 --
398 -- Compile a C program to assembler
399 --
400 makecToAssembler :: Options -> String -> String -> String -> [ RuleToken ]
401 makecToAssembler opts phase src obj =
402     cToAssembler opts phase src (assemblerFilePath opts src) (dependFilePath obj)
403
404 --
405 -- Assemble an assembly language file
406 --
407 assemble :: Options -> String -> [ RuleToken ]
408 assemble opts src =
409     assembler opts src (objectFilePath opts src)
410
411 --
412 -- Create a library from a set of object files
413 --
414 archiveLibrary :: Options -> String -> [String] -> [String] -> [ RuleToken ]
415 archiveLibrary opts name objs libs =
416     archive opts objs libs name (libraryPath name)
417
418 --
419 -- Link an executable
420 --
421 linkExecutable :: Options -> [String] -> [String] -> String -> [RuleToken]
422 linkExecutable opts objs libs bin =
423     linker opts objs libs (applicationPath bin)
424
425 --
426 -- Link a C++ executable
427 --
428 linkCxxExecutable :: Options -> [String] -> [String] -> String -> [RuleToken]
429 linkCxxExecutable opts objs libs bin =
430     cxxlinker opts objs libs (applicationPath bin)
431
432 -------------------------------------------------------------------------
433
434
435
436
437
438 -------------------------------------------------------------------------
439 --
440 -- Hake macros (hacros?): each of these evaluates to HRule, i.e. a
441 -- list of templates for Makefile rules
442 --
443 -------------------------------------------------------------------------
444
445 --
446 -- Compile a C file for a particular architecture
447 -- We include cToAssembler to permit humans to type "make foo/bar.s"
448 --
449 compileCFile :: Options -> String -> HRule
450 compileCFile opts src =
451     Rules [ Rule (cCompiler opts "src" src (objectFilePath opts src)),
452             Rule (makecToAssembler opts "src" src (objectFilePath opts src)),
453             makeDependObj opts "src" src
454           ]
455
456 --
457 -- Compile a C++ file for a particular architecture
458 --
459 compileCxxFile :: Options -> String -> HRule
460 compileCxxFile opts src =
461     Rules [ Rule (cxxCompiler opts "src" src (objectFilePath opts src)),
462             makeDependCxxObj opts "src" src
463           ]
464
465 --
466 -- Compile a C file for a particular architecture
467 --
468 compileGeneratedCFile :: Options -> String -> HRule
469 compileGeneratedCFile opts src =
470     let o2 = opts { optSuffix = "" }
471         arch = optArch o2
472     in
473       Rules [ Rule (cCompiler o2 arch src (objectFilePath o2 src) ),
474               Rule (makecToAssembler o2 arch src (objectFilePath o2 src)),
475               makeDependObj o2 arch src
476             ]
477
478 compileGeneratedCxxFile :: Options -> String -> HRule
479 compileGeneratedCxxFile opts src =
480     let o2 = opts { optSuffix = "" }
481         arch = optArch o2
482     in
483       Rules [ Rule (cxxCompiler o2 arch src (objectFilePath o2 src) ),
484               makeDependCxxObj o2 arch src
485             ]
486
487 compileCFiles :: Options -> [String] -> HRule
488 compileCFiles opts srcs = Rules [ compileCFile opts s | s <- srcs ]
489 compileCxxFiles :: Options -> [String] -> HRule
490 compileCxxFiles opts srcs = Rules [ compileCxxFile opts s | s <- srcs ]
491 compileGeneratedCFiles :: Options -> [String] -> HRule
492 compileGeneratedCFiles opts srcs =
493     Rules [ compileGeneratedCFile opts s | s <- srcs ]
494 compileGeneratedCxxFiles :: Options -> [String] -> HRule
495 compileGeneratedCxxFiles opts srcs =
496     Rules [ compileGeneratedCxxFile opts s | s <- srcs ]
497
498 --
499 -- Add a set of C (or whatever) dependences on a *generated* file.
500 -- Somewhere else this file has to be defined as a target, of
501 -- course...
502 --
503 extraCDependencyForObj :: Options -> String -> String -> String -> [RuleToken]
504 extraCDependencyForObj opts file s obj =
505     let arch = optArch opts
506     in
507       [ Target arch (dependFilePath obj),
508         Target arch obj,
509         Dep BuildTree arch file
510       ]
511
512 extraCDependency :: Options -> String -> String -> HRule
513 extraCDependency opts file s = Rule (extraCDependencyForObj opts file s obj)
514     where obj = objectFilePath opts s
515
516
517 extraCDependencies :: Options -> String -> [String] -> HRule
518 extraCDependencies opts file srcs =
519     Rules [ extraCDependency opts file s | s <- srcs ]
520
521 extraGeneratedCDependency :: Options -> String -> String -> HRule
522 extraGeneratedCDependency opts file s =
523     extraCDependency (opts { optSuffix = "" }) file s
524
525 --
526 -- Copy include files to the appropriate directory
527 --
528 includeFile :: Options -> String -> HRule
529 includeFile opts hdr =
530     Rules [ (Rule [ Str "cp", In SrcTree "src" hdr, Out (optArch opts) hdr ]),
531             (Rule [ PreDep BuildTree (optArch opts) hdr,
532                     Target (optArch opts) "/include/errors/errno.h" ]
533             )
534           ]
535
536 --
537 -- Build a Mackerel header file from a definition.
538 --
539 mackerelProgLoc = In InstallTree "tools" "/bin/mackerel"
540 mackerelDevFileLoc d = In SrcTree "src" ("/devices" ./. (d ++ ".dev"))
541 mackerelDevHdrPath d = "/include/dev/" ./. (d ++ "_dev.h")
542
543 mackerel2 :: Options -> String -> HRule
544 mackerel2 opts dev = mackerel_generic opts dev "shift-driver"
545
546 mackerel :: Options -> String -> HRule
547 mackerel opts dev = mackerel_generic opts dev "bitfield-driver"
548
549 mackerel_generic :: Options -> String -> String -> HRule
550 mackerel_generic opts dev flag =
551     let
552         arch = optArch opts
553     in
554       Rule [ mackerelProgLoc,
555              Str ("--" ++ flag),
556              Str "-c", mackerelDevFileLoc dev,
557              Str "-o", Out arch (mackerelDevHdrPath dev)
558            ]
559
560 mackerelDependencies :: Options -> String -> [String] -> HRule
561 mackerelDependencies opts d srcs =
562     extraCDependencies opts (mackerelDevHdrPath d) srcs
563
564 --
565 -- Basic Flounder definitions: where things are
566 --
567
568 flounderProgLoc = In InstallTree "tools" "/bin/flounder"
569 flounderIfFileLoc ifn = In SrcTree "src" ("/if" ./. (ifn ++ ".if"))
570
571 -- new-style stubs: path for generic header
572 flounderIfDefsPath ifn = "/include/if" ./. (ifn ++ "_defs.h")
573 -- new-style stubs: path for specific backend header
574 flounderIfDrvDefsPath ifn drv = "/include/if" ./. (ifn ++ "_" ++ drv ++ "_defs.h")
575
576 -- new-style stubs: generated C code (for all default enabled backends)
577 flounderBindingPath opts ifn =
578     (optSuffix opts) ./. (ifn ++ "_flounder_bindings.c")
579 -- new-style stubs: generated C code (for extra backends enabled by the user)
580 flounderExtraBindingPath opts ifn =
581     (optSuffix opts) ./. (ifn ++ "_flounder_extra_bindings.c")
582
583 flounderTHCHdrPath ifn = "/include/if" ./. (ifn ++ "_thc.h")
584 flounderTHCStubPath opts ifn =
585     (optSuffix opts) ./. (ifn ++ "_thc.c")
586
587 applicationPath name = "/sbin" ./. name
588 libraryPath libname = "/lib" ./. ("lib" ++ libname ++ ".a")
589 kernelPath = "/sbin/cpu"
590
591 -- construct include arguments to flounder for common types
592 -- these are:
593 --  1. platform-specific types (if/platform/foo.if)
594 --  2. architecture-specific types (if/arch/foo.if)
595 --  3. generic types (if/types.if)
596 flounderIncludes :: Options -> [RuleToken]
597 flounderIncludes opts
598     = concat [ [Str "-i", flounderIfFileLoc ifn]
599                | ifn <- [ "platform" ./. (optArch opts), -- XXX: optPlatform
600                           "arch" ./. (optArch opts),
601                           "types" ] ]
602
603 flounderRule :: Options -> [RuleToken] -> HRule
604 flounderRule opts args
605     = Rule $ [ flounderProgLoc ] ++ (flounderIncludes opts) ++ args
606
607 --
608 -- Build new-style Flounder header files from a definition
609 -- (generic header, plus one per backend)
610 --
611 flounderGenDefs :: Options -> String -> HRule
612 flounderGenDefs opts ifn =
613     Rules $ flounderRule opts [
614            Str "--generic-header", flounderIfFileLoc ifn,
615            Out (optArch opts) (flounderIfDefsPath ifn)
616          ] : [ flounderRule opts [
617            Str $ "--" ++ drv ++ "-header", flounderIfFileLoc ifn,
618            Out (optArch opts) (flounderIfDrvDefsPath ifn drv)]
619            | drv <- Args.allFlounderBackends ]
620
621 --
622 -- Build a new Flounder binding file from a definition.
623 -- This builds the binding for all enabled backends
624 --
625 flounderBinding :: Options -> String -> [String] -> HRule
626 flounderBinding opts ifn =
627     flounderBindingHelper opts ifn backends (flounderBindingPath opts ifn)
628     where
629         backends = "generic" : (optFlounderBackends opts)
630
631 -- as above, but for a specific set of user-specified backends
632 flounderExtraBinding :: Options -> String -> [String] -> [String] -> HRule
633 flounderExtraBinding opts ifn backends =
634     flounderBindingHelper opts ifn backends (flounderExtraBindingPath opts ifn)
635
636 flounderBindingHelper :: Options -> String -> [String] -> String -> [String] -> HRule
637 flounderBindingHelper opts ifn backends cfile srcs = Rules $
638     [ flounderRule opts $ args ++ [flounderIfFileLoc ifn, Out arch cfile ],
639         compileGeneratedCFile opts cfile,
640         flounderDefsDepend opts ifn allbackends srcs]
641     ++ [extraGeneratedCDependency opts (flounderIfDrvDefsPath ifn d) cfile
642         | d <- allbackends]
643     where
644         arch = optArch opts
645         archfam = optArchFamily opts
646         args = [Str "-a", Str archfam] ++ [Str $ "--" ++ d ++ "-stub" | d <- backends]
647         allbackends = backends `union` optFlounderBackends opts \\ ["generic"]
648
649 --
650 -- Build a Flounder THC header file from a definition.
651 --
652 flounderTHCFile :: Options -> String -> HRule
653 flounderTHCFile opts ifn =
654     flounderRule opts [
655            Str "--thc-header", flounderIfFileLoc ifn,
656            Out (optArch opts) (flounderTHCHdrPath ifn)
657          ]
658
659 --
660 -- Build a Flounder THC stubs file from a definition.
661 --
662 flounderTHCStub :: Options -> String -> [String] -> HRule
663 flounderTHCStub opts ifn srcs =
664     let cfile = flounderTHCStubPath opts ifn
665         hfile = flounderTHCHdrPath ifn
666         arch = optArch opts
667     in
668       Rules [ flounderRule opts [
669                      Str "--thc-stubs", flounderIfFileLoc ifn,
670                      Out arch cfile
671                    ],
672               compileGeneratedCFile opts cfile,
673               extraCDependencies opts hfile srcs,
674               extraGeneratedCDependency opts hfile cfile
675             ]
676
677 --
678 -- Create a dependency on a Flounder header file for a set of files,
679 -- but don't actually build either stub (useful for libraries)
680 --
681 flounderDefsDepend :: Options -> String -> [String] -> [String] -> HRule
682 flounderDefsDepend opts ifn backends srcs = Rules $
683     (extraCDependencies opts (flounderIfDefsPath ifn) srcs) :
684     [extraCDependencies opts (flounderIfDrvDefsPath ifn drv) srcs
685            | drv <- backends, drv /= "generic" ]
686
687 --
688 -- Emit all the Flounder-related rules/dependencies for a given target
689 --
690
691 flounderRules :: Options -> Args.Args -> [String] -> [HRule]
692 flounderRules opts args csrcs =
693     ([ flounderBinding opts f csrcs | f <- Args.flounderBindings args ]
694      ++
695      [ flounderExtraBinding opts f backends csrcs
696        | (f, backends) <- Args.flounderExtraBindings args ]
697      ++
698      [ flounderTHCStub opts f csrcs | f <- Args.flounderTHCStubs args ]
699      ++
700      -- Flounder extra defs (header files) also depend on the base
701      -- Flounder headers for the same interface
702      [ flounderDefsDepend opts f baseBackends csrcs | f <- allIf ]
703      ++
704      -- Extra defs only for non-base backends (those were already emitted above)
705      [ flounderDefsDepend opts f (backends \\ baseBackends) csrcs
706        | (f, backends) <- Args.flounderExtraDefs args ]
707     )
708     where
709       -- base backends enabled by default
710       baseBackends = optFlounderBackends opts
711
712       -- all interfaces mentioned in flounderDefs or ExtraDefs
713       allIf = nub $ Args.flounderDefs args ++ [f | (f,_) <- Args.flounderExtraDefs args]
714
715
716 --
717 -- Build a Fugu library
718 --
719 fuguFile :: Options -> String -> HRule
720 fuguFile opts file =
721     let arch = optArch opts
722         cfile = file ++ ".c"
723         hfile = "/include/errors/" ++ file ++ ".h"
724     in
725       Rules [ Rule [In InstallTree "tools" "/bin/fugu",
726                     In SrcTree "src" (file++".fugu"),
727                     Out arch hfile,
728                     Out arch cfile ],
729               compileGeneratedCFile opts cfile
730          ]
731
732 --
733 -- Build a Pleco library
734 --
735 plecoFile :: Options -> String -> HRule
736 plecoFile opts file =
737     let arch = optArch opts
738         cfile = file ++ ".c"
739         hfile = "/include/trace_definitions/" ++ file ++ ".h"
740         jsonfile = "/trace_definitions/" ++ file ++ ".json"
741     in
742       Rules [ Rule [In InstallTree "tools" "/bin/pleco",
743                     In SrcTree "src" (file++".pleco"),
744                     Out arch hfile,
745                     Out arch jsonfile,
746                     Out arch cfile ],
747               compileGeneratedCFile opts cfile
748          ]
749
750 --
751 -- Build a Hamlet file
752 --
753 hamletFile :: Options -> String -> HRule
754 hamletFile opts file =
755     let arch = optArch opts
756         hfile = "/include/barrelfish_kpi/capbits.h"
757         cfile = "cap_predicates.c"
758         usercfile = "user_cap_predicates.c"
759         ofile = "user_cap_predicates.o"
760         nfile = "cap_predicates"
761         afile = "/lib/libcap_predicates.a"
762     in
763       Rules [ Rule [In InstallTree "tools" "/bin/hamlet",
764                     In SrcTree "src" (file++".hl"),
765                     Out arch hfile,
766                     Out arch cfile,
767                     Out arch usercfile ],
768               compileGeneratedCFile opts usercfile,
769               Rule (archive opts [ ofile ] [] nfile afile)
770          ]
771
772 --
773 -- Link a set of object files and libraries together
774 --
775 link :: Options -> [String] -> [ String ] -> String -> HRule
776 link opts objs libs bin =
777     Rule (linkExecutable opts objs libs bin)
778
779 --
780 -- Link a set of C++ object files and libraries together
781 --
782 linkCxx :: Options -> [String] -> [ String ] -> String -> HRule
783 linkCxx opts objs libs bin =
784     Rule (linkCxxExecutable opts objs libs bin)
785
786 --
787 -- Link a CPU driver.  This is where it gets distinctly architecture-specific.
788 --
789 linkKernel :: Options -> String -> [String] -> [String] -> HRule
790 linkKernel opts name objs libs
791     | optArch opts == "x86_64" = X86_64.linkKernel opts objs [libraryPath l | l <- libs ] ("/sbin" ./. name)
792     | optArch opts == "k1om" = K1om.linkKernel opts objs [libraryPath l | l <- libs ] ("/sbin" ./. name)
793     | optArch opts == "x86_32" = X86_32.linkKernel opts objs [libraryPath l | l <- libs ] ("/sbin" ./. name)
794     | optArch opts == "scc"    = SCC.linkKernel opts objs [libraryPath l | l <- libs ] ("/sbin" ./. name)
795     | optArch opts == "armv5" = ARMv5.linkKernel opts objs [libraryPath l | l <- libs ] ("/sbin" ./. name)
796     | optArch opts == "arm11mp" = ARM11MP.linkKernel opts objs [libraryPath l | l <- libs ] ("/sbin" ./. name)
797     | optArch opts == "xscale" = XScale.linkKernel opts objs [libraryPath l | l <- libs ] ("/sbin" ./. name)
798     | optArch opts == "armv7" = ARMv7.linkKernel opts objs [libraryPath l | l <- libs ] name
799     | optArch opts == "armv7-m" = ARMv7_M.linkKernel opts objs [libraryPath l | l <- libs ] name
800     | optArch opts == "armv8" = ARMv8.linkKernel opts objs [libraryPath l | l <- libs ] name
801     | otherwise = Rule [ Str ("Error: Can't link kernel for '" ++ (optArch opts) ++ "'") ]
802
803 --
804 -- Copy a file from one place to another
805 --
806 copy :: Options -> String -> String -> HRule
807 copy opts src dest =
808     Rule [ Str "cp", In BuildTree (optArch opts) src, Out (optArch opts) dest ]
809
810 --
811 -- Assemble a list of S files for a particular architecture
812 --
813 assembleSFile :: Options -> String -> HRule
814 assembleSFile opts src =
815     Rules [ Rule (assemble opts src),
816             makeDependObj opts "src" src
817           ]
818
819 assembleSFiles :: Options -> [String] -> HRule
820 assembleSFiles opts srcs = Rules [ assembleSFile opts s | s <- srcs ]
821
822 --
823 -- Archive a bunch of objects into a library
824 --
825 staticLibrary :: Options -> String -> [String] -> [String] -> HRule
826 staticLibrary opts libpath objs libs =
827     Rule (archiveLibrary opts libpath objs libs)
828
829 --
830 -- Compile a Haskell binary (for the host architecture)
831 --
832 compileHaskell prog main deps = compileHaskellWithLibs prog main deps []
833 compileHaskellWithLibs prog main deps dirs =
834   let 
835     tools_dir = (Dep InstallTree "tools" "/tools/.marker")
836   in
837     Rule ([ NStr "ghc -i",
838             NoDep SrcTree "src" ".",
839             Str "-odir ", NoDep BuildTree "tools" ".",
840             Str "-hidir ", NoDep BuildTree "tools" ".",
841             Str "-rtsopts=all",
842             Str "--make ",
843             In SrcTree "src" main,
844             Str "-o ",
845             Out "tools" ("/bin" ./. prog),
846             Str "$(LDFLAGS)" ]
847           ++ concat [[ NStr "-i", NoDep SrcTree "src" d] | d <- dirs]
848           ++ [ (Dep SrcTree "src" dep) | dep <- deps ]
849           ++ [ tools_dir ])
850
851 --
852 -- Compile (and link) a C binary (for the host architecture)
853 --
854 compileNativeC :: String -> [String] -> [String] -> [String] -> HRule
855 compileNativeC prog cfiles cflags ldflags =
856     Rule ([ Str nativeCCompiler,
857             Str "-o",
858             Out "tools" ("/bin" ./. prog),
859             Str "$(CFLAGS)",
860             Str "$(LDFLAGS)" ]
861           ++ [ (Str flag) | flag <- cflags ]
862           ++ [ (Str flag) | flag <- ldflags ]
863           ++ [ (In SrcTree "src" dep) | dep <- cfiles ])
864
865 --
866 -- Build a Technical Note
867 --
868 buildTechNote :: String -> String -> Bool -> Bool -> [String] -> HRule
869 buildTechNote input output bib glo figs =
870     buildTechNoteWithDeps input output bib glo figs []
871 buildTechNoteWithDeps :: String -> String -> Bool -> Bool -> [String] -> [RuleToken] -> HRule
872 buildTechNoteWithDeps input output bib glo figs deps =
873     let
874         working_dir = NoDep BuildTree "tools" "/tmp/"
875         style_files = [ "bfish-logo.pdf", "bftn.sty", "defs.bib", "barrelfish.bib" ]
876     in
877       Rule ( [ Dep SrcTree "src" (f ++ ".pdf") | f <- figs]
878              ++
879              [ Dep SrcTree "src" ("/doc/style" ./. f) | f <- style_files ]
880              ++
881              [ Str "mkdir", Str "-p", working_dir, NL ]
882              ++
883              deps
884              ++
885              [ In SrcTree "src" "/tools/run-pdflatex.sh",
886                Str "--input-tex", In SrcTree "src" input,
887                Str "--working-dir", working_dir,
888                Str "--output-pdf", Out "docs" ("/" ++ output),
889                Str "--texinput", NoDep SrcTree "src" "/doc/style",
890                Str "--bibinput", NoDep SrcTree "src" "/doc/style"
891              ]
892              ++ (if bib then [ Str "--has-bib" ] else [])
893              ++ (if glo then [ Str "--has-glo" ] else [])
894            )
895
896 ---------------------------------------------------------------------
897 --
898 -- Transformations on file names
899 --
900 ----------------------------------------------------------------------
901
902 allObjectPaths :: Options -> Args.Args -> [String]
903 allObjectPaths opts args =
904     [objectFilePath opts g
905          | g <- (Args.cFiles args)++(Args.cxxFiles args)++(Args.assemblyFiles args)]
906     ++
907     [generatedObjectFilePath opts g
908          | g <- [ flounderBindingPath opts f
909                       | f <- (Args.flounderBindings args)]
910                 ++
911                 [ flounderExtraBindingPath opts f
912                       | (f, _) <- (Args.flounderExtraBindings args)]
913                 ++
914                 [ flounderTHCStubPath opts f
915                       | f <- (Args.flounderTHCStubs args)]
916                 ++
917                 (Args.generatedCFiles args) ++ (Args.generatedCxxFiles args)
918     ]
919
920 allLibraryPaths :: Args.Args -> [String]
921 allLibraryPaths args =
922     [ libraryPath l | l <- Args.addLibraries args ]
923
924
925 ---------------------------------------------------------------------
926 --
927 -- Very large-scale macros
928 --
929 ----------------------------------------------------------------------
930
931 --
932 -- Build an application binary
933 --
934
935 application :: Args.Args
936 application = Args.defaultArgs { Args.buildFunction = applicationBuildFn }
937
938 applicationBuildFn :: [String] -> String -> Args.Args -> HRule
939 applicationBuildFn af tf args
940     | debugFlag && trace (Args.showArgs (tf ++ " Application ") args) False
941         = undefined
942 applicationBuildFn af tf args =
943     Rules [ appBuildArch af tf args arch | arch <- Args.architectures args ]
944
945 appGetOptionsForArch arch args =
946     (options arch) { extraIncludes =
947                          [ NoDep SrcTree "src" a | a <- Args.addIncludes args]
948                          ++                         
949                          [ NoDep BuildTree arch a | a <- Args.addGeneratedIncludes args],
950                      optIncludes = (optIncludes $ options arch) \\
951                          [ NoDep SrcTree "src" i | i <- Args.omitIncludes args ],
952                      optFlags = (optFlags $ options arch) \\
953                                 [ Str f | f <- Args.omitCFlags args ],
954                      optCxxFlags = (optCxxFlags $ options arch) \\
955                                    [ Str f | f <- Args.omitCxxFlags args ],
956                      optSuffix = "_for_app_" ++ Args.target args,
957                      extraFlags = Args.addCFlags args, 
958                      extraCxxFlags = Args.addCxxFlags args,
959                      extraLdFlags = [ Str f | f <- Args.addLinkFlags args ],
960                      extraDependencies =
961                          [Dep BuildTree arch s | s <- Args.addGeneratedDependencies args]
962                    }
963
964 appBuildArch af tf args arch =
965     let -- Fiddle the options
966         opts = appGetOptionsForArch arch args
967         csrcs = Args.cFiles args
968         cxxsrcs = Args.cxxFiles args
969         gencsrc = Args.generatedCFiles args
970         gencxxsrc = Args.generatedCxxFiles args
971         
972
973         appname = Args.target args
974         -- XXX: Not sure if this is correct. Currently assuming that if the app
975         -- contains C++ files, we have to use the C++ linker.
976         mylink = if cxxsrcs == [] then link else linkCxx
977     in
978       Rules ( flounderRules opts args csrcs
979               ++
980               [ mackerelDependencies opts m csrcs | m <- Args.mackerelDevices args ]
981               ++
982               [ compileCFiles opts csrcs,
983                 compileCxxFiles opts cxxsrcs,
984                 compileGeneratedCFiles opts gencsrc,
985                 compileGeneratedCxxFiles opts gencxxsrc,
986                 assembleSFiles opts (Args.assemblyFiles args),
987                 mylink opts (allObjectPaths opts args) (allLibraryPaths args) appname
988               ]
989             )
990
991 --
992 -- Build an Arrakis application binary
993 --
994
995 arrakisapplication :: Args.Args
996 arrakisapplication = Args.defaultArgs { Args.buildFunction = arrakisApplicationBuildFn }
997
998 arrakisApplicationBuildFn :: [String] -> String -> Args.Args -> HRule
999 arrakisApplicationBuildFn af tf args
1000     | debugFlag && trace (Args.showArgs (tf ++ " Arrakis Application ") args) False
1001         = undefined
1002 arrakisApplicationBuildFn af tf args =
1003     Rules [ arrakisAppBuildArch af tf args arch | arch <- Args.architectures args ]
1004
1005 arrakisAppGetOptionsForArch arch args =
1006     (options arch) { extraIncludes =
1007                          [ NoDep SrcTree "src" a | a <- Args.addIncludes args],
1008                      optIncludes = (optIncludes $ options arch) \\
1009                          [ NoDep SrcTree "src" i | i <- Args.omitIncludes args ],
1010                      optFlags = ((optFlags $ options arch) ++ [ Str "-DARRAKIS" ]) \\
1011                                 [ Str f | f <- Args.omitCFlags args ],
1012                      optCxxFlags = (optCxxFlags $ options arch) \\
1013                                    [ Str f | f <- Args.omitCxxFlags args ],
1014                      optSuffix = "_for_app_" ++ Args.target args,
1015                      optLibs = [ In InstallTree arch "/lib/libarrakis.a" ] ++
1016                                ((optLibs $ options arch) \\
1017                                 [ In InstallTree arch "/lib/libbarrelfish.a" ]),
1018                      extraFlags = Args.addCFlags args, 
1019                      extraCxxFlags = Args.addCxxFlags args,
1020                      extraLdFlags = [ Str f | f <- Args.addLinkFlags args ],
1021                      extraDependencies =
1022                          [Dep BuildTree arch s | s <- Args.addGeneratedDependencies args]
1023                    }
1024
1025 arrakisAppBuildArch af tf args arch =
1026     let -- Fiddle the options
1027         opts = arrakisAppGetOptionsForArch arch args
1028         csrcs = Args.cFiles args
1029         cxxsrcs = Args.cxxFiles args
1030         gencsrc = Args.generatedCFiles args
1031         gencxxsrc = Args.generatedCxxFiles args
1032         appname = Args.target args
1033         -- XXX: Not sure if this is correct. Currently assuming that if the app
1034         -- contains C++ files, we have to use the C++ linker.
1035         mylink = if cxxsrcs == [] then link else linkCxx
1036     in
1037       Rules ( flounderRules opts args csrcs
1038               ++
1039               [ mackerelDependencies opts m csrcs | m <- Args.mackerelDevices args ]
1040               ++
1041               [ compileCFiles opts csrcs,
1042                 compileCxxFiles opts cxxsrcs,
1043                 compileGeneratedCFiles opts gencsrc,
1044                 compileGeneratedCxxFiles opts gencxxsrc,
1045                 assembleSFiles opts (Args.assemblyFiles args),
1046                 mylink opts (allObjectPaths opts args) (allLibraryPaths args) appname
1047               ]
1048             )
1049
1050 --
1051 -- Build a static library
1052 --
1053
1054 library :: Args.Args
1055 library = Args.defaultArgs { Args.buildFunction = libraryBuildFn }
1056
1057 libraryBuildFn :: [String] -> String -> Args.Args -> HRule
1058 libraryBuildFn af tf args | debugFlag && trace (Args.showArgs (tf ++ " Library ") args) False = undefined
1059 libraryBuildFn af tf args =
1060     Rules [ libBuildArch af tf args arch | arch <- Args.architectures args ]
1061
1062 libGetOptionsForArch arch args =
1063     (options arch) { extraIncludes =
1064                          [ NoDep SrcTree "src" a | a <- Args.addIncludes args],
1065                      optIncludes = (optIncludes $ options arch) \\
1066                          [ NoDep SrcTree "src" i | i <- Args.omitIncludes args ],
1067                      optFlags = (optFlags $ options arch) \\
1068                                 [ Str f | f <- Args.omitCFlags args ],
1069                      optCxxFlags = (optCxxFlags $ options arch) \\
1070                                    [ Str f | f <- Args.omitCxxFlags args ],
1071                      optSuffix = "_for_lib_" ++ Args.target args,
1072                      extraFlags = Args.addCFlags args, 
1073                      extraCxxFlags = Args.addCxxFlags args,
1074                      extraDependencies =
1075                          [Dep BuildTree arch s | s <- Args.addGeneratedDependencies args]
1076                    }
1077
1078 libBuildArch af tf args arch =
1079     let -- Fiddle the options
1080         opts = libGetOptionsForArch arch args
1081         csrcs = Args.cFiles args
1082         cxxsrcs = Args.cxxFiles args
1083         gencsrc = Args.generatedCFiles args
1084         gencxxsrc = Args.generatedCxxFiles args
1085     in
1086       Rules ( flounderRules opts args csrcs
1087               ++
1088               [ mackerelDependencies opts m csrcs | m <- Args.mackerelDevices args ]
1089               ++
1090               [ compileCFiles opts csrcs,
1091                 compileCxxFiles opts cxxsrcs,
1092                 compileGeneratedCFiles opts gencsrc,
1093                 compileGeneratedCxxFiles opts gencxxsrc,
1094                 assembleSFiles opts (Args.assemblyFiles args),
1095                 staticLibrary opts (Args.target args) (allObjectPaths opts args) (allLibraryPaths args)
1096               ]
1097             )
1098
1099 --
1100 -- Library dependecies
1101 --
1102
1103 -- The following code is under heavy construction, and also somewhat ugly
1104 data LibDepTree = LibDep String | LibDeps [LibDepTree] deriving (Show,Eq)
1105
1106 -- manually add dependencies for now (it would be better if each library
1107 -- defined each own dependencies locally, but that does not seem to be an
1108 -- easy thing to do currently
1109 libposixcompat_deps   = LibDeps [ LibDep "posixcompat",
1110                                   libvfs_deps_all, LibDep "term_server" ]
1111 liblwip_deps          = LibDeps $ [ LibDep x | x <- deps ]
1112     where deps = ["lwip" ,"contmng" ,"net_if_raw" ,"timer" ,"hashtable"]
1113 libnetQmng_deps       = LibDeps $ [ LibDep x | x <- deps ]
1114     where deps = ["net_queue_manager", "contmng" ,"procon" , "net_if_raw", "bfdmuxvm"]
1115 libnfs_deps           = LibDeps $ [ LibDep "nfs", liblwip_deps]
1116 libssh_deps           = LibDeps [ libposixcompat_deps, libopenbsdcompat_deps,
1117                                   LibDep "zlib", LibDep "crypto", LibDep "ssh" ]
1118 libopenbsdcompat_deps = LibDeps [ libposixcompat_deps, LibDep "crypto",
1119                                   LibDep "openbsdcompat" ]
1120
1121 -- we need to make vfs more modular to make this actually useful
1122 data VFSModules = VFS_RamFS | VFS_NFS | VFS_BlockdevFS | VFS_FAT
1123 vfsdeps :: [VFSModules] -> [LibDepTree]
1124 vfsdeps []                  = [LibDep "vfs"]
1125 vfsdeps (VFS_RamFS:xs)      = [] ++ vfsdeps xs
1126 vfsdeps (VFS_NFS:xs)        = [libnfs_deps] ++ vfsdeps xs
1127 vfsdeps (VFS_BlockdevFS:xs) = [LibDep "ahci", LibDep "megaraid"] ++ vfsdeps xs
1128 vfsdeps (VFS_FAT:xs)        = [] ++ vfsdeps xs
1129
1130 libvfs_deps_all        = LibDeps $ vfsdeps [VFS_NFS, VFS_RamFS, VFS_BlockdevFS,
1131                                             VFS_FAT]
1132 libvfs_deps_nonfs      = LibDeps $ vfsdeps [VFS_RamFS, VFS_BlockdevFS, VFS_FAT]
1133 libvfs_deps_nfs        = LibDeps $ vfsdeps [VFS_NFS]
1134 libvfs_deps_ramfs      = LibDeps $ vfsdeps [VFS_RamFS]
1135 libvfs_deps_blockdevfs = LibDeps $ vfsdeps [VFS_BlockdevFS]
1136 libvfs_deps_fat        = LibDeps $ vfsdeps [VFS_FAT, VFS_BlockdevFS]
1137
1138 -- flatten the dependency tree
1139 flat :: [LibDepTree] -> [LibDepTree]
1140 flat [] = []
1141 flat ((LibDep  l):xs) = [LibDep l] ++ flat xs
1142 flat ((LibDeps t):xs) = flat t ++ flat xs
1143
1144 str2dep :: String -> LibDepTree
1145 str2dep  str
1146     | str == "vfs"           = libvfs_deps_all
1147     | str == "vfs_nonfs"     = libvfs_deps_nonfs
1148     | str == "posixcompat"   = libposixcompat_deps
1149     | str == "lwip"          = liblwip_deps
1150     | str == "netQmng"       = libnetQmng_deps
1151     | str == "ssh"           = libssh_deps
1152     | str == "openbsdcompat" = libopenbsdcompat_deps
1153     | otherwise              = LibDep str
1154
1155 -- get library depdencies
1156 --   we need a specific order for the .a, so we define a total order
1157 libDeps :: [String] -> [String]
1158 libDeps xs = [x | (LibDep x) <- (sortBy xcmp) . nub . flat $ map str2dep xs ]
1159     where xord = [ "ssh"
1160                   , "openbsdcompat"
1161                   , "crypto"
1162                   , "zlib"
1163                   , "posixcompat"
1164                   , "term_server"
1165                   , "vfs"
1166                   , "ahci"
1167                   , "megaraid"
1168                   , "nfs"
1169                   , "net_queue_manager"
1170                   , "bfdmuxvm"
1171                   , "lwip"
1172                   , "arranet"
1173                   , "e1000n"
1174                   , "e10k"
1175                   , "e10k_vf"
1176                   , "contmng"
1177                   , "procon"
1178                   , "net_if_raw"
1179                   , "vfsfd"
1180                   , "timer"
1181                   , "hashtable"]
1182           xcmp (LibDep a) (LibDep b) = compare (elemIndex a xord) (elemIndex b xord)
1183
1184
1185 --
1186 -- Build a CPU driver
1187 --
1188
1189 cpuDriver :: Args.Args
1190 cpuDriver = Args.defaultArgs { Args.buildFunction = cpuDriverBuildFn, 
1191                                Args.target = "cpu" }
1192
1193 -- CPU drivers are built differently
1194 cpuDriverBuildFn :: [String] -> String -> Args.Args -> HRule
1195 cpuDriverBuildFn af tf args = Rules []
1196