------------------------------------------------------------------------- -- Copyright (c) 2007-2011, 2012, 2015 ETH Zurich. -- All rights reserved. -- -- This file is distributed under the terms in the attached LICENSE file. -- If you do not find this file, copies can be found by writing to:- -- ETH Zurich D-INFK CAB F.78, Universitaetstr 6, CH-8092 Zurich. -- Attn: Systems Group. -- -- Basic Hake rule definitions and combinators -- -------------------------------------------------------------------------- module RuleDefs where import Data.List (intersect, isSuffixOf, union, (\\), nub, sortBy, elemIndex) import Data.Maybe (fromMaybe, fromJust) import System.FilePath import qualified ARMv8 import HakeTypes import qualified Args import qualified Config import TreeDB import Data.Char import Debug.Trace -- enable debug spew -- should we move this to Config.hs? -AB debugFlag = False -- -- Is a token to be displayed in a rule? -- inRule :: RuleToken -> Bool inRule (Dep _ _ _) = False inRule (PreDep _ _ _) = False inRule (LDep _ _) = False inRule (Target _ _) = False inRule _ = True -- -- Look for a set of files: this is called using the "find" combinator -- withSuffix :: TreeDB -> String -> String -> [String] withSuffix srcDB hakepath extension = map (\f -> "/" f) $ fromMaybe [] $ tdbByDirExt (takeDirectory hakepath) extension srcDB withSuffices :: TreeDB -> String -> [String] -> [String] withSuffices srcDB hakepath extensions = map (\f -> "/" f) $ fromMaybe [] $ tdbByDirExts (takeDirectory hakepath) extensions srcDB -- -- Find files with a given suffix in a given dir -- inDir :: TreeDB -> String -> String -> String -> [String] inDir srcDB hakepath dir extension = map (\f -> "/" f) $ fromMaybe [] $ tdbByDirExt (dropTrailingPathSeparator $ normalise $ takeDirectory hakepath dir) extension srcDB cInDir :: TreeDB -> String -> String -> [String] cInDir tdb tf dir = inDir tdb tf dir ".c" cxxInDir :: TreeDB -> String -> String -> [String] cxxInDir tdb tf dir = (inDir tdb tf dir ".cpp") ++ (inDir tdb tf dir ".cc") sInDir :: TreeDB -> String -> String -> [String] sInDir tdb tf dir = inDir tdb tf dir ".S" ------------------------------------------------------------------------- -- -- Architecture specific definitions -- ------------------------------------------------------------------------- options :: String -> Options options "armv8" = ARMv8.options options s = error $ "Unknown architecture " ++ s kernelCFlags "armv8" = ARMv8.kernelCFlags kernelCFlags s = error $ "Unknown architecture " ++ s kernelLdFlags "armv8" = ARMv8.kernelLdFlags kernelLdFlags s = error $ "Unknown architecture " ++ s archFamily :: String -> String archFamily arch = optArchFamily (options arch) ------------------------------------------------------------------------- -- -- Options for compiling the kernel, which is special -- ------------------------------------------------------------------------- kernelOptIncludes :: String -> [ RuleToken ] kernelOptIncludes arch | otherwise = [ ] kernelIncludes arch = [ NoDep BuildTree arch f | f <- [ "/include" ]] ++ [ NoDep SrcTree "src" f | f <- [ "/kernel/include/arch" arch, "/kernel/include/arch" archFamily arch, "/kernel/include", "/include", "/include/arch" archFamily arch, "/include/target" archFamily arch]] ++ kernelOptIncludes arch kernelOptions arch = Options { optArch = arch, optArchFamily = archFamily arch, optFlags = kernelCFlags arch, optCxxFlags = [], optLibDep = [], optCxxLibDep = [], optDefines = (optDefines (options arch)) ++ [ Str "-DIN_KERNEL", Str ("-DCONFIG_SCHEDULER_" ++ (show Config.scheduler)), Str ("-DCONFIG_TIMESLICE=" ++ (show Config.timeslice)) ], optIncludes = kernelIncludes arch, optDependencies = [ Dep InstallTree arch "/include/errors/errno.h", Dep InstallTree arch "/include/barrelfish_kpi/capbits.h", Dep InstallTree arch "/include/asmoffsets.h", Dep InstallTree arch "/include/trace_definitions/trace_defs.h" ], optLdFlags = kernelLdFlags arch, optLdCxxFlags = [], optLibs = [], optCxxLibs = [], optSuffix = [], optInterconnectDrivers = [], optFlounderBackends = [], extraFlags = [], extraCxxFlags = [], extraDefines = [], extraIncludes = [], extraDependencies = [], extraLdFlags = [], optInstallPath = OptionsPath { optPathBin = "/sbin", optPathLib = "/lib" } } ------------------------------------------------------------------------- -- -- IMPORTANT: This section contains extraction of functions from the -- relevant architecture module. The names and types should be -- exactly the same as in the architecture.hs file. This section -- should not contain any logic; ony architecture extraction. -- -------------------------------------------------------------------------- -- -- First, the default C compiler for an architecture -- compiler :: Options -> String compiler opts | optArch opts == "armv8" = ARMv8.compiler cCompiler :: Options -> String -> String -> String -> [ RuleToken ] cCompiler opts phase src obj | optArch opts == "armv8" = ARMv8.cCompiler opts phase src obj | otherwise = [ ErrorMsg ("no C compiler for " ++ (optArch opts)) ] cPreprocessor :: Options -> String -> String -> String -> [ RuleToken ] cPreprocessor opts phase src obj | otherwise = [ ErrorMsg ("no C preprocessor for " ++ (optArch opts)) ] -- -- C++ compiler, where supported -- cxxCompiler :: Options -> String -> String -> String -> [ RuleToken ] cxxCompiler opts phase src obj | optArch opts == "armv8" = ARMv8.cxxCompiler opts phase src obj | otherwise = [ ErrorMsg ("no C++ compiler for " ++ (optArch opts)) ] -- -- makeDepend step; note that obj can be whatever the intended output is -- makeDepend :: Options -> String -> String -> String -> String -> [ RuleToken ] makeDepend opts phase src obj depfile | optArch opts == "armv8" = ARMv8.makeDepend opts phase src obj depfile | otherwise = [ ErrorMsg ("no dependency generator for " ++ (optArch opts)) ] makeCxxDepend :: Options -> String -> String -> String -> String -> [ RuleToken ] makeCxxDepend opts phase src obj depfile | optArch opts == "armv8" = ARMv8.makeCxxDepend opts phase src obj depfile | otherwise = [ ErrorMsg ("no C++ dependency generator for " ++ (optArch opts)) ] cToAssembler :: Options -> String -> String -> String -> String -> [ RuleToken ] cToAssembler opts phase src afile objdepfile | optArch opts == "armv8" = ARMv8.cToAssembler opts phase src afile objdepfile | otherwise = [ ErrorMsg ("no C compiler for " ++ (optArch opts)) ] -- -- Assemble an assembly language file -- assembler :: Options -> String -> String -> [ RuleToken ] assembler opts src obj | optArch opts == "armv8" = ARMv8.assembler opts src obj | otherwise = [ ErrorMsg ("no assembler for " ++ (optArch opts)) ] archive :: Options -> [String] -> [String] -> String -> String -> [ RuleToken ] archive opts objs libs name libname | optArch opts == "armv8" = ARMv8.archive opts objs libs name libname | otherwise = [ ErrorMsg ("Can't build a library for " ++ (optArch opts)) ] linker :: Options -> [String] -> [String] -> [String] -> String -> [RuleToken] linker opts objs libs mods bin | optArch opts == "armv8" = ARMv8.linker opts objs libs mods bin | otherwise = [ ErrorMsg ("Can't link executables for " ++ (optArch opts)) ] ldtLinker :: Options -> [String] -> String -> String -> [RuleToken] ldtLinker opts objs app bin | optArch opts == "armv8" = ARMv8.ldtLinker opts objs app bin | otherwise = [ ErrorMsg ("Can't link executables for " ++ (optArch opts)) ] strip :: Options -> String -> String -> String -> [RuleToken] strip opts src debuglink target | optArch opts == "armv8" = ARMv8.strip opts src debuglink target | otherwise = [ ErrorMsg ("Can't strip executables for " ++ (optArch opts)) ] debug :: Options -> String -> String -> [RuleToken] debug opts src target | optArch opts == "armv8" = ARMv8.debug opts src target | otherwise = [ ErrorMsg ("Can't extract debug symbols for " ++ (optArch opts)) ] cxxlinker :: Options -> [String] -> [String] -> [String] -> String -> [RuleToken] cxxlinker opts objs libs mods bin | optArch opts == "armv8" = ARMv8.cxxlinker opts objs libs mods bin | otherwise = [ ErrorMsg ("Can't link C++ executables for " ++ (optArch opts)) ] ldtCxxlinker :: Options -> [String] -> String -> String -> [RuleToken] ldtCxxlinker opts objs app bin | optArch opts == "armv8" = ARMv8.ldtCxxlinker opts objs app bin | otherwise = [ ErrorMsg ("Can't link C++ executables for " ++ (optArch opts)) ] -- -- The C compiler for compiling things on the host -- nativeCCompiler :: String nativeCCompiler = "$(CC)" nativeArchiver :: String nativeArchiver = "ar" ------------------------------------------------------------------------- -- -- Functions to create useful filenames -- dependFilePath :: String -> String dependFilePath obj = obj ++ ".depend" objectFilePath :: Options -> String -> String objectFilePath opts src = optSuffix opts replaceExtension src ".o" generatedObjectFilePath :: Options -> String -> String generatedObjectFilePath opts src = replaceExtension src ".o" preprocessedFilePath :: Options -> String -> String preprocessedFilePath opts src = optSuffix opts replaceExtension src ".i" -- Standard convention is that human generated assembler is .S, machine generated is .s assemblerFilePath :: Options -> String -> String assemblerFilePath opts src = optSuffix opts replaceExtension src ".s" ------------------------------------------------------------------------- -- -- Functions with logic to start doing things -- -- -- Create C file dependencies -- -- Since this is where we know what the depfile is called it is here that we also -- decide to include it. This stops many different places below trying to -- guess what the depfile is called -- makeDependArchSub :: Options -> String -> String -> String -> String -> [ RuleToken ] makeDependArchSub opts phase src objfile depfile = [ Str ("@if [ -z $Q ]; then echo Generating $@; fi"), NL ] ++ makeDepend opts phase src objfile depfile makeDependArch :: Options -> String -> String -> String -> String -> HRule makeDependArch opts phase src objfile depfile = Rules [ Rule (makeDependArchSub opts phase src objfile depfile), Include (Out (optArch opts) depfile) ] -- Make depend for a standard object file makeDependObj :: Options -> String -> String -> HRule makeDependObj opts phase src = let objfile = (objectFilePath opts src) in makeDependArch opts phase src objfile (dependFilePath objfile) -- Make depend for a C++ object file makeDependCxxArchSub :: Options -> String -> String -> String -> String -> [ RuleToken ] makeDependCxxArchSub opts phase src objfile depfile = [ Str ("@if [ -z $Q ]; then echo Generating $@; fi"), NL ] ++ makeCxxDepend opts phase src objfile depfile makeDependCxxArch :: Options -> String -> String -> String -> String -> HRule makeDependCxxArch opts phase src objfile depfile = Rules [ Rule (makeDependCxxArchSub opts phase src objfile depfile), Include (Out (optArch opts) depfile) ] makeDependCxxObj :: Options -> String -> String -> HRule makeDependCxxObj opts phase src = let objfile = (objectFilePath opts src) in makeDependCxxArch opts phase src objfile (dependFilePath objfile) -- Make depend for an assembler output makeDependAssembler :: Options -> String -> String -> HRule makeDependAssembler opts phase src = let objfile = (assemblerFilePath opts src) in makeDependArch opts phase src objfile (dependFilePath objfile) -- -- Compile a C program to assembler -- makecToAssembler :: Options -> String -> String -> String -> [ RuleToken ] makecToAssembler opts phase src obj = cToAssembler opts phase src (assemblerFilePath opts src) (dependFilePath obj) -- -- Assemble an assembly language file -- assemble :: Options -> String -> [ RuleToken ] assemble opts src = assembler opts src (objectFilePath opts src) -- -- Create a library from a set of object files -- archiveLibrary :: Options -> String -> [String] -> [String] -> [ RuleToken ] archiveLibrary opts name objs libs = archive opts objs libs name (libraryPath opts name) -- -- Link an executable, explicit libs/mods -- linkExecutable :: Options -> [String] -> [String] -> [String] -> String -> [RuleToken] linkExecutable opts objs libs mods bin = linker opts objs libs mods (applicationPath opts bin) -- -- Link an executable, use ldt to calculate dependencies -- ldtLinkExecutable :: Options -> [String] -> String -> String -> [RuleToken] ldtLinkExecutable opts objs app bin = ldtLinker opts objs app (applicationPath opts bin) -- -- Strip debug symbols from an executable -- stripExecutable :: Options -> String -> String -> String -> [RuleToken] stripExecutable opts src debuglink target = strip opts (applicationPath opts src) (applicationPath opts debuglink) (applicationPath opts target) -- -- Extract debug symbols from an executable -- debugExecutable :: Options -> String -> String -> [RuleToken] debugExecutable opts src target = debug opts (applicationPath opts src) (applicationPath opts target) -- -- Link a C++ executable -- linkCxxExecutable :: Options -> [String] -> [String] -> [String] -> String -> [RuleToken] linkCxxExecutable opts objs libs mods bin = cxxlinker opts objs libs mods (applicationPath opts bin) -- -- Link a C++ executable using ldt. -- XXX: This has not been tested -- ldtLinkCxxExecutable :: Options -> [String] -> String -> String -> [RuleToken] ldtLinkCxxExecutable opts objs app bin = ldtCxxlinker opts objs app (applicationPath opts bin) ------------------------------------------------------------------------- -- -- Emit dependency tokens for libs in Options stdLibDepsRules :: Options -> String -> [HRule] stdLibDepsRules opts app = [Rule [LDep (DepApp arch app) (DepLib arch l) | l <- optLibDep opts]] where arch = optArch opts stdCxxLibDepsRules :: Options -> String -> [HRule] stdCxxLibDepsRules opts app = [Rule [LDep (DepApp arch app) (DepLib arch l) | l <- optCxxLibDep opts]] where arch = optArch opts ------------------------------------------------------------------------- -- -- Hake macros (hacros?): each of these evaluates to HRule, i.e. a -- list of templates for Makefile rules -- ------------------------------------------------------------------------- -- -- Compile a C file for a particular architecture -- We include cToAssembler to permit humans to type "make foo/bar.s" -- compileCFile :: Options -> String -> HRule compileCFile opts src = Rules [ Rule (cCompiler opts "src" src (objectFilePath opts src)), Rule (makecToAssembler opts "src" src (objectFilePath opts src)), makeDependObj opts "src" src ] -- -- Compile a C++ file for a particular architecture -- compileCxxFile :: Options -> String -> HRule compileCxxFile opts src = Rules [ Rule (cxxCompiler opts "src" src (objectFilePath opts src)), makeDependCxxObj opts "src" src ] -- -- Compile a C file for a particular architecture -- compileGeneratedCFile :: Options -> String -> HRule compileGeneratedCFile opts src = let o2 = opts { optSuffix = "" } arch = optArch o2 in Rules [ Rule (cCompiler o2 arch src (objectFilePath o2 src) ), Rule (makecToAssembler o2 arch src (objectFilePath o2 src)), makeDependObj o2 arch src ] compileGeneratedCxxFile :: Options -> String -> HRule compileGeneratedCxxFile opts src = let o2 = opts { optSuffix = "" } arch = optArch o2 in Rules [ Rule (cxxCompiler o2 arch src (objectFilePath o2 src) ), makeDependCxxObj o2 arch src ] compileCFiles :: Options -> [String] -> HRule compileCFiles opts srcs = Rules [ compileCFile opts s | s <- srcs ] compileCxxFiles :: Options -> [String] -> HRule compileCxxFiles opts srcs = Rules [ compileCxxFile opts s | s <- srcs ] compileGeneratedCFiles :: Options -> [String] -> HRule compileGeneratedCFiles opts srcs = Rules [ compileGeneratedCFile opts s | s <- srcs ] compileGeneratedCxxFiles :: Options -> [String] -> HRule compileGeneratedCxxFiles opts srcs = Rules [ compileGeneratedCxxFile opts s | s <- srcs ] -- -- Add a set of C (or whatever) dependences on a *generated* file. -- Somewhere else this file has to be defined as a target, of -- course... -- extraCDependencyForObj :: Options -> String -> String -> String -> [RuleToken] extraCDependencyForObj opts file s obj = let arch = optArch opts in [ Target arch (dependFilePath obj), Target arch obj, Dep BuildTree arch file ] extraCDependency :: Options -> String -> String -> HRule extraCDependency opts file s = Rule (extraCDependencyForObj opts file s obj) where obj = objectFilePath opts s extraCDependencies :: Options -> String -> [String] -> HRule extraCDependencies opts file srcs = Rules [ extraCDependency opts file s | s <- srcs ] extraGeneratedCDependency :: Options -> String -> String -> HRule extraGeneratedCDependency opts file s = extraCDependency (opts { optSuffix = "" }) file s -- -- Copy include files to the appropriate directory -- includeFile :: [ String ] -> HRule includeFile hdrs = Rules ([ Rule [ Str "cp", In SrcTree "src" hdr, Out "root" hdr] | hdr <- hdrs ] ++ [ Phony "install_headers" False [ Dep BuildTree "root" hdr | hdr <- hdrs ] ]) -- -- Build a Mackerel header file from a definition. -- mackerelProgLoc = In InstallTree "tools" "/bin/mackerel" mackerelDevFileLoc d = In SrcTree "src" ("/devices" (d ++ ".dev")) mackerelDevHdrPath d = "/include/dev/" (d ++ "_dev.h") mackerel2 :: Options -> String -> HRule mackerel2 opts dev = mackerel_generic opts dev "shift-driver" mackerel :: Options -> String -> HRule mackerel opts dev = mackerel_generic opts dev "bitfield-driver" mackerel_generic :: Options -> String -> String -> HRule mackerel_generic opts dev flag = let arch = optArch opts in Rule [ mackerelProgLoc, Str ("--" ++ flag), Str "-c", mackerelDevFileLoc dev, Str "-o", Out arch (mackerelDevHdrPath dev) ] mackerelDependencies :: Options -> String -> [String] -> HRule mackerelDependencies opts d srcs = extraCDependencies opts (mackerelDevHdrPath d) srcs -- -- Basic Flounder definitions: where things are -- flounderProgLoc = In InstallTree "tools" "/bin/flounder" flounderIfFileLoc ifn = In SrcTree "src" ("/if" (ifn ++ ".if")) flounderIfFileDep ifn = Dep SrcTree "src" ("/if" (ifn ++ ".if")) -- new-style stubs: path for generic header flounderIfDefsPath ifn = "/include/if" (ifn ++ "_defs.h") -- new-style stubs: path for specific backend header flounderIfDrvDefsPath ifn drv = "/include/if" (ifn ++ "_" ++ drv ++ "_defs.h") -- new-style stubs: generated C code (for all default enabled backends) flounderBindingPath opts ifn = (optSuffix opts) (ifn ++ "_flounder_bindings.c") -- new-style stubs: generated C code (for extra backends enabled by the user) flounderExtraBindingPath opts ifn = (optSuffix opts) (ifn ++ "_flounder_extra_bindings.c") flounderTHCHdrPath ifn = "/include/if" (ifn ++ "_thc.h") flounderTHCStubPath opts ifn = (optSuffix opts) (ifn ++ "_thc.c") applicationPath :: Options -> String -> String applicationPath opts name = optPathBin (optInstallPath opts) name libraryPath :: Options -> String -> String libraryPath opts libname = optPathLib (optInstallPath opts) ("lib" ++ libname ++ ".a") kernelPath = "/sbin/cpu" -- construct include arguments to flounder for common types -- these are: -- 1. platform-specific types (if/platform/foo.if) -- 2. architecture-specific types (if/arch/foo.if) -- 3. generic types (if/types.if) flounderIncludes :: Options -> [RuleToken] flounderIncludes opts = concat [ [Str "-i", flounderIfFileLoc ifn] | ifn <- [ "platform" (optArch opts), -- XXX: optPlatform "arch" (optArch opts), "types" ] ] flounderRule :: Options -> [RuleToken] -> HRule flounderRule opts args = Rule $ [ flounderProgLoc ] ++ (flounderIncludes opts) ++ args flounderTypesProgLoc = In InstallTree "tools" "/bin/floundertypes" -- -- Build interface types header file -- flounderGenIfTypes :: Options -> [String] -> HRule flounderGenIfTypes opts ifs = let arch = optArch opts ifn_tokens = map flounderIfFileDep ifs in Rule $ [ flounderTypesProgLoc, Str Config.source_dir, Str Config.install_dir, Str arch, Out arch ("/include/if/if_types.h") ] ++ ifn_tokens -- -- Build new-style Flounder header files from a definition -- (generic header, plus one per backend) -- flounderGenDefs :: Options -> String -> HRule flounderGenDefs opts ifn = Rules $ flounderRule opts [ Str "--generic-header", flounderIfFileLoc ifn, Out (optArch opts) (flounderIfDefsPath ifn), Dep BuildTree (optArch opts) ("/include/if/if_types.h") ] : [ flounderRule opts [ Str $ "--" ++ drv ++ "-header", flounderIfFileLoc ifn, Dep BuildTree (optArch opts) ("/include/if/if_types.h"), Out (optArch opts) (flounderIfDrvDefsPath ifn drv)] | drv <- Args.allFlounderBackends ] -- -- Build a new Flounder binding file from a definition. -- This builds the binding for all enabled backends -- flounderBinding :: Options -> String -> [String] -> HRule flounderBinding opts ifn = flounderBindingHelper opts ifn backends (flounderBindingPath opts ifn) where backends = "generic" : (optFlounderBackends opts) -- as above, but for a specific set of user-specified backends flounderExtraBinding :: Options -> String -> [String] -> [String] -> HRule flounderExtraBinding opts ifn backends = flounderBindingHelper opts ifn backends (flounderExtraBindingPath opts ifn) flounderBindingHelper :: Options -> String -> [String] -> String -> [String] -> HRule flounderBindingHelper opts ifn backends cfile srcs = Rules $ [ flounderRule opts $ args ++ [flounderIfFileLoc ifn, Out arch cfile ], compileGeneratedCFile opts cfile, flounderDefsDepend opts ifn allbackends srcs] ++ [extraGeneratedCDependency opts (flounderIfDefsPath ifn) cfile] ++ [extraGeneratedCDependency opts (flounderIfDrvDefsPath ifn d) cfile | d <- allbackends] where arch = optArch opts archfam = optArchFamily opts args = [Str "-a", Str archfam] ++ [Str $ "--" ++ d ++ "-stub" | d <- backends] allbackends = backends `union` optFlounderBackends opts \\ ["generic"] -- -- Build a Flounder THC header file from a definition. -- flounderTHCFile :: Options -> String -> HRule flounderTHCFile opts ifn = flounderRule opts [ Str "--thc-header", flounderIfFileLoc ifn, Out (optArch opts) (flounderTHCHdrPath ifn) ] -- -- Build a Flounder THC stubs file from a definition. -- flounderTHCStub :: Options -> String -> [String] -> HRule flounderTHCStub opts ifn srcs = let cfile = flounderTHCStubPath opts ifn hfile = flounderTHCHdrPath ifn arch = optArch opts in Rules [ flounderRule opts [ Str "--thc-stubs", flounderIfFileLoc ifn, Out arch cfile ], compileGeneratedCFile opts cfile, extraCDependencies opts hfile srcs, extraGeneratedCDependency opts hfile cfile, extraGeneratedCDependency opts (flounderIfDefsPath ifn) cfile ] -- -- Create a dependency on a Flounder header file for a set of files, -- but don't actually build either stub (useful for libraries) -- flounderDefsDepend :: Options -> String -> [String] -> [String] -> HRule flounderDefsDepend opts ifn backends srcs = Rules $ (extraCDependencies opts (flounderIfDefsPath ifn) srcs) : [extraCDependencies opts (flounderIfDrvDefsPath ifn drv) srcs | drv <- backends, drv /= "generic" ] -- -- Emit all the Flounder-related rules/dependencies for a given target -- flounderRules :: Options -> Args.Args -> [String] -> [HRule] flounderRules opts args csrcs = ([ flounderBinding opts f csrcs | f <- Args.flounderBindings args ] ++ [ flounderExtraBinding opts f backends csrcs | (f, backends) <- Args.flounderExtraBindings args ] ++ [ flounderTHCStub opts f csrcs | f <- Args.flounderTHCStubs args ] ++ -- Flounder extra defs (header files) also depend on the base -- Flounder headers for the same interface [ flounderDefsDepend opts f baseBackends csrcs | f <- allIf ] ++ -- Extra defs only for non-base backends (those were already emitted above) [ flounderDefsDepend opts f (backends \\ baseBackends) csrcs | (f, backends) <- Args.flounderExtraDefs args ] ) where -- base backends enabled by default baseBackends = optFlounderBackends opts -- all interfaces mentioned in flounderDefs or ExtraDefs allIf = nub $ Args.flounderDefs args ++ [f | (f,_) <- Args.flounderExtraDefs args] -- -- Build a Skate library and header file -- skateSchemaPath opts ifn = (optSuffix opts) (ifn ++ "_skate_schema.c") skateProgLoc = In InstallTree "tools" "/bin/skate" skateSksFileLoc schema = In SrcTree "src" ("/schemas" (schema ++ ".sks")) skateSchemaDefsPath schema = "/include/schemas" (schema ++ "_schema.h") skateSchemaHelper :: Options -> String -> String -> [String] -> HRule skateSchemaHelper opts ifn cfile srcs = Rules $ [ skateRule opts $ args ++ [ Str "-o", Out arch cfile, skateSksFileLoc ifn], compileGeneratedCFile opts cfile, skateDefsDepend opts ifn srcs] ++ [extraGeneratedCDependency opts (skateSchemaDefsPath ifn) cfile] where arch = optArch opts archfam = optArchFamily opts args = [Str "-a", Str arch, Str "-C"] skateSchema :: Options -> String -> [String] -> HRule skateSchema opts schema = skateSchemaHelper opts schema (skateSchemaPath opts schema) skateDefsDepend :: Options -> String -> [String] -> HRule skateDefsDepend opts schema srcs = Rules $ [(extraCDependencies opts (skateSchemaDefsPath schema) srcs)] skateRules :: Options -> Args.Args -> [String] -> [HRule] skateRules opts args csrcs = ([ skateSchema opts f csrcs | f <- Args.skateSchemas args ] ++ [ skateDefsDepend opts f csrcs | f <- nub $ Args.skateSchemaDefs args ]) skateIncludes :: Options -> [RuleToken] skateIncludes opts = [] skateRule :: Options -> [RuleToken] -> HRule skateRule opts args = Rule $ [ skateProgLoc ] ++ (skateIncludes opts) ++ args skateGenSchemas :: Options -> String -> HRule skateGenSchemas opts schema = Rules $ [skateRule opts [ Str "-H", Str "-o", Out (optArch opts) (skateSchemaDefsPath schema), skateSksFileLoc schema ]] -- -- Build SKB facts from Sockeye file -- sockeyeProgLoc = In InstallTree "tools" "/bin/sockeye" sockeyeProgLoc2 = In InstallTree "tools" "/bin/sockeye2" sockeyeSocDir = In SrcTree "src" "/socs" sockeyeSocFileLoc d = In SrcTree "src" ("/socs" d <.> "soc") sockeyeFactFilePath d = "/sockeyefacts" d <.> "pl" sockeyeFactFileLoc d = In BuildTree "" $ sockeyeFactFilePath d sockeyeNS :: String -> String -> HRule sockeyeNS net rootns = let factFile = sockeyeFactFilePath net depFile = dependFilePath factFile in Rules [ Rule [ sockeyeProgLoc , Str "-i", sockeyeSocDir , Str "-o", Out "" factFile , Str "-d", Out "" depFile , Str "-r", Str rootns , sockeyeSocFileLoc net ] , Include (Out "" depFile) ] sockeye :: String -> HRule sockeye net = let factFile = sockeyeFactFilePath net depFile = dependFilePath factFile in Rules [ Rule [ sockeyeProgLoc , Str "-i", sockeyeSocDir , Str "-o", Out "" factFile , Str "-d", Out "" depFile , sockeyeSocFileLoc net ] , Include (Out "" depFile) ] sockeye2 :: String -> HRule sockeye2 net = let factFile = sockeyeFactFilePath net depFile = dependFilePath factFile in Rules [ Rule [ sockeyeProgLoc2 , Str "-i", sockeyeSocDir , Str "-o", Out "" factFile , Str "-d", Out "" depFile , sockeyeSocFileLoc net ] , Include (Out "" depFile) ] sockeye2Lisa :: String -> HRule sockeye2Lisa net = let outFile = Out "" ("/platforms" net <.> ".lisa") inSgproj = "/socs" net <.> ".sgproj" outSgproj = "/platforms" net <.> ".sgproj" in Rules [ Rule [ sockeyeProgLoc2 , Str "-o", outFile , Str "-L", sockeyeSocFileLoc net ], copyFile SrcTree "" inSgproj "" outSgproj ] -- -- Build a Fugu library -- fuguCFile :: Options -> String -> HRule fuguCFile opts file = let arch = optArch opts cfile = file ++ ".c" ofile = file ++ ".o" in Rules [ Rule [ In InstallTree "tools" "/bin/fugu", In SrcTree "src" (file++".fugu"), Str "-c", Out arch cfile ], compileGeneratedCFile opts cfile, staticLibrary opts "errno" [ofile] [] ] fuguHFile :: Options -> String -> HRule fuguHFile opts file = let arch = optArch opts hfile = "/include/errors/" ++ file ++ ".h" in Rule [ In InstallTree "tools" "/bin/fugu", In SrcTree "src" (file++".fugu"), Str "-h", Out arch hfile ] -- -- Build a Pleco library -- plecoFile :: Options -> String -> HRule plecoFile opts file = let arch = optArch opts cfile = file ++ ".c" hfile = "/include/trace_definitions/" ++ file ++ ".h" jsonfile = "/trace_definitions/" ++ file ++ ".json" in Rules [ Rule [In InstallTree "tools" "/bin/pleco", In SrcTree "src" (file++".pleco"), Out arch hfile, Out arch jsonfile, Out arch cfile ], compileGeneratedCFile opts cfile ] -- -- Build a Hamlet file -- hamletFile :: Options -> String -> HRule hamletFile opts file = let arch = optArch opts hfile = "/include/barrelfish_kpi/capbits.h" cfile = "cap_predicates.c" usercfile = "user_cap_predicates.c" ofile = "user_cap_predicates.o" nfile = "cap_predicates" afile = "/lib/libcap_predicates.a" in Rules [ Rule [In InstallTree "tools" "/bin/hamlet", In SrcTree "src" (file++".hl"), Out arch hfile, Out arch cfile, Out arch usercfile ], compileGeneratedCFile opts usercfile, Rule (archive opts [ ofile ] [] nfile afile) ] -- -- Link a set of object files and libraries together -- link :: Options -> [String] -> [String] -> [String] -> String -> HRule link opts objs libs mods bin = let full = bin ++ ".full" debug = bin ++ ".debug" in Rules [ Rule $ linkExecutable opts objs libs mods full, Rule $ debugExecutable opts full debug, Rule $ stripExecutable opts full debug bin ] -- -- Link a set of object files and libraries together -- ldtLink :: Options -> [String] -> String -> String -> HRule ldtLink opts objs app bin = let full = bin ++ ".full" debug = bin ++ ".debug" in Rules [ Rule $ ldtLinkExecutable opts objs app full, Rule $ debugExecutable opts full debug, Rule $ stripExecutable opts full debug bin ] -- -- Link a set of C++ object files and libraries together -- linkCxx :: Options -> [String] -> [String] -> [String] -> String -> HRule linkCxx opts objs libs mods bin = Rule (linkCxxExecutable opts objs libs mods bin) -- -- Link a set of object files and libraries together -- ldtLinkCxx :: Options -> [String] -> String -> String -> HRule ldtLinkCxx opts objs app bin = Rule (ldtLinkCxxExecutable opts objs app bin) -- -- Link a CPU driver. This is where it gets distinctly architecture-specific. -- linkKernel :: Options -> String -> [String] -> [String] -> String -> HRule linkKernel opts name objs libs driverType | optArch opts == "armv8" = ARMv8.linkKernel opts objs [libraryPath opts l | l <- libs ] name driverType | otherwise = Rule [ Str ("Error: Can't link kernel for '" ++ (optArch opts) ++ "'") ] -- -- Copy a file from one place to another -- copy :: Options -> String -> String -> HRule copy opts src dest = Rule [ Str "cp", In BuildTree (optArch opts) src, Out (optArch opts) dest ] -- -- Assemble a list of S files for a particular architecture -- assembleSFile :: Options -> String -> HRule assembleSFile opts src = Rules [ Rule (assemble opts src), makeDependObj opts "src" src ] assembleSFiles :: Options -> [String] -> HRule assembleSFiles opts srcs = Rules [ assembleSFile opts s | s <- srcs ] -- -- Archive a bunch of objects into a library -- staticLibrary :: Options -> String -> [String] -> [String] -> HRule staticLibrary opts libpath objs libs = Rule (archiveLibrary opts libpath objs libs) -- -- Compile a Haskell binary (for the host architecture) -- compileHaskell prog main deps = compileHaskellWithLibs prog main deps [] compileHaskellWithLibs prog main deps dirs = let tools_dir = (Dep InstallTree "tools" "/tools/.marker") in Rule ([ NStr "ghc -i", NoDep SrcTree "src" ".", Str "-odir ", NoDep BuildTree "tools" ".", Str "-hidir ", NoDep BuildTree "tools" ".", Str "-rtsopts=all", Str "--make ", In SrcTree "src" main, Str "-o ", Out "tools" ("/bin" prog), Str "$(LDFLAGS)" ] ++ concat [[ NStr "-i", NoDep SrcTree "src" d] | d <- dirs] ++ [ (Dep SrcTree "src" dep) | dep <- deps ] ++ [ tools_dir ]) nativeOptions = Options { optArch = "", optArchFamily = "", optFlags = [], optCxxFlags = [], optDefines = [], optIncludes = [], optDependencies = [], optLdFlags = [], optLdCxxFlags = [], optLibDep = [], optLibs = [], optCxxLibDep = [], optCxxLibs = [], optInterconnectDrivers = [], optFlounderBackends = [], extraFlags = [], extraCxxFlags = [], extraDefines = [], extraIncludes = [], extraDependencies = [], extraLdFlags = [], optSuffix = "", optInstallPath = OptionsPath { optPathBin = "/sbin", optPathLib = "/lib" } } -- -- Compile (and link) a C binary (for the host architecture) -- compileNativeC :: String -> [String] -> [String] -> [String] -> [String] -> HRule compileNativeC prog cfiles cflags ldflags localLibs = Rule ([ Str nativeCCompiler, Str "-o", Out "tools" ("/bin" prog), Str "$(CFLAGS)", Str "$(LDFLAGS)" ] ++ [ (Str flag) | flag <- cflags ] ++ [ (In SrcTree "src" dep) | dep <- cfiles ] -- source file needs to be left of ldflags for modern-ish GCC ++ [ (Str flag) | flag <- ldflags ] ++ [ In BuildTree "tools" ("/lib" ("lib" ++ l ++ ".a")) | l <- localLibs ]) -- -- Compile a static library for the host architecture -- compileNativeLib :: String -> [String] -> [String] -> HRule compileNativeLib name cfiles cflags = Rules ( [ Rule ([ Str nativeCCompiler, Str "-c", In SrcTree "src" s, Str "-o", Out "tools" (objectFilePath nativeOptions s), Str "$(CFLAGS)", Str "$(LDFLAGS)" ] ++ [ (Str flag) | flag <- cflags ]) | s <- cfiles ] ++ [ Rule ([ Str nativeArchiver, Str "rcs", Out "tools" ("/lib" ("lib" ++ name ++ ".a")) ] ++ [ In BuildTree "tools" o | o <- objs ]) ] ) where objs = [ objectFilePath nativeOptions s | s <- cfiles ] -- -- Build a Technical Note -- buildTechNote :: String -> String -> Bool -> Bool -> [String] -> HRule buildTechNote input output bib glo figs = buildTechNoteWithDeps input output bib glo figs [] buildTechNoteWithDeps :: String -> String -> Bool -> Bool -> [String] -> [RuleToken] -> HRule buildTechNoteWithDeps input output bib glo figs deps = let working_dir = NoDep BuildTree "tools" "/tmp/" style_files = [ "bfish-logo.pdf", "bftn.sty", "defs.bib", "barrelfish.bib" ] in Rule ( [ Dep SrcTree "src" (f ++ ".pdf") | f <- figs] ++ [ Dep SrcTree "src" ("/doc/style" f) | f <- style_files ] ++ [ Str "mkdir", Str "-p", working_dir, NL ] ++ deps ++ [ In SrcTree "src" "/tools/run-pdflatex.sh", Str "--input-tex", In SrcTree "src" input, Str "--working-dir", working_dir, Str "--output-pdf", Out "docs" ("/" ++ output), Str "--texinput", NoDep SrcTree "src" "/doc/style", Str "--bibinput", NoDep SrcTree "src" "/doc/style" ] ++ (if bib then [ Str "--has-bib" ] else []) ++ (if glo then [ Str "--has-glo" ] else []) ) --------------------------------------------------------------------- -- -- Transformations on file names -- ---------------------------------------------------------------------- allObjectPaths :: Options -> Args.Args -> [String] allObjectPaths opts args = [objectFilePath opts g | g <- (Args.cFiles args)++(Args.cxxFiles args)++(Args.assemblyFiles args)] ++ [generatedObjectFilePath opts g | g <- [ flounderBindingPath opts f | f <- (Args.flounderBindings args)] ++ [ flounderExtraBindingPath opts f | (f, _) <- (Args.flounderExtraBindings args)] ++ [ flounderTHCStubPath opts f | f <- (Args.flounderTHCStubs args)] ++ [ skateSchemaPath opts f | f <- (Args.skateSchemas args)] ++ (Args.generatedCFiles args) ++ (Args.generatedCxxFiles args) ] allLibraryPaths :: Options -> Args.Args -> [String] allLibraryPaths opts args = [ libraryPath opts l | l <- Args.addLibraries args ] allModulesPaths :: Options -> Args.Args -> [String] allModulesPaths opts args = [ libraryPath opts l | l <- Args.addModules args ] --------------------------------------------------------------------- -- -- Very large-scale macros -- ---------------------------------------------------------------------- -- -- Build an application binary -- application :: Args.Args application = Args.defaultArgs { Args.buildFunction = applicationBuildFn -- we let libraryOs default to Nothing, and grab the right default one for -- the architecture we're building in appGetOptionsForArch } system :: Args.Args -> Args.Args system args = args { Args.installDirs = (Args.installDirs args) { Args.bindir = "/sbin" }} applicationBuildFn :: TreeDB -> String -> Args.Args -> HRule applicationBuildFn tdb tf args | debugFlag && trace (Args.showArgs (tf ++ " Application ") args) False = undefined applicationBuildFn tdb tf args = -- The order is important: The application libs -- must be inserted before the optLibs (which are inserted in -- appBuildArch..). Otherwise it's impossible to override -- libc symbols. And we use that trick for instance in libposixcompat -- and the VFS. Rules (concat [ appLibDeps args arch | arch <- Args.architectures args ] ++ [ appBuildArch tdb tf args arch | arch <- Args.architectures args ] ) where appLibDeps :: Args.Args -> String -> [HRule] appLibDeps args arch = let app = DepApp arch (Args.target args) libs = Args.addLibraries args mods = Args.addModules args in [Rule ([LDep app (DepLib arch l) | l <- (libs)])] ++ [Rule ([LDep app (DepMod arch l) | l <- (mods)])] extraIncs libs = [ NoDep SrcTree "src" ("/include" l) | l <- filter libNeedsInc libs ] where libNeedsInc lib | lib == "lwip" = True | lib == "lwip2" = True | otherwise = False -- appGetOptionsForArch :: String -> Args.Args -> Options -- appGetOptionsForArch arch args = -- (options arch) { extraIncludes = -- [ NoDep SrcTree "src" a | a <- Args.addIncludes args] -- ++ -- [ NoDep BuildTree arch a | a <- Args.addGeneratedIncludes args] -- ++ -- -- Only add extra include directory for libraries -- -- that actually need it. -SG,2017-09-19. -- extraIncs (Args.addLibraries args) -- ++ -- extraIncs (Args.addLibraries libos), -- optIncludes = (optIncludes $ options arch) \\ -- [ NoDep SrcTree "src" i | i <- Args.omitIncludes args ], -- optFlags = (optFlags $ options arch) \\ -- ([ Str f | f <- Args.omitCFlags args ] ++ -- [ Str f | f <- Args.omitCFlags libos]), -- optCxxFlags = (optCxxFlags $ options arch) \\ -- ([ Str f | f <- Args.omitCxxFlags args ] ++ -- [ Str f | f <- Args.omitCxxFlags libos]), -- optSuffix = "_for_app_" ++ Args.target args, -- optLibs = (library_os arch) ++ (optLibs $ options arch), -- optCxxLibs = (library_os arch) ++ (optCxxLibs $ options arch), -- extraFlags = (Args.addCFlags args) ++ (Args.addCFlags libos), -- extraCxxFlags = (Args.addCxxFlags args) ++ (Args.addCFlags libos) ++ -- (Args.addCxxFlags libos), -- extraLdFlags = [ Str f | f <- Args.addLinkFlags args ] ++ -- [ Str f | f <- Args.addLinkFlags libos ], -- extraDependencies = -- [Dep BuildTree arch s | -- s <- Args.addGeneratedDependencies args], -- optInstallPath = OptionsPath { -- optPathBin = Args.bindir (Args.installDirs args), -- optPathLib = Args.libdir (Args.installDirs args) -- } -- } -- where -- libos = fromMaybe (fromJust $ Config.libbarrelfish arch) (Args.libraryOs args) -- library_os arch = -- [ In InstallTree arch ("/lib" "lib" ++ (Args.target libos) ++ ".a") ] ++ -- [ LDep (DepApp arch (Args.target args)) (DepLib arch (Args.target libos))] appGetOptionsForArch arch args = (options arch) { extraIncludes = [ NoDep SrcTree "src" a | a <- Args.addIncludes args] ++ [ NoDep BuildTree arch a | a <- Args.addGeneratedIncludes args] ++ -- Only add extra include directory for libraries -- that actually need it. -SG,2017-09-19. extraIncs (Args.addLibraries args), optIncludes = (optIncludes $ options arch) \\ [ NoDep SrcTree "src" i | i <- Args.omitIncludes args ], optFlags = (optFlags $ options arch) \\ [ Str f | f <- Args.omitCFlags args ], optSuffix = "_for_app_" ++ Args.target args, extraFlags = Args.addCFlags args, extraLdFlags = [ Str f | f <- Args.addLinkFlags args ], extraDependencies = [Dep BuildTree arch s | s <- Args.addGeneratedDependencies args], optInstallPath = OptionsPath { optPathBin = Args.bindir (Args.installDirs args), optPathLib = Args.libdir (Args.installDirs args) } } fullTarget :: Options -> String -> String -> HRule fullTarget opts arch appname = Phony ((map toUpper arch) ++ "_All") False [ Dep BuildTree arch (applicationPath opts appname) ] appBuildArch tdb tf args arch = let -- Fiddle the options opts = appGetOptionsForArch arch args csrcs = Args.cFiles args cxxsrcs = Args.cxxFiles args gencsrc = Args.generatedCFiles args gencxxsrc = Args.generatedCxxFiles args appname = Args.target args -- XXX: Not sure if this is correct. Currently assuming that if the app -- contains C++ files, we have to use the C++ linker. mylink = if cxxsrcs == [] then ldtLink else ldtLinkCxx mystdlibs = if cxxsrcs == [] then stdLibDepsRules else stdCxxLibDepsRules in Rules ( flounderRules opts args csrcs ++ skateRules opts args csrcs ++ [ mackerelDependencies opts m csrcs | m <- Args.mackerelDevices args ] ++ [ compileCFiles opts csrcs, compileCxxFiles opts cxxsrcs, compileGeneratedCFiles opts gencsrc, compileGeneratedCxxFiles opts gencxxsrc, assembleSFiles opts (Args.assemblyFiles args), mylink opts (allObjectPaths opts args) appname appname, fullTarget opts arch appname ] ++ mystdlibs opts (Args.target args) ) -- -- Build a driverdomain application binary -- -- Similar to application, but adds driverdomain library (which implements -- main) and adds linker script -- driverdomain :: Args.Args driverdomain = Args.defaultArgs { Args.buildFunction = applicationBuildFn, Args.addLinkFlags = ["-T" ++ Config.source_dir ++ "/lib/driverkit/bfdrivers.ld"], Args.addLibraries = ["driverdomain"] } -- This is pretty much libraryBuildFn, except that it produces the LDep token -- for the module drivermoduleBuildFn :: TreeDB -> String -> Args.Args -> HRule drivermoduleBuildFn tdb tf args | debugFlag && trace (Args.showArgs (tf ++ " DriverModule ") args) False = undefined drivermoduleBuildFn tdb tf args = Rules ([ libBuildArch tdb tf args arch | arch <- Args.architectures args ] ++ concat [modLibDeps args arch | arch <- Args.architectures args]) where modLibDeps :: Args.Args -> String -> [HRule] modLibDeps args arch = let me = DepMod arch (Args.target args) libs = Args.addLibraries args in [Rule ([LDep me (DepLib arch l) | l <- libs])] drivermodule :: Args.Args drivermodule = Args.defaultArgs { Args.buildFunction = drivermoduleBuildFn } -- -- Build an Arrakis application binary -- -- The arrakisapplication macro still exists for convenience, new arrakis -- applications should use application and override libraryOs. -- arrakisapplication :: Args.Args arrakisapplication = Args.defaultArgs { Args.buildFunction = applicationBuildFn, Args.libraryOs = Config.libarrakis } -- -- Build a static library -- library :: Args.Args library = Args.defaultArgs { Args.buildFunction = libraryBuildFn -- we let libraryOs default to Nothing, and grab the right default one for -- the architecture we're building in libGetOptionsForArch } libraryBuildFn :: TreeDB -> String -> Args.Args -> HRule libraryBuildFn tdb tf args | debugFlag && trace (Args.showArgs (tf ++ " Library ") args) False = undefined libraryBuildFn tdb tf args = Rules ([ libBuildArch tdb tf args arch | arch <- Args.architectures args ] ++ concat [libLibDeps args arch | arch <- Args.architectures args]) where libLibDeps :: Args.Args -> String -> [HRule] libLibDeps args arch = let lib = DepLib arch (Args.target args) libs = Args.addLibraries args in [Rule ([LDep lib (DepLib arch l) | l <- libs])] libGetOptionsForArch arch args = (options arch) { extraIncludes = [ NoDep SrcTree "src" a | a <- Args.addIncludes args] ++ [ NoDep SrcTree "src" ("/include" l) | l <- Args.addLibraries args ], optIncludes = (optIncludes $ options arch) \\ [ NoDep SrcTree "src" i | i <- Args.omitIncludes args ], optFlags = (optFlags $ options arch) \\ [ Str f | f <- Args.omitCFlags args ], optSuffix = "_for_lib_" ++ Args.target args, extraFlags = Args.addCFlags args, extraDependencies = [Dep BuildTree arch s | s <- Args.addGeneratedDependencies args] } -- libGetOptionsForArch arch args = -- (options arch) { extraIncludes = -- [ NoDep SrcTree "src" a | a <- Args.addIncludes args] -- ++ -- [ NoDep SrcTree "src" ("/include" l) | l <- Args.addLibraries args ], -- optIncludes = (optIncludes $ options arch) \\ -- [ NoDep SrcTree "src" i | i <- Args.omitIncludes args ], -- optFlags = (optFlags $ options arch) \\ -- ([ Str f | f <- Args.omitCFlags args ] ++ -- [ Str f | f <- Args.omitCFlags libos]), -- optCxxFlags = (optCxxFlags $ options arch) \\ -- ([ Str f | f <- Args.omitCxxFlags args ] ++ -- [ Str f | f <- Args.omitCxxFlags libos]), -- optSuffix = "_for_lib_" ++ Args.target args, -- extraFlags = (Args.addCFlags args) ++ (Args.addCFlags libos), -- extraCxxFlags = (Args.addCxxFlags args) ++ (Args.addCFlags libos) ++ -- (Args.addCxxFlags libos), -- extraDependencies = -- [Dep BuildTree arch s | s <- Args.addGeneratedDependencies args] -- } -- where -- libos = fromMaybe (fromJust $ Config.libbarrelfish arch) (Args.libraryOs args) libBuildArch tdb tf args arch = let -- Fiddle the options opts = libGetOptionsForArch arch args csrcs = Args.cFiles args cxxsrcs = Args.cxxFiles args gencsrc = Args.generatedCFiles args gencxxsrc = Args.generatedCxxFiles args in Rules ( flounderRules opts args csrcs ++ skateRules opts args csrcs ++ [ mackerelDependencies opts m csrcs | m <- Args.mackerelDevices args ] ++ [ compileCFiles opts csrcs, compileCxxFiles opts cxxsrcs, compileGeneratedCFiles opts gencsrc, compileGeneratedCxxFiles opts gencxxsrc, assembleSFiles opts (Args.assemblyFiles args), -- we dont pass the libraries, since they will be added in the linker phase staticLibrary opts (Args.target args) (allObjectPaths opts args) [] ] ) -- -- Library dependecies -- -- The following code is under heavy construction, and also somewhat ugly data LibDepTree = LibDep String | LibDeps [LibDepTree] deriving (Show,Eq) -- manually add dependencies for now (it would be better if each library -- defined each own dependencies locally, but that does not seem to be an -- easy thing to do currently libposixcompat_deps = LibDeps [ LibDep "posixcompat", (libvfs_deps_all "vfs"), LibDep "term_server" ] liblwip_deps = LibDeps $ [ LibDep x | x <- deps ] where deps = ["lwip" ,"net_if_raw" ,"timer" ,"hashtable", "netbench" ] libnetQmng_deps = LibDeps $ [ LibDep x | x <- deps ] where deps = ["net_queue_manager"] libnfs_deps = LibDeps $ [ LibDep "nfs", liblwip_deps] -- we need to make vfs more modular to make this actually useful data VFSModules = VFS_RamFS | VFS_NFS | VFS_BlockdevFS | VFS_FAT vfsdeps :: [VFSModules] -> String -> [LibDepTree] vfsdeps [] t = [LibDep t] vfsdeps (VFS_RamFS:xs) t = [] ++ vfsdeps xs t vfsdeps (VFS_NFS:xs) t = [libnfs_deps] ++ vfsdeps xs t vfsdeps (VFS_BlockdevFS:xs) t = [LibDep "ahci"] ++ vfsdeps xs t vfsdeps (VFS_FAT:xs) t = [] ++ vfsdeps xs t libvfs_deps_all t = LibDeps $ (vfsdeps [VFS_NFS, VFS_RamFS, VFS_BlockdevFS, VFS_FAT] t) libvfs_deps_noblockdev t = LibDeps $ (vfsdeps [VFS_NFS, VFS_RamFS] t) libvfs_deps_nonfs t = LibDeps $ (vfsdeps [VFS_RamFS, VFS_BlockdevFS, VFS_FAT] t) libvfs_deps_nfs t = LibDeps $ (vfsdeps [VFS_NFS] t) libvfs_deps_ramfs t = LibDeps $ (vfsdeps [VFS_RamFS] t) libvfs_deps_blockdevfs t = LibDeps $ (vfsdeps [VFS_BlockdevFS] t) libvfs_deps_fat t = LibDeps $ (vfsdeps [VFS_FAT, VFS_BlockdevFS] t) -- flatten the dependency tree flat :: [LibDepTree] -> [LibDepTree] flat [] = [] flat ((LibDep l):xs) = [LibDep l] ++ flat xs flat ((LibDeps t):xs) = flat t ++ flat xs str2dep :: String -> LibDepTree str2dep str | str == "vfs" = libvfs_deps_all str | str == "vfs_ramfs" = libvfs_deps_ramfs str | str == "vfs_nonfs" = libvfs_deps_nonfs str | str == "vfs_noblockdev"= libvfs_deps_noblockdev str | str == "lwip" = liblwip_deps | str == "netQmng" = libnetQmng_deps | otherwise = LibDep str -- get library depdencies -- we need a specific order for the .a, so we define a total order libDeps :: [String] -> [String] libDeps xs = [x | (LibDep x) <- (sortBy xcmp) . nub . flat $ map str2dep xs ] where xord = [ "crypto" , "zlib" , "posixcompat" , "posixcompat_arrakis" , "term_server" , "vfs" , "ahci" , "megaraid" , "nfs" , "net_queue_manager" , "bfdmuxvm" , "lwip" , "arranet" , "e1000n" , "e10k" , "e10k_vf" , "contmng" , "procon" , "net_if_raw" , "vfsfd" , "timer" , "hashtable"] xcmp (LibDep a) (LibDep b) = compare (elemIndex a xord) (elemIndex b xord) -- -- Build a CPU driver -- cpuDriver :: Args.Args cpuDriver = Args.defaultArgs { Args.buildFunction = cpuDriverBuildFn, Args.target = "cpu", Args.driverType = "cpu" } bootDriver :: Args.Args bootDriver = Args.defaultArgs { Args.buildFunction = cpuDriverBuildFn, Args.driverType = "boot" } -- CPU drivers are built differently cpuDriverBuildFn :: TreeDB -> String -> Args.Args -> HRule cpuDriverBuildFn tdb tf args = Rules [] bootDriverBuildFn :: TreeDB -> String -> Args.Args -> HRule bootDriverBuildFn tdb tf args = Rules [] -- -- Build a platform -- platform :: String -> [ String ] -> [ ( String, String ) ] -> String -> HRule platform name archs files docstr = if null $ archs Data.List.\\ Config.architectures then Rules [ Phony name False ([ NStr "@echo 'Built platform <", NStr name, NStr ">'" ] ++ [ Dep BuildTree arch file | (arch,file) <- files ]) , Phony "clean-platform" True ([ NStr "@echo 'Cleaning platform <", NStr name, NStr ">'", NL, Str "$(RM)" ] ++ [ NoDep BuildTree arch file | (arch,file) <- files ]), Phony ("install_" ++ name) False ([ NStr "@echo 'Installing platform <", NStr name, NStr ">'" ] ++ [ NL, Str "rsync -v -a --relative" ] ++ [ In BuildTree arch file | (arch,file) <- files ] ++ [ Str "${INSTALL_PREFIX}" ]), Phony "help-platforms" True [ Str "@echo \"", NStr name, Str ":\\n\\t", NStr docstr, Str "\"", Dep BuildTree "root" "/help-platforms-header" ] ] else Rules [] -- -- Creates a -- armv8Image ::[Char] -> [Char] -> [Char] -> [Char] -> [[Char]] -> [[Char]] -> HRule armv8Image target menu bootTarget cpuTarget modules_generic modules = let bootDriver = "/sbin/boot_" ++ bootTarget cpuDriver = "/sbin/cpu_" ++ cpuTarget blob = "/" ++ target ++ "_blob" blob_o = "/" ++ target ++ "_blob.o" image_o = "/" ++ target ++ "_image.o" image = "/" ++ target ++ "_image.efi" in Rules [ Rule ([ In BuildTree "tools" "/bin/armv8_bootimage", In BuildTree "root" ("/platforms/arm/menu.lst." ++ menu), Out "root" blob, NoDep BuildTree "root" "/", Dep BuildTree "armv8" bootDriver, Dep BuildTree "armv8" cpuDriver ] ++ [ (Dep BuildTree "armv8" m) | m <- modules ] ++ [ (Dep BuildTree "" m) | m <- modules_generic ] ), Rule ([ Str Config.aarch64_objcopy, Str "-I binary", Str "-O elf64-littleaarch64", Str "-B aarch64", Str ("--redefine-sym _binary_" ++ target ++ "_blob_start=barrelfish_blob_start"), Str ("--redefine-sym _binary_" ++ target ++ "_blob_end=barrelfish_blob_end"), Str ("--redefine-sym _binary_" ++ target ++ "_blob_size=barrelfish_blob_size"), In BuildTree "root" blob, Out "root" blob_o ]), Rule ([ Str "aarch64-linux-gnu-ld", In SrcTree "tools" "/tools/armv8_bootimage/crt0-efi-aarch64.o", Str "-znocombreloc", Str "-Bsymbolic", Str "-T", In SrcTree "tools" "/tools/armv8_bootimage/elf_aarch64_efi.lds", Str "-shared", Str "--no-undefined", Str "--defsym=EFI_SUBSYSTEM=10", In BuildTree "root" blob_o, In BuildTree "armv8" "/tools/armv8_bootimage/efi_loader.o", Str "-o", Out "root" image_o, In SrcTree "tools" "/tools/armv8_bootimage/libgnuefi.a", In SrcTree "tools" "/tools/armv8_bootimage/libefi.a" ]), Rule ([ Str Config.aarch64_objcopy, Str "-O binary", In BuildTree "root" image_o, Out "root" image ]) ] armv8EFIImage ::[Char] -> [Char] -> [Char] -> [Char] -> [[Char]] -> [[Char]] -> HRule armv8EFIImage target menu bootTarget cpuTarget modules_generic modules = let bootDriver = "/sbin/boot_" ++ bootTarget cpuDriver = "/sbin/cpu_" ++ cpuTarget target_image = "/" ++ target ++ "_image" in Rules [ Rule $ [ In SrcTree "tools" "/tools/harness/efiimage.py", In BuildTree "root" ("/platforms/arm/menu.lst." ++ menu), Str Config.install_dir, Out "root" target_image, Dep SrcTree "tools" "/tools/hagfish/Hagfish.efi", Dep BuildTree "armv8" bootDriver, Dep BuildTree "armv8" cpuDriver ] ++ [(Dep BuildTree "armv8" f) | f <- modules ] ++ [(Dep BuildTree "" f) | f <- modules_generic ] ] -- -- Boot an image. -- name: the boot target name -- archs: list of architectures required -- tokens: the hake tokens for the target -- docstr: description of the target -- boot :: String -> [ String ] -> [ RuleToken ] -> String -> HRule boot name archs tokens docstr = if null $ archs Data.List.\\ Config.architectures then Rules [ Phony name False tokens, Phony "help-boot" True [ Str "@echo \"", NStr name, Str ":\\n\\t", NStr docstr, Str "\"", Dep BuildTree "root" "/help-boot-header" ] ] else Rules [] barebones_simargs :: String -> [RuleToken] barebones_simargs imgpath = [ Str "-C terminal.start_telnet=0", Str "-C terminal1.start_telnet=0", Str "--data /home/netos/tools/fvp-uefi/bl1.bin@0x0000000000", Str "--data /home/netos/tools/fvp-uefi/fip.bin@0x0008000000", NStr "-C mmc.p_mmc_file=", In BuildTree "root" imgpath, Str "-C uart.unbuffered_output=1", Str "-C uart.out_file=-", Str "-C uart1.unbuffered_output=1", Str "-C uart1.out_file=-"] fvp_simargs :: String -> [RuleToken] fvp_simargs imgpath = [ -- Don't try to pop an LCD window up Str "-C bp.vis.disable_visualisation=1", -- # Don't start a telnet xterm Str "-C bp.terminal_0.start_telnet=0", Str "-C bp.terminal_1.start_telnet=0", Str "-C bp.secureflashloader.fname=/home/netos/tools/fvp-uefi/bl1.bin", Str "-C bp.flashloader0.fname=/home/netos/tools/fvp-uefi/fip.bin", NStr "-C bp.mmc.p_mmc_file=", In BuildTree "root" imgpath, Str "-C bp.pl011_uart0.unbuffered_output=1", -- This has to be the last parameter because otherwise the command -- passed to the OS has incorrect parameters. Don't know why -- MH 11/2016 Str "-C bp.pl011_uart0.out_file=-"] -- Build buildpath/isim_system using the sgproj file fastmodel_sim_target :: RuleToken -> String -> [RuleToken] fastmodel_sim_target sgproj buildpath= let binary = buildpath "isim_system" build_dir = (Dep InstallTree "tools" (buildpath ".marker")) in [ Str ("ARM_FM_ROOT=" ++ Config.fastmodels_root), In SrcTree "src" "/tools/fastmodels/simgen", Str "--num-comps-file 50", Str "--gen-sysgen", Str "--build-directory", NoDep BuildTree "tools" buildpath, Str "--warnings-as-errors ", Str "-p", sgproj, Str "-b", Target "tools" binary, build_dir ] boot_fastmodels :: String -> [ String ] -> String -> String -> (String -> [RuleToken]) -> String -> HRule boot_fastmodels name archs img sims simargs docstr = let sgproj = In SrcTree "src" ("/platforms" (sims ++ ".sgproj")) in boot_fastmodels_int name archs img sims sgproj simargs docstr boot_fastmodels_lisa :: String -> [ String ] -> String -> String -> (String -> [RuleToken]) -> String -> HRule boot_fastmodels_lisa name archs img sims simargs docstr = let sgproj = In BuildTree "" ("/platforms" sims <.> ".sgproj") -- We assume here that the sgproj depends exactly on one lisa -- file with the same base name lisaDep = Dep BuildTree "" ("/platforms" sims <.> ".lisa") buildpath = "/fastmodels" (sims ++ "_Build") binary = buildpath "isim_system" imgpath = "/" ++ img boot_target = [In InstallTree "tools" binary] ++ (simargs imgpath) ++ [Dep InstallTree "tools" binary ] in if null $ archs Data.List.\\ Config.architectures then Rules [ Rule $ [lisaDep] ++ fastmodel_sim_target sgproj buildpath, Phony name False boot_target, Phony "help-boot" True [ Str "@echo \"", NStr name, Str ":\\n\\t", NStr docstr, Str "\"", Dep BuildTree "root" "/help-boot-header" ] ] else Rules [] boot_fastmodels_int :: String -> [ String ] -> String -> String -> RuleToken -> (String -> [RuleToken]) -> String -> HRule boot_fastmodels_int name archs img sims sgproj simargs docstr = let imgpath = "/" ++ img buildpath = "/fastmodels" (sims ++ "_Build") binary = buildpath "isim_system" tools_dir = (Dep InstallTree "tools" "/tools/.marker") boot_target = [In InstallTree "tools" binary] ++ (simargs imgpath) ++ [Dep InstallTree "tools" binary ] in if null $ archs Data.List.\\ Config.architectures then Rules [ Rule $ fastmodel_sim_target sgproj buildpath, Phony name False boot_target, Phony "help-boot" True [ Str "@echo \"", NStr name, Str ":\\n\\t", NStr docstr, Str "\"", Dep BuildTree "root" "/help-boot-header" ] ] else Rules [] -- -- Copy a file from the source tree -- copyFile :: TreeRef -> String -> String -> String -> String -> HRule copyFile stree sarch spath darch dpath = Rule [ Str "cp", Str "-v", In stree sarch spath, Out darch dpath ] getExternalDependency :: String -> String -> [ HRule ] getExternalDependency url name = [ Rule ( [ Str "curl", Str "--insecure", Str "--create-dirs", Str "-o", Out "cache" name, Str url ] ), copyFile SrcTree "cache" name "" name ] scalebenchProgLoc = In SrcTree "root" "/tools/harness/scalebench.py" -- A testJob corresponds to a job in jenkins. It has name, description -- and will execute a sequence of scalebench invocations testJob :: String -> String -> [RuleToken] -> HRule testJob name desc exec = Rules [ Phony "help-tests" True [Str "@echo \"", NStr name, Str ":\\t", NStr desc, Str "\""], Phony name False exec ] -- Execute scalebench scalebenchO :: String -> [String] -> [String] -> [RuleToken] scalebenchO buildType tests machines = [ Str "mkdir", Str "-p", Str result_dir, NL, scalebenchProgLoc ] ++ test_tokens ++ machine_tokens ++ [ Str "--debug" ] ++ build_args buildType ++ [ -- positional arguments Str Config.source_dir, -- sourcedir Str result_dir, -- resultdir NL ] where build_args "" = [Str "-e", Str "."] build_args x = [Str "-b", Str x] result_dir = "results/" test_tokens = concat [[Str "-t", Str t] | t <- tests] machine_tokens = concat [[Str "-m", Str t] | t <- machines] scalebench :: [String] -> [String] -> [RuleToken] scalebench = scalebenchO ""