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