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