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