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