Hake: Ddd dependency tracking for sockeye
[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                     "/lib/newlib/newlib/libc/include",
127                     "/include/c",
128                     "/include/target" </> archFamily arch]]
129                  ++ kernelOptIncludes arch
130
131 kernelOptions arch = Options {
132             optArch = arch,
133             optArchFamily = archFamily arch,
134             optFlags = kernelCFlags arch,
135             optCxxFlags = [],
136             optDefines = (optDefines (options arch)) ++ [ Str "-DIN_KERNEL",
137                 Str ("-DCONFIG_SCHEDULER_" ++ (show Config.scheduler)),
138                 Str ("-DCONFIG_TIMESLICE=" ++ (show Config.timeslice)) ],
139             optIncludes = kernelIncludes arch,
140             optDependencies =
141                 [ Dep InstallTree arch "/include/errors/errno.h",
142                   Dep InstallTree arch "/include/barrelfish_kpi/capbits.h",
143                   Dep InstallTree arch "/include/asmoffsets.h",
144                   Dep InstallTree arch "/include/trace_definitions/trace_defs.h" ],
145             optLdFlags = kernelLdFlags arch,
146             optLdCxxFlags = [],
147             optLibs = [],
148             optCxxLibs = [],
149             optSuffix = [],
150             optInterconnectDrivers = [],
151             optFlounderBackends = [],
152             extraFlags = [],
153             extraCxxFlags = [],
154             extraDefines = [],
155             extraIncludes = [],
156             extraDependencies = [],
157             extraLdFlags = [],
158             optInstallPath = OptionsPath {
159                 optPathBin = "/sbin",
160                 optPathLib = "/lib"
161             }
162           }
163
164
165 -------------------------------------------------------------------------
166 --
167 -- IMPORTANT: This section contains extraction of functions from the
168 -- relevant architecture module.  The names and types should be
169 -- exactly the same as in the architecture.hs file.  This section
170 -- should not contain any logic; ony architecture extraction.
171 --
172 --------------------------------------------------------------------------
173
174 --
175 -- First, the default C compiler for an architecture
176 --
177
178 compiler :: Options -> String
179 compiler opts
180     | optArch opts == "x86_64"  = X86_64.compiler
181     | optArch opts == "k1om"    = K1om.compiler
182     | optArch opts == "x86_32"  = X86_32.compiler
183     | optArch opts == "armv7" = ARMv7.compiler
184     | optArch opts == "armv8" = ARMv8.compiler
185
186 cCompiler :: Options -> String -> String -> String -> [ RuleToken ]
187 cCompiler opts phase src obj
188     | optArch opts == "x86_64"  = X86_64.cCompiler opts phase src obj
189     | optArch opts == "k1om"    = K1om.cCompiler opts phase src obj
190     | optArch opts == "x86_32"  = X86_32.cCompiler opts phase src obj
191     | optArch opts == "armv7" = ARMv7.cCompiler opts phase src obj
192     | optArch opts == "armv8" = ARMv8.cCompiler opts phase src obj
193     | otherwise = [ ErrorMsg ("no C compiler for " ++ (optArch opts)) ]
194
195 cPreprocessor :: Options -> String -> String -> String -> [ RuleToken ]
196 cPreprocessor opts phase src obj
197     | otherwise = [ ErrorMsg ("no C preprocessor for " ++ (optArch opts)) ]
198
199 --
200 -- C++ compiler, where supported
201 --
202 cxxCompiler :: Options -> String -> String -> String -> [ RuleToken ]
203 cxxCompiler opts phase src obj
204     | optArch opts == "x86_64"  = X86_64.cxxCompiler opts phase src obj
205     | optArch opts == "k1om"  = K1om.cxxCompiler opts phase src obj
206     | otherwise = [ ErrorMsg ("no C++ compiler for " ++ (optArch opts)) ]
207
208
209 --
210 -- makeDepend step; note that obj can be whatever the intended output is
211 --
212 makeDepend :: Options -> String -> String -> String -> String -> [ RuleToken ]
213 makeDepend opts phase src obj depfile
214     | optArch opts == "x86_64" =
215         X86_64.makeDepend opts phase src obj depfile
216     | optArch opts == "k1om" =
217         K1om.makeDepend opts phase src obj depfile
218     | optArch opts == "x86_32" =
219         X86_32.makeDepend opts phase src obj depfile
220     | optArch opts == "armv7" =
221         ARMv7.makeDepend opts phase src obj depfile
222     | optArch opts == "armv8" =
223         ARMv8.makeDepend opts phase src obj depfile
224     | otherwise = [ ErrorMsg ("no dependency generator for " ++ (optArch opts)) ]
225
226 makeCxxDepend :: Options -> String -> String -> String -> String -> [ RuleToken ]
227 makeCxxDepend opts phase src obj depfile
228     | optArch opts == "x86_64" =
229         X86_64.makeCxxDepend opts phase src obj depfile
230     | optArch opts == "k1om" =
231         K1om.makeCxxDepend opts phase src obj depfile
232     | optArch opts == "x86_32" =
233         X86_32.makeCxxDepend opts phase src obj depfile
234     | otherwise = [ ErrorMsg ("no C++ dependency generator for " ++ (optArch opts)) ]
235
236 cToAssembler :: Options -> String -> String -> String -> String -> [ RuleToken ]
237 cToAssembler opts phase src afile objdepfile
238     | optArch opts == "x86_64"  = X86_64.cToAssembler opts phase src afile objdepfile
239     | optArch opts == "k1om"  = K1om.cToAssembler opts phase src afile objdepfile
240     | optArch opts == "x86_32"  = X86_32.cToAssembler opts phase src afile objdepfile
241     | optArch opts == "armv7" = ARMv7.cToAssembler opts phase src afile objdepfile
242     | optArch opts == "armv8" = ARMv8.cToAssembler opts phase src afile objdepfile
243     | otherwise = [ ErrorMsg ("no C compiler for " ++ (optArch opts)) ]
244
245 --
246 -- Assemble an assembly language file
247 --
248 assembler :: Options -> String -> String -> [ RuleToken ]
249 assembler opts src obj
250     | optArch opts == "x86_64"  = X86_64.assembler opts src obj
251     | optArch opts == "k1om"  = K1om.assembler opts src obj
252     | optArch opts == "x86_32"  = X86_32.assembler opts src obj
253     | optArch opts == "armv7" = ARMv7.assembler opts src obj
254     | optArch opts == "armv8" = ARMv8.assembler opts src obj
255     | otherwise = [ ErrorMsg ("no assembler for " ++ (optArch opts)) ]
256
257 archive :: Options -> [String] -> [String] -> String -> String -> [ RuleToken ]
258 archive opts objs libs name libname
259     | optArch opts == "x86_64"  = X86_64.archive opts objs libs name libname
260     | optArch opts == "k1om"  = K1om.archive opts objs libs name libname
261     | optArch opts == "x86_32"  = X86_32.archive opts objs libs name libname
262     | optArch opts == "armv7" = ARMv7.archive opts objs libs name libname
263     | optArch opts == "armv8" = ARMv8.archive opts objs libs name libname
264     | otherwise = [ ErrorMsg ("Can't build a library for " ++ (optArch opts)) ]
265
266 linker :: Options -> [String] -> [String] -> [String] -> String -> [RuleToken]
267 linker opts objs libs mods bin
268     | optArch opts == "x86_64" = X86_64.linker opts objs libs mods bin
269     | optArch opts == "k1om" = K1om.linker opts objs libs mods bin
270     | optArch opts == "x86_32" = X86_32.linker opts objs libs mods bin
271     | optArch opts == "armv7" = ARMv7.linker opts objs libs mods bin
272     | optArch opts == "armv8" = ARMv8.linker opts objs libs mods bin
273     | otherwise = [ ErrorMsg ("Can't link executables for " ++ (optArch opts)) ]
274
275 strip :: Options -> String -> String -> String -> [RuleToken]
276 strip opts src debuglink target
277     | optArch opts == "x86_64" = X86_64.strip opts src debuglink target
278     | optArch opts == "k1om" = K1om.strip opts src debuglink target
279     | optArch opts == "x86_32" = X86_32.strip opts src debuglink target
280     | optArch opts == "armv7" = ARMv7.strip opts src debuglink target
281     | optArch opts == "armv8" = ARMv8.strip opts src debuglink target
282     | otherwise = [ ErrorMsg ("Can't strip executables for " ++ (optArch opts)) ]
283
284 debug :: Options -> String -> String -> [RuleToken]
285 debug opts src target
286     | optArch opts == "x86_64" = X86_64.debug opts src target
287     | optArch opts == "k1om" = K1om.debug opts src target
288     | optArch opts == "x86_32" = X86_32.debug opts src target
289     | optArch opts == "armv7" = ARMv7.debug opts src target
290     | optArch opts == "armv8" = ARMv8.debug opts src target
291     | otherwise = [ ErrorMsg ("Can't extract debug symbols for " ++ (optArch opts)) ]
292
293 cxxlinker :: Options -> [String] -> [String] -> [String] -> String -> [RuleToken]
294 cxxlinker opts objs libs mods bin
295     | optArch opts == "x86_64" = X86_64.cxxlinker opts objs libs mods bin
296     | optArch opts == "k1om" = K1om.cxxlinker opts objs libs mods bin
297     | otherwise = [ ErrorMsg ("Can't link C++ executables for " ++ (optArch opts)) ]
298
299 --
300 -- The C compiler for compiling things on the host
301 --
302 nativeCCompiler :: String
303 nativeCCompiler = "$(CC)"
304
305 nativeArchiver :: String
306 nativeArchiver = "ar"
307
308 -------------------------------------------------------------------------
309 --
310 -- Functions to create useful filenames
311 --
312
313 dependFilePath :: String -> String
314 dependFilePath obj = obj ++ ".depend"
315
316 objectFilePath :: Options -> String -> String
317 objectFilePath opts src = optSuffix opts </> replaceExtension src ".o"
318
319 generatedObjectFilePath :: Options -> String -> String
320 generatedObjectFilePath opts src = replaceExtension src ".o"
321
322 preprocessedFilePath :: Options -> String -> String
323 preprocessedFilePath opts src = optSuffix opts </> replaceExtension src ".i"
324
325 -- Standard convention is that human generated assembler is .S, machine generated is .s
326 assemblerFilePath :: Options -> String -> String
327 assemblerFilePath opts src = optSuffix opts </> replaceExtension src ".s"
328
329
330 -------------------------------------------------------------------------
331 --
332 -- Functions with logic to start doing things
333 --
334
335 --
336 -- Create C file dependencies
337 --
338
339 -- Since this is where we know what the depfile is called it is here that we also
340 -- decide to include it.  This stops many different places below trying to
341 -- guess what the depfile is called
342 --
343 makeDependArchSub :: Options -> String -> String -> String -> String -> [ RuleToken ]
344 makeDependArchSub opts phase src objfile depfile =
345    [ Str ("@if [ -z $Q ]; then echo Generating $@; fi"), NL ] ++
346      makeDepend opts phase src objfile depfile
347
348 makeDependArch :: Options -> String -> String -> String -> String -> HRule
349 makeDependArch opts phase src objfile depfile =
350     Rules [ Rule (makeDependArchSub opts phase src objfile depfile),
351             Include (Out (optArch opts) depfile)
352           ]
353
354 -- Make depend for a standard object file
355 makeDependObj :: Options -> String -> String -> HRule
356 makeDependObj opts phase src =
357     let objfile = (objectFilePath opts src)
358     in
359       makeDependArch opts phase src objfile (dependFilePath objfile)
360
361 -- Make depend for a C++ object file
362 makeDependCxxArchSub :: Options -> String -> String -> String -> String -> [ RuleToken ]
363 makeDependCxxArchSub opts phase src objfile depfile =
364    [ Str ("@if [ -z $Q ]; then echo Generating $@; fi"), NL ] ++
365      makeCxxDepend opts phase src objfile depfile
366
367 makeDependCxxArch :: Options -> String -> String -> String -> String -> HRule
368 makeDependCxxArch opts phase src objfile depfile =
369     Rules [ Rule (makeDependCxxArchSub opts phase src objfile depfile),
370             Include (Out (optArch opts) depfile)
371           ]
372
373 makeDependCxxObj :: Options -> String -> String -> HRule
374 makeDependCxxObj opts phase src =
375     let objfile = (objectFilePath opts src)
376     in
377       makeDependCxxArch opts phase src objfile (dependFilePath objfile)
378
379 -- Make depend for an assembler output
380 makeDependAssembler :: Options -> String -> String -> HRule
381 makeDependAssembler opts phase src =
382     let objfile = (assemblerFilePath opts src)
383     in
384       makeDependArch opts phase src objfile (dependFilePath objfile)
385
386 --
387 -- Compile a C program to assembler
388 --
389 makecToAssembler :: Options -> String -> String -> String -> [ RuleToken ]
390 makecToAssembler opts phase src obj =
391     cToAssembler opts phase src (assemblerFilePath opts src) (dependFilePath obj)
392
393 --
394 -- Assemble an assembly language file
395 --
396 assemble :: Options -> String -> [ RuleToken ]
397 assemble opts src =
398     assembler opts src (objectFilePath opts src)
399
400 --
401 -- Create a library from a set of object files
402 --
403 archiveLibrary :: Options -> String -> [String] -> [String] -> [ RuleToken ]
404 archiveLibrary opts name objs libs =
405     archive opts objs libs name (libraryPath opts name)
406
407 --
408 -- Link an executable
409 --
410 linkExecutable :: Options -> [String] -> [String] -> [String] -> String -> [RuleToken]
411 linkExecutable opts objs libs mods bin =
412     linker opts objs libs mods (applicationPath opts bin)
413
414 --
415 -- Strip debug symbols from an executable
416 --
417 stripExecutable :: Options -> String -> String -> String -> [RuleToken]
418 stripExecutable opts src debuglink target =
419     strip opts (applicationPath opts src) (applicationPath opts debuglink)
420                (applicationPath opts target)
421
422 --
423 -- Extract debug symbols from an executable
424 --
425 debugExecutable :: Options -> String -> String -> [RuleToken]
426 debugExecutable opts src target =
427     debug opts (applicationPath opts src) (applicationPath opts target)
428
429 --
430 -- Link a C++ executable
431 --
432 linkCxxExecutable :: Options -> [String] -> [String] -> [String] -> String -> [RuleToken]
433 linkCxxExecutable opts objs libs mods bin =
434     cxxlinker opts objs libs mods (applicationPath opts bin)
435
436 -------------------------------------------------------------------------
437
438
439
440
441
442 -------------------------------------------------------------------------
443 --
444 -- Hake macros (hacros?): each of these evaluates to HRule, i.e. a
445 -- list of templates for Makefile rules
446 --
447 -------------------------------------------------------------------------
448
449 --
450 -- Compile a C file for a particular architecture
451 -- We include cToAssembler to permit humans to type "make foo/bar.s"
452 --
453 compileCFile :: Options -> String -> HRule
454 compileCFile opts src =
455     Rules [ Rule (cCompiler opts "src" src (objectFilePath opts src)),
456             Rule (makecToAssembler opts "src" src (objectFilePath opts src)),
457             makeDependObj opts "src" src
458           ]
459
460 --
461 -- Compile a C++ file for a particular architecture
462 --
463 compileCxxFile :: Options -> String -> HRule
464 compileCxxFile opts src =
465     Rules [ Rule (cxxCompiler opts "src" src (objectFilePath opts src)),
466             makeDependCxxObj opts "src" src
467           ]
468
469 --
470 -- Compile a C file for a particular architecture
471 --
472 compileGeneratedCFile :: Options -> String -> HRule
473 compileGeneratedCFile opts src =
474     let o2 = opts { optSuffix = "" }
475         arch = optArch o2
476     in
477       Rules [ Rule (cCompiler o2 arch src (objectFilePath o2 src) ),
478               Rule (makecToAssembler o2 arch src (objectFilePath o2 src)),
479               makeDependObj o2 arch src
480             ]
481
482 compileGeneratedCxxFile :: Options -> String -> HRule
483 compileGeneratedCxxFile opts src =
484     let o2 = opts { optSuffix = "" }
485         arch = optArch o2
486     in
487       Rules [ Rule (cxxCompiler o2 arch src (objectFilePath o2 src) ),
488               makeDependCxxObj o2 arch src
489             ]
490
491 compileCFiles :: Options -> [String] -> HRule
492 compileCFiles opts srcs = Rules [ compileCFile opts s | s <- srcs ]
493 compileCxxFiles :: Options -> [String] -> HRule
494 compileCxxFiles opts srcs = Rules [ compileCxxFile opts s | s <- srcs ]
495 compileGeneratedCFiles :: Options -> [String] -> HRule
496 compileGeneratedCFiles opts srcs =
497     Rules [ compileGeneratedCFile opts s | s <- srcs ]
498 compileGeneratedCxxFiles :: Options -> [String] -> HRule
499 compileGeneratedCxxFiles opts srcs =
500     Rules [ compileGeneratedCxxFile opts s | s <- srcs ]
501
502 --
503 -- Add a set of C (or whatever) dependences on a *generated* file.
504 -- Somewhere else this file has to be defined as a target, of
505 -- course...
506 --
507 extraCDependencyForObj :: Options -> String -> String -> String -> [RuleToken]
508 extraCDependencyForObj opts file s obj =
509     let arch = optArch opts
510     in
511       [ Target arch (dependFilePath obj),
512         Target arch obj,
513         Dep BuildTree arch file
514       ]
515
516 extraCDependency :: Options -> String -> String -> HRule
517 extraCDependency opts file s = Rule (extraCDependencyForObj opts file s obj)
518     where obj = objectFilePath opts s
519
520
521 extraCDependencies :: Options -> String -> [String] -> HRule
522 extraCDependencies opts file srcs =
523     Rules [ extraCDependency opts file s | s <- srcs ]
524
525 extraGeneratedCDependency :: Options -> String -> String -> HRule
526 extraGeneratedCDependency opts file s =
527     extraCDependency (opts { optSuffix = "" }) file s
528
529 --
530 -- Copy include files to the appropriate directory
531 --
532 includeFile :: [ String ] -> HRule
533 includeFile hdrs =
534     Rules ([ Rule [ Str "cp", In SrcTree "src" hdr, Out "root" hdr] | hdr <- hdrs ]
535     ++ [
536         Phony "install_headers" False [ Dep BuildTree "root" hdr | hdr <- hdrs ]
537     ])
538
539 --
540 -- Build a Mackerel header file from a definition.
541 --
542 mackerelProgLoc = In InstallTree "tools" "/bin/mackerel"
543 mackerelDevFileLoc d = In SrcTree "src" ("/devices" </> (d ++ ".dev"))
544 mackerelDevHdrPath d = "/include/dev/" </> (d ++ "_dev.h")
545
546 mackerel2 :: Options -> String -> HRule
547 mackerel2 opts dev = mackerel_generic opts dev "shift-driver"
548
549 mackerel :: Options -> String -> HRule
550 mackerel opts dev = mackerel_generic opts dev "bitfield-driver"
551
552 mackerel_generic :: Options -> String -> String -> HRule
553 mackerel_generic opts dev flag =
554     let
555         arch = optArch opts
556     in
557       Rule [ mackerelProgLoc,
558              Str ("--" ++ flag),
559              Str "-c", mackerelDevFileLoc dev,
560              Str "-o", Out arch (mackerelDevHdrPath dev)
561            ]
562
563 mackerelDependencies :: Options -> String -> [String] -> HRule
564 mackerelDependencies opts d srcs =
565     extraCDependencies opts (mackerelDevHdrPath d) srcs
566
567 --
568 -- Basic Flounder definitions: where things are
569 --
570
571 flounderProgLoc = In InstallTree "tools" "/bin/flounder"
572 flounderIfFileLoc ifn = In SrcTree "src" ("/if" </> (ifn ++ ".if"))
573
574 -- new-style stubs: path for generic header
575 flounderIfDefsPath ifn = "/include/if" </> (ifn ++ "_defs.h")
576 -- new-style stubs: path for specific backend header
577 flounderIfDrvDefsPath ifn drv = "/include/if" </> (ifn ++ "_" ++ drv ++ "_defs.h")
578
579 -- new-style stubs: generated C code (for all default enabled backends)
580 flounderBindingPath opts ifn =
581     (optSuffix opts) </> (ifn ++ "_flounder_bindings.c")
582 -- new-style stubs: generated C code (for extra backends enabled by the user)
583 flounderExtraBindingPath opts ifn =
584     (optSuffix opts) </> (ifn ++ "_flounder_extra_bindings.c")
585
586 flounderTHCHdrPath ifn = "/include/if" </> (ifn ++ "_thc.h")
587 flounderTHCStubPath opts ifn =
588     (optSuffix opts) </> (ifn ++ "_thc.c")
589
590 applicationPath :: Options -> String -> String
591 applicationPath opts name = optPathBin (optInstallPath opts) </> name
592
593 libraryPath :: Options -> String -> String
594 libraryPath opts libname = optPathLib (optInstallPath opts) </> ("lib" ++ libname ++ ".a")
595
596 kernelPath = "/sbin/cpu"
597
598 -- construct include arguments to flounder for common types
599 -- these are:
600 --  1. platform-specific types (if/platform/foo.if)
601 --  2. architecture-specific types (if/arch/foo.if)
602 --  3. generic types (if/types.if)
603 flounderIncludes :: Options -> [RuleToken]
604 flounderIncludes opts
605     = concat [ [Str "-i", flounderIfFileLoc ifn]
606                | ifn <- [ "platform" </> (optArch opts), -- XXX: optPlatform
607                           "arch" </> (optArch opts),
608                           "types" ] ]
609
610 flounderRule :: Options -> [RuleToken] -> HRule
611 flounderRule opts args
612     = Rule $ [ flounderProgLoc ] ++ (flounderIncludes opts) ++ args
613
614 --
615 -- Build new-style Flounder header files from a definition
616 -- (generic header, plus one per backend)
617 --
618 flounderGenDefs :: Options -> String -> HRule
619 flounderGenDefs opts ifn =
620     Rules $ flounderRule opts [
621            Str "--generic-header", flounderIfFileLoc ifn,
622            Out (optArch opts) (flounderIfDefsPath ifn)
623          ] : [ flounderRule opts [
624            Str $ "--" ++ drv ++ "-header", flounderIfFileLoc ifn,
625            Out (optArch opts) (flounderIfDrvDefsPath ifn drv)]
626            | drv <- Args.allFlounderBackends ]
627
628 --
629 -- Build a new Flounder binding file from a definition.
630 -- This builds the binding for all enabled backends
631 --
632 flounderBinding :: Options -> String -> [String] -> HRule
633 flounderBinding opts ifn =
634     flounderBindingHelper opts ifn backends (flounderBindingPath opts ifn)
635     where
636         backends = "generic" : (optFlounderBackends opts)
637
638 -- as above, but for a specific set of user-specified backends
639 flounderExtraBinding :: Options -> String -> [String] -> [String] -> HRule
640 flounderExtraBinding opts ifn backends =
641     flounderBindingHelper opts ifn backends (flounderExtraBindingPath opts ifn)
642
643 flounderBindingHelper :: Options -> String -> [String] -> String -> [String] -> HRule
644 flounderBindingHelper opts ifn backends cfile srcs = Rules $
645     [ flounderRule opts $ args ++ [flounderIfFileLoc ifn, Out arch cfile ],
646         compileGeneratedCFile opts cfile,
647         flounderDefsDepend opts ifn allbackends srcs]
648     ++ [extraGeneratedCDependency opts (flounderIfDefsPath ifn) cfile]
649     ++ [extraGeneratedCDependency opts (flounderIfDrvDefsPath ifn d) cfile
650         | d <- allbackends]
651     where
652         arch = optArch opts
653         archfam = optArchFamily opts
654         args = [Str "-a", Str archfam] ++ [Str $ "--" ++ d ++ "-stub" | d <- backends]
655         allbackends = backends `union` optFlounderBackends opts \\ ["generic"]
656
657 --
658 -- Build a Flounder THC header file from a definition.
659 --
660 flounderTHCFile :: Options -> String -> HRule
661 flounderTHCFile opts ifn =
662     flounderRule opts [
663            Str "--thc-header", flounderIfFileLoc ifn,
664            Out (optArch opts) (flounderTHCHdrPath ifn)
665          ]
666
667 --
668 -- Build a Flounder THC stubs file from a definition.
669 --
670 flounderTHCStub :: Options -> String -> [String] -> HRule
671 flounderTHCStub opts ifn srcs =
672     let cfile = flounderTHCStubPath opts ifn
673         hfile = flounderTHCHdrPath ifn
674         arch = optArch opts
675     in
676       Rules [ flounderRule opts [
677                      Str "--thc-stubs", flounderIfFileLoc ifn,
678                      Out arch cfile
679                    ],
680               compileGeneratedCFile opts cfile,
681               extraCDependencies opts hfile srcs,
682               extraGeneratedCDependency opts hfile cfile,
683               extraGeneratedCDependency opts (flounderIfDefsPath ifn) cfile
684             ]
685
686 --
687 -- Create a dependency on a Flounder header file for a set of files,
688 -- but don't actually build either stub (useful for libraries)
689 --
690 flounderDefsDepend :: Options -> String -> [String] -> [String] -> HRule
691 flounderDefsDepend opts ifn backends srcs = Rules $
692     (extraCDependencies opts (flounderIfDefsPath ifn) srcs) :
693     [extraCDependencies opts (flounderIfDrvDefsPath ifn drv) srcs
694            | drv <- backends, drv /= "generic" ]
695
696 --
697 -- Emit all the Flounder-related rules/dependencies for a given target
698 --
699
700 flounderRules :: Options -> Args.Args -> [String] -> [HRule]
701 flounderRules opts args csrcs =
702     ([ flounderBinding opts f csrcs | f <- Args.flounderBindings args ]
703      ++
704      [ flounderExtraBinding opts f backends csrcs
705        | (f, backends) <- Args.flounderExtraBindings args ]
706      ++
707      [ flounderTHCStub opts f csrcs | f <- Args.flounderTHCStubs args ]
708      ++
709      -- Flounder extra defs (header files) also depend on the base
710      -- Flounder headers for the same interface
711      [ flounderDefsDepend opts f baseBackends csrcs | f <- allIf ]
712      ++
713      -- Extra defs only for non-base backends (those were already emitted above)
714      [ flounderDefsDepend opts f (backends \\ baseBackends) csrcs
715        | (f, backends) <- Args.flounderExtraDefs args ]
716     )
717     where
718       -- base backends enabled by default
719       baseBackends = optFlounderBackends opts
720
721       -- all interfaces mentioned in flounderDefs or ExtraDefs
722       allIf = nub $ Args.flounderDefs args ++ [f | (f,_) <- Args.flounderExtraDefs args]
723
724
725  --
726  -- Build a Skate library and header file
727  --
728
729
730 skateSchemaPath opts ifn = (optSuffix opts) </> (ifn ++ "_skate_schema.c")
731 skateProgLoc = In InstallTree "tools" "/bin/skate"
732 skateSksFileLoc schema = In SrcTree "src" ("/schemas" </> (schema ++ ".sks"))
733 skateSchemaDefsPath schema = "/include/schemas" </> (schema ++ "_schema.h")
734
735
736 skateSchemaHelper :: Options -> String -> String -> [String] -> HRule
737 skateSchemaHelper opts ifn cfile srcs = Rules $
738     [ skateRule opts $ args ++ [
739         Str "-o", Out arch cfile, skateSksFileLoc ifn],
740         compileGeneratedCFile opts cfile,
741         skateDefsDepend opts ifn srcs]
742     ++ [extraGeneratedCDependency opts (skateSchemaDefsPath ifn) cfile]
743     where
744         arch = optArch opts
745         archfam = optArchFamily opts
746         args = [Str "-a", Str arch, Str "-C"]
747
748
749 skateSchema :: Options -> String -> [String] -> HRule
750 skateSchema opts schema =
751     skateSchemaHelper opts schema (skateSchemaPath opts schema)
752
753
754 skateDefsDepend :: Options -> String -> [String] -> HRule
755 skateDefsDepend opts schema srcs = Rules $
756     [(extraCDependencies opts (skateSchemaDefsPath schema) srcs)]
757
758
759 skateRules :: Options -> Args.Args -> [String] -> [HRule]
760 skateRules opts args csrcs =
761     ([ skateSchema opts f csrcs | f <- Args.skateSchemas args ]
762      ++
763      [ skateDefsDepend opts f csrcs | f <- nub $ Args.skateSchemaDefs args ])
764
765
766 skateIncludes :: Options -> [RuleToken]
767 skateIncludes opts = []
768
769
770 skateRule :: Options -> [RuleToken] -> HRule
771 skateRule opts args = Rule $ [ skateProgLoc ] ++ (skateIncludes opts) ++ args
772
773
774 skateGenSchemas :: Options -> String -> HRule
775 skateGenSchemas opts schema =
776  Rules $ [skateRule opts [
777         Str "-H",
778         Str "-o", Out (optArch opts) (skateSchemaDefsPath schema),
779         skateSksFileLoc schema
780       ]]
781
782
783 --
784 -- Build SKB facts from Sockeye file
785 --
786 sockeyeProgLoc = In InstallTree "tools" "/bin/sockeye"
787 sockeyeSocFileLoc d = In SrcTree "src" ("/socs" </> (d ++ ".soc"))
788 sockeyeFactFilePath d = "/sockeyefacts" </> (d ++ ".pl")
789 sockeyeFactFileLoc d = In BuildTree "" $ sockeyeFactFilePath d
790
791 sockeye :: String -> HRule
792 sockeye net = 
793     let
794         factFile = sockeyeFactFilePath net
795         depFile = dependFilePath factFile
796     in Rules
797         [ Rule
798             [ sockeyeProgLoc
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                      optIncludes = (optIncludes $ options arch) \\
1112                          [ NoDep SrcTree "src" i | i <- Args.omitIncludes args ],
1113                      optFlags = (optFlags $ options arch) \\
1114                                 [ Str f | f <- Args.omitCFlags args ],
1115                      optCxxFlags = (optCxxFlags $ options arch) \\
1116                                    [ Str f | f <- Args.omitCxxFlags args ],
1117                      optSuffix = "_for_app_" ++ Args.target args,
1118                      extraFlags = Args.addCFlags args,
1119                      extraCxxFlags = Args.addCxxFlags args,
1120                      extraLdFlags = [ Str f | f <- Args.addLinkFlags args ],
1121                      extraDependencies =
1122                          [Dep BuildTree arch s |
1123                             s <- Args.addGeneratedDependencies args],
1124                      optInstallPath = OptionsPath {
1125                         optPathBin = Args.bindir (Args.installDirs args),
1126                         optPathLib = Args.libdir (Args.installDirs args)
1127                      }
1128                    }
1129
1130 fullTarget :: Options -> String -> String -> HRule
1131 fullTarget opts arch appname =
1132     Phony (arch ++ "_All") False
1133         [ Dep BuildTree arch (applicationPath opts appname) ]
1134
1135 appBuildArch tdb tf args arch =
1136     let -- Fiddle the options
1137         opts = appGetOptionsForArch arch args
1138         csrcs = Args.cFiles args
1139         cxxsrcs = Args.cxxFiles args
1140         gencsrc = Args.generatedCFiles args
1141         gencxxsrc = Args.generatedCxxFiles args
1142
1143
1144         appname = Args.target args
1145         -- XXX: Not sure if this is correct. Currently assuming that if the app
1146         -- contains C++ files, we have to use the C++ linker.
1147         mylink = if cxxsrcs == [] then link else linkCxx
1148     in
1149       Rules ( flounderRules opts args csrcs
1150               ++
1151               skateRules opts args csrcs
1152               ++
1153               [ mackerelDependencies opts m csrcs | m <- Args.mackerelDevices args ]
1154               ++
1155               [ compileCFiles opts csrcs,
1156                 compileCxxFiles opts cxxsrcs,
1157                 compileGeneratedCFiles opts gencsrc,
1158                 compileGeneratedCxxFiles opts gencxxsrc,
1159                 assembleSFiles opts (Args.assemblyFiles args),
1160                 mylink opts (allObjectPaths opts args) (allLibraryPaths opts args) (allModulesPaths opts args)
1161                        appname,
1162                 fullTarget opts arch appname
1163               ]
1164             )
1165
1166 --
1167 -- Build an Arrakis application binary
1168 --
1169
1170 arrakisapplication :: Args.Args
1171 arrakisapplication = Args.defaultArgs { Args.buildFunction = arrakisApplicationBuildFn }
1172
1173 arrakisApplicationBuildFn :: TreeDB -> String -> Args.Args -> HRule
1174 arrakisApplicationBuildFn tdb tf args
1175     | debugFlag && trace (Args.showArgs (tf ++ " Arrakis Application ") args) False
1176         = undefined
1177 arrakisApplicationBuildFn tdb tf args =
1178     Rules [ arrakisAppBuildArch tdb tf args arch | arch <- Args.architectures args ]
1179
1180 arrakisAppGetOptionsForArch arch args =
1181     (options arch) { extraIncludes =
1182                          [ NoDep SrcTree "src" a | a <- Args.addIncludes args],
1183                      optIncludes = (optIncludes $ options arch) \\
1184                          [ NoDep SrcTree "src" i | i <- Args.omitIncludes args ],
1185                      optFlags = ((optFlags $ options arch) ++ [ Str "-DARRAKIS" ]) \\
1186                                 [ Str f | f <- Args.omitCFlags args ],
1187                      optCxxFlags = (optCxxFlags $ options arch) \\
1188                                    [ Str f | f <- Args.omitCxxFlags args ],
1189                      optSuffix = "_for_app_" ++ Args.target args,
1190                      optLibs = [ In InstallTree arch "/lib/libarrakis.a" ] ++
1191                                ((optLibs $ options arch) \\
1192                                 [ In InstallTree arch "/lib/libbarrelfish.a" ]),
1193                      extraFlags = Args.addCFlags args,
1194                      extraCxxFlags = Args.addCxxFlags args,
1195                      extraLdFlags = [ Str f | f <- Args.addLinkFlags args ],
1196                      extraDependencies =
1197                          [Dep BuildTree arch s | s <- Args.addGeneratedDependencies args]
1198                    }
1199
1200 arrakisAppBuildArch tdb tf args arch =
1201     let -- Fiddle the options
1202         opts = arrakisAppGetOptionsForArch arch args
1203         csrcs = Args.cFiles args
1204         cxxsrcs = Args.cxxFiles args
1205         gencsrc = Args.generatedCFiles args
1206         gencxxsrc = Args.generatedCxxFiles args
1207         appname = Args.target args
1208         -- XXX: Not sure if this is correct. Currently assuming that if the app
1209         -- contains C++ files, we have to use the C++ linker.
1210         mylink = if cxxsrcs == [] then link else linkCxx
1211     in
1212       Rules ( flounderRules opts args csrcs
1213               ++
1214               skateRules opts args csrcs
1215               ++
1216               [ mackerelDependencies opts m csrcs | m <- Args.mackerelDevices args ]
1217               ++
1218               [ compileCFiles opts csrcs,
1219                 compileCxxFiles opts cxxsrcs,
1220                 compileGeneratedCFiles opts gencsrc,
1221                 compileGeneratedCxxFiles opts gencxxsrc,
1222                 assembleSFiles opts (Args.assemblyFiles args),
1223                 mylink opts (allObjectPaths opts args) (allLibraryPaths opts args) (allModulesPaths opts args) appname
1224               ]
1225             )
1226
1227 --
1228 -- Build a static library
1229 --
1230
1231 library :: Args.Args
1232 library = Args.defaultArgs { Args.buildFunction = libraryBuildFn }
1233
1234 libraryBuildFn :: TreeDB -> String -> Args.Args -> HRule
1235 libraryBuildFn tdb tf args | debugFlag && trace (Args.showArgs (tf ++ " Library ") args) False = undefined
1236 libraryBuildFn tdb tf args =
1237     Rules [ libBuildArch tdb tf args arch | arch <- Args.architectures args ]
1238
1239 libGetOptionsForArch arch args =
1240     (options arch) { extraIncludes =
1241                          [ NoDep SrcTree "src" a | a <- Args.addIncludes args],
1242                      optIncludes = (optIncludes $ options arch) \\
1243                          [ NoDep SrcTree "src" i | i <- Args.omitIncludes args ],
1244                      optFlags = (optFlags $ options arch) \\
1245                                 [ Str f | f <- Args.omitCFlags args ],
1246                      optCxxFlags = (optCxxFlags $ options arch) \\
1247                                    [ Str f | f <- Args.omitCxxFlags args ],
1248                      optSuffix = "_for_lib_" ++ Args.target args,
1249                      extraFlags = Args.addCFlags args,
1250                      extraCxxFlags = Args.addCxxFlags args,
1251                      extraDependencies =
1252                          [Dep BuildTree arch s | s <- Args.addGeneratedDependencies args]
1253                    }
1254
1255 libBuildArch tdb tf args arch =
1256     let -- Fiddle the options
1257         opts = libGetOptionsForArch arch args
1258         csrcs = Args.cFiles args
1259         cxxsrcs = Args.cxxFiles args
1260         gencsrc = Args.generatedCFiles args
1261         gencxxsrc = Args.generatedCxxFiles args
1262     in
1263       Rules ( flounderRules opts args csrcs
1264               ++
1265               skateRules opts args csrcs
1266               ++
1267               [ mackerelDependencies opts m csrcs | m <- Args.mackerelDevices args ]
1268               ++
1269               [ compileCFiles opts csrcs,
1270                 compileCxxFiles opts cxxsrcs,
1271                 compileGeneratedCFiles opts gencsrc,
1272                 compileGeneratedCxxFiles opts gencxxsrc,
1273                 assembleSFiles opts (Args.assemblyFiles args),
1274                 staticLibrary opts (Args.target args) (allObjectPaths opts args) (allLibraryPaths opts args)
1275               ]
1276             )
1277
1278 --
1279 -- Library dependecies
1280 --
1281
1282 -- The following code is under heavy construction, and also somewhat ugly
1283 data LibDepTree = LibDep String | LibDeps [LibDepTree] deriving (Show,Eq)
1284
1285 -- manually add dependencies for now (it would be better if each library
1286 -- defined each own dependencies locally, but that does not seem to be an
1287 -- easy thing to do currently
1288 libposixcompat_deps   = LibDeps [ LibDep "posixcompat",
1289                                   (libvfs_deps_all "vfs"), LibDep "term_server" ]
1290 liblwip_deps          = LibDeps $ [ LibDep x | x <- deps ]
1291     where deps = ["lwip" ,"net_if_raw" ,"timer" ,"hashtable", "netbench" ]
1292 libnetQmng_deps       = LibDeps $ [ LibDep x | x <- deps ]
1293     where deps = ["net_queue_manager"]
1294 libnfs_deps           = LibDeps $ [ LibDep "nfs", liblwip_deps]
1295 libssh_deps           = LibDeps [ libposixcompat_deps, libopenbsdcompat_deps,
1296                                   LibDep "zlib", LibDep "crypto", LibDep "ssh" ]
1297 libopenbsdcompat_deps = LibDeps [ libposixcompat_deps, LibDep "crypto",
1298                                   LibDep "openbsdcompat" ]
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     | str == "ssh"           = libssh_deps
1333     | str == "openbsdcompat" = libopenbsdcompat_deps
1334     | otherwise              = LibDep str
1335
1336 -- get library depdencies
1337 --   we need a specific order for the .a, so we define a total order
1338 libDeps :: [String] -> [String]
1339 libDeps xs = [x | (LibDep x) <- (sortBy xcmp) . nub . flat $ map str2dep xs ]
1340     where xord = [ "ssh"
1341                   , "openbsdcompat"
1342                   , "crypto"
1343                   , "zlib"
1344                   , "posixcompat"
1345                   , "term_server"
1346                   , "vfs"
1347                   , "ahci"
1348                   , "megaraid"
1349                   , "nfs"
1350                   , "net_queue_manager"
1351                   , "bfdmuxvm"
1352                   , "lwip"
1353                   , "arranet"
1354                   , "e1000n"
1355                   , "e10k"
1356                   , "e10k_vf"
1357                   , "contmng"
1358                   , "procon"
1359                   , "net_if_raw"
1360                   , "vfsfd"
1361                   , "timer"
1362                   , "hashtable"]
1363           xcmp (LibDep a) (LibDep b) = compare (elemIndex a xord) (elemIndex b xord)
1364
1365
1366 --
1367 -- Build a CPU driver
1368 --
1369
1370 cpuDriver :: Args.Args
1371 cpuDriver = Args.defaultArgs { Args.buildFunction = cpuDriverBuildFn,
1372                                Args.target = "cpu",
1373                                Args.driverType = "cpu" }
1374
1375 bootDriver :: Args.Args
1376 bootDriver = Args.defaultArgs { Args.buildFunction = cpuDriverBuildFn,
1377                                 Args.driverType = "boot" }
1378
1379 -- CPU drivers are built differently
1380 cpuDriverBuildFn :: TreeDB -> String -> Args.Args -> HRule
1381 cpuDriverBuildFn tdb tf args = Rules []
1382
1383 bootDriverBuildFn :: TreeDB -> String -> Args.Args -> HRule
1384 bootDriverBuildFn tdb tf args = Rules []
1385
1386 --
1387 -- Build a platform
1388 --
1389 platform :: String -> [ String ] -> [ ( String, String ) ] -> String -> HRule
1390 platform name archs files docstr =
1391   if null $ archs Data.List.\\ Config.architectures then
1392     Rules [
1393       Phony name False
1394       ([ NStr "@echo 'Built platform <",  NStr name, NStr ">'" ] ++
1395        [ Dep BuildTree arch file | (arch,file) <- files ]) ,
1396       Phony "clean-platform" True
1397       ([ NStr "@echo 'Cleaning platform <",  NStr name, NStr ">'", NL,
1398          Str "$(RM)" ] ++
1399        [ NoDep BuildTree arch file | (arch,file) <- files ]),
1400       Phony ("install_" ++ name) False
1401       ([ NStr "@echo 'Installing platform <",  NStr name, NStr ">'" ] ++
1402        [ NL, Str "rsync -v -a --relative" ] ++
1403        [ In BuildTree arch file | (arch,file) <- files ] ++
1404        [ Str "${INSTALL_PREFIX}" ]),
1405       Phony "help-platforms" True
1406       [ Str "@echo \"", NStr name, Str ":\\n\\t", NStr docstr, Str "\"",
1407         Dep BuildTree "root" "/help-platforms-header" ]
1408       ]
1409   else
1410     Rules []
1411
1412 --
1413 -- Boot an image.
1414 --   name: the boot target name
1415 --   archs: list of architectures required
1416 --   tokens: the hake tokens for the target
1417 --   docstr: description of the target
1418 --
1419 boot :: String -> [ String ] -> [ RuleToken ] -> String -> HRule
1420 boot name archs tokens docstr =
1421   if null $ archs Data.List.\\ Config.architectures then
1422     Rules [
1423       Phony name False tokens,
1424       Phony "help-boot" True
1425       [ Str "@echo \"", NStr name, Str ":\\n\\t", NStr docstr, Str "\"",
1426         Dep BuildTree "root" "/help-boot-header"  ]
1427       ]
1428   else
1429     Rules []
1430
1431 --
1432 -- Copy a file from the source tree
1433 --
1434 copyFile :: TreeRef -> String -> String -> String -> String -> HRule
1435 copyFile stree sarch spath darch dpath =
1436   Rule [ Str "cp", Str "-v", In stree sarch spath, Out darch dpath ]
1437
1438 getExternalDependency :: String -> String -> [ HRule ]
1439 getExternalDependency url name =
1440     [
1441         Rule ( [
1442             Str "curl",
1443             Str "--insecure",
1444             Str "--create-dirs",
1445             Str "-o",
1446             Out "cache" name,
1447             Str url
1448         ] ),
1449         copyFile SrcTree "cache" name "" name
1450     ]