Merge remote-tracking branch 'upstream/master' into 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                     "/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 sockeyeSocFileLoc d = In SrcTree "src" ("/socs" </> (d ++ ".soc"))
786 sockeyeFactFilePath d = "/sockeyefacts" </> (d ++ ".pl")
787 sockeyeFactFileLoc d = In BuildTree "" $ sockeyeFactFilePath d
788
789 sockeye :: String -> HRule
790 sockeye net = 
791     let
792         factFile = sockeyeFactFilePath net
793         depFile = dependFilePath factFile
794     in Rules
795         [ Rule
796             [ sockeyeProgLoc
797             , Str "-o", Out "" factFile
798             , Str "-d", Out "" depFile
799             , sockeyeSocFileLoc net
800             ]
801         , Include (Out "" depFile)
802         ]
803
804 --
805 -- Build a Fugu library
806 --
807 fuguCFile :: Options -> String -> HRule
808 fuguCFile opts file =
809     let arch = optArch opts
810         cfile = file ++ ".c"
811     in
812       Rules [ Rule [ In InstallTree "tools" "/bin/fugu",
813                      In SrcTree "src" (file++".fugu"),
814                      Str "-c",
815                      Out arch cfile ],
816               compileGeneratedCFile opts cfile
817          ]
818
819 fuguHFile :: Options -> String -> HRule
820 fuguHFile opts file =
821     let arch = optArch opts
822         hfile = "/include/errors/" ++ file ++ ".h"
823     in
824       Rule [ In InstallTree "tools" "/bin/fugu",
825              In SrcTree "src" (file++".fugu"),
826              Str "-h",
827              Out arch hfile ]
828
829 --
830 -- Build a Pleco library
831 --
832 plecoFile :: Options -> String -> HRule
833 plecoFile opts file =
834     let arch = optArch opts
835         cfile = file ++ ".c"
836         hfile = "/include/trace_definitions/" ++ file ++ ".h"
837         jsonfile = "/trace_definitions/" ++ file ++ ".json"
838     in
839       Rules [ Rule [In InstallTree "tools" "/bin/pleco",
840                     In SrcTree "src" (file++".pleco"),
841                     Out arch hfile,
842                     Out arch jsonfile,
843                     Out arch cfile ],
844               compileGeneratedCFile opts cfile
845          ]
846
847 --
848 -- Build a Hamlet file
849 --
850 hamletFile :: Options -> String -> HRule
851 hamletFile opts file =
852     let arch = optArch opts
853         hfile = "/include/barrelfish_kpi/capbits.h"
854         cfile = "cap_predicates.c"
855         usercfile = "user_cap_predicates.c"
856         ofile = "user_cap_predicates.o"
857         nfile = "cap_predicates"
858         afile = "/lib/libcap_predicates.a"
859     in
860       Rules [ Rule [In InstallTree "tools" "/bin/hamlet",
861                     In SrcTree "src" (file++".hl"),
862                     Out arch hfile,
863                     Out arch cfile,
864                     Out arch usercfile ],
865               compileGeneratedCFile opts usercfile,
866               Rule (archive opts [ ofile ] [] nfile afile)
867          ]
868
869 --
870 -- Link a set of object files and libraries together
871 --
872 link :: Options -> [String] -> [String] -> [String] -> String -> HRule
873 link opts objs libs mods bin =
874     let full = bin ++ ".full"
875         debug = bin ++ ".debug"
876     in Rules [
877         Rule $ linkExecutable opts objs libs mods full,
878         Rule $ debugExecutable opts full debug,
879         Rule $ stripExecutable opts full debug bin
880     ]
881
882 --
883 -- Link a set of C++ object files and libraries together
884 --
885 linkCxx :: Options -> [String] -> [String] -> [String] -> String -> HRule
886 linkCxx opts objs libs mods bin =
887     Rule (linkCxxExecutable opts objs libs mods bin)
888
889 --
890 -- Link a CPU driver.  This is where it gets distinctly architecture-specific.
891 --
892 linkKernel :: Options -> String -> [String] -> [String] -> String -> HRule
893 linkKernel opts name objs libs driverType
894     | optArch opts == "x86_64" = X86_64.linkKernel opts objs [libraryPath opts l | l <- libs ] ("/sbin" </> name)
895     | optArch opts == "k1om" = K1om.linkKernel opts objs [libraryPath opts l | l <- libs ] ("/sbin" </> name)
896     | optArch opts == "x86_32" = X86_32.linkKernel opts objs [libraryPath opts l | l <- libs ] ("/sbin" </> name)
897     | optArch opts == "armv7" = ARMv7.linkKernel opts objs [libraryPath opts l | l <- libs ] name driverType
898     | optArch opts == "armv8" = ARMv8.linkKernel opts objs [libraryPath opts l | l <- libs ] name driverType
899     | otherwise = Rule [ Str ("Error: Can't link kernel for '" ++ (optArch opts) ++ "'") ]
900
901 --
902 -- Copy a file from one place to another
903 --
904 copy :: Options -> String -> String -> HRule
905 copy opts src dest =
906     Rule [ Str "cp", In BuildTree (optArch opts) src, Out (optArch opts) dest ]
907
908 --
909 -- Assemble a list of S files for a particular architecture
910 --
911 assembleSFile :: Options -> String -> HRule
912 assembleSFile opts src =
913     Rules [ Rule (assemble opts src),
914             makeDependObj opts "src" src
915           ]
916
917 assembleSFiles :: Options -> [String] -> HRule
918 assembleSFiles opts srcs = Rules [ assembleSFile opts s | s <- srcs ]
919
920 --
921 -- Archive a bunch of objects into a library
922 --
923 staticLibrary :: Options -> String -> [String] -> [String] -> HRule
924 staticLibrary opts libpath objs libs =
925     Rule (archiveLibrary opts libpath objs libs)
926
927 --
928 -- Compile a Haskell binary (for the host architecture)
929 --
930 compileHaskell prog main deps = compileHaskellWithLibs prog main deps []
931 compileHaskellWithLibs prog main deps dirs =
932   let
933     tools_dir = (Dep InstallTree "tools" "/tools/.marker")
934   in
935     Rule ([ NStr "ghc -i",
936             NoDep SrcTree "src" ".",
937             Str "-odir ", NoDep BuildTree "tools" ".",
938             Str "-hidir ", NoDep BuildTree "tools" ".",
939             Str "-rtsopts=all",
940             Str "--make ",
941             In SrcTree "src" main,
942             Str "-o ",
943             Out "tools" ("/bin" </> prog),
944             Str "$(LDFLAGS)" ]
945           ++ concat [[ NStr "-i", NoDep SrcTree "src" d] | d <- dirs]
946           ++ [ (Dep SrcTree "src" dep) | dep <- deps ]
947           ++ [ tools_dir ])
948
949 nativeOptions = Options {
950       optArch                = "",
951       optArchFamily          = "",
952       optFlags               = [],
953       optCxxFlags            = [],
954       optDefines             = [],
955       optIncludes            = [],
956       optDependencies        = [],
957       optLdFlags             = [],
958       optLdCxxFlags          = [],
959       optLibs                = [],
960       optCxxLibs             = [],
961       optInterconnectDrivers = [],
962       optFlounderBackends    = [],
963       extraFlags             = [],
964       extraCxxFlags          = [],
965       extraDefines           = [],
966       extraIncludes          = [],
967       extraDependencies      = [],
968       extraLdFlags           = [],
969       optSuffix              = "",
970       optInstallPath         = OptionsPath {
971             optPathBin = "/sbin",
972             optPathLib = "/lib"
973       }
974     }
975
976 --
977 -- Compile (and link) a C binary (for the host architecture)
978 --
979 compileNativeC :: String -> [String] -> [String] -> [String] -> [String] ->
980                   HRule
981 compileNativeC prog cfiles cflags ldflags localLibs =
982     Rule ([ Str nativeCCompiler,
983             Str "-o",
984             Out "tools" ("/bin" </> prog),
985             Str "$(CFLAGS)",
986             Str "$(LDFLAGS)" ]
987           ++ [ (Str flag) | flag <- cflags ]
988           ++ [ (In SrcTree "src" dep) | dep <- cfiles ]
989           -- source file needs to be left of ldflags for modern-ish GCC
990           ++ [ (Str flag) | flag <- ldflags ]
991           ++ [ In BuildTree "tools" ("/lib" </> ("lib" ++ l ++ ".a")) |
992                l <- localLibs ])
993
994 --
995 -- Compile a static library for the host architecture
996 --
997 compileNativeLib :: String -> [String] -> [String] -> HRule
998 compileNativeLib name cfiles cflags =
999     Rules (
1000         [ Rule ([ Str nativeCCompiler,
1001                   Str "-c", In SrcTree "src" s,
1002                   Str "-o", Out "tools" (objectFilePath nativeOptions s),
1003                   Str "$(CFLAGS)",
1004                   Str "$(LDFLAGS)" ]
1005                 ++ [ (Str flag) | flag <- cflags ])
1006             | s <- cfiles ] ++
1007         [ Rule ([ Str nativeArchiver,
1008                   Str "rcs",
1009                   Out "tools" ("/lib" </> ("lib" ++ name ++ ".a")) ] ++
1010                 [ In BuildTree "tools" o | o <- objs ]) ]
1011         )
1012     where
1013         objs = [ objectFilePath nativeOptions s | s <- cfiles ]
1014 --
1015 -- Build a Technical Note
1016 --
1017 buildTechNote :: String -> String -> Bool -> Bool -> [String] -> HRule
1018 buildTechNote input output bib glo figs =
1019     buildTechNoteWithDeps input output bib glo figs []
1020 buildTechNoteWithDeps :: String -> String -> Bool -> Bool -> [String] -> [RuleToken] -> HRule
1021 buildTechNoteWithDeps input output bib glo figs deps =
1022     let
1023         working_dir = NoDep BuildTree "tools" "/tmp/"
1024         style_files = [ "bfish-logo.pdf", "bftn.sty", "defs.bib", "barrelfish.bib" ]
1025     in
1026       Rule ( [ Dep SrcTree "src" (f ++ ".pdf") | f <- figs]
1027              ++
1028              [ Dep SrcTree "src" ("/doc/style" </> f) | f <- style_files ]
1029              ++
1030              [ Str "mkdir", Str "-p", working_dir, NL ]
1031              ++
1032              deps
1033              ++
1034              [ In SrcTree "src" "/tools/run-pdflatex.sh",
1035                Str "--input-tex", In SrcTree "src" input,
1036                Str "--working-dir", working_dir,
1037                Str "--output-pdf", Out "docs" ("/" ++ output),
1038                Str "--texinput", NoDep SrcTree "src" "/doc/style",
1039                Str "--bibinput", NoDep SrcTree "src" "/doc/style"
1040              ]
1041              ++ (if bib then [ Str "--has-bib" ] else [])
1042              ++ (if glo then [ Str "--has-glo" ] else [])
1043            )
1044
1045 ---------------------------------------------------------------------
1046 --
1047 -- Transformations on file names
1048 --
1049 ----------------------------------------------------------------------
1050
1051 allObjectPaths :: Options -> Args.Args -> [String]
1052 allObjectPaths opts args =
1053     [objectFilePath opts g
1054          | g <- (Args.cFiles args)++(Args.cxxFiles args)++(Args.assemblyFiles args)]
1055     ++
1056     [generatedObjectFilePath opts g
1057          | g <- [ flounderBindingPath opts f
1058                       | f <- (Args.flounderBindings args)]
1059                 ++
1060                 [ flounderExtraBindingPath opts f
1061                       | (f, _) <- (Args.flounderExtraBindings args)]
1062                 ++
1063                 [ flounderTHCStubPath opts f
1064                       | f <- (Args.flounderTHCStubs args)]
1065                 ++
1066                 [ skateSchemaPath opts f
1067                       | f <- (Args.skateSchemas args)]
1068                 ++
1069                 (Args.generatedCFiles args) ++ (Args.generatedCxxFiles args)
1070     ]
1071
1072 allLibraryPaths :: Options -> Args.Args -> [String]
1073 allLibraryPaths opts args =
1074     [ libraryPath opts l | l <- Args.addLibraries args ]
1075
1076
1077 allModulesPaths :: Options -> Args.Args -> [String]
1078 allModulesPaths opts args =
1079     [ libraryPath opts l | l <- Args.addModules args ]
1080
1081 ---------------------------------------------------------------------
1082 --
1083 -- Very large-scale macros
1084 --
1085 ----------------------------------------------------------------------
1086
1087 --
1088 -- Build an application binary
1089 --
1090
1091 application :: Args.Args
1092 application = Args.defaultArgs { Args.buildFunction = applicationBuildFn }
1093
1094 system :: Args.Args -> Args.Args
1095 system args = args { Args.installDirs = (Args.installDirs args) { Args.bindir = "/sbin" }}
1096
1097 applicationBuildFn :: TreeDB -> String -> Args.Args -> HRule
1098 applicationBuildFn tdb tf args
1099     | debugFlag && trace (Args.showArgs (tf ++ " Application ") args) False
1100         = undefined
1101 applicationBuildFn tdb tf args =
1102     Rules [ appBuildArch tdb tf args arch | arch <- Args.architectures args ]
1103
1104 appGetOptionsForArch arch args =
1105     (options arch) { extraIncludes =
1106                          [ NoDep SrcTree "src" a | a <- Args.addIncludes args]
1107                          ++
1108                          [ NoDep BuildTree arch a | a <- Args.addGeneratedIncludes args]
1109                          ++
1110                          [ NoDep SrcTree "src" ("/include" </> l) | l <- Args.addLibraries 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                          ++
1243                          [ NoDep SrcTree "src" ("/include" </> l) | l <- Args.addLibraries args ],
1244                      optIncludes = (optIncludes $ options arch) \\
1245                          [ NoDep SrcTree "src" i | i <- Args.omitIncludes args ],
1246                      optFlags = (optFlags $ options arch) \\
1247                                 [ Str f | f <- Args.omitCFlags args ],
1248                      optCxxFlags = (optCxxFlags $ options arch) \\
1249                                    [ Str f | f <- Args.omitCxxFlags args ],
1250                      optSuffix = "_for_lib_" ++ Args.target args,
1251                      extraFlags = Args.addCFlags args,
1252                      extraCxxFlags = Args.addCxxFlags args,
1253                      extraDependencies =
1254                          [Dep BuildTree arch s | s <- Args.addGeneratedDependencies args]
1255                    }
1256
1257 libBuildArch tdb tf args arch =
1258     let -- Fiddle the options
1259         opts = libGetOptionsForArch arch args
1260         csrcs = Args.cFiles args
1261         cxxsrcs = Args.cxxFiles args
1262         gencsrc = Args.generatedCFiles args
1263         gencxxsrc = Args.generatedCxxFiles args
1264     in
1265       Rules ( flounderRules opts args csrcs
1266               ++
1267               skateRules opts args csrcs
1268               ++
1269               [ mackerelDependencies opts m csrcs | m <- Args.mackerelDevices args ]
1270               ++
1271               [ compileCFiles opts csrcs,
1272                 compileCxxFiles opts cxxsrcs,
1273                 compileGeneratedCFiles opts gencsrc,
1274                 compileGeneratedCxxFiles opts gencxxsrc,
1275                 assembleSFiles opts (Args.assemblyFiles args),
1276                 staticLibrary opts (Args.target args) (allObjectPaths opts args) (allLibraryPaths opts args)
1277               ]
1278             )
1279
1280 --
1281 -- Library dependecies
1282 --
1283
1284 -- The following code is under heavy construction, and also somewhat ugly
1285 data LibDepTree = LibDep String | LibDeps [LibDepTree] deriving (Show,Eq)
1286
1287 -- manually add dependencies for now (it would be better if each library
1288 -- defined each own dependencies locally, but that does not seem to be an
1289 -- easy thing to do currently
1290 libposixcompat_deps   = LibDeps [ LibDep "posixcompat",
1291                                   (libvfs_deps_all "vfs"), LibDep "term_server" ]
1292 liblwip_deps          = LibDeps $ [ LibDep x | x <- deps ]
1293     where deps = ["lwip" ,"net_if_raw" ,"timer" ,"hashtable", "netbench" ]
1294 libnetQmng_deps       = LibDeps $ [ LibDep x | x <- deps ]
1295     where deps = ["net_queue_manager"]
1296 libnfs_deps           = LibDeps $ [ LibDep "nfs", liblwip_deps]
1297
1298 -- we need to make vfs more modular to make this actually useful
1299 data VFSModules = VFS_RamFS | VFS_NFS | VFS_BlockdevFS | VFS_FAT
1300 vfsdeps :: [VFSModules] -> String -> [LibDepTree]
1301 vfsdeps [] t                  = [LibDep t]
1302 vfsdeps (VFS_RamFS:xs) t      = [] ++ vfsdeps xs t
1303 vfsdeps (VFS_NFS:xs) t        = [libnfs_deps] ++ vfsdeps xs t
1304 vfsdeps (VFS_BlockdevFS:xs) t = [LibDep "ahci", LibDep "megaraid"] ++ vfsdeps xs t
1305 vfsdeps (VFS_FAT:xs) t        = [] ++ vfsdeps xs t
1306
1307 libvfs_deps_all t        = LibDeps $ (vfsdeps [VFS_NFS, VFS_RamFS, VFS_BlockdevFS,
1308                                                VFS_FAT] t)
1309 libvfs_deps_noblockdev t = LibDeps $ (vfsdeps [VFS_NFS, VFS_RamFS] t)
1310 libvfs_deps_nonfs t      = LibDeps $ (vfsdeps [VFS_RamFS, VFS_BlockdevFS, VFS_FAT] t)
1311 libvfs_deps_nfs t        = LibDeps $ (vfsdeps [VFS_NFS] t)
1312 libvfs_deps_ramfs t      = LibDeps $ (vfsdeps [VFS_RamFS] t)
1313 libvfs_deps_blockdevfs t = LibDeps $ (vfsdeps [VFS_BlockdevFS] t)
1314 libvfs_deps_fat t        = LibDeps $ (vfsdeps [VFS_FAT, VFS_BlockdevFS] t)
1315
1316 -- flatten the dependency tree
1317 flat :: [LibDepTree] -> [LibDepTree]
1318 flat [] = []
1319 flat ((LibDep  l):xs) = [LibDep l] ++ flat xs
1320 flat ((LibDeps t):xs) = flat t ++ flat xs
1321
1322 str2dep :: String -> LibDepTree
1323 str2dep  str
1324     | str == "vfs"           = libvfs_deps_all str
1325     | str == "vfs_ramfs"     = libvfs_deps_ramfs str
1326     | str == "vfs_nonfs"     = libvfs_deps_nonfs str
1327     | str == "vfs_noblockdev"= libvfs_deps_noblockdev str
1328     | str == "lwip"          = liblwip_deps
1329     | str == "netQmng"       = libnetQmng_deps
1330     | otherwise              = LibDep str
1331
1332 -- get library depdencies
1333 --   we need a specific order for the .a, so we define a total order
1334 libDeps :: [String] -> [String]
1335 libDeps xs = [x | (LibDep x) <- (sortBy xcmp) . nub . flat $ map str2dep xs ]
1336     where xord = [  "crypto"
1337                   , "zlib"
1338                   , "posixcompat"
1339                   , "term_server"
1340                   , "vfs"
1341                   , "ahci"
1342                   , "megaraid"
1343                   , "nfs"
1344                   , "net_queue_manager"
1345                   , "bfdmuxvm"
1346                   , "lwip"
1347                   , "arranet"
1348                   , "e1000n"
1349                   , "e10k"
1350                   , "e10k_vf"
1351                   , "contmng"
1352                   , "procon"
1353                   , "net_if_raw"
1354                   , "vfsfd"
1355                   , "timer"
1356                   , "hashtable"]
1357           xcmp (LibDep a) (LibDep b) = compare (elemIndex a xord) (elemIndex b xord)
1358
1359
1360 --
1361 -- Build a CPU driver
1362 --
1363
1364 cpuDriver :: Args.Args
1365 cpuDriver = Args.defaultArgs { Args.buildFunction = cpuDriverBuildFn,
1366                                Args.target = "cpu",
1367                                Args.driverType = "cpu" }
1368
1369 bootDriver :: Args.Args
1370 bootDriver = Args.defaultArgs { Args.buildFunction = cpuDriverBuildFn,
1371                                 Args.driverType = "boot" }
1372
1373 -- CPU drivers are built differently
1374 cpuDriverBuildFn :: TreeDB -> String -> Args.Args -> HRule
1375 cpuDriverBuildFn tdb tf args = Rules []
1376
1377 bootDriverBuildFn :: TreeDB -> String -> Args.Args -> HRule
1378 bootDriverBuildFn tdb tf args = Rules []
1379
1380 --
1381 -- Build a platform
1382 --
1383 platform :: String -> [ String ] -> [ ( String, String ) ] -> String -> HRule
1384 platform name archs files docstr =
1385   if null $ archs Data.List.\\ Config.architectures then
1386     Rules [
1387       Phony name False
1388       ([ NStr "@echo 'Built platform <",  NStr name, NStr ">'" ] ++
1389        [ Dep BuildTree arch file | (arch,file) <- files ]) ,
1390       Phony "clean-platform" True
1391       ([ NStr "@echo 'Cleaning platform <",  NStr name, NStr ">'", NL,
1392          Str "$(RM)" ] ++
1393        [ NoDep BuildTree arch file | (arch,file) <- files ]),
1394       Phony ("install_" ++ name) False
1395       ([ NStr "@echo 'Installing platform <",  NStr name, NStr ">'" ] ++
1396        [ NL, Str "rsync -v -a --relative" ] ++
1397        [ In BuildTree arch file | (arch,file) <- files ] ++
1398        [ Str "${INSTALL_PREFIX}" ]),
1399       Phony "help-platforms" True
1400       [ Str "@echo \"", NStr name, Str ":\\n\\t", NStr docstr, Str "\"",
1401         Dep BuildTree "root" "/help-platforms-header" ]
1402       ]
1403   else
1404     Rules []
1405
1406 --
1407 -- Boot an image.
1408 --   name: the boot target name
1409 --   archs: list of architectures required
1410 --   tokens: the hake tokens for the target
1411 --   docstr: description of the target
1412 --
1413 boot :: String -> [ String ] -> [ RuleToken ] -> String -> HRule
1414 boot name archs tokens docstr =
1415   if null $ archs Data.List.\\ Config.architectures then
1416     Rules [
1417       Phony name False tokens,
1418       Phony "help-boot" True
1419       [ Str "@echo \"", NStr name, Str ":\\n\\t", NStr docstr, Str "\"",
1420         Dep BuildTree "root" "/help-boot-header"  ]
1421       ]
1422   else
1423     Rules []
1424
1425 --
1426 -- Copy a file from the source tree
1427 --
1428 copyFile :: TreeRef -> String -> String -> String -> String -> HRule
1429 copyFile stree sarch spath darch dpath =
1430   Rule [ Str "cp", Str "-v", In stree sarch spath, Out darch dpath ]
1431
1432 getExternalDependency :: String -> String -> [ HRule ]
1433 getExternalDependency url name =
1434     [
1435         Rule ( [
1436             Str "curl",
1437             Str "--insecure",
1438             Str "--create-dirs",
1439             Str "-o",
1440             Out "cache" name,
1441             Str url
1442         ] ),
1443         copyFile SrcTree "cache" name "" name
1444     ]