1 -------------------------------------------------------------------------
2 -- Copyright (c) 2007-2011, 2012 ETH Zurich.
3 -- All rights reserved.
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.
10 -- Basic Hake rule definitions and combinators
12 --------------------------------------------------------------------------
15 import Data.List (intersect, isSuffixOf, union, (\\), nub, sortBy, elemIndex)
17 import qualified X86_64
19 import qualified X86_32
20 import qualified ARMv5
21 import qualified ARM11MP
22 import qualified XScale
23 import qualified ARMv7
24 import qualified ARMv7_M
27 import qualified Config
31 -- should we move this to Config.hs? -AB
35 -- Is a token to be displayed in a rule?
37 inRule :: RuleToken -> Bool
38 inRule (Dep _ _ _) = False
39 inRule (PreDep _ _ _) = False
40 inRule (Target _ _) = False
44 -- Look for a set of files: this is called using the "find" combinator
46 withSuffix :: [String] -> String -> String -> [String]
47 withSuffix af tf arg =
48 [ basename f | f <- af, f `isInSameDirAs` tf, isSuffixOf arg f ]
49 withSuffices :: [String] -> String -> [String] -> [String]
50 withSuffices af tf args =
51 concat [ withSuffix af tf arg | arg <- args ]
54 -- Find files with a given suffix in a given dir
56 inDir :: [String] -> String -> String -> String -> [String]
57 inDir af tf dir suffix =
58 -- Dummy is here so that we can find files in the same dir :-/
59 let subdir = (if head dir == '/' then absdir else reldir) ./. "dummy"
60 absdir = if head tf == '/' then dir else '.':dir
61 reldir = (dirname tf) ./. dir
62 files = withSuffix af subdir suffix
64 [ dir ./. f | f <- files ]
66 cInDir :: [String] -> String -> String -> [String]
67 cInDir af tf dir = inDir af tf dir ".c"
68 cxxInDir :: [String] -> String -> String -> [String]
69 cxxInDir af tf dir = (inDir af tf dir ".cpp") ++ (inDir af tf dir ".cc")
70 sInDir :: [String] -> String -> String -> [String]
71 sInDir af tf dir = inDir af tf dir ".S"
73 -------------------------------------------------------------------------
75 -- Architecture specific definitions
77 -------------------------------------------------------------------------
79 options :: String -> Options
80 options "x86_64" = X86_64.options
81 options "k1om" = K1om.options
82 options "x86_32" = X86_32.options
83 options "armv5" = ARMv5.options
84 options "arm11mp" = ARM11MP.options
85 options "xscale" = XScale.options
86 options "armv7" = ARMv7.options
87 options "armv7-m" = ARMv7_M.options
89 options "scc" = X86_32.options
91 kernelCFlags "x86_64" = X86_64.kernelCFlags
92 kernelCFlags "k1om" = K1om.kernelCFlags
93 kernelCFlags "x86_32" = X86_32.kernelCFlags
94 kernelCFlags "armv5" = ARMv5.kernelCFlags
95 kernelCFlags "arm11mp" = ARM11MP.kernelCFlags
96 kernelCFlags "xscale" = XScale.kernelCFlags
97 kernelCFlags "armv7" = ARMv7.kernelCFlags
98 kernelCFlags "armv7-m" = ARMv7_M.kernelCFlags
100 kernelLdFlags "x86_64" = X86_64.kernelLdFlags
101 kernelLdFlags "k1om" = K1om.kernelLdFlags
102 kernelLdFlags "x86_32" = X86_32.kernelLdFlags
103 kernelLdFlags "armv5" = ARMv5.kernelLdFlags
104 kernelLdFlags "arm11mp" = ARM11MP.kernelLdFlags
105 kernelLdFlags "xscale" = XScale.kernelLdFlags
106 kernelLdFlags "armv7" = ARMv7.kernelLdFlags
107 kernelLdFlags "armv7-m" = ARMv7_M.kernelLdFlags
109 archFamily :: String -> String
110 archFamily arch = optArchFamily (options arch)
112 -------------------------------------------------------------------------
114 -- Options for compiling the kernel, which is special
116 -------------------------------------------------------------------------
118 kernelOptIncludes :: String -> [ RuleToken ]
119 kernelOptIncludes arch
120 | arch == "k1om" = K1om.kernelOptIncludes
123 kernelIncludes arch = [ NoDep BuildTree arch f | f <- [
126 [ NoDep SrcTree "src" f | f <- [
127 "/kernel/include/arch" ./. arch,
128 "/kernel/include/arch" ./. archFamily arch,
131 "/include/arch" ./. archFamily arch,
134 "/include/target" ./. archFamily arch]]
135 ++ kernelOptIncludes arch
137 kernelOptions arch = Options {
139 optArchFamily = archFamily arch,
140 optFlags = kernelCFlags arch,
142 optDefines = (optDefines (options arch)) ++ [ Str "-DIN_KERNEL",
143 Str ("-DCONFIG_SCHEDULER_" ++ (show Config.scheduler)),
144 Str ("-DCONFIG_TIMESLICE=" ++ (show Config.timeslice)) ],
145 optIncludes = kernelIncludes arch,
147 [ Dep InstallTree arch "/include/errors/errno.h",
148 Dep InstallTree arch "/include/barrelfish_kpi/capbits.h",
149 Dep InstallTree arch "/include/asmoffsets.h",
150 Dep InstallTree arch "/include/trace_definitions/trace_defs.h" ],
151 optLdFlags = kernelLdFlags arch,
156 optInterconnectDrivers = [],
157 optFlounderBackends = [],
162 extraDependencies = [],
167 -------------------------------------------------------------------------
169 -- IMPORTANT: This section contains extraction of functions from the
170 -- relevant architecture module. The names and types should be
171 -- exactly the same as in the architecture.hs file. This section
172 -- should not contain any logic; ony architecture extraction.
174 --------------------------------------------------------------------------
177 -- First, the default C compiler for an architecture
179 cCompiler :: Options -> String -> String -> String -> [ RuleToken ]
180 cCompiler opts phase src obj
181 | optArch opts == "x86_64" = X86_64.cCompiler opts phase src obj
182 | optArch opts == "k1om" = K1om.cCompiler opts phase src obj
183 | optArch opts == "x86_32" = X86_32.cCompiler opts phase src obj
184 | optArch opts == "armv5" = ARMv5.cCompiler opts phase src obj
185 | optArch opts == "arm11mp" = ARM11MP.cCompiler opts phase src obj
186 | optArch opts == "xscale" = XScale.cCompiler opts phase src obj
187 | optArch opts == "armv7" = ARMv7.cCompiler opts phase src obj
188 | optArch opts == "armv7-m" = ARMv7_M.cCompiler opts phase src obj
189 | otherwise = [ ErrorMsg ("no C compiler for " ++ (optArch opts)) ]
191 cPreprocessor :: Options -> String -> String -> String -> [ RuleToken ]
192 cPreprocessor opts phase src obj
193 | otherwise = [ ErrorMsg ("no C preprocessor for " ++ (optArch opts)) ]
196 -- C++ compiler, where supported
198 cxxCompiler :: Options -> String -> String -> String -> [ RuleToken ]
199 cxxCompiler opts phase src obj
200 | optArch opts == "x86_64" = X86_64.cxxCompiler opts phase src obj
201 | optArch opts == "k1om" = K1om.cxxCompiler opts phase src obj
202 | otherwise = [ ErrorMsg ("no C++ compiler for " ++ (optArch opts)) ]
206 -- makeDepend step; note that obj can be whatever the intended output is
208 makeDepend :: Options -> String -> String -> String -> String -> [ RuleToken ]
209 makeDepend opts phase src obj depfile
210 | optArch opts == "x86_64" =
211 X86_64.makeDepend opts phase src obj depfile
212 | optArch opts == "k1om" =
213 K1om.makeDepend opts phase src obj depfile
214 | optArch opts == "x86_32" =
215 X86_32.makeDepend opts phase src obj depfile
216 | optArch opts == "armv5" =
217 ARMv5.makeDepend opts phase src obj depfile
218 | optArch opts == "arm11mp" =
219 ARM11MP.makeDepend opts phase src obj depfile
220 | optArch opts == "xscale" =
221 XScale.makeDepend opts phase src obj depfile
222 | optArch opts == "armv7" =
223 ARMv7.makeDepend opts phase src obj depfile
224 | optArch opts == "armv7-m" =
225 ARMv7_M.makeDepend opts phase src obj depfile
226 | otherwise = [ ErrorMsg ("no dependency generator for " ++ (optArch opts)) ]
228 makeCxxDepend :: Options -> String -> String -> String -> String -> [ RuleToken ]
229 makeCxxDepend opts phase src obj depfile
230 | optArch opts == "x86_64" =
231 X86_64.makeCxxDepend opts phase src obj depfile
232 | optArch opts == "k1om" =
233 K1om.makeCxxDepend opts phase src obj depfile
234 | otherwise = [ ErrorMsg ("no C++ dependency generator for " ++ (optArch opts)) ]
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 == "armv5" = ARMv5.cToAssembler opts phase src afile objdepfile
242 | optArch opts == "arm11mp" = ARM11MP.cToAssembler opts phase src afile objdepfile
243 | optArch opts == "xscale" = XScale.cToAssembler opts phase src afile objdepfile
244 | optArch opts == "armv7" = ARMv7.cToAssembler opts phase src afile objdepfile
245 | optArch opts == "armv7-m" = ARMv7_M.cToAssembler opts phase src afile objdepfile
246 | otherwise = [ ErrorMsg ("no C compiler for " ++ (optArch opts)) ]
249 -- Assemble an assembly language file
251 assembler :: Options -> String -> String -> [ RuleToken ]
252 assembler opts src obj
253 | optArch opts == "x86_64" = X86_64.assembler opts src obj
254 | optArch opts == "k1om" = K1om.assembler opts src obj
255 | optArch opts == "x86_32" = X86_32.assembler opts src obj
256 | optArch opts == "armv5" = ARMv5.assembler opts src obj
257 | optArch opts == "arm11mp" = ARM11MP.assembler opts src obj
258 | optArch opts == "xscale" = XScale.assembler opts src obj
259 | optArch opts == "armv7" = ARMv7.assembler opts src obj
260 | optArch opts == "armv7-m" = ARMv7_M.assembler opts src obj
261 | otherwise = [ ErrorMsg ("no assembler for " ++ (optArch opts)) ]
263 archive :: Options -> [String] -> [String] -> String -> String -> [ RuleToken ]
264 archive opts objs libs name libname
265 | optArch opts == "x86_64" = X86_64.archive opts objs libs name libname
266 | optArch opts == "k1om" = K1om.archive opts objs libs name libname
267 | optArch opts == "x86_32" = X86_32.archive opts objs libs name libname
268 | optArch opts == "armv5" = ARMv5.archive opts objs libs name libname
269 | optArch opts == "arm11mp" = ARM11MP.archive opts objs libs name libname
270 | optArch opts == "xscale" = XScale.archive opts objs libs name libname
271 | optArch opts == "armv7" = ARMv7.archive opts objs libs name libname
272 | optArch opts == "armv7-m" = ARMv7_M.archive opts objs libs name libname
273 | otherwise = [ ErrorMsg ("Can't build a library for " ++ (optArch opts)) ]
275 linker :: Options -> [String] -> [String] -> String -> [RuleToken]
276 linker opts objs libs bin
277 | optArch opts == "x86_64" = X86_64.linker opts objs libs bin
278 | optArch opts == "k1om" = K1om.linker opts objs libs bin
279 | optArch opts == "x86_32" = X86_32.linker opts objs libs bin
280 | optArch opts == "armv5" = ARMv5.linker opts objs libs bin
281 | optArch opts == "arm11mp" = ARM11MP.linker opts objs libs bin
282 | optArch opts == "xscale" = XScale.linker opts objs libs bin
283 | optArch opts == "armv7" = ARMv7.linker opts objs libs bin
284 | optArch opts == "armv7-m" = ARMv7_M.linker opts objs libs bin
285 | otherwise = [ ErrorMsg ("Can't link executables for " ++ (optArch opts)) ]
287 cxxlinker :: Options -> [String] -> [String] -> String -> [RuleToken]
288 cxxlinker opts objs libs bin
289 | optArch opts == "x86_64" = X86_64.cxxlinker opts objs libs bin
290 | optArch opts == "k1om" = K1om.cxxlinker opts objs libs bin
291 | otherwise = [ ErrorMsg ("Can't link C++ executables for " ++ (optArch opts)) ]
294 -- The C compiler for compiling things on the host
296 nativeCCompiler :: String
297 nativeCCompiler = "$(CC)"
299 -------------------------------------------------------------------------
301 -- Functions to create useful filenames
304 dependFilePath :: String -> String
305 dependFilePath obj = obj ++ ".depend"
307 objectFilePath :: Options -> String -> String
308 objectFilePath opts src = (optSuffix opts) ./. ((removeSuffix src) ++ ".o")
310 generatedObjectFilePath :: Options -> String -> String
311 generatedObjectFilePath opts src = (removeSuffix src) ++ ".o"
313 preprocessedFilePath :: Options -> String -> String
314 preprocessedFilePath opts src = (optSuffix opts) ./. ((removeSuffix src) ++ ".i")
316 -- Standard convention is that human generated assembler is .S, machine generated is .s
317 assemblerFilePath :: Options -> String -> String
318 assemblerFilePath opts src = (optSuffix opts) ./. ((removeSuffix src) ++ ".s")
321 -------------------------------------------------------------------------
323 -- Functions with logic to start doing things
327 -- Create C file dependencies
330 -- Since this is where we know what the depfile is called it is here that we also
331 -- decide to include it. This stops many different places below trying to
332 -- guess what the depfile is called
334 makeDependArchSub :: Options -> String -> String -> String -> String -> [ RuleToken ]
335 makeDependArchSub opts phase src objfile depfile =
336 [ Str ("@echo Generating $@"), NL ] ++
337 makeDepend opts phase src objfile depfile
339 makeDependArch :: Options -> String -> String -> String -> String -> HRule
340 makeDependArch opts phase src objfile depfile =
341 Rules [ Rule (makeDependArchSub opts phase src objfile depfile),
342 Include (Out (optArch opts) depfile)
345 -- Make depend for a standard object file
346 makeDependObj :: Options -> String -> String -> HRule
347 makeDependObj opts phase src =
348 let objfile = (objectFilePath opts src)
350 makeDependArch opts phase src objfile (dependFilePath objfile)
352 -- Make depend for a C++ object file
353 makeDependCxxArchSub :: Options -> String -> String -> String -> String -> [ RuleToken ]
354 makeDependCxxArchSub opts phase src objfile depfile =
355 [ Str ("@echo Generating $@"), NL ] ++
356 makeCxxDepend opts phase src objfile depfile
358 makeDependCxxArch :: Options -> String -> String -> String -> String -> HRule
359 makeDependCxxArch opts phase src objfile depfile =
360 Rules [ Rule (makeDependCxxArchSub opts phase src objfile depfile),
361 Include (Out (optArch opts) depfile)
364 makeDependCxxObj :: Options -> String -> String -> HRule
365 makeDependCxxObj opts phase src =
366 let objfile = (objectFilePath opts src)
368 makeDependCxxArch opts phase src objfile (dependFilePath objfile)
370 -- Make depend for an assembler output
371 makeDependAssembler :: Options -> String -> String -> HRule
372 makeDependAssembler opts phase src =
373 let objfile = (assemblerFilePath opts src)
375 makeDependArch opts phase src objfile (dependFilePath objfile)
378 -- Compile a C program to assembler
380 makecToAssembler :: Options -> String -> String -> String -> [ RuleToken ]
381 makecToAssembler opts phase src obj =
382 cToAssembler opts phase src (assemblerFilePath opts src) (dependFilePath obj)
385 -- Assemble an assembly language file
387 assemble :: Options -> String -> [ RuleToken ]
389 assembler opts src (objectFilePath opts src)
392 -- Create a library from a set of object files
394 archiveLibrary :: Options -> String -> [String] -> [String] -> [ RuleToken ]
395 archiveLibrary opts name objs libs =
396 archive opts objs libs name (libraryPath name)
399 -- Link an executable
401 linkExecutable :: Options -> [String] -> [String] -> String -> [RuleToken]
402 linkExecutable opts objs libs bin =
403 linker opts objs libs (applicationPath bin)
406 -- Link a C++ executable
408 linkCxxExecutable :: Options -> [String] -> [String] -> String -> [RuleToken]
409 linkCxxExecutable opts objs libs bin =
410 cxxlinker opts objs libs (applicationPath bin)
412 -------------------------------------------------------------------------
418 -------------------------------------------------------------------------
420 -- Hake macros (hacros?): each of these evaluates to HRule, i.e. a
421 -- list of templates for Makefile rules
423 -------------------------------------------------------------------------
426 -- Compile a C file for a particular architecture
427 -- We include cToAssembler to permit humans to type "make foo/bar.s"
429 compileCFile :: Options -> String -> HRule
430 compileCFile opts src =
431 Rules [ Rule (cCompiler opts "src" src (objectFilePath opts src)),
432 Rule (makecToAssembler opts "src" src (objectFilePath opts src)),
433 makeDependObj opts "src" src
437 -- Compile a C++ file for a particular architecture
439 compileCxxFile :: Options -> String -> HRule
440 compileCxxFile opts src =
441 Rules [ Rule (cxxCompiler opts "src" src (objectFilePath opts src)),
442 makeDependCxxObj opts "src" src
446 -- Compile a C file for a particular architecture
448 compileGeneratedCFile :: Options -> String -> HRule
449 compileGeneratedCFile opts src =
450 let o2 = opts { optSuffix = "" }
453 Rules [ Rule (cCompiler o2 arch src (objectFilePath o2 src) ),
454 Rule (makecToAssembler o2 arch src (objectFilePath o2 src)),
455 makeDependObj o2 arch src
458 compileGeneratedCxxFile :: Options -> String -> HRule
459 compileGeneratedCxxFile opts src =
460 let o2 = opts { optSuffix = "" }
463 Rules [ Rule (cxxCompiler o2 arch src (objectFilePath o2 src) ),
464 makeDependCxxObj o2 arch src
467 compileCFiles :: Options -> [String] -> HRule
468 compileCFiles opts srcs = Rules [ compileCFile opts s | s <- srcs ]
469 compileCxxFiles :: Options -> [String] -> HRule
470 compileCxxFiles opts srcs = Rules [ compileCxxFile opts s | s <- srcs ]
471 compileGeneratedCFiles :: Options -> [String] -> HRule
472 compileGeneratedCFiles opts srcs =
473 Rules [ compileGeneratedCFile opts s | s <- srcs ]
474 compileGeneratedCxxFiles :: Options -> [String] -> HRule
475 compileGeneratedCxxFiles opts srcs =
476 Rules [ compileGeneratedCxxFile opts s | s <- srcs ]
479 -- Add a set of C (or whatever) dependences on a *generated* file.
480 -- Somewhere else this file has to be defined as a target, of
483 extraCDependencyForObj :: Options -> String -> String -> String -> [RuleToken]
484 extraCDependencyForObj opts file s obj =
485 let arch = optArch opts
487 [ Target arch (dependFilePath obj),
489 Dep BuildTree arch file
492 extraCDependency :: Options -> String -> String -> HRule
493 extraCDependency opts file s = Rule (extraCDependencyForObj opts file s obj)
494 where obj = objectFilePath opts s
497 extraCDependencies :: Options -> String -> [String] -> HRule
498 extraCDependencies opts file srcs =
499 Rules [ extraCDependency opts file s | s <- srcs ]
501 extraGeneratedCDependency :: Options -> String -> String -> HRule
502 extraGeneratedCDependency opts file s =
503 extraCDependency (opts { optSuffix = "" }) file s
506 -- Copy include files to the appropriate directory
508 includeFile :: Options -> String -> HRule
509 includeFile opts hdr =
510 Rules [ (Rule [ Str "cp", In SrcTree "src" hdr, Out (optArch opts) hdr ]),
511 (Rule [ PreDep BuildTree (optArch opts) hdr,
512 Target (optArch opts) "/include/errors/errno.h" ]
517 -- Build a Mackerel header file from a definition.
519 mackerelProgLoc = In InstallTree "tools" "/bin/mackerel"
520 mackerelDevFileLoc d = In SrcTree "src" ("/devices" ./. (d ++ ".dev"))
521 mackerelDevHdrPath d = "/include/dev/" ./. (d ++ "_dev.h")
523 mackerel2 :: Options -> String -> HRule
524 mackerel2 opts dev = mackerel_generic opts dev "shift-driver"
526 mackerel :: Options -> String -> HRule
527 mackerel opts dev = mackerel_generic opts dev "bitfield-driver"
529 mackerel_generic :: Options -> String -> String -> HRule
530 mackerel_generic opts dev flag =
534 Rule [ mackerelProgLoc,
536 Str "-c", mackerelDevFileLoc dev,
537 Str "-o", Out arch (mackerelDevHdrPath dev)
540 mackerelDependencies :: Options -> String -> [String] -> HRule
541 mackerelDependencies opts d srcs =
542 extraCDependencies opts (mackerelDevHdrPath d) srcs
545 -- Basic Flounder definitions: where things are
548 flounderProgLoc = In InstallTree "tools" "/bin/flounder"
549 flounderIfFileLoc ifn = In SrcTree "src" ("/if" ./. (ifn ++ ".if"))
551 -- new-style stubs: path for generic header
552 flounderIfDefsPath ifn = "/include/if" ./. (ifn ++ "_defs.h")
553 -- new-style stubs: path for specific backend header
554 flounderIfDrvDefsPath ifn drv = "/include/if" ./. (ifn ++ "_" ++ drv ++ "_defs.h")
556 -- new-style stubs: generated C code (for all default enabled backends)
557 flounderBindingPath opts ifn =
558 (optSuffix opts) ./. (ifn ++ "_flounder_bindings.c")
559 -- new-style stubs: generated C code (for extra backends enabled by the user)
560 flounderExtraBindingPath opts ifn =
561 (optSuffix opts) ./. (ifn ++ "_flounder_extra_bindings.c")
563 flounderTHCHdrPath ifn = "/include/if" ./. (ifn ++ "_thc.h")
564 flounderTHCStubPath opts ifn =
565 (optSuffix opts) ./. (ifn ++ "_thc.c")
567 applicationPath name = "/sbin" ./. name
568 libraryPath libname = "/lib" ./. ("lib" ++ libname ++ ".a")
569 kernelPath = "/sbin/cpu"
571 -- construct include arguments to flounder for common types
573 -- 1. platform-specific types (if/platform/foo.if)
574 -- 2. architecture-specific types (if/arch/foo.if)
575 -- 3. generic types (if/types.if)
576 flounderIncludes :: Options -> [RuleToken]
577 flounderIncludes opts
578 = concat [ [Str "-i", flounderIfFileLoc ifn]
579 | ifn <- [ "platform" ./. (optArch opts), -- XXX: optPlatform
580 "arch" ./. (optArch opts),
583 flounderRule :: Options -> [RuleToken] -> HRule
584 flounderRule opts args
585 = Rule $ [ flounderProgLoc ] ++ (flounderIncludes opts) ++ args
588 -- Build new-style Flounder header files from a definition
589 -- (generic header, plus one per backend)
591 flounderGenDefs :: Options -> String -> HRule
592 flounderGenDefs opts ifn =
593 Rules $ flounderRule opts [
594 Str "--generic-header", flounderIfFileLoc ifn,
595 Out (optArch opts) (flounderIfDefsPath ifn)
596 ] : [ flounderRule opts [
597 Str $ "--" ++ drv ++ "-header", flounderIfFileLoc ifn,
598 Out (optArch opts) (flounderIfDrvDefsPath ifn drv)]
599 | drv <- Args.allFlounderBackends ]
602 -- Build a new Flounder binding file from a definition.
603 -- This builds the binding for all enabled backends
605 flounderBinding :: Options -> String -> [String] -> HRule
606 flounderBinding opts ifn =
607 flounderBindingHelper opts ifn backends (flounderBindingPath opts ifn)
609 backends = "generic" : (optFlounderBackends opts)
611 -- as above, but for a specific set of user-specified backends
612 flounderExtraBinding :: Options -> String -> [String] -> [String] -> HRule
613 flounderExtraBinding opts ifn backends =
614 flounderBindingHelper opts ifn backends (flounderExtraBindingPath opts ifn)
616 flounderBindingHelper :: Options -> String -> [String] -> String -> [String] -> HRule
617 flounderBindingHelper opts ifn backends cfile srcs = Rules $
618 [ flounderRule opts $ args ++ [flounderIfFileLoc ifn, Out arch cfile ],
619 compileGeneratedCFile (opts { extraDependencies = [flounderHeader] }) cfile,
620 flounderDefsDepend opts ifn allbackends srcs]
621 ++ [extraGeneratedCDependency opts (flounderIfDrvDefsPath ifn d) cfile
625 archfam = optArchFamily opts
626 args = [Str "-a", Str archfam] ++ [Str $ "--" ++ d ++ "-stub" | d <- backends]
627 allbackends = backends `union` optFlounderBackends opts \\ ["generic"]
628 flounderHeader = Dep BuildTree arch $ flounderIfDefsPath ifn
631 -- Build a Flounder THC header file from a definition.
633 flounderTHCFile :: Options -> String -> HRule
634 flounderTHCFile opts ifn =
636 Str "--thc-header", flounderIfFileLoc ifn,
637 Out (optArch opts) (flounderTHCHdrPath ifn)
641 -- Build a Flounder THC stubs file from a definition.
643 flounderTHCStub :: Options -> String -> [String] -> HRule
644 flounderTHCStub opts ifn srcs =
645 let cfile = flounderTHCStubPath opts ifn
646 hfile = flounderTHCHdrPath ifn
649 Rules [ flounderRule opts [
650 Str "--thc-stubs", flounderIfFileLoc ifn,
653 compileGeneratedCFile opts cfile,
654 extraCDependencies opts hfile srcs,
655 extraGeneratedCDependency opts hfile cfile
659 -- Create a dependency on a Flounder header file for a set of files,
660 -- but don't actually build either stub (useful for libraries)
662 flounderDefsDepend :: Options -> String -> [String] -> [String] -> HRule
663 flounderDefsDepend opts ifn backends srcs = Rules $
664 (extraCDependencies opts (flounderIfDefsPath ifn) srcs) :
665 [extraCDependencies opts (flounderIfDrvDefsPath ifn drv) srcs
666 | drv <- backends, drv /= "generic" ]
669 -- Emit all the Flounder-related rules/dependencies for a given target
672 flounderRules :: Options -> Args.Args -> [String] -> [HRule]
673 flounderRules opts args csrcs =
674 ([ flounderBinding opts f csrcs | f <- Args.flounderBindings args ]
676 [ flounderExtraBinding opts f backends csrcs
677 | (f, backends) <- Args.flounderExtraBindings args ]
679 [ flounderTHCStub opts f csrcs | f <- Args.flounderTHCStubs args ]
681 -- Flounder extra defs (header files) also depend on the base
682 -- Flounder headers for the same interface
683 [ flounderDefsDepend opts f baseBackends csrcs | f <- allIf ]
685 -- Extra defs only for non-base backends (those were already emitted above)
686 [ flounderDefsDepend opts f (backends \\ baseBackends) csrcs
687 | (f, backends) <- Args.flounderExtraDefs args ]
690 -- base backends enabled by default
691 baseBackends = optFlounderBackends opts
693 -- all interfaces mentioned in flounderDefs or ExtraDefs
694 allIf = nub $ Args.flounderDefs args ++ [f | (f,_) <- Args.flounderExtraDefs args]
698 -- Build a Fugu library
700 fuguFile :: Options -> String -> HRule
702 let arch = optArch opts
704 hfile = "/include/errors/" ++ file ++ ".h"
706 Rules [ Rule [In InstallTree "tools" "/bin/fugu",
707 In SrcTree "src" (file++".fugu"),
710 compileGeneratedCFile opts cfile
714 -- Build a Pleco library
716 plecoFile :: Options -> String -> HRule
717 plecoFile opts file =
718 let arch = optArch opts
720 hfile = "/include/trace_definitions/" ++ file ++ ".h"
721 jsonfile = "/trace_definitions/" ++ file ++ ".json"
723 Rules [ Rule [In InstallTree "tools" "/bin/pleco",
724 In SrcTree "src" (file++".pleco"),
728 compileGeneratedCFile opts cfile
732 -- Build a Hamlet file
734 hamletFile :: Options -> String -> HRule
735 hamletFile opts file =
736 let arch = optArch opts
737 hfile = "/include/barrelfish_kpi/capbits.h"
738 cfile = "cap_predicates.c"
739 usercfile = "user_cap_predicates.c"
740 ofile = "user_cap_predicates.o"
741 nfile = "cap_predicates"
742 afile = "/lib/libcap_predicates.a"
744 Rules [ Rule [In InstallTree "tools" "/bin/hamlet",
745 In SrcTree "src" (file++".hl"),
748 Out arch usercfile ],
749 compileGeneratedCFile opts usercfile,
750 Rule (archive opts [ ofile ] [] nfile afile)
754 -- Link a set of object files and libraries together
756 link :: Options -> [String] -> [ String ] -> String -> HRule
757 link opts objs libs bin =
758 Rule (linkExecutable opts objs libs bin)
761 -- Link a set of C++ object files and libraries together
763 linkCxx :: Options -> [String] -> [ String ] -> String -> HRule
764 linkCxx opts objs libs bin =
765 Rule (linkCxxExecutable opts objs libs bin)
768 -- Link a CPU driver. This is where it gets distinctly architecture-specific.
770 linkKernel :: Options -> String -> [String] -> [String] -> HRule
771 linkKernel opts name objs libs
772 | optArch opts == "x86_64" = X86_64.linkKernel opts objs [libraryPath l | l <- libs ] ("/sbin" ./. name)
773 | optArch opts == "k1om" = K1om.linkKernel opts objs [libraryPath l | l <- libs ] ("/sbin" ./. name)
774 | optArch opts == "x86_32" = X86_32.linkKernel opts objs [libraryPath l | l <- libs ] ("/sbin" ./. name)
775 | optArch opts == "armv5" = ARMv5.linkKernel opts objs [libraryPath l | l <- libs ] ("/sbin" ./. name)
776 | optArch opts == "arm11mp" = ARM11MP.linkKernel opts objs [libraryPath l | l <- libs ] ("/sbin" ./. name)
777 | optArch opts == "xscale" = XScale.linkKernel opts objs [libraryPath l | l <- libs ] ("/sbin" ./. name)
778 | optArch opts == "armv7" = ARMv7.linkKernel opts objs [libraryPath l | l <- libs ] name
779 | optArch opts == "armv7-m" = ARMv7_M.linkKernel opts objs [libraryPath l | l <- libs ] name
780 | otherwise = Rule [ Str ("Error: Can't link kernel for '" ++ (optArch opts) ++ "'") ]
783 -- Copy a file from one place to another
785 copy :: Options -> String -> String -> HRule
787 Rule [ Str "cp", In BuildTree (optArch opts) src, Out (optArch opts) dest ]
790 -- Assemble a list of S files for a particular architecture
792 assembleSFile :: Options -> String -> HRule
793 assembleSFile opts src =
794 Rules [ Rule (assemble opts src),
795 makeDependObj opts "src" src
798 assembleSFiles :: Options -> [String] -> HRule
799 assembleSFiles opts srcs = Rules [ assembleSFile opts s | s <- srcs ]
802 -- Archive a bunch of objects into a library
804 staticLibrary :: Options -> String -> [String] -> [String] -> HRule
805 staticLibrary opts libpath objs libs =
806 Rule (archiveLibrary opts libpath objs libs)
809 -- Compile a Haskell binary (for the host architecture)
811 compileHaskell prog main deps = compileHaskellWithLibs prog main deps []
812 compileHaskellWithLibs prog main deps dirs =
814 tools_dir = (Dep InstallTree "tools" "/tools/.marker")
816 Rule ([ NStr "ghc -i",
817 NoDep SrcTree "src" ".",
818 Str "-odir ", NoDep BuildTree "tools" ".",
819 Str "-hidir ", NoDep BuildTree "tools" ".",
822 In SrcTree "src" main,
824 Out "tools" ("/bin" ./. prog),
826 ++ concat [[ NStr "-i", NoDep SrcTree "src" d] | d <- dirs]
827 ++ [ (Dep SrcTree "src" dep) | dep <- deps ]
831 -- Compile (and link) a C binary (for the host architecture)
833 compileNativeC :: String -> [String] -> [String] -> [String] -> HRule
834 compileNativeC prog cfiles cflags ldflags =
835 Rule ([ Str nativeCCompiler,
837 Out "tools" ("/bin" ./. prog),
840 ++ [ (Str flag) | flag <- cflags ]
841 ++ [ (Str flag) | flag <- ldflags ]
842 ++ [ (In SrcTree "src" dep) | dep <- cfiles ])
845 -- Build a Technical Note
847 buildTechNote :: String -> String -> Bool -> Bool -> [String] -> HRule
848 buildTechNote input output bib glo figs =
849 buildTechNoteWithDeps input output bib glo figs []
850 buildTechNoteWithDeps :: String -> String -> Bool -> Bool -> [String] -> [RuleToken] -> HRule
851 buildTechNoteWithDeps input output bib glo figs deps =
853 working_dir = NoDep BuildTree "tools" "/tmp/"
854 style_files = [ "bfish-logo.pdf", "bftn.sty", "defs.bib", "barrelfish.bib" ]
856 Rule ( [ Dep SrcTree "src" (f ++ ".pdf") | f <- figs]
858 [ Dep SrcTree "src" ("/doc/style" ./. f) | f <- style_files ]
860 [ Str "mkdir", Str "-p", working_dir, NL ]
864 [ In SrcTree "src" "/tools/run-pdflatex.sh",
865 Str "--input-tex", In SrcTree "src" input,
866 Str "--working-dir", working_dir,
867 Str "--output-pdf", Out "docs" ("/" ++ output),
868 Str "--texinput", NoDep SrcTree "src" "/doc/style",
869 Str "--bibinput", NoDep SrcTree "src" "/doc/style"
871 ++ (if bib then [ Str "--has-bib" ] else [])
872 ++ (if glo then [ Str "--has-glo" ] else [])
875 ---------------------------------------------------------------------
877 -- Transformations on file names
879 ----------------------------------------------------------------------
881 allObjectPaths :: Options -> Args.Args -> [String]
882 allObjectPaths opts args =
883 [objectFilePath opts g
884 | g <- (Args.cFiles args)++(Args.cxxFiles args)++(Args.assemblyFiles args)]
886 [generatedObjectFilePath opts g
887 | g <- [ flounderBindingPath opts f
888 | f <- (Args.flounderBindings args)]
890 [ flounderExtraBindingPath opts f
891 | (f, _) <- (Args.flounderExtraBindings args)]
893 [ flounderTHCStubPath opts f
894 | f <- (Args.flounderTHCStubs args)]
896 (Args.generatedCFiles args) ++ (Args.generatedCxxFiles args)
899 allLibraryPaths :: Args.Args -> [String]
900 allLibraryPaths args =
901 [ libraryPath l | l <- Args.addLibraries args ]
904 ---------------------------------------------------------------------
906 -- Very large-scale macros
908 ----------------------------------------------------------------------
911 -- Build an application binary
914 application :: Args.Args
915 application = Args.defaultArgs { Args.buildFunction = applicationBuildFn }
917 applicationBuildFn :: [String] -> String -> Args.Args -> HRule
918 applicationBuildFn af tf args
919 | debugFlag && trace (Args.showArgs (tf ++ " Application ") args) False
921 applicationBuildFn af tf args =
922 Rules [ appBuildArch af tf args arch | arch <- Args.architectures args ]
924 appGetOptionsForArch arch args =
925 (options arch) { extraIncludes =
926 [ NoDep SrcTree "src" a | a <- Args.addIncludes args]
928 [ NoDep BuildTree arch a | a <- Args.addGeneratedIncludes args],
929 optIncludes = (optIncludes $ options arch) \\
930 [ NoDep SrcTree "src" i | i <- Args.omitIncludes args ],
931 optFlags = (optFlags $ options arch) \\
932 [ Str f | f <- Args.omitCFlags args ],
933 optCxxFlags = (optCxxFlags $ options arch) \\
934 [ Str f | f <- Args.omitCxxFlags args ],
935 optSuffix = "_for_app_" ++ Args.target args,
936 extraFlags = Args.addCFlags args,
937 extraCxxFlags = Args.addCxxFlags args,
938 extraLdFlags = [ Str f | f <- Args.addLinkFlags args ],
940 [Dep BuildTree arch s | s <- Args.addGeneratedDependencies args]
943 appBuildArch af tf args arch =
944 let -- Fiddle the options
945 opts = appGetOptionsForArch arch args
946 csrcs = Args.cFiles args
947 cxxsrcs = Args.cxxFiles args
948 gencsrc = Args.generatedCFiles args
949 gencxxsrc = Args.generatedCxxFiles args
952 appname = Args.target args
953 -- XXX: Not sure if this is correct. Currently assuming that if the app
954 -- contains C++ files, we have to use the C++ linker.
955 mylink = if cxxsrcs == [] then link else linkCxx
957 Rules ( flounderRules opts args csrcs
959 [ mackerelDependencies opts m csrcs | m <- Args.mackerelDevices args ]
961 [ compileCFiles opts csrcs,
962 compileCxxFiles opts cxxsrcs,
963 compileGeneratedCFiles opts gencsrc,
964 compileGeneratedCxxFiles opts gencxxsrc,
965 assembleSFiles opts (Args.assemblyFiles args),
966 mylink opts (allObjectPaths opts args) (allLibraryPaths args) appname
971 -- Build an Arrakis application binary
974 arrakisapplication :: Args.Args
975 arrakisapplication = Args.defaultArgs { Args.buildFunction = arrakisApplicationBuildFn }
977 arrakisApplicationBuildFn :: [String] -> String -> Args.Args -> HRule
978 arrakisApplicationBuildFn af tf args
979 | debugFlag && trace (Args.showArgs (tf ++ " Arrakis Application ") args) False
981 arrakisApplicationBuildFn af tf args =
982 Rules [ arrakisAppBuildArch af tf args arch | arch <- Args.architectures args ]
984 arrakisAppGetOptionsForArch arch args =
985 (options arch) { extraIncludes =
986 [ NoDep SrcTree "src" a | a <- Args.addIncludes args],
987 optIncludes = (optIncludes $ options arch) \\
988 [ NoDep SrcTree "src" i | i <- Args.omitIncludes args ],
989 optFlags = ((optFlags $ options arch) ++ [ Str "-DARRAKIS" ]) \\
990 [ Str f | f <- Args.omitCFlags args ],
991 optCxxFlags = (optCxxFlags $ options arch) \\
992 [ Str f | f <- Args.omitCxxFlags args ],
993 optSuffix = "_for_app_" ++ Args.target args,
994 optLibs = [ In InstallTree arch "/lib/libarrakis.a" ] ++
995 ((optLibs $ options arch) \\
996 [ In InstallTree arch "/lib/libbarrelfish.a" ]),
997 extraFlags = Args.addCFlags args,
998 extraCxxFlags = Args.addCxxFlags args,
999 extraLdFlags = [ Str f | f <- Args.addLinkFlags args ],
1001 [Dep BuildTree arch s | s <- Args.addGeneratedDependencies args]
1004 arrakisAppBuildArch af tf args arch =
1005 let -- Fiddle the options
1006 opts = arrakisAppGetOptionsForArch arch args
1007 csrcs = Args.cFiles args
1008 cxxsrcs = Args.cxxFiles args
1009 gencsrc = Args.generatedCFiles args
1010 gencxxsrc = Args.generatedCxxFiles args
1011 appname = Args.target args
1012 -- XXX: Not sure if this is correct. Currently assuming that if the app
1013 -- contains C++ files, we have to use the C++ linker.
1014 mylink = if cxxsrcs == [] then link else linkCxx
1016 Rules ( flounderRules opts args csrcs
1018 [ mackerelDependencies opts m csrcs | m <- Args.mackerelDevices args ]
1020 [ compileCFiles opts csrcs,
1021 compileCxxFiles opts cxxsrcs,
1022 compileGeneratedCFiles opts gencsrc,
1023 compileGeneratedCxxFiles opts gencxxsrc,
1024 assembleSFiles opts (Args.assemblyFiles args),
1025 mylink opts (allObjectPaths opts args) (allLibraryPaths args) appname
1030 -- Build a static library
1033 library :: Args.Args
1034 library = Args.defaultArgs { Args.buildFunction = libraryBuildFn }
1036 libraryBuildFn :: [String] -> String -> Args.Args -> HRule
1037 libraryBuildFn af tf args | debugFlag && trace (Args.showArgs (tf ++ " Library ") args) False = undefined
1038 libraryBuildFn af tf args =
1039 Rules [ libBuildArch af tf args arch | arch <- Args.architectures args ]
1041 libGetOptionsForArch arch args =
1042 (options arch) { extraIncludes =
1043 [ NoDep SrcTree "src" a | a <- Args.addIncludes args],
1044 optIncludes = (optIncludes $ options arch) \\
1045 [ NoDep SrcTree "src" i | i <- Args.omitIncludes args ],
1046 optFlags = (optFlags $ options arch) \\
1047 [ Str f | f <- Args.omitCFlags args ],
1048 optCxxFlags = (optCxxFlags $ options arch) \\
1049 [ Str f | f <- Args.omitCxxFlags args ],
1050 optSuffix = "_for_lib_" ++ Args.target args,
1051 extraFlags = Args.addCFlags args,
1052 extraCxxFlags = Args.addCxxFlags args,
1054 [Dep BuildTree arch s | s <- Args.addGeneratedDependencies args]
1057 libBuildArch af tf args arch =
1058 let -- Fiddle the options
1059 opts = libGetOptionsForArch arch args
1060 csrcs = Args.cFiles args
1061 cxxsrcs = Args.cxxFiles args
1062 gencsrc = Args.generatedCFiles args
1063 gencxxsrc = Args.generatedCxxFiles args
1065 Rules ( flounderRules opts args csrcs
1067 [ mackerelDependencies opts m csrcs | m <- Args.mackerelDevices args ]
1069 [ compileCFiles opts csrcs,
1070 compileCxxFiles opts cxxsrcs,
1071 compileGeneratedCFiles opts gencsrc,
1072 compileGeneratedCxxFiles opts gencxxsrc,
1073 assembleSFiles opts (Args.assemblyFiles args),
1074 staticLibrary opts (Args.target args) (allObjectPaths opts args) (allLibraryPaths args)
1079 -- Library dependecies
1082 -- The following code is under heavy construction, and also somewhat ugly
1083 data LibDepTree = LibDep String | LibDeps [LibDepTree] deriving (Show,Eq)
1085 -- manually add dependencies for now (it would be better if each library
1086 -- defined each own dependencies locally, but that does not seem to be an
1087 -- easy thing to do currently
1088 libposixcompat_deps = LibDeps [ LibDep "posixcompat",
1089 libvfs_deps_all, LibDep "term_server" ]
1090 liblwip_deps = LibDeps $ [ LibDep x | x <- deps ]
1091 where deps = ["lwip" ,"contmng" ,"net_if_raw" ,"timer" ,"hashtable"]
1092 libnetQmng_deps = LibDeps $ [ LibDep x | x <- deps ]
1093 where deps = ["net_queue_manager", "contmng" ,"procon" , "net_if_raw", "bfdmuxvm"]
1094 libnfs_deps = LibDeps $ [ LibDep "nfs", liblwip_deps]
1095 libssh_deps = LibDeps [ libposixcompat_deps, libopenbsdcompat_deps,
1096 LibDep "zlib", LibDep "crypto", LibDep "ssh" ]
1097 libopenbsdcompat_deps = LibDeps [ libposixcompat_deps, LibDep "crypto",
1098 LibDep "openbsdcompat" ]
1100 -- we need to make vfs more modular to make this actually useful
1101 data VFSModules = VFS_RamFS | VFS_NFS | VFS_BlockdevFS | VFS_FAT
1102 vfsdeps :: [VFSModules] -> [LibDepTree]
1103 vfsdeps [] = [LibDep "vfs"]
1104 vfsdeps (VFS_RamFS:xs) = [] ++ vfsdeps xs
1105 vfsdeps (VFS_NFS:xs) = [libnfs_deps] ++ vfsdeps xs
1106 vfsdeps (VFS_BlockdevFS:xs) = [LibDep "ahci" ] ++ vfsdeps xs
1107 vfsdeps (VFS_FAT:xs) = [] ++ vfsdeps xs
1109 libvfs_deps_all = LibDeps $ vfsdeps [VFS_NFS, VFS_RamFS, VFS_BlockdevFS,
1111 libvfs_deps_nonfs = LibDeps $ vfsdeps [VFS_RamFS, VFS_BlockdevFS, VFS_FAT]
1112 libvfs_deps_nfs = LibDeps $ vfsdeps [VFS_NFS]
1113 libvfs_deps_ramfs = LibDeps $ vfsdeps [VFS_RamFS]
1114 libvfs_deps_blockdevfs = LibDeps $ vfsdeps [VFS_BlockdevFS]
1115 libvfs_deps_fat = LibDeps $ vfsdeps [VFS_FAT, VFS_BlockdevFS]
1117 -- flatten the dependency tree
1118 flat :: [LibDepTree] -> [LibDepTree]
1120 flat ((LibDep l):xs) = [LibDep l] ++ flat xs
1121 flat ((LibDeps t):xs) = flat t ++ flat xs
1123 str2dep :: String -> LibDepTree
1125 | str == "vfs" = libvfs_deps_all
1126 | str == "vfs_nonfs" = libvfs_deps_nonfs
1127 | str == "posixcompat" = libposixcompat_deps
1128 | str == "lwip" = liblwip_deps
1129 | str == "netQmng" = libnetQmng_deps
1130 | str == "ssh" = libssh_deps
1131 | str == "openbsdcompat" = libopenbsdcompat_deps
1132 | otherwise = LibDep str
1134 -- get library depdencies
1135 -- we need a specific order for the .a, so we define a total order
1136 libDeps :: [String] -> [String]
1137 libDeps xs = [x | (LibDep x) <- (sortBy xcmp) . nub . flat $ map str2dep xs ]
1138 where xord = [ "ssh"
1147 , "net_queue_manager"
1160 xcmp (LibDep a) (LibDep b) = compare (elemIndex a xord) (elemIndex b xord)
1164 -- Build a CPU driver
1167 cpuDriver :: Args.Args
1168 cpuDriver = Args.defaultArgs { Args.buildFunction = cpuDriverBuildFn,
1169 Args.target = "cpu" }
1171 -- CPU drivers are built differently
1172 cpuDriverBuildFn :: [String] -> String -> Args.Args -> HRule
1173 cpuDriverBuildFn af tf args = Rules []
1178 platform :: String -> [ String ] -> [ ( String, String ) ] -> String -> HRule
1179 platform name archs files docstr =
1180 if null $ archs Data.List.\\ Config.architectures then
1183 ([ NStr "@echo 'Built platform <", NStr name, NStr ">'" ] ++
1184 [ Dep BuildTree arch file | (arch,file) <- files ]) ,
1185 Phony "help-platforms" True
1186 [ Str "@echo \"", NStr name, Str ":\\n\\t", NStr docstr, Str "\"" ]
1193 -- name: the boot target name
1194 -- archs: list of architectures required
1195 -- tokens: the hake tokens for the target
1196 -- docstr: description of the target
1198 boot :: String -> [ String ] -> [ RuleToken ] -> String -> HRule
1199 boot name archs tokens docstr =
1200 if null $ archs Data.List.\\ Config.architectures then
1202 Phony name False tokens,
1203 Phony "help-boot" True
1204 [ Str "@echo \"", NStr name, Str ":\\n\\t", NStr docstr, Str "\"" ]
1210 -- Copy a file from the source tree
1212 copyFile :: TreeRef -> String -> String -> String -> String -> HRule
1213 copyFile stree sarch spath darch dpath =
1214 Rule [ Str "cp", Str "-v", In stree sarch spath, Out darch dpath ]