1 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2 % Copyright (c) 2011, ETH Zurich.
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, Universitaetstr. 6, CH-8092 Zurich. Attn: Systems Group.
8 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10 \documentclass[a4paper,twoside]{report} % for a report (default)
12 \usepackage{bftn} % You need this
14 \title{Hake} % title of report
15 \author{Timothy Roscoe} % author
16 \tnnumber{003} % give the number of the tech report
17 \tnkey{Hake: the Barrelfish build system} % Short title, will appear in footer
19 % \date{Month Year} % Not needed - will be taken from version history
25 % Include version history first
27 \begin{versionhistory}
28 \vhEntry{1.0}{3.06.2010}{TR}{Initial version}
29 \vhEntry{1.1}{11.04.2010}{TR}{Support for out-of-tree builds}
32 % \intro{Abstract} % Insert abstract here
33 % \intro{Acknowledgements} % Uncomment (if needed) for acknowledgements
34 \tableofcontents % Uncomment (if needed) for final draft
35 % \listoffigures % Uncomment (if needed) for final draft
36 % \listoftables % Uncomment (if needed) for final draft
38 \chapter{Introduction}
40 Hake is how we build Barrelfish.
42 Hake isn't designed to operate outside Barrelfish, so this document
43 will assume you're trying to build Barrelfish.
47 Suppose you have a fresh Barrelfish source tree in:
49 \texttt{/home/barrelfish/src}
51 To build a tree, create a directory for it, \texttt{cd} to that
52 directory, and run the Hake bootstrap script, and then Make:
55 $ cd /home/barrelfish/src
58 $ ../src/hake/hake.sh -s ../src
64 Edit the file \texttt{symbolic\_targets.mk} in your build directory to
65 add extra make targets.
67 Edit the file \texttt{hake/Config.hs} in your build directory and
68 rebuild Hake to reconfigure your build tree.
72 \section{How to think about hake}
74 Hake is essentially a Haskell embedded domain-specific language,
75 except that it is also evaluated dyanically (using the
76 \texttt{System.Eval.Haskell} package) and written by scattering code
77 around the source tree.
79 Hake consists of the main hake program (which itself contains
80 considerable information on how to build code), together with a set of
81 Hakefiles spread throughout the source tree.
83 Each Hakefile should be thought of as containing a Haskell expression
84 which evaluates to a set of rules for Make. The expression will be
85 evaluated in an environment which includes the path to the directory
86 where the Hakefile is located, plus a complete list of all files in
89 \section{When hake runs}
91 When you run Hake in a Barrelfish source tree, it does the following things:
93 \item Hake builds a list of (almost) every file and directory in the
94 source tree. The list of files Hake ignores is currently hardcoded
95 into Hake, but basically it skips editor temporary files, version
96 control directories, and products of a previous build process.
97 \item From this, Hake extracts a list of all Hakefiles in the tree.
98 \item Hake reads every Hakefile. Each Hakefile contains a single
99 Haskell expression which itself evaluates to a set of Make rules.
100 \item Hake constructs a single very large Haskell expression out of
101 all these Hakefiles. Each Hakefile is evaluated in an environment
102 which includes the pathname of the Hakefile itself (to resolve
103 relative names), and the entire list is evaluated in an environment
104 which includes the list of files in the whole tree (to allow
106 \item This large expression is then evaluated. The result is a single
107 tree of Hake rule representations (see
108 Chapter~\ref{sec:reprules}).
109 \item The rule tree is traversed to derive a list of every directory
111 \item Finally, a single Makefile is generated which contains rules to
112 build every target in the build tree, for every architecture
113 (including the host-based build tools themsevles), and also create
114 every directory in the build tree.
117 This single Makefile is large, but is also quite simple: it contains
118 no use of Make variables or generic Make rules, instead it simply
119 includes explicit rules to build every file required for Barrelfish.
121 \section{Motivation and Design Principles}
123 \paragraph{Hake should be a full programming language.} The lesson
124 from countless built systems is that if one starts without a full
125 programming language built in, one ends up implementing a bad one
126 (CMake being only one example). It's much easier to bite the bullet
127 and admit that we need a complete language, and plenty are available
130 \paragraph{Hake should be a functional language.} \texttt{make} is a
131 canonical example of a successful declarative language: Hake should
132 not try and replicate what make does well.
134 \paragraph{Hake should generate one Makefile.} One Makefile is easier
135 to debug: all the information is available in the same file. There is
136 no need to hunt through 5 levels of include files. The only thing
137 Hake-generated Makefiles include are generated C dependency lists, and
138 a single, top-level file giving symbolic targets. The Makefile
139 generated by Hake also makes minimal, and highly stylized, use of make
140 variables: wherever, any variable substitution is done in Haskell
141 before the Makefile is generated.
143 \paragraph{Hake is for building Barrelfish.} We make no claims as to
144 Hake's suitability for any project other than Barrelfish, and indeed
145 the current implementation is pretty tied to the Barrelfish tree.
146 This has helped to keep the system focussed and tractable. One
147 non-goal of Hake, for example, is to support portability across host
148 machines (as CMake tries to do).
150 \chapter{Simple Hakefiles}
152 Hake can in principle build anything, but there are two simple use
153 cases for Hake: building Barrelfish applications (user-space
154 binaries), and building Barrelfish libraries. Here's how, at time of
155 writing, the Barrelfish PCI driver is specified. This is the entire
160 [ build application {
162 cFiles = [ "pcimain.c", "pci.c", "pci_service.c",
163 "ioapic.c", "acpi.c", "ht_config.c",
164 "acpica_osglue.c", "interrupts.c",
165 "pci_confspace.c", "pcie_confspace.c",
166 "video.c", "buttons.c", "acpi_ec.c" ],
167 flounderBindings = [ "pci" ],
168 flounderDefs = [ "monitor" ],
169 mackerelDevices = [ "pci_hdr0", "pci_hdr1",
170 "lpc_ioapic", "ht_config",
171 "lpc_bridge", "acpi_ec" ],
172 addIncludes = [ "acpica/include" ],
173 addCFlags = [ "-Wno-redundant-decls" ],
174 addLibraries = [ "mm", "acpi", "skb", "pci" ],
175 architectures = [ "x86_64", "x86_32" ]
180 The outermost square brackets are a Haskell list expression - each
181 Hakefile should be such a list (the exact type will be explained
182 later). This list has a single element, the instruction to built an
183 application (you can have more of these, separated by commas).
185 The \texttt{build application} specifies a number of arguments, all of
186 which are optional. These are actually Haskell record field
187 specifiers, and \texttt{application} returns a complete default set.
188 \texttt{build} then generates the Make rules to build the
191 The complete list of possible arguments for applications (or
192 libraries) can be found by looking at \texttt{Args.hs}. The ones used
195 \item[target]: the name of the binary to build.
196 \item[cFiles]: list of names of C source files. You need to include
198 \item[flounderBindings]: Flounder interfaces for which to compile
200 \item[flounderDefs]: Flounder interfaces to use from a library
201 \item[mackerelDevices]: list of Mackerel device specs this application uses or depends on.
202 \item[addIncludes]: additional include paths for header files.
203 \item[addLibraries]: additional libraries to link against.
206 Note that filenames are relative to the current source
207 directory. Those with a leading '/' are interpreted relative to the
208 root of the tree (not the root file system).
210 Libraries are similar. Here's the Hakefile for the X86 emulator
215 cFiles = [ "debug.c", "decode.c", "fpu.c", "ops2.c",
216 "ops.c", "prim_ops.c", "sys.c"],
217 addCFlags = ["-Wno-shadow" ]
221 This should be all you need to know to write simple Hakefile{s} for
222 the Barrelfish, and indeed to understand most of the Hakefile{s} in
225 Doing (or understanding) more fancy things in the Hakefile requires
226 more knowledge of how Hake internally generates and represents Make
227 rules, described later.
229 \chapter{Hake from the bottom up}
231 The core of Hake consists of the code to walk the source tree, a
232 minimal set of data types used to represent Make rules, and codes to
233 render these data types into a Makefile.
235 \section{The Hake name space for files}
237 Unlike most build systems, Hake uses a 3-dimensional name space for
240 The first component is called the ``tree''. Whenever Hake runs, it
241 deals with three ``trees'':
244 \item The ``source tree'' (written as \texttt{SrcTree}) is the fle
245 system directory tree containing the source code for the programs
246 and libraries currently being built. When building the core OS,
247 this is the main OS source tree. When building an external
248 application or library, this is the directory tree containing the
249 application or library's source code.
251 \item The ``build tree'' (written as \texttt{BuildTree}) is where the
252 intermediate and final results of the compilation end up. This is
253 typically the current working directory when Hake was run.
255 \item The ``install tree'' (written as \texttt{InstallTree}) is the
256 directory tree containing a core Barrelfish OS build tree. When
257 building the OS, the install tree and the build tree are the same,
258 but when building an external application or library, the install
259 tree is a pre-built Barrelfish tree and the build tree is where the
260 new application or library is built.
263 The second component is called the ``architecture'' (for want
264 of a better name), and corresponds to building the same code for
265 different target architectures (\texttt{x86\_64}, \texttt{arm}, etc.)
266 Architectures themselves form a flat namespace.
268 Some ``architectures'' are special when building the core Barrelfish OS:
270 \item[src] refers to files which are always present in the source
271 tree. Hake should not be used to build anything in the \texttt{src}
272 architecture, and anything in any other architecture must be generated
274 \item[hake] is used by Hake as part of the bootstrapping process.
275 \item[root] refers to files relative to the top of the build
276 tree, and should be used with caution.
277 \item[tools] is used to build other build process tools (Mackerel,
278 Fugu, Flounder, etc.)
279 \item[docs] is used to build documentation (Technical Notes),
280 including this document.
283 The final component is called the ``path'', and corresponds roughly
284 to the pathname of the file from the root of the designated tree.
285 In the source for hake itself,``path'' usually refers to this path,
286 and file ``location'' or just ``loc'' refers to the 3-dimensional file
289 Here are some examples of hake file locations:
291 \begin{tabular}{crll} Tree & Architecture & Path & Description \\ \hline
292 \texttt{SrcTree} & \texttt{src} & \texttt{/tools/hake/Main.hs} & Part of the source code for Hake
294 \texttt{InstallTree} & \texttt{tools} & \texttt{/tools/flounder/flounder} & The (built) binary for the
296 \texttt{InstallTree} & \texttt{x86\_64} & \texttt{/lib/libbarrelfish.a} & The Barrelfish
298 \texttt{InstallTree} & \texttt{src} & \texttt{/include/stdio.h} & C header file \\
299 \texttt{BuildTree} & \texttt{x86\_64} & \texttt{/include/asmoffsets.h} & Generated C header
301 \texttt{SrcTree} & \texttt{src} & \texttt{/devices/xapic.dev} & Mackerel source file \\
302 \texttt{BuildTree} & \texttt{x86\_64} &
303 \texttt{/include/dev/xapic\_dev.h} & Generated header file from Mackerel \\
306 When referring to files in Hake, files whose paths are ``relative''
307 (i.e.\ do not start with a leading ``/'') are considered relative to
308 the path of their Hakefile, and are converted into
309 ``absolute'' paths from the top of their tree when they appear.
310 This is more intuitive than it sounds. For example, a file referred
311 to as \texttt{(SrcTree,``src'',''e1000.c'')} in
312 \texttt{drivers/e1000/Hakefile} will appear in the resulting Makefile
313 as {drivers/e1000/e1000.c}.
315 The Hake namespace is mapped onto the file system as follows: all
316 files with architecture \texttt{src} are relative to the top of the
317 source tree, whereas a file in a different architecture \texttt{foo}
318 is relative to directory \texttt{foo/} in the build or install tree.
319 Thus, \texttt{(BuildTree,``x86\_64'',''e1000.o'')} in
320 \texttt{drivers/e1000/Hakefile} will appear in the resulting Makefile
321 as {./x86\_64/drivers/e1000/e1000.o}.
323 Hake will generate all Makefile rules necessary to create any
324 directories in the build tree that it needs - it's perfectly possible
325 (and sometimes useful) with Hake to type ``\texttt{rm -rf ./*;
326 make}'' and have everything work.
328 \section{Representing rules}\label{sec:reprules}
330 Each Hakefile is an expression that must evaluate to a list of
331 \texttt{HRule}s. The declaration of \texttt{HRule} is:
333 data HRule = Rule [ RuleToken ]
337 deriving (Show,Typeable)
340 The \texttt{Include} constructor creates an ``include'' directive in a
341 Makefile. In theory, there should be no need for developers to use
342 this; it is only used currently to include automatically-generated
343 dependency files for C and assembly source.
345 The \texttt{Rules} constructor allows a tree of rules to be
346 constructed. This is purely a convenience: any time that one can
347 return a single rule, one can also return a list of rules. This makes
348 it easier to write functions which return rules, which is the basis of
351 The \texttt{Error} constructor is used to signal errors, but in
352 practice is rarely used.
354 An actual basic Makefile rule is constructed by \texttt{Rule} as a
355 list of \texttt{RuleToken}s. The declaration of \texttt{RuleToken}
359 data TreeRef = SrcTree | BuildTree | InstallTree
362 data RuleToken = In TreeRef String String -- Input to the computation
363 | Dep TreeRef String String -- Extra (implicit) dependency
364 | NoDep TreeRef String String -- File that's not a dependency
365 | PreDep TreeRef String String -- One-time dependency
366 | Out String String -- Output of the computation
367 | Target String String -- Target that's not involved
368 | Str String -- String with trailing " "
369 | NStr String -- Just a string
370 | ErrorMsg String -- Error message: $(error x)
374 Each rule token can either be a string of some form, or a reference to
375 a file. Note that for some file references, the tree is implicit:
376 \texttt{Out} and \texttt{Target} files are always in the
379 Rules in Hake differ from plain Makefile rules in that
380 they only consist of rule bodies (i.e., exactly what needs to be
381 done), and the targets and dependencies are inferred (so they only
382 need to be written once). An example may make this clear - here is a
383 function which returns list of \texttt{RuleToken}s for maintaining a
386 archive :: Options -> [String] -> String -> [ RuleToken ]
387 archive opts objs libpath =
388 [ Str "ar cr ", Out arch libpath ]
390 [ In BuildTree arch o | o <- objs ]
392 [ NL, Str "ranlib ", Out arch libpath ]
394 The arguments to this function include a set of ``options'', which are
395 used extensively inside Hake to pass around values like C flags,
396 include paths, link options, etc., together with a set of object file
397 paths and the path of a library file to build. The architecture
398 ``\texttt{arch}'' is defined elsewhere (this example is from the file
399 with rules specific to \texttt{x86\_64}, so within the scope it is
402 The library is referred to as an \texttt{Out} token, since it is a target
403 of the rule, whereas the object files are referred to by \texttt{In}
404 tokens, since they are prerequisites. Both are in the \texttt{arch}
405 architecture, since they have presumably been built by other rules.
407 This function is called from another, \texttt{arch}-independent
408 function called ``\texttt{archiveLibrary}, which dispatches based on
409 the architectures that need to be built for a given library.
410 Hence, if a Hakefile at ``\texttt{drivers/e1000/Hakefile}'' contained
413 archiveLibrary "x86_64" "e1000drv" [ "e1000.o", "e1000srv.o"]
415 -- the resulting Makefile would contain:
417 ./x86_64/drivers/e1000/libe1000drv.a: \
418 ./x86_64/drivers/e1000/e1000.o \
419 ./x86_64/drivers/e1000/e1000srv.o
420 ar cr ./x86_64/drivers/e1000/libe1000drv.a \
421 ./x86_64/drivers/e1000/e1000.o \
422 ./x86_64/drivers/e1000/e1000srv.o
423 ranlib ./x86_64/drivers/e1000/libe1000drv.a
426 The precise definitions of each token are as follows:
428 \item[In] tokens are file references which are dependent inputs for a
429 Make rule. In other words, they refer to files which will appear
430 both in the rule body and the list of dependencies (the right hand
432 head. \textbf{In} file references can be in any architecture.
434 \item[Dep] tokens are file references to implicit dependencies. In
435 Make terms, these are file names which appear in the list of
436 dependencies in rule head, but don't explicitly appear in the rule
439 \item[PreDep] tokens are like \textbf{Dep} tokens, but appear in the
440 rule head following a \textbf{$|$} character. GNU Make will require
441 these dependencies to be built only if they do not already exist -
442 it does not check for modification times. In Barrelfish, such
443 dependencies are used for files such as \texttt{errno.h} which must
444 be generated first in order to calculate C dependencies, but which
445 ultimately not all C files depend upon. Any true dependency of a C
446 file on \texttt{errno.h} will be specified by the generated depend
447 files, and thus override the \textbf{PreDep} declaration.
449 \item[NoDep] tokens are file references that are not dependencies at
450 all. The file name only appears in the rule body, never in the
451 head. For example, \textbf{NoDep} references are used for
452 directories for include files.
454 \item[Out] tokens are file references to output files from a rule,
455 which are mentioned in the rule body. This is the common case for
456 most files generated by Make rules.
458 \item[Target] tokens are file references that are implicit outputs of
459 the rule, but do not appear in the rule body. In Make terms they
460 appear only in the left-hand side of the rule head, and not in the
463 \item[Str] tokens are simply strings. They will be followed in the
464 Makefile by a space character, which is usually what you want.
466 \item[NStr] tokens are like \textbf{Str}, but not followed by a
467 space. This is useful for situations like the \texttt{-I} flag to
468 the C compiler, which takes a directory name (specified by a
469 \textbf{NoDep} token) without any intervening whitespace.
471 \item[ErrorMsg] tokens are a way to incorporate error conditions into
472 the Makefile - they are translated into the GNU make construct
473 \texttt{\$(error \textit{x})}.
475 \item[NL] tokens are simply newlines in the rule.
479 In practice, a Hakefile rarely has to resort to explicit
480 \texttt{RuleToken}s, but instead calls functions inside Hake to return
484 \section{Higher rule abstractions}
486 The guts of Hake is mostly contained in the file \texttt{RuleDefs.hs},
487 which provides a big lattice of functions to automate generating
488 rules for commonly used patterns. If you want to do more complex
489 things than simply ``\texttt{build application}'' or ``\texttt{build
490 library}'', it's a good idea to understand how these features use
491 the definitions in \texttt{RuleDefs.hs}.
493 \section{Target architectures}
495 Most of the flexibility required of Hake in building for multiple
496 architectures is simply coded into the Haskell source of the program.
498 For every target architecture (at time of writing, only
499 \texttt{x86\_64}), there is a file (\texttt{X64\_64.hs}) which
500 contains the definitions required to build the system for that
501 target. Adding a new target architecture for Barrelfish involves
502 writing a new one of these files (e.g. \texttt{ARM.hs}, or
503 \texttt{X86\_32.hs}, etc.) and modifying the code in
504 \texttt{RuleDefs.hs} to dispatch to the correct module.
506 \section{Host architectures}
508 Hake at present supports only a single host architecture: the
509 toolchain to build Barrelfish is specified once in the target
510 architecture files (see above).
512 To add support for multiple host build environments, one way to slice the
513 problem is for the target architecture modules to import different
514 host architecture modules and decide which one to call to get tool and
515 path defnitions at runtime.
517 \section{Configuration}
519 The file \texttt{hake/Config.hs} in the build directory contains all
520 the configuration variables (at time of writing) used for Barrelfish.
521 Unlike in Make or CMake, these are Haskell values of arbitrary type,
522 since they are evaluated entirely within Hake.
524 To reconfigure a build tree, therefore, one modifies this file,
525 and rebuilds Hake and the top-level Makefile.
526 The \texttt{rehake} target performs this task.
528 \chapter{Bootstrapping and Configuring Hake}
530 Hake is bootstrapped using a shell script found in the Barrelfish
531 source tree in \texttt{hake/hake.sh}. This script is the place to
532 start configuring a new core Barrelfish OS build tree, and must be
533 run in the root of the new build directory.
535 \texttt{hake.sh} takes the following command-line options:
537 \item[-s,--source-dir:] This option is mandatory and specifies the
538 path to the Barrelfish source directory tree.
539 \item[-i,--install-dir:] This option specifies a path to an
540 alternative install directory, and defaults to \texttt{`pwd`}.
541 \item[-a,--architecture:] This option can be given multiple times and
542 specifies the list of architectures to build Barrelfish for. Run
543 the script with the \texttt{-h} option to get the default list of
545 \item[-h,--help:] Prints a usage message.
546 \item[-n,--no-hake:] This option simply rebuilds Hake, but does not
547 run it to generate a Makefile. It can be handy for debugging Hake
551 After parsing and checking arguments, \texttt{hake.sh} next creates a new
552 configuration file \texttt{hake/Config.hs} in the build tree. The
553 configuration options in this file are defaults: it is a copy of the
554 template \texttt{hake/Config.hs.template} in the source tree.
556 If this file already exists in the build tree, however, it is left
557 unchanged, which means that any user modifications to this file
558 persist across multiple bootstrapping runs of \texttt{hake.sh}.
559 If you really want to reconfigure a build tree from scratch, you
560 should therefore remove everything in the build tree, including this
563 \texttt{hake.sh} next similarly creates a file called
564 \texttt{symbolic\_targets.mk} in the root of the build tree, if it
565 does not already exist.
567 After this, Hake itself is recompiled in the build tree (including the
568 new \texttt{Config.hs} file), and then run with default options (most
569 of which will be picked up from \texttt{Config.hs}).
571 \chapter{Debugging Hakefiles}
573 At least three things can go wrong when you modify or write a
576 \section{The Hakefile has a compile error}
578 If you make a mistake in a Hakefile, the most likely output you will
579 see is a funny-looking Haskell compile error, e.g.:
581 ../barrelfish.oothake/usr/pci/Hakefile:13:0:
582 Couldn't match expected type `t -> [HRule]'
583 against inferred type `[a]'
587 {target = "pci", flounderBindings = ["pci"],
588 flounderDefs = ["monitor"],
589 mackerelDevices = ["pci_hdr0", "pci_hdr1", ....],
592 <command line>: module is not loaded: `Hakefiles' (Hakefiles.hs)
595 Ignoring the last line for the moment, if you know enough Haskell this
596 should tell you exactly what is wrong with some Hakefile. However,
597 even if you don't know enough Haskell, it does say which Hakefile is
598 at fault and whereabouts in the offending Hakefile the problem is (in
599 this case line 13 of \texttt{usr/pci/Hakefile}).
601 Also, the file that Hake tried to compile will be left for you in
602 \texttt{Hakefiles.hs}. If you look at this, you'll see it's
603 constructed out of individual Hakefile{s} together with a preamble
604 giving details of the files in the tree.
606 \section{The Makefile has an error}
608 Hake generates a single large Makefile at the top of the tree.
609 While it's huge (often several 100,000 lines), it's actually very easy to
611 since (a) it only refers to files, (b) it contains comments saying
612 where each bit comes from, and (c) it barely uses any
613 Make variables at all.
615 It is hard to persuade Hake to generate an invalid Makefile,
616 but it's possible. If so, it may still be due to an error in some
617 Hakefile, in which case look at the file comments preceding the line
618 where Make thinks the error is to find out which Hakefile to look
621 The most common problem is actually due to out of date dependencies.
622 Hake does its best to calculate dependencies properly, but sometimes
623 (such as when Hakefiles themselves change) they get confused. In this
624 case, the first thing to try to is completely remove the build tree
625 and try again. As you get more of a feel for the system it's possible
626 to more surgically remove bits of the tree (the Makefile knows how to
627 recreate any part of the build tree).
629 \section{The Makefile works, but the build fails}
631 In this case, you've written valid Hake rules, but they don't do what
632 you want them to. In this case as well, looking at the generated Makefile
633 can often help work out what went wrong.
635 \chapter{Command-line arguments}
637 The Hake binary built in a Barrelfish tree can be found in
638 \texttt{/hake/hake}, and takes the following command-line arguments:
640 \item[--source-dir:] this option is mandatory and specifies the root
642 \item[--output-filename:] this option specifies the name of the output
643 Makefile, and defaults to \texttt{Makefile}
644 \item[--quiet:] this option turns off some information and warning
645 messages as Hake runs.
646 \item[--verbose:] this option increases the verbosity level of Hake's
647 information messages.
648 \item[--install-dir:] this option specifies the install tree. It
649 defaults to the build tree (the current working directory where Hake runs).
650 \item[--architecture:] this option can be specified multiple times and
651 gives an architecture for Hake to build. It overrides the default
652 list of architectures to build that was set when Hake was
653 configured. At time of writing, supported architectures include
654 \texttt{x86\_64}, \texttt{x86\_32}, \texttt{arm}, \texttt{arm11mp},
655 \texttt{beehive}, and \texttt{scc}.
658 \subsection{Building an external application or library}
660 Building an application or library \emph{outside} the main Barrelfish
661 tree involves invoking Hake directly (rather than bootstrapping with
662 \texttt{hake.sh}), and requires to you have a pre-built Barrelfish
663 tree with at least as many architectures built as you would like to
664 build the application or library for.
666 For example, suppose \texttt{/projects/barrelfish/install} contains a
667 core Barrelfish tree built for all supported architectures, and the
668 user's home directory contains a small source tree
669 \verb!~/quake3! containing an application to be built for
670 \texttt{x86\_32} only. As long as this source tree has a correct
671 Hakefile (or Hakefiles), the following should build the application:
676 $ /projects/barrelfish/install/hake/hake \
677 --source-dir ~/quake \
678 --install-dir /projects/barrelfish/install \
679 --architecture x86_32
685 Hake is missing many desirable features. Hopefully, this list will
686 reduce in size over time. Here are a few:
689 \item Support for multiple host build environments (such a Cygwin).
690 \item The bootstrapping process for Hake, while short, is a little