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