cdb1a5d95b03088546de9af40bb5aaae4d28ffe3
[barrelfish] / hake / RuleDefs.hs
1 -------------------------------------------------------------------------
2 -- Copyright (c) 2007-2011, 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, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
8 --
9 -- Basic Hake rule definitions and combinators
10 -- 
11 --------------------------------------------------------------------------
12
13 module RuleDefs where
14 import Data.List
15 import List (intersect)
16 import Path
17 import qualified X86_64
18 import qualified X86_32
19 import qualified SCC
20 import qualified ARM
21 import qualified ARM11MP
22 import qualified Beehive
23 import qualified XScale
24 import HakeTypes
25 import qualified Args
26 import qualified Config
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 :: [String] -> String -> String -> [String]
46 withSuffix af tf arg = 
47     [ basename f | f <- af, f `isInSameDirAs` tf, isSuffixOf arg f ]
48 withSuffices :: [String] -> String -> [String] -> [String]
49 withSuffices af tf args = 
50     concat [ withSuffix af tf arg | arg <- args ]
51
52 -- 
53 -- Find files with a given suffix in a given dir
54 --
55 inDir :: [String] -> String -> String -> String -> [String]
56 inDir af tf dir suffix =
57     -- Dummy is here so that we can find files in the same dir :-/
58     let subdir = (if head dir == '/' then absdir else reldir) ./. "dummy"
59         absdir = if head tf == '/' then dir else '.':dir
60         reldir = (dirname tf) ./. dir
61         files = withSuffix af subdir suffix
62     in
63         [ dir ./. f | f <- files ]
64
65 cInDir :: [String] -> String -> String -> [String]
66 cInDir af tf dir = inDir af tf dir ".c"
67 cxxInDir :: [String] -> String -> String -> [String]
68 cxxInDir af tf dir = inDir af tf dir ".cpp"
69 sInDir :: [String] -> String -> String -> [String]
70 sInDir af tf dir = inDir af tf dir ".S"
71
72 -------------------------------------------------------------------------
73 --
74 -- Architecture specific definitions
75 --
76 -------------------------------------------------------------------------
77
78 options :: String -> Options
79 options "x86_64" = X86_64.options
80 options "x86_32" = X86_32.options
81 options "scc" = SCC.options
82 options "arm" = ARM.options
83 options "arm11mp" = ARM11MP.options
84 options "beehive" = Beehive.options
85 options "xscale" = XScale.options
86
87 kernelCFlags "x86_64" = X86_64.kernelCFlags
88 kernelCFlags "x86_32" = X86_32.kernelCFlags
89 kernelCFlags "scc" = SCC.kernelCFlags
90 kernelCFlags "arm" = ARM.kernelCFlags
91 kernelCFlags "arm11mp" = ARM11MP.kernelCFlags
92 kernelCFlags "beehive" = Beehive.kernelCFlags
93 kernelCFlags "xscale" = XScale.kernelCFlags
94
95 kernelLdFlags "x86_64" = X86_64.kernelLdFlags
96 kernelLdFlags "x86_32" = X86_32.kernelLdFlags
97 kernelLdFlags "scc" = SCC.kernelLdFlags
98 kernelLdFlags "arm" = ARM.kernelLdFlags
99 kernelLdFlags "arm11mp" = ARM11MP.kernelLdFlags
100 kernelLdFlags "beehive" = Beehive.kernelLdFlags
101 kernelLdFlags "xscale" = XScale.kernelLdFlags
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 kernelIncludes arch = [ NoDep BuildTree arch f | f <- [
113                     "/include",
114                     "/include/dev" ]]
115                  ++
116                  [ NoDep SrcTree "src" f | f <- [ 
117                     "/kernel/include/arch" ./. arch,
118                     "/kernel/include/arch" ./. archFamily arch,
119                     "/kernel/include",
120                     "/include",
121                     "/include/arch" ./. archFamily arch,
122                     "/include/target" ./. archFamily arch]]
123
124 kernelOptions arch = Options { 
125             optArch = arch,
126             optArchFamily = archFamily arch,
127             optFlags = kernelCFlags arch,
128             optCxxFlags = [],
129             optDefines = (optDefines (options arch)) ++ [ Str "-DIN_KERNEL",
130                 Str ("-DCONFIG_SCHEDULER_" ++ (show Config.scheduler)),
131                 Str ("-DCONFIG_TIMESLICE=" ++ (show Config.timeslice)) ],
132             optIncludes = kernelIncludes arch,
133             optDependencies = 
134                 [ Dep InstallTree arch "/include/errors/errno.h",
135                   Dep InstallTree arch "/include/barrelfish_kpi/capbits.h",
136                   Dep InstallTree arch "/include/asmoffsets.h" ],
137             optLdFlags = kernelLdFlags arch,
138             optLdCxxFlags = [],
139             optLibs = [],
140             optCxxLibs = [],
141             optSuffix = [],
142             optInterconnectDrivers = [],
143             optFlounderBackends = [],
144             extraFlags = [],
145             extraDefines = [],
146             extraIncludes = [],
147             extraDependencies = [],
148             extraLdFlags = []
149           }
150
151
152 -------------------------------------------------------------------------
153 --
154 -- IMPORTANT: This section contains extraction of functions from the
155 -- relevant architecture module.  The names and types should be
156 -- exactly the same as in the architecture.hs file.  This section
157 -- should not contain any logic; ony architecture extraction.
158 --
159 --------------------------------------------------------------------------
160
161 --
162 -- First, the default C compiler for an architecture
163 --
164 cCompiler :: Options -> String -> String -> String -> [ RuleToken ]
165 cCompiler opts phase src obj
166     | optArch opts == "x86_64"  = X86_64.cCompiler opts phase src obj
167     | optArch opts == "x86_32"  = X86_32.cCompiler opts phase src obj
168     | optArch opts == "scc"     = SCC.cCompiler opts phase src obj
169     | optArch opts == "arm"     = ARM.cCompiler opts phase src obj
170     | optArch opts == "arm11mp" = ARM11MP.cCompiler opts phase src obj
171     | optArch opts == "beehive" = Beehive.cCompiler opts phase src obj
172     | optArch opts == "xscale" = XScale.cCompiler opts phase src obj
173     | otherwise = [ ErrorMsg ("no C compiler for " ++ (optArch opts)) ]
174
175 cPreprocessor :: Options -> String -> String -> String -> [ RuleToken ]
176 cPreprocessor opts phase src obj
177     | optArch opts == "beehive" = Beehive.cPreprocessor opts phase src obj
178     | otherwise = [ ErrorMsg ("no C preprocessor for " ++ (optArch opts)) ]
179
180 --
181 -- C++ compiler, where supported
182 --
183 cxxCompiler :: Options -> String -> String -> String -> [ RuleToken ]
184 cxxCompiler opts phase src obj
185     | optArch opts == "x86_64"  = X86_64.cxxCompiler opts phase src obj
186     | optArch opts == "beehive" = Beehive.cxxCompiler opts phase src obj
187     | otherwise = [ ErrorMsg ("no C++ compiler for " ++ (optArch opts)) ]
188
189
190 --
191 -- makeDepend step; note that obj can be whatever the intended output is
192 --
193 makeDepend :: Options -> String -> String -> String -> String -> [ RuleToken ]
194 makeDepend opts phase src obj depfile
195     | optArch opts == "x86_64" = 
196         X86_64.makeDepend opts phase src obj depfile
197     | optArch opts == "x86_32" = 
198         X86_32.makeDepend opts phase src obj depfile
199     | optArch opts == "scc" = 
200         SCC.makeDepend opts phase src obj depfile
201     | optArch opts == "arm" = 
202         ARM.makeDepend opts phase src obj depfile
203     | optArch opts == "arm11mp" = 
204         ARM11MP.makeDepend opts phase src obj depfile
205     | optArch opts == "beehive" = 
206         Beehive.makeDepend opts phase src obj depfile
207     | optArch opts == "xscale" = 
208         XScale.makeDepend opts phase src obj depfile
209     | otherwise = [ ErrorMsg ("no dependency generator for " ++ (optArch opts)) ]
210
211 makeCxxDepend :: Options -> String -> String -> String -> String -> [ RuleToken ]
212 makeCxxDepend opts phase src obj depfile
213     | optArch opts == "x86_64" = 
214         X86_64.makeCxxDepend opts phase src obj depfile
215     | optArch opts == "beehive" = 
216         Beehive.makeCxxDepend opts phase src obj depfile
217     | otherwise = [ ErrorMsg ("no C++ dependency generator for " ++ (optArch opts)) ]
218
219 cToAssembler :: Options -> String -> String -> String -> String -> [ RuleToken ]
220 cToAssembler opts phase src afile objdepfile
221     | optArch opts == "x86_64"  = X86_64.cToAssembler opts phase src afile objdepfile
222     | optArch opts == "x86_32"  = X86_32.cToAssembler opts phase src afile objdepfile
223     | optArch opts == "scc"     = SCC.cToAssembler opts phase src afile objdepfile
224     | optArch opts == "arm"     = ARM.cToAssembler opts phase src afile objdepfile
225     | optArch opts == "arm11mp" = ARM11MP.cToAssembler opts phase src afile objdepfile
226     | optArch opts == "beehive" = Beehive.cToAssembler opts phase src afile objdepfile
227     | optArch opts == "xscale" = XScale.cToAssembler opts phase src afile objdepfile
228     | otherwise = [ ErrorMsg ("no C compiler for " ++ (optArch opts)) ]
229
230 --
231 -- Assemble an assembly language file
232 --
233 assembler :: Options -> String -> String -> [ RuleToken ]
234 assembler opts src obj
235     | optArch opts == "x86_64"  = X86_64.assembler opts src obj
236     | optArch opts == "x86_32"  = X86_32.assembler opts src obj
237     | optArch opts == "scc"     = SCC.assembler opts src obj
238     | optArch opts == "arm"     = ARM.assembler opts src obj
239     | optArch opts == "arm11mp" = ARM11MP.assembler opts src obj
240     | optArch opts == "beehive" = Beehive.assembler opts src obj
241     | optArch opts == "xscale" = XScale.assembler opts src obj
242     | otherwise = [ ErrorMsg ("no assembler for " ++ (optArch opts)) ]
243
244 archive :: Options -> [String] -> String -> [ RuleToken ]
245 archive opts objs libname
246     | optArch opts == "x86_64"  = X86_64.archive opts objs libname
247     | optArch opts == "x86_32"  = X86_32.archive opts objs libname
248     | optArch opts == "scc"     = SCC.archive opts objs libname
249     | optArch opts == "arm"     = ARM.archive opts objs libname
250     | optArch opts == "arm11mp" = ARM11MP.archive opts objs libname
251     | optArch opts == "beehive" = Beehive.archive opts objs libname
252     | optArch opts == "xscale" = XScale.archive opts objs libname
253     | otherwise = [ ErrorMsg ("Can't build a library for " ++ (optArch opts)) ]
254
255 linker :: Options -> [String] -> [String] -> String -> [RuleToken]
256 linker opts objs libs bin
257     | optArch opts == "x86_64" = X86_64.linker opts objs libs bin
258     | optArch opts == "x86_32" = X86_32.linker opts objs libs bin
259     | optArch opts == "scc"    = SCC.linker opts objs libs bin
260     | optArch opts == "arm" = ARM.linker opts objs libs bin
261     | optArch opts == "arm11mp" = ARM11MP.linker opts objs libs bin
262     | optArch opts == "beehive" = Beehive.linker opts objs libs bin
263     | optArch opts == "xscale" = XScale.linker opts objs libs bin
264     | otherwise = [ ErrorMsg ("Can't link executables for " ++ (optArch opts)) ]
265
266 cxxlinker :: Options -> [String] -> [String] -> String -> [RuleToken]
267 cxxlinker opts objs libs bin
268     | optArch opts == "x86_64" = X86_64.cxxlinker opts objs libs bin
269     | otherwise = [ ErrorMsg ("Can't link C++ executables for " ++ (optArch opts)) ]
270
271 --
272 -- The C compiler for compiling things on the host
273 --
274 nativeCCompiler :: String
275 nativeCCompiler = "$(CC)"
276
277 -------------------------------------------------------------------------
278 --
279 -- Functions to create useful filenames
280 -- 
281
282 dependFilePath :: String -> String
283 dependFilePath obj = obj ++ ".depend"
284
285 objectFilePath :: Options -> String -> String
286 objectFilePath opts src = (optSuffix opts) ./. ((removeSuffix src) ++ ".o")
287
288 generatedObjectFilePath :: Options -> String -> String
289 generatedObjectFilePath opts src = (removeSuffix src) ++ ".o"
290
291 preprocessedFilePath :: Options -> String -> String
292 preprocessedFilePath opts src = (optSuffix opts) ./. ((removeSuffix src) ++ ".i")
293
294 -- Standard convention is that human generated assembler is .S, machine generated is .s
295 assemblerFilePath :: Options -> String -> String
296 assemblerFilePath opts src = (optSuffix opts) ./. ((removeSuffix src) ++ ".s")
297
298
299 -------------------------------------------------------------------------
300 --
301 -- Functions with logic to start doing things
302 -- 
303
304 --
305 -- Create C file dependencies
306 --
307
308 -- Since this is where we know what the depfile is called it is here that we also
309 -- decide to include it.  This stops many different places below trying to
310 -- guess what the depfile is called
311 --
312 makeDependArchSub :: Options -> String -> String -> String -> String -> [ RuleToken ]
313 makeDependArchSub opts phase src objfile depfile =
314    [ Str ("@echo Generating $@"), NL ] ++
315      makeDepend opts phase src objfile depfile
316
317 makeDependArch :: Options -> String -> String -> String -> String -> HRule
318 makeDependArch opts phase src objfile depfile =
319     Rules [ Rule (makeDependArchSub opts phase src objfile depfile),
320             Include (Out (optArch opts) depfile)
321           ]
322
323 -- Make depend for a standard object file
324 makeDependObj :: Options -> String -> String -> HRule
325 makeDependObj opts phase src =
326     let objfile = (objectFilePath opts src)
327     in
328       makeDependArch opts phase src objfile (dependFilePath objfile)
329
330 -- Make depend for a C++ object file
331 makeDependCxxArchSub :: Options -> String -> String -> String -> String -> [ RuleToken ]
332 makeDependCxxArchSub opts phase src objfile depfile =
333    [ Str ("@echo Generating $@"), NL ] ++
334      makeCxxDepend opts phase src objfile depfile
335
336 makeDependCxxArch :: Options -> String -> String -> String -> String -> HRule
337 makeDependCxxArch opts phase src objfile depfile =
338     Rules [ Rule (makeDependCxxArchSub opts phase src objfile depfile),
339             Include (Out (optArch opts) depfile)
340           ]
341
342 makeDependCxxObj :: Options -> String -> String -> HRule
343 makeDependCxxObj opts phase src =
344     let objfile = (objectFilePath opts src)
345     in
346       makeDependCxxArch opts phase src objfile (dependFilePath objfile)
347
348 -- Make depend for an assembler output
349 makeDependAssembler :: Options -> String -> String -> HRule
350 makeDependAssembler opts phase src =
351     let objfile = (assemblerFilePath opts src)
352     in
353       makeDependArch opts phase src objfile (dependFilePath objfile)
354
355 --
356 -- Compile a C program to assembler
357 --
358 makecToAssembler :: Options -> String -> String -> String -> [ RuleToken ]
359 makecToAssembler opts phase src obj =
360     cToAssembler opts phase src (assemblerFilePath opts src) (dependFilePath obj)
361
362 --
363 -- Assemble an assembly language file
364 --
365 assemble :: Options -> String -> [ RuleToken ]
366 assemble opts src =
367     assembler opts src (objectFilePath opts src)
368
369 --
370 -- Create a library from a set of object files
371 --
372 archiveLibrary :: Options -> String -> [String] -> [ RuleToken ]
373 archiveLibrary opts name objs =
374     archive opts objs (libraryPath name)
375
376 --
377 -- Link an executable
378 -- 
379 linkExecutable :: Options -> [String] -> [String] -> String -> [RuleToken]
380 linkExecutable opts objs libs bin =
381     linker opts objs libs (applicationPath bin)
382
383 --
384 -- Link a C++ executable
385 -- 
386 linkCxxExecutable :: Options -> [String] -> [String] -> String -> [RuleToken]
387 linkCxxExecutable opts objs libs bin =
388     cxxlinker opts objs libs (applicationPath bin)
389
390 -------------------------------------------------------------------------
391
392
393                   
394
395
396 -------------------------------------------------------------------------
397 --
398 -- Hake macros (hacros?): each of these evaluates to HRule, i.e. a
399 -- list of templates for Makefile rules
400 --
401 -------------------------------------------------------------------------
402
403 --
404 -- Compile a C file for a particular architecture
405 -- We include cToAssembler to permit humans to type "make foo/bar.s"
406 --
407 compileCFile :: Options -> String -> HRule
408 compileCFile opts src = 
409     Rules [ Rule (cCompiler opts "src" src (objectFilePath opts src)),
410             Rule (makecToAssembler opts "src" src (objectFilePath opts src)),
411             makeDependObj opts "src" src
412           ]
413
414 --
415 -- Compile a C++ file for a particular architecture
416 --
417 compileCxxFile :: Options -> String -> HRule
418 compileCxxFile opts src = 
419     Rules [ Rule (cxxCompiler opts "src" src (objectFilePath opts src)),
420             makeDependCxxObj opts "src" src
421           ]
422
423 --
424 -- Compile a C file for a particular architecture
425 --
426 compileGeneratedCFile :: Options -> String -> HRule
427 compileGeneratedCFile opts src = 
428     let o2 = opts { optSuffix = "" }
429         arch = optArch o2
430     in
431       Rules [ Rule (cCompiler o2 arch src (objectFilePath o2 src) ),
432               Rule (makecToAssembler o2 arch src (objectFilePath o2 src)),
433               makeDependObj o2 arch src
434             ]
435
436 compileCFiles :: Options -> [String] -> HRule
437 compileCFiles opts srcs = Rules [ compileCFile opts s | s <- srcs ]
438 compileCxxFiles :: Options -> [String] -> HRule
439 compileCxxFiles opts srcs = Rules [ compileCxxFile opts s | s <- srcs ]
440 compileGeneratedCFiles :: Options -> [String] -> HRule
441 compileGeneratedCFiles opts srcs = 
442     Rules [ compileGeneratedCFile opts s | s <- srcs ]
443
444 -- 
445 -- Add a set of C (or whatever) dependences on a *generated* file.
446 -- Somewhere else this file has to be defined as a target, of
447 -- course...
448 --
449 extraCDependencyForObj :: Options -> String -> String -> String -> [RuleToken]
450 extraCDependencyForObj opts file s obj = 
451     let arch = optArch opts
452     in
453       [ Target arch (dependFilePath obj),
454         Target arch obj,
455         Dep BuildTree arch file 
456       ] 
457
458 extraCDependency :: Options -> String -> String -> HRule
459 extraCDependency opts file s = Rule (extraCDependencyForObj opts file s obj)
460     where obj = objectFilePath opts s
461
462
463 extraCDependencies :: Options -> String -> [String] -> HRule
464 extraCDependencies opts file srcs = 
465     Rules [ extraCDependency opts file s | s <- srcs ]
466
467 extraGeneratedCDependency :: Options -> String -> String -> HRule
468 extraGeneratedCDependency opts file s = 
469     extraCDependency (opts { optSuffix = "" }) file s
470
471 --
472 -- Copy include files to the appropriate directory
473 --
474 includeFile :: Options -> String -> HRule
475 includeFile opts hdr = 
476     Rules [ (Rule [ Str "cp", In SrcTree "src" hdr, Out (optArch opts) hdr ]),
477             (Rule [ PreDep BuildTree (optArch opts) hdr, 
478                     Target (optArch opts) "/include/errors/errno.h" ]
479             )
480           ]
481
482 -- 
483 -- Build a Mackerel header file from a definition. 
484 --
485 mackerelProgLoc = In InstallTree "tools" "/bin/mackerel"
486 mackerelDevFileLoc d = In SrcTree "src" ("/devices" ./. (d ++ ".dev"))
487 mackerelDevHdrPath d = "/include/dev/" ./. (d ++ "_dev.h")
488
489 mackerel2 :: Options -> String -> HRule
490 mackerel2 opts dev = mackerel_generic opts dev "shift-driver"
491
492 mackerel :: Options -> String -> HRule
493 mackerel opts dev = mackerel_generic opts dev "bitfield-driver"
494
495 mackerel_generic :: Options -> String -> String -> HRule
496 mackerel_generic opts dev flag = 
497     let 
498         arch = optArch opts
499     in
500       Rule [ mackerelProgLoc,
501              Str ("--" ++ flag), 
502              Str "-c", mackerelDevFileLoc dev,
503              Str "-o", Out arch (mackerelDevHdrPath dev) 
504            ]
505
506 mackerelDependencies :: Options -> String -> [String] -> HRule
507 mackerelDependencies opts d srcs =
508     extraCDependencies opts (mackerelDevHdrPath d) srcs
509
510 --
511 -- Basic Flounder definitions: where things are
512 --
513
514 flounderProgLoc = In InstallTree "tools" "/bin/flounder"
515 flounderIfFileLoc ifn = In SrcTree "src" ("/if" ./. (ifn ++ ".if"))
516
517 -- new-style stubs: path for generic header
518 flounderIfDefsPath ifn = "/include/if" ./. (ifn ++ "_defs.h")
519 -- new-style stubs: path for specific backend header
520 flounderIfDrvDefsPath ifn drv = "/include/if" ./. (ifn ++ "_" ++ drv ++ "_defs.h")
521
522 -- new-style stubs: generated C code (for all default enabled backends)
523 flounderBindingPath opts ifn =
524     (optSuffix opts) ./. (ifn ++ "_flounder_bindings.c")
525 -- new-style stubs: generated C code (for extra backends enabled by the user)
526 flounderExtraBindingPath opts ifn =
527     (optSuffix opts) ./. (ifn ++ "_flounder_extra_bindings.c")
528
529 flounderTHCHdrPath ifn = "/include/if" ./. (ifn ++ "_thc.h")
530 flounderTHCStubPath opts ifn = 
531     (optSuffix opts) ./. (ifn ++ "_thc.c")
532
533 applicationPath name = "/sbin" ./. name
534 libraryPath libname = "/lib" ./. ("lib" ++ libname ++ ".a")
535 kernelPath = "/sbin/cpu"
536
537 -- construct include arguments to flounder for common types
538 -- these are:
539 --  1. platform-specific types (if/platform/foo.if)
540 --  2. architecture-specific types (if/arch/foo.if)
541 --  3. generic types (if/types.if)
542 flounderIncludes :: Options -> [RuleToken]
543 flounderIncludes opts
544     = concat [ [Str "-i", flounderIfFileLoc ifn]
545                | ifn <- [ "platform" ./. (optArch opts), -- XXX: optPlatform
546                           "arch" ./. (optArch opts),
547                           "types" ] ]
548
549 flounderRule :: Options -> [RuleToken] -> HRule
550 flounderRule opts args
551     = Rule $ [ flounderProgLoc ] ++ (flounderIncludes opts) ++ args
552
553 -- 
554 -- Build new-style Flounder header files from a definition
555 -- (generic header, plus one per backend)
556 --
557 flounderGenDefs :: Options -> String -> HRule
558 flounderGenDefs opts ifn = 
559     Rules $ flounderRule opts [
560            Str "--generic-header", flounderIfFileLoc ifn,
561            Out (optArch opts) (flounderIfDefsPath ifn)
562          ] : [ flounderRule opts [
563            Str $ "--" ++ drv ++ "-header", flounderIfFileLoc ifn,
564            Out (optArch opts) (flounderIfDrvDefsPath ifn drv)]
565            | drv <- Args.allFlounderBackends ]
566
567 -- 
568 -- Build a new Flounder binding file from a definition.
569 -- This builds the binding for all enabled backends
570 --
571 flounderBinding :: Options -> String -> [String] -> HRule
572 flounderBinding opts ifn =
573     flounderBindingHelper opts ifn backends (flounderBindingPath opts ifn)
574     where
575         backends = "generic" : (optFlounderBackends opts)
576
577 -- as above, but for a specific set of user-specified backends
578 flounderExtraBinding :: Options -> String -> [String] -> [String] -> HRule
579 flounderExtraBinding opts ifn backends = 
580     flounderBindingHelper opts ifn backends (flounderExtraBindingPath opts ifn)
581
582 flounderBindingHelper :: Options -> String -> [String] -> String -> [String] -> HRule
583 flounderBindingHelper opts ifn backends cfile srcs = Rules $
584     [ flounderRule opts $ args ++ [flounderIfFileLoc ifn, Out arch cfile ],
585         compileGeneratedCFile opts cfile,
586         flounderDefsDepend opts ifn allbackends srcs]
587     ++ [extraGeneratedCDependency opts (flounderIfDrvDefsPath ifn d) cfile
588         | d <- allbackends]
589     where
590         arch = optArch opts
591         archfam = optArchFamily opts
592         args = [Str "-a", Str archfam] ++ [Str $ "--" ++ d ++ "-stub" | d <- backends]
593         allbackends = backends `union` optFlounderBackends opts \\ ["generic"]
594
595 -- 
596 -- Build a Flounder THC header file from a definition. 
597 --
598 flounderTHCFile :: Options -> String -> HRule
599 flounderTHCFile opts ifn = 
600     flounderRule opts [
601            Str "--thc-header", flounderIfFileLoc ifn,
602            Out (optArch opts) (flounderTHCHdrPath ifn)
603          ]
604
605 -- 
606 -- Build a Flounder THC stubs file from a definition. 
607 --
608 flounderTHCStub :: Options -> String -> [String] -> HRule
609 flounderTHCStub opts ifn srcs = 
610     let cfile = flounderTHCStubPath opts ifn
611         hfile = flounderTHCHdrPath ifn
612         arch = optArch opts
613     in
614       Rules [ flounderRule opts [
615                      Str "--thc-stubs", flounderIfFileLoc ifn, 
616                      Out arch cfile
617                    ],
618               compileGeneratedCFile opts cfile,
619               extraCDependencies opts hfile srcs,
620               extraGeneratedCDependency opts hfile cfile
621             ]
622
623 --
624 -- Create a dependency on a Flounder header file for a set of files,
625 -- but don't actually build either stub (useful for libraries)
626 --
627 flounderDefsDepend :: Options -> String -> [String] -> [String] -> HRule
628 flounderDefsDepend opts ifn backends srcs = Rules $
629     (extraCDependencies opts (flounderIfDefsPath ifn) srcs) :
630     [extraCDependencies opts (flounderIfDrvDefsPath ifn drv) srcs
631            | drv <- backends, drv /= "generic" ]
632
633 --
634 -- Emit all the Flounder-related rules/dependencies for a given target
635 --
636
637 flounderRules :: Options -> Args.Args -> [String] -> [HRule]
638 flounderRules opts args csrcs = 
639     ([ flounderBinding opts f csrcs | f <- Args.flounderBindings args ]
640      ++
641      [ flounderExtraBinding opts f backends csrcs
642        | (f, backends) <- Args.flounderExtraBindings args ]
643      ++
644      [ flounderTHCStub opts f csrcs | f <- Args.flounderTHCStubs args ]
645      ++
646      -- Flounder extra defs (header files) also depend on the base
647      -- Flounder headers for the same interface
648      [ flounderDefsDepend opts f baseBackends csrcs | f <- allIf ]
649      ++
650      -- Extra defs only for non-base backends (those were already emitted above)
651      [ flounderDefsDepend opts f (backends \\ baseBackends) csrcs
652        | (f, backends) <- Args.flounderExtraDefs args ]
653     )
654     where
655       -- base backends enabled by default
656       baseBackends = optFlounderBackends opts
657
658       -- all interfaces mentioned in flounderDefs or ExtraDefs
659       allIf = nub $ Args.flounderDefs args ++ [f | (f,_) <- Args.flounderExtraDefs args]
660
661
662 --
663 -- Build a Fugu library 
664 -- 
665 fuguFile :: Options -> String -> HRule
666 fuguFile opts file = 
667     let arch = optArch opts
668         cfile = file ++ ".c"
669         hfile = "/include/errors/" ++ file ++ ".h"
670     in
671       Rules [ Rule [In InstallTree "tools" "/bin/fugu", 
672                     In SrcTree "src" (file++".fugu"),
673                     Out arch hfile,
674                     Out arch cfile ],
675               compileGeneratedCFile opts cfile
676          ]
677
678 --
679 -- Build a Hamlet file
680 -- 
681 hamletFile :: Options -> String -> HRule
682 hamletFile opts file = 
683     let arch = optArch opts
684         hfile = "/include/barrelfish_kpi/capbits.h"
685         cfile = "cap_predicates.c"
686         usercfile = "user_cap_predicates.c"
687         ofile = "user_cap_predicates.o"
688         afile = "/lib/libcap_predicates.a"
689     in
690       Rules [ Rule [In InstallTree "tools" "/bin/hamlet",
691                     In SrcTree "src" (file++".hl"),
692                     Out arch hfile,
693                     Out arch cfile, 
694                     Out arch usercfile ],
695               compileGeneratedCFile opts usercfile,
696               Rule (archive opts [ ofile ] afile)
697          ]
698
699 --
700 -- Link a set of object files and libraries together
701 --
702 link :: Options -> [String] -> [ String ] -> String -> HRule
703 link opts objs libs bin = 
704     Rule (linkExecutable opts objs libs bin)
705
706 --
707 -- Link a set of C++ object files and libraries together
708 --
709 linkCxx :: Options -> [String] -> [ String ] -> String -> HRule
710 linkCxx opts objs libs bin = 
711     Rule (linkCxxExecutable opts objs libs bin)
712
713 --
714 -- Link a CPU driver.  This is where it gets distinctly architecture-specific.
715 -- 
716 linkKernel :: Options -> String -> [String] -> [String] -> HRule
717 linkKernel opts name objs libs 
718     | optArch opts == "x86_64" = X86_64.linkKernel opts objs [libraryPath l | l <- libs ] kernelPath
719     | optArch opts == "x86_32" = X86_32.linkKernel opts objs [libraryPath l | l <- libs ] kernelPath
720     | optArch opts == "scc"    = SCC.linkKernel opts objs [libraryPath l | l <- libs ] kernelPath
721     | optArch opts == "arm" = ARM.linkKernel opts objs [libraryPath l | l <- libs ] kernelPath
722     | optArch opts == "arm11mp" = ARM11MP.linkKernel opts objs [libraryPath l | l <- libs ] kernelPath
723     | optArch opts == "beehive" = Beehive.linkKernel opts objs [libraryPath l | l <- libs ] kernelPath
724     | optArch opts == "xscale" = XScale.linkKernel opts objs [libraryPath l | l <- libs ] kernelPath
725     | otherwise = 
726         Rule [ Str ("Error: Can't link kernel for '" ++ (optArch opts) ++ "'") ]
727
728 --
729 -- Copy a file from one place to another
730 -- 
731 copy :: Options -> String -> String -> HRule
732 copy opts src dest = 
733     Rule [ Str "cp", In BuildTree (optArch opts) src, Out (optArch opts) dest ]
734
735 --
736 -- Assemble a list of S files for a particular architecture
737 --
738 assembleSFile :: Options -> String -> HRule
739 assembleSFile opts src = 
740     Rules [ Rule (assemble opts src),
741             makeDependObj opts "src" src
742           ]
743
744 assembleSFiles :: Options -> [String] -> HRule
745 assembleSFiles opts srcs = Rules [ assembleSFile opts s | s <- srcs ]
746
747 --
748 -- Archive a bunch of objects into a library
749 --
750 staticLibrary :: Options -> String -> [String] -> HRule
751 staticLibrary opts libpath objs = 
752     Rule (archiveLibrary opts libpath objs)
753
754 --
755 -- Compile a Haskell binary (for the host architecture)
756 --
757 compileHaskell prog main deps = compileHaskellWithLibs prog main deps []
758 compileHaskellWithLibs prog main deps dirs = 
759     Rule ([ NStr "ghc -i",
760             NoDep SrcTree "src" ".",
761             Str "-odir ", NoDep BuildTree "tools" ".",
762             Str "-hidir ", NoDep BuildTree "tools" ".",
763             Str "--make ",
764             In SrcTree "src" main,
765             Str "-o ",
766             Out "tools" ("/bin" ./. prog),
767             Str "$(LDFLAGS)" ]
768           ++ concat [[ NStr "-i", NoDep SrcTree "src" d] | d <- dirs]
769           ++ [ (Dep SrcTree "src" dep) | dep <- deps ])
770
771 --
772 -- Compile (and link) a C binary (for the host architecture)
773 --
774 compileNativeC :: String -> [String] -> [String] -> [String] -> HRule
775 compileNativeC prog cfiles cflags ldflags =
776     Rule ([ Str nativeCCompiler,
777             Str "-o",
778             Out "tools" ("/bin" ./. prog),
779             Str "$(CFLAGS)",
780             Str "$(LDFLAGS)" ]
781           ++ [ (Str flag) | flag <- cflags ]
782           ++ [ (Str flag) | flag <- ldflags ]
783           ++ [ (In SrcTree "src" dep) | dep <- cfiles ])
784
785 --
786 -- Build a Technical Note
787 --
788 buildTechNote :: String -> String -> Bool -> [String] -> HRule
789 buildTechNote input output bib figs = 
790     buildTechNoteWithDeps input output bib figs []
791 buildTechNoteWithDeps :: String -> String -> Bool -> [String] -> [RuleToken] -> HRule
792 buildTechNoteWithDeps input output bib figs deps = 
793     let
794         working_dir = NoDep BuildTree "tools" "/tmp/"
795         style_files = [ "bfish-logo.pdf", "bftn.sty", "defs.bib", "barrelfish.bib" ]
796     in
797       Rule ( [ Dep SrcTree "src" (f ++ ".pdf") | f <- figs]
798              ++
799              [ Dep SrcTree "src" ("/doc/style" ./. f) | f <- style_files ]
800              ++
801              [ Str "mkdir", Str "-p", working_dir, NL ]
802              ++
803              deps
804              ++
805              [ In SrcTree "src" "/tools/run-pdflatex.sh",
806                Str "--input-tex", In SrcTree "src" input,
807                Str "--working-dir", working_dir,
808                Str "--output-pdf", Out "docs" ("/" ++ output),
809                Str "--texinput", NoDep SrcTree "src" "/doc/style",
810                Str "--bibinput", NoDep SrcTree "src" "/doc/style"
811              ]
812              ++ if bib then [ Str "--has-bib" ] else []
813            )
814
815 ---------------------------------------------------------------------
816 --
817 -- Transformations on file names
818 --
819 ----------------------------------------------------------------------
820    
821 allObjectPaths :: Options -> Args.Args -> [String]
822 allObjectPaths opts args = 
823     [objectFilePath opts g 
824          | g <- (Args.cFiles args)++(Args.cxxFiles args)++(Args.assemblyFiles args)]
825     ++ 
826     [generatedObjectFilePath opts g 
827          | g <- [ flounderBindingPath opts f 
828                       | f <- (Args.flounderBindings args)]
829                 ++
830                 [ flounderExtraBindingPath opts f 
831                       | (f, _) <- (Args.flounderExtraBindings args)]
832                 ++
833                 [ flounderTHCStubPath opts f 
834                       | f <- (Args.flounderTHCStubs args)]
835     ]
836
837 allLibraryPaths :: Args.Args -> [String]
838 allLibraryPaths args = 
839     [ libraryPath l | l <- Args.addLibraries args ]
840
841
842 ---------------------------------------------------------------------
843 --
844 -- Very large-scale macros
845 --
846 ----------------------------------------------------------------------
847
848 --
849 -- Build an application binary
850 --
851
852 application :: Args.Args
853 application = Args.defaultArgs { Args.buildFunction = applicationBuildFn }
854
855 applicationBuildFn :: [String] -> String -> Args.Args -> HRule
856 applicationBuildFn af tf args 
857     | debugFlag && trace (Args.showArgs (tf ++ " Application ") args) False 
858         = undefined
859 applicationBuildFn af tf args = 
860     Rules [ appBuildArch af tf args arch | arch <- Args.architectures args ]
861
862 appGetOptionsForArch arch args = 
863     (options arch) { extraIncludes = 
864                          [ NoDep SrcTree "src" a | a <- Args.addIncludes args],
865                      optIncludes = (optIncludes $ options arch) \\
866                          [ NoDep SrcTree "src" i | i <- Args.omitIncludes args ],
867                      optFlags = (optFlags $ options arch) \\
868                                 [ Str f | f <- Args.omitCFlags args ],
869                      optCxxFlags = (optCxxFlags $ options arch) \\
870                                    [ Str f | f <- Args.omitCxxFlags args ],
871                      optSuffix = "_for_app_" ++ Args.target args,
872                      extraFlags = Args.addCFlags args ++ Args.addCxxFlags args,
873                      extraLdFlags = [ Str f | f <- Args.addLinkFlags args ],
874                      extraDependencies = 
875                          [Dep BuildTree arch s | s <- Args.addGeneratedDependencies args]
876                    }
877           
878 appBuildArch af tf args arch = 
879     let -- Fiddle the options
880         opts = appGetOptionsForArch arch args
881         csrcs = Args.cFiles args
882         cxxsrcs = Args.cxxFiles args
883         appname = Args.target args
884         -- XXX: Not sure if this is correct. Currently assuming that if the app
885         -- contains C++ files, we have to use the C++ linker.
886         mylink = if cxxsrcs == [] then link else linkCxx
887     in
888       Rules ( flounderRules opts args csrcs
889               ++
890               [ mackerelDependencies opts m csrcs | m <- Args.mackerelDevices args ]
891               ++
892               [ compileCFiles opts csrcs,
893                 compileCxxFiles opts cxxsrcs,
894                 assembleSFiles opts (Args.assemblyFiles args),
895                 mylink opts (allObjectPaths opts args) (allLibraryPaths args) appname
896               ]
897             )
898
899 --
900 -- Build a static library
901 --
902
903 library :: Args.Args
904 library = Args.defaultArgs { Args.buildFunction = libraryBuildFn }
905
906 libraryBuildFn :: [String] -> String -> Args.Args -> HRule
907 libraryBuildFn af tf args | debugFlag && trace (Args.showArgs (tf ++ " Library ") args) False = undefined
908 libraryBuildFn af tf args = 
909     Rules [ libBuildArch af tf args arch | arch <- Args.architectures args ]
910
911 libGetOptionsForArch arch args = 
912     (options arch) { extraIncludes = 
913                          [ NoDep SrcTree "src" a | a <- Args.addIncludes args],
914                      optIncludes = (optIncludes $ options arch) \\
915                          [ NoDep SrcTree "src" i | i <- Args.omitIncludes args ],
916                      optFlags = (optFlags $ options arch) \\
917                                 [ Str f | f <- Args.omitCFlags args ],
918                      optCxxFlags = (optCxxFlags $ options arch) \\
919                                    [ Str f | f <- Args.omitCxxFlags args ],
920                      optSuffix = "_for_lib_" ++ Args.target args,
921                      extraFlags = Args.addCFlags args ++ Args.addCxxFlags args,
922                      extraDependencies = 
923                          [Dep BuildTree arch s | s <- Args.addGeneratedDependencies args]
924                    }
925        
926 libBuildArch af tf args arch = 
927     let -- Fiddle the options
928         opts = libGetOptionsForArch arch args
929         csrcs = Args.cFiles args 
930         cxxsrcs = Args.cxxFiles args 
931     in
932       Rules ( flounderRules opts args csrcs
933               ++
934               [ mackerelDependencies opts m csrcs | m <- Args.mackerelDevices args ]
935               ++
936               [ compileCFiles opts csrcs,
937                 compileCxxFiles opts cxxsrcs,
938                 assembleSFiles opts (Args.assemblyFiles args),
939                 staticLibrary opts (Args.target args) (allObjectPaths opts args)
940               ]
941             )