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