Add addModules flag to hake.
authorGerd Zellweger <mail@gerdzellweger.com>
Mon, 15 May 2017 11:17:25 +0000 (13:17 +0200)
committerGerd Zellweger <mail@gerdzellweger.com>
Mon, 15 May 2017 11:19:22 +0000 (13:19 +0200)
Any library specified in addModules will be linked using the
--whole-archive flag which prevents the linker from dropping
the symbols if they are not referenced anywhere.
We will use this to make sure device driver modules can
be found and started dynamically inside a driver domain.

Signed-off-by: Gerd Zellweger <mail@gerdzellweger.com>

doc/003-hake/Hake.tex
hake/ArchDefaults.hs
hake/Args.hs
hake/RuleDefs.hs
hake/X86_64.hs
tools/elver/Hakefile
tools/fastmodels/Hakefile
tools/weever/Hakefile

index 77e50d6..cafb7d7 100644 (file)
@@ -28,6 +28,7 @@
 \vhEntry{1.0}{3.06.2010}{TR}{Initial version}
 \vhEntry{1.1}{11.04.2010}{TR}{Support for out-of-tree builds}
 \vhEntry{1.2}{03.07.2015}{TR}{Added platform and boot constructs}
+\vhEntry{1.3}{15.04.2017}{GZ}{Support for Modules}
 \end{versionhistory}
 
 % \intro{Abstract}             % Insert abstract here
 
 \chapter{Introduction}
 
-Hake is how we build Barrelfish. 
+Hake is how we build Barrelfish.
 
 Hake isn't designed to operate outside Barrelfish, so this document
-will assume you're trying to build Barrelfish. 
+will assume you're trying to build Barrelfish.
 
 \section{Quick start}
 
@@ -63,35 +64,35 @@ $ ../src/hake/hake.sh -s ../src -a x86_64
 Type \texttt{make help-platforms} for a list of platforms you can now
 build for, and \texttt{make help-boot} for a list of options for
 booting Barrelfish under simulation if you don't want to use real
-hardware. 
+hardware.
 
 You can supply multiple \texttt{-a} options to build for multiple
-architectures at the same time. 
+architectures at the same time.
 
 Edit the file \texttt{hake/Config.hs} in your build directory and
-rebuild Hake to reconfigure your build tree. 
+rebuild Hake to reconfigure your build tree.
 
-That's about it. 
+That's about it.
 
 \section{How to think about hake}
 
 Hake builds a single, very large \texttt{Makefile} which
-\texttt{make} can then use to build any part of Barrelfish. 
+\texttt{make} can then use to build any part of Barrelfish.
 
 Hake is essentially a Haskell embedded domain-specific language,
 except that it is also evaluated dyanically (using the
 \texttt{System.Eval.Haskell} package) and written by scattering code
-around the source tree. 
+around the source tree.
 
 Hake consists of the main hake program (which itself contains
 considerable information on how to build code), together with a set of
-Hakefiles spread throughout the source tree.  
+Hakefiles spread throughout the source tree.
 
 Each Hakefile should be thought of as containing a Haskell expression
-which evaluates to a set of rules for Make.  The expression will be 
+which evaluates to a set of rules for Make.  The expression will be
 evaluated in an environment which includes the path to the directory
 where the Hakefile is located, plus a complete list of all files in
-the source tree. 
+the source tree.
 
 \section{When hake runs}
 
@@ -100,33 +101,33 @@ When you run Hake in a Barrelfish source tree, it does the following things:
 \item Hake builds a list of (almost) every file and directory in the
   source tree.  The list of files Hake ignores is currently hardcoded
   into Hake, but basically it skips editor temporary files, version
-  control directories, and products of a previous build process. 
-\item From this, Hake extracts a list of all Hakefiles in the tree. 
+  control directories, and products of a previous build process.
+\item From this, Hake extracts a list of all Hakefiles in the tree.
 \item Hake reads every Hakefile.  Each Hakefile contains a single
-  Haskell expression which itself evaluates to a set of Make rules. 
+  Haskell expression which itself evaluates to a set of Make rules.
 \item Hake constructs a single very large Haskell expression out of
   all these Hakefiles.  Each Hakefile is evaluated in an environment
   which includes the pathname of the Hakefile itself (to resolve
   relative names), and the entire list is evaluated in an environment
   which includes the list of files in the whole tree (to allow
-  wildcards). 
+  wildcards).
 \item This large expression is then evaluated.  The result is a single
   tree of Hake rule representations (see
-  Chapter~\ref{sec:reprules}). 
+  Chapter~\ref{sec:reprules}).
 \item The rule tree is traversed to derive a list of every directory
-  in the build tree.  
+  in the build tree.
 \item Finally, a single Makefile is generated which contains rules to
   build every target in the build tree, for every architecture
   (including the host-based build tools themsevles), and also create
-  every directory in the build tree. 
+  every directory in the build tree.
 \end{enumerate}
 
 This single Makefile is large, but is also quite simple: it contains
 no use of Make variables or generic Make rules, instead it simply
-includes explicit rules to build every file required for Barrelfish. 
+includes explicit rules to build every file required for Barrelfish.
 
 The Makefile also includes comments to help you locate the make rules
-generated from any particular Hakefile. 
+generated from any particular Hakefile.
 
 \section{Motivation and Design Principles}
 
@@ -135,11 +136,11 @@ from countless built systems is that if one starts without a full
 programming language built in, one ends up implementing a bad one
 (CMake being only one example).  It's much easier to bite the bullet
 and admit that we need a complete language, and plenty are available
-for this. 
+for this.
 
 \paragraph{Hake should be a functional language.}  \texttt{make} is a
 canonical example of a successful declarative language: Hake should
-not try and replicate what make does well.  
+not try and replicate what make does well.
 
 \paragraph{Hake should generate one Makefile.} One Makefile is easier
 to debug: all the information is available in the same file.  There is
@@ -148,14 +149,14 @@ Hake-generated Makefiles include are generated C dependency lists, and
 a single, top-level file giving symbolic targets.  The Makefile
 generated by Hake also makes minimal, and highly stylized, use of make
 variables: wherever possible, any variable substitution is done in Haskell
-before the Makefile is generated. 
+before the Makefile is generated.
 
 \paragraph{Hake is for building Barrelfish.}  We make no claims as to
 Hake's suitability for any project other than Barrelfish, and indeed
 the current implementation is pretty tied to the Barrelfish tree.
 This has helped to keep the system focussed and tractable.  One
 non-goal of Hake, for example, is to support portability across host
-machines (as CMake tries to do). 
+machines (as CMake tries to do).
 
 \chapter{Simple Hakefiles}
 
@@ -163,15 +164,15 @@ Hake can in principle build anything, but there are two simple use
 cases for Hake: building Barrelfish applications (user-space
 binaries), and building Barrelfish libraries.  Here's how, at time of
 writing, the Barrelfish PCI driver is specified.  This is the entire
-Hakefile: 
+Hakefile:
 
 \begin{verbatim}
 
-[ build application { 
+[ build application {
        target = "pci",
-       cFiles = [ "pcimain.c", "pci.c", "pci_service.c", 
+       cFiles = [ "pcimain.c", "pci.c", "pci_service.c",
                   "ioapic.c", "acpi.c", "ht_config.c",
-                  "acpica_osglue.c", "interrupts.c", 
+                  "acpica_osglue.c", "interrupts.c",
                   "pci_confspace.c", "pcie_confspace.c",
                   "video.c", "buttons.c", "acpi_ec.c" ],
         flounderBindings = [ "pci" ],
@@ -190,37 +191,41 @@ Hakefile:
 The outermost square brackets are a Haskell list expression - each
 Hakefile should be such a list (the exact type will be explained
 later).   This list has a single element, the instruction to built an
-application (you can have more of these, separated by commas). 
+application (you can have more of these, separated by commas).
 
 The \texttt{build application} specifies a number of arguments, all of
 which are optional.  These are actually Haskell record field
 specifiers, and \texttt{application} returns a complete default set.
 \texttt{build} then generates the Make rules to build the
-application. 
+application.
 
 The complete list of possible arguments for applications (or
 libraries) can be found by looking at \texttt{Args.hs}.  The ones used
 here are:
 \begin{description}
-\item[target]: the name of the binary to build.  
+\item[target]: the name of the binary to build.
 \item[cFiles]: list of names of C source files. You need to include
-  ``\texttt{.c}''. 
-\item[flounderBindings]: Flounder interfaces for which to compile 
-  the stub files.  
+  ``\texttt{.c}''.
+\item[flounderBindings]: Flounder interfaces for which to compile
+  the stub files.
 \item[flounderDefs]: Flounder interfaces to use from a library
-\item[mackerelDevices]: list of Mackerel device specs this application uses or depends on. 
-\item[addIncludes]: additional include paths for header files. 
+\item[mackerelDevices]: list of Mackerel device specs this application uses or depends on.
+\item[addIncludes]: additional include paths for header files.
 \item[addLibraries]: additional libraries to link against.
+\item[addModules]: additional libraries to link against. In contrast to
+\texttt{addLibraries}, the linker makes sure to include all symbols by passing
+the \texttt{--whole-archive} option. This is useful if you want to have a more
+dynamic discovery of code (e.g., device drivers modules).
 \end{description}
 
 Note that filenames are relative to the current source
 directory. Those with a leading '/' are interpreted relative to the
-root of the tree (not the root file system).   
+root of the tree (not the root file system).
 
 Libraries are similar.  Here's the Hakefile for the X86 emulator
 library:
 \begin{verbatim}
-[ build library { 
+[ build library {
          target = "x86emu",
          cFiles = [ "debug.c", "decode.c", "fpu.c", "ops2.c",
                     "ops.c", "prim_ops.c", "sys.c"],
@@ -245,11 +250,11 @@ the second is a set of architectures which must be built (and
 configured) for this platform.  The third argument is a list of
 pathnames in the build tree of files which must be built, and the
 final argument is a description to be printed by \texttt{make
-  help-platforms}. 
+  help-platforms}.
 
 The final high-level construct is a ``\texttt{boot}'' - a make target
 that boots Barrelfish in some kind of emulator.  Examples can be found
-in \texttt{/platforms/Hakefile}. 
+in \texttt{/platforms/Hakefile}.
 
 This should be all you need to know to write simple Hakefile{s} for
 the Barrelfish, and indeed to understand most of the Hakefile{s} in
@@ -257,18 +262,18 @@ the Barrelfish tree.
 
 Doing (or understanding) more fancy things in the Hakefile requires
 more knowledge of how Hake internally generates and represents Make
-rules, described later. 
+rules, described later.
 
 \chapter{Hake from the bottom up}
 
 The core of Hake consists of the code to walk the source tree, a
 minimal set of data types used to represent Make rules, and codes to
-render these data types into a Makefile.  
+render these data types into a Makefile.
 
 \section{The Hake name space for files}
 
 Unlike most build systems, Hake uses a 3-dimensional name space for
-files.  
+files.
 
 The first component is called the ``tree''.  Whenever Hake runs, it
 deals with three ``trees'':
@@ -279,34 +284,34 @@ deals with three ``trees'':
   and libraries currently being built.  When building the core OS,
   this is the main OS source tree. When building an external
   application or library, this is the directory tree containing the
-  application or library's source code. 
+  application or library's source code.
 
 \item The ``build tree'' (written as \texttt{BuildTree}) is where the
   intermediate and final results of the compilation end up.  This is
-  typically the current working directory when Hake was run. 
+  typically the current working directory when Hake was run.
 
 \item The ``install tree'' (written as \texttt{InstallTree}) is the
   directory tree containing a core Barrelfish OS build tree.  When
   building the OS, the install tree and the build tree are the same,
   but when building an external application or library, the install
   tree is a pre-built Barrelfish tree and the build tree is where the
-  new application or library is built. 
+  new application or library is built.
 \end{enumerate}
 
 The second component is called the ``architecture'' (for want
 of a better name), and corresponds to building the same code for
 different target architectures (\texttt{x86\_64}, \texttt{arm}, etc.)
-Architectures themselves form a flat namespace. 
+Architectures themselves form a flat namespace.
 
 Some ``architectures'' are special when building the core Barrelfish OS:
 \begin{description}
 \item[src] refers to files which are always present in the source
 tree.  Hake should not be used to build anything in the \texttt{src}
 architecture, and anything in any other architecture must be generated
-at build time. 
+at build time.
 \item[hake] is used by Hake as part of the bootstrapping process.
 \item[root] refers to files relative to the top of the build
-tree, and should be used with caution. 
+tree, and should be used with caution.
 \item[tools] is used to build other build process tools (Mackerel,
   Fugu, Flounder, etc.)
 \item[docs] is used to build documentation (Technical Notes),
@@ -314,10 +319,10 @@ tree, and should be used with caution.
 \end{description}
 
 The final component is called the ``path'', and corresponds roughly
-to the pathname of the file from the root of the designated tree. 
+to the pathname of the file from the root of the designated tree.
 In the source for hake itself,``path'' usually refers to this path,
 and file ``location'' or just ``loc'' refers to the 3-dimensional file
-reference. 
+reference.
 
 Here are some examples of hake file locations:
 
@@ -343,7 +348,7 @@ the path of their Hakefile, and are converted into
 This is more intuitive than it sounds.  For example, a file referred
 to as \texttt{(SrcTree,"src","e1000.c")} in
 \texttt{drivers/e1000/Hakefile} will appear in the resulting Makefile
-as {drivers/e1000/e1000.c}.  
+as {drivers/e1000/e1000.c}.
 
 The Hake namespace is mapped onto the file system as follows: all
 files with architecture \texttt{src} are relative to the top of the
@@ -351,12 +356,12 @@ source tree, whereas a file in a different architecture \texttt{foo}
 is relative to directory \texttt{foo/} in the build or install tree.
 Thus, \texttt{(BuildTree,"x86\_64","e1000.o")} in
 \texttt{drivers/e1000/Hakefile} will  appear in the resulting Makefile
-as {./x86\_64/drivers/e1000/e1000.o}. 
+as {./x86\_64/drivers/e1000/e1000.o}.
 
 Hake will generate all Makefile rules necessary to create any
 directories in the build tree that it needs - it's perfectly possible
 (and sometimes useful) with Hake to type ``\texttt{rm -rf ./*;
-  make}'' and have everything work.  
+  make}'' and have everything work.
 
 \section{Representing rules}\label{sec:reprules}
 
@@ -374,7 +379,7 @@ data HRule = Rule [ RuleToken ]
 The \texttt{Include} constructor creates an ``include'' directive in a
 Makefile.  In theory, there should be no need for developers to use
 this; it is only used currently to include automatically-generated
-dependency files for C and assembly source. 
+dependency files for C and assembly source.
 
 The \texttt{Rules} constructor allows a tree of rules to be
 constructed.  This is purely a convenience: any time that one can
@@ -383,7 +388,7 @@ it easier to write functions which return rules, which is the basis of
 Hake.
 
 The \texttt{Error} constructor is used to signal errors, but in
-practice is rarely used. 
+practice is rarely used.
 
 The \texttt{Phony} constructor is used to create rules whose target is
 not actually a file.  This should hardly ever be used in practice:
@@ -425,10 +430,10 @@ Unix library:
 \begin{verbatim}
 archive :: Options -> [String] -> String -> [ RuleToken ]
 archive opts objs libpath =
-    [ Str "ar cr ", Out arch libpath ] 
-    ++ 
+    [ Str "ar cr ", Out arch libpath ]
+    ++
     [ In BuildTree arch o | o <- objs ]
-    ++ 
+    ++
     [ NL, Str "ranlib ", Out arch libpath ]
 \end{verbatim}
 The arguments to this function include a set of ``options'', which are
@@ -442,11 +447,11 @@ defined globally)
 The library is referred to as an \texttt{Out} token, since it is a target
 of the rule, whereas the object files are referred to by \texttt{In}
 tokens, since they are prerequisites.   Both are in the \texttt{arch}
-architecture, since they have presumably been built by other rules. 
+architecture, since they have presumably been built by other rules.
 
 This function is called from another, \texttt{arch}-independent
 function called ``\texttt{archiveLibrary}'', which dispatches based on
-the architectures that need to be built for a given library. 
+the architectures that need to be built for a given library.
 Hence, if a Hakefile at ``\texttt{drivers/e1000/Hakefile}'' contained
 the expression:
 \begin{verbatim}
@@ -456,10 +461,10 @@ archiveLibrary "x86_64" "e1000drv" [ "e1000.o", "e1000srv.o"]
 \begin{verbatim}
 ./x86_64/drivers/e1000/libe1000drv.a: \
                        ./x86_64/drivers/e1000/e1000.o \
-                       ./x86_64/drivers/e1000/e1000srv.o 
+                       ./x86_64/drivers/e1000/e1000srv.o
         ar cr ./x86_64/drivers/e1000/libe1000drv.a \
                        ./x86_64/drivers/e1000/e1000.o \
-                       ./x86_64/drivers/e1000/e1000srv.o 
+                       ./x86_64/drivers/e1000/e1000srv.o
         ranlib ./x86_64/drivers/e1000/libe1000drv.a
 \end{verbatim}
 
@@ -469,12 +474,12 @@ The precise definitions of each token are as follows:
   Make rule.   In other words, they refer to files which will appear
   both in the rule body and the list of dependencies (the right hand
   side) in the rule
-  head.  \textbf{In} file references can be in any architecture. 
+  head.  \textbf{In} file references can be in any architecture.
 
 \item[Dep] tokens are file references to implicit dependencies.  In
   Make terms, these are file names which appear in the list of
   dependencies in rule head, but don't explicitly appear in the rule
-  body. 
+  body.
 
 \item[PreDep] tokens are like \textbf{Dep} tokens, but appear in the
   rule head following a \textbf{$|$} character.  GNU Make will require
@@ -484,24 +489,24 @@ The precise definitions of each token are as follows:
   be generated first in order to calculate C dependencies, but which
   ultimately not all C files depend upon.  Any true dependency of a C
   file on \texttt{errno.h} will be specified by the generated depend
-  files, and thus override the \textbf{PreDep} declaration. 
+  files, and thus override the \textbf{PreDep} declaration.
 
 \item[NoDep] tokens are file references that are not dependencies at
   all.  The file name only appears in the rule body, never in the
   head.   For example, \textbf{NoDep} references are used for
-  directories for include files. 
+  directories for include files.
 
 \item[Out] tokens are file references to output files from a rule,
   which are mentioned in the rule body. This is the common case for
-  most files generated by Make rules. 
+  most files generated by Make rules.
 
 \item[Target] tokens are file references that are implicit outputs of
   the rule, but do not appear in the rule body.  In Make terms they
   appear only in the left-hand side of the rule head, and not in the
-  body.  
+  body.
 
 \item[Str] tokens are simply strings.  They will be followed in the
-  Makefile by a space character, which is usually what you want.  
+  Makefile by a space character, which is usually what you want.
 
 \item[NStr] tokens are like \textbf{Str}, but not followed by a
   space.  This is useful for situations like the \texttt{-I} flag to
@@ -510,7 +515,7 @@ The precise definitions of each token are as follows:
 
 \item[ErrorMsg] tokens are a way to incorporate error conditions into
   the Makefile - they are translated into the GNU make construct
-  \texttt{\$(error \textit{x})}. 
+  \texttt{\$(error \textit{x})}.
 
 \item[NL] tokens are simply newlines in the rule.
 
@@ -522,7 +527,7 @@ The precise definitions of each token are as follows:
 
 In practice, a Hakefile rarely has to resort to explicit
 \texttt{RuleToken}s, but instead calls functions inside Hake to return
-\texttt{HRule}s.  
+\texttt{HRule}s.
 
 
 \section{Higher rule abstractions}
@@ -532,12 +537,12 @@ which provides a big lattice of functions to automate generating
 rules for commonly used patterns.  If you want to do more complex
 things than simply ``\texttt{build application}'' or ``\texttt{build
   library}'', it's a good idea to understand how these features use
-the definitions in \texttt{RuleDefs.hs}. 
+the definitions in \texttt{RuleDefs.hs}.
 
 \section{Target architectures}
 
 Most of the flexibility required of Hake in building for multiple
-architectures is simply coded into the Haskell source of the program.  
+architectures is simply coded into the Haskell source of the program.
 
 For every target architecture (at time of writing, only
 \texttt{x86\_64}), there is a file (\texttt{X64\_64.hs}) which
@@ -545,25 +550,25 @@ contains the definitions required to build the system for that
 target.   Adding a new target architecture for Barrelfish involves
 writing a new one of these files (e.g. \texttt{ARMv8.hs}, or
 \texttt{X86\_64.hs}, etc.) and modifying the code in
-\texttt{RuleDefs.hs} to dispatch to the correct module. 
+\texttt{RuleDefs.hs} to dispatch to the correct module.
 
 \section{Host architectures}
 
 Hake at present supports only a single host architecture: the
 toolchain to build Barrelfish is specified once in the target
-architecture files (see above).  
+architecture files (see above).
 
 To add support for multiple host build environments, one way to slice the
 problem is for the target architecture modules to import different
 host architecture modules and decide which one to call to get tool and
-path defnitions at runtime. 
+path defnitions at runtime.
 
 \section{Configuration}
 
 The file \texttt{hake/Config.hs} in the build directory contains all
 the configuration variables (at time of writing) used for Barrelfish.
 Unlike in Make or CMake, these are Haskell values of arbitrary type,
-since they are evaluated entirely within Hake. 
+since they are evaluated entirely within Hake.
 
 To reconfigure a build tree, therefore, one modifies this file,
 and rebuilds Hake and the top-level Makefile.
@@ -574,7 +579,7 @@ The \texttt{rehake} target performs this task.
 Hake is bootstrapped using a shell script found in the Barrelfish
 source tree in \texttt{hake/hake.sh}.  This script is the place to
 start configuring a new core Barrelfish OS build tree, and must be
-run in the root of the new build directory. 
+run in the root of the new build directory.
 
 \texttt{hake.sh} takes the following command-line options:
 \begin{description}
@@ -585,7 +590,7 @@ run in the root of the new build directory.
 \item[-a,--architecture:] This option can be given multiple times and
   specifies the list of architectures to build Barrelfish for.  Run
   the script with the \texttt{-h} option to get the default list of
-  architectures. 
+  architectures.
 \item[-h,--help:] Prints a usage message.
 \item[-n,--no-hake:] This option simply rebuilds Hake, but does not
   run it to generate a Makefile. It can be handy for debugging Hake
@@ -597,23 +602,23 @@ run in the root of the new build directory.
 After parsing and checking arguments, \texttt{hake.sh} next creates a new
 configuration file \texttt{hake/Config.hs} in the build tree.   The
 configuration options in this file are defaults: it is a copy of the
-template \texttt{hake/Config.hs.template} in the source tree. 
+template \texttt{hake/Config.hs.template} in the source tree.
 
 If this file already exists in the build tree, however, it is left
 unchanged, which means that any user modifications to this file
 persist across multiple bootstrapping runs of \texttt{hake.sh}.
 If you really want to reconfigure a build tree from scratch, you
 should therefore remove everything in the build tree, including this
-file. 
+file.
 
 After this, Hake itself is recompiled in the build tree (including the
 new \texttt{Config.hs} file), and then run with default options (most
-of which will be picked up from \texttt{Config.hs}). 
+of which will be picked up from \texttt{Config.hs}).
 
 \chapter{Debugging Hakefiles}
 
 At least three things can go wrong when you modify or write a
-Hakefile.  
+Hakefile.
 
 \section{The Hakefile has a compile error}
 
@@ -638,27 +643,27 @@ Ignoring the last line for the moment, if you know enough Haskell this
 should tell you exactly what is wrong with some Hakefile.   However,
 even if you don't know enough Haskell, it does say which Hakefile is
 at fault and whereabouts in the offending Hakefile the problem is (in
-this case line 13 of \texttt{usr/pci/Hakefile}). 
+this case line 13 of \texttt{usr/pci/Hakefile}).
 
 Also, the file that Hake tried to compile will be left for you in
 \texttt{Hakefiles.hs}.  If you look at this, you'll see it's
 constructed out of individual Hakefile{s} together with a preamble
-giving details of the files in the tree.  
+giving details of the files in the tree.
 
 \section{The Makefile has an error}
 
 Hake generates a single large Makefile at the top of the tree.
 While it's huge (often several 100,000 lines), it's actually very easy to
-understand 
+understand
 since (a) it only refers to files, (b) it contains comments saying
 where each bit comes from, and (c) it barely uses any
-Make variables at all.  
+Make variables at all.
 
 It is hard to persuade Hake to generate an invalid Makefile,
 but it's possible.  If so, it may still be due to an error in some
 Hakefile, in which case look at the file comments preceding the line
 where Make thinks the error is to find out which Hakefile to look
-at. 
+at.
 
 The most common problem is actually due to out of date dependencies.
 Hake does its best to calculate dependencies properly, but sometimes
@@ -666,13 +671,13 @@ Hake does its best to calculate dependencies properly, but sometimes
 case, the first thing to try to is completely remove the build tree
 and try again.  As you get more of a feel for the system it's possible
 to more surgically remove bits of the tree (the Makefile knows how to
-recreate any part of the build tree). 
+recreate any part of the build tree).
 
 \section{The Makefile works, but the build fails}
 
 In this case, you've written valid Hake rules, but they don't do what
 you want them to.  In this case as well, looking at the generated Makefile
-can often help work out what went wrong. 
+can often help work out what went wrong.
 
 \chapter{Command-line arguments}
 
@@ -680,7 +685,7 @@ The Hake binary built in a Barrelfish tree can be found in
 \texttt{/hake/hake}, and takes the following command-line arguments:
 \begin{description}
 \item[--source-dir:] this option is mandatory and specifies the root
-  of the source tree. 
+  of the source tree.
 \item[--output-filename:] this option specifies the name of the output
   Makefile, and defaults to \texttt{Makefile}
 \item[--quiet:] this option turns off some information and warning
@@ -732,8 +737,8 @@ Hake is missing many desirable features.  Hopefully, this list will
 reduce in size over time.  Here are a few:
 
 \begin{itemize}
-\item Support for multiple host build environments (such as Cygwin). 
+\item Support for multiple host build environments (such as Cygwin).
 \item The bootstrapping process for Hake, while short, is a little
-  unsatisfactory. 
+  unsatisfactory.
 \end{itemize}
 \end{document}
index 4bb3864..705c3d3 100644 (file)
@@ -7,7 +7,7 @@
 -- ETH Zurich D-INFK, Universitaetstasse 6, CH-8092 Zurich. Attn: Systems Group.
 --
 -- Default architecture-specific definitions for Barrelfish
--- 
+--
 --------------------------------------------------------------------------
 
 module ArchDefaults where
@@ -71,15 +71,15 @@ cStdIncs arch archFamily =
       NoDep BFSrcTree "src" ".",
       NoDep SrcTree "src" ".",
       NoDep BuildTree arch "." ]
-                      
-ldFlags arch = 
+
+ldFlags arch =
     map Str Config.cOptFlags ++
     [ In InstallTree arch "/lib/crt0.o",
       In InstallTree arch "/lib/crtbegin.o",
       Str "-fno-builtin",
       Str "-nostdlib" ]
-          
-ldCxxFlags arch = 
+
+ldCxxFlags arch =
     map Str Config.cOptFlags ++
     [ In InstallTree arch "/lib/crt0.o",
       In InstallTree arch "/lib/crtbegin.o",
@@ -90,7 +90,7 @@ kernelLibs arch =
     [ In InstallTree arch "/lib/libcompiler-rt.a" ]
 
 -- Libraries that are linked to all applications.
-stdLibs arch = 
+stdLibs arch =
     [ In InstallTree arch "/lib/libbarrelfish.a",
       In InstallTree arch "/lib/libterm_client.a",
       In InstallTree arch "/lib/liboctopus_parser.a", -- XXX: For NS client in libbarrelfish
@@ -107,18 +107,18 @@ stdLibs arch =
       In InstallTree arch "/lib/crtend.o" ,
       In InstallTree arch "/lib/libcollections.a" ]
 
-stdCxxLibs arch = 
+stdCxxLibs arch =
     [ In InstallTree arch "/lib/libcxx.a" ]
-    ++ stdLibs arch 
+    ++ stdLibs arch
 
-options arch archFamily = Options { 
+options arch archFamily = Options {
             optArch = arch,
             optArchFamily = archFamily,
             optFlags = cFlags,
             optCxxFlags = cxxFlags,
             optDefines = [ Str "-DBARRELFISH" ] ++ Config.defines,
             optIncludes = cStdIncs arch archFamily,
-            optDependencies = 
+            optDependencies =
                 [ Dep InstallTree arch "/include/errors/errno.h",
                   Dep InstallTree arch "/include/barrelfish_kpi/capbits.h",
                   Dep InstallTree arch "/include/asmoffsets.h",
@@ -153,16 +153,16 @@ options arch archFamily = Options {
 --
 cCompiler :: String -> String -> [String] -> Options -> String ->
              String -> String -> [RuleToken]
-cCompiler arch compiler opt_flags opts phase src obj = 
+cCompiler arch compiler opt_flags opts phase src obj =
     let incls = (extraIncludes opts) ++ (optIncludes opts)
-        flags = (optFlags opts) 
+        flags = (optFlags opts)
                 ++ (optDefines opts)
                 ++ [ Str f | f <- extraFlags opts ]
                 ++ [ Str f | f <- extraDefines opts ]
         deps = (optDependencies opts) ++ (extraDependencies opts)
     in
       [ Str compiler ] ++ flags ++ (map Str opt_flags)
-      ++ concat [ [ NStr "-I", i ] | i <- incls ] 
+      ++ concat [ [ NStr "-I", i ] | i <- incls ]
       ++ [ Str "-o", Out arch obj,
            Str "-c", In (if phase == "src" then SrcTree else BuildTree) phase src ]
       ++ deps
@@ -172,9 +172,9 @@ cCompiler arch compiler opt_flags opts phase src obj =
 --
 cPreprocessor :: String -> String -> [String] -> Options -> String ->
                  String -> String -> [RuleToken]
-cPreprocessor arch compiler opt_flags opts phase src obj = 
+cPreprocessor arch compiler opt_flags opts phase src obj =
     let incls = (extraIncludes opts) ++ (optIncludes opts)
-        flags = (optFlags opts) 
+        flags = (optFlags opts)
                 ++ (optDefines opts)
                 ++ [ Str f | f <- extraFlags opts ]
                 ++ [ Str f | f <- extraDefines opts ]
@@ -182,7 +182,7 @@ cPreprocessor arch compiler opt_flags opts phase src obj =
         cOptFlags = opt_flags \\ ["-g"]
     in
       [ Str compiler ] ++ flags ++ (map Str cOptFlags)
-      ++ concat [ [ NStr "-I", i ] | i <- incls ] 
+      ++ concat [ [ NStr "-I", i ] | i <- incls ]
       ++ [ Str "-o", Out arch obj,
            Str "-E", In (if phase == "src" then SrcTree else BuildTree) phase src ]
       ++ deps
@@ -190,16 +190,16 @@ cPreprocessor arch compiler opt_flags opts phase src obj =
 --
 -- C++ compiler
 --
-cxxCompiler arch cxxcompiler opt_flags opts phase src obj = 
+cxxCompiler arch cxxcompiler opt_flags opts phase src obj =
     let incls = (extraIncludes opts) ++ (optIncludes opts)
-        flags = (optCxxFlags opts) 
+        flags = (optCxxFlags opts)
                 ++ (optDefines opts)
                 ++ [ Str f | f <- extraCxxFlags opts ]
                 ++ [ Str f | f <- extraDefines opts ]
         deps = (optDependencies opts) ++ (extraDependencies opts)
     in
       [ Str cxxcompiler ] ++ flags ++ (map Str opt_flags)
-      ++ concat [ [ NStr "-I", i ] | i <- incls ] 
+      ++ concat [ [ NStr "-I", i ] | i <- incls ]
       ++ [ Str "-o", Out arch obj,
            Str "-c", In (if phase == "src" then SrcTree else BuildTree) phase src ]
       ++ deps
@@ -209,40 +209,40 @@ cxxCompiler arch cxxcompiler opt_flags opts phase src obj =
 --
 makeDepend arch compiler opts phase src obj depfile =
     let incls = (extraIncludes opts) ++ (optIncludes opts)
-        flags = (optFlags opts) 
+        flags = (optFlags opts)
                 ++ (optDefines opts)
                 ++ [ Str f | f <- extraFlags opts ]
                 ++ [ Str f | f <- extraDefines opts ]
     in
-      [ Str ('@':compiler) ] ++ flags 
-      ++ concat [ [ NStr "-I", i ] | i <- incls ] 
+      [ Str ('@':compiler) ] ++ flags
+      ++ concat [ [ NStr "-I", i ] | i <- incls ]
       ++ (optDependencies opts) ++ (extraDependencies opts)
-      ++ [ Str "-M -MF", 
+      ++ [ Str "-M -MF",
            Out arch depfile,
-           Str "-MQ", NoDep BuildTree arch obj, 
+           Str "-MQ", NoDep BuildTree arch obj,
            Str "-MQ", NoDep BuildTree arch depfile,
            Str "-c", In (if phase == "src" then SrcTree else BuildTree) phase src
-         ] 
+         ]
 
 --
 -- Create C++ file dependencies
 --
 makeCxxDepend arch cxxcompiler opts phase src obj depfile =
     let incls = (extraIncludes opts) ++ (optIncludes opts)
-        flags = (optCxxFlags opts) 
+        flags = (optCxxFlags opts)
                 ++ (optDefines opts)
                 ++ [ Str f | f <- extraCxxFlags opts ]
                 ++ [ Str f | f <- extraDefines opts ]
     in
-      [ Str ('@':cxxcompiler) ] ++ flags 
-      ++ concat [ [ NStr "-I", i ] | i <- incls ] 
+      [ Str ('@':cxxcompiler) ] ++ flags
+      ++ concat [ [ NStr "-I", i ] | i <- incls ]
       ++ (optDependencies opts) ++ (extraDependencies opts)
-      ++ [ Str "-M -MF", 
+      ++ [ Str "-M -MF",
            Out arch depfile,
-           Str "-MQ", NoDep BuildTree arch obj, 
+           Str "-MQ", NoDep BuildTree arch obj,
            Str "-MQ", NoDep BuildTree arch depfile,
            Str "-c", In (if phase == "src" then SrcTree else BuildTree) phase src
-         ] 
+         ]
 
 --
 -- Compile a C program to assembler
@@ -260,8 +260,8 @@ cToAssembler arch compiler opt_flags opts phase src afile objdepfile =
                (extraDependencies opts)
     in
       [ Str compiler ] ++ flags ++ (map Str opt_flags)
-      ++ concat [ [ NStr "-I", i ] | i <- incls ] 
-      ++ [ Str "-o ", Out arch afile, 
+      ++ concat [ [ NStr "-I", i ] | i <- incls ]
+      ++ [ Str "-o ", Out arch afile,
            Str "-S ", In (if phase == "src" then SrcTree else BuildTree) phase src ]
       ++ deps
 
@@ -270,16 +270,16 @@ cToAssembler arch compiler opt_flags opts phase src afile objdepfile =
 --
 assembler :: String -> String -> [ String ] -> Options -> String ->
              String -> [ RuleToken ]
-assembler arch compiler opt_flags opts src obj = 
+assembler arch compiler opt_flags opts src obj =
     let incls = (extraIncludes opts) ++ (optIncludes opts)
-        flags = (optFlags opts) 
+        flags = (optFlags opts)
                 ++ (optDefines opts)
                 ++ [ Str f | f <- extraFlags opts ]
                 ++ [ Str f | f <- extraDefines opts ]
         deps = (optDependencies opts) ++ (extraDependencies opts)
     in
       [ Str compiler ] ++ flags ++ (map Str opt_flags)
-      ++ concat [ [ NStr "-I", i ] | i <- incls ] 
+      ++ concat [ [ NStr "-I", i ] | i <- incls ]
       ++ [ Str "-o ", Out arch obj, Str "-c ", In SrcTree "src" src ]
       ++ deps
 
@@ -289,9 +289,9 @@ assembler arch compiler opt_flags opts src obj =
 archive :: String -> Options -> [String] -> [String] -> String -> String -> [ RuleToken ]
 archive arch opts objs libs name libname =
     [ Str "rm -f ", Out arch libname ]
-    ++ 
+    ++
     [ NL, Str "ar crT ", Out arch libname ]
-    ++ 
+    ++
     [ In BuildTree arch o | o <- objs ]
     ++
     if libs == [] then []
@@ -301,38 +301,43 @@ archive arch opts objs libs name libname =
 
 --
 -- Link an executable
--- 
-linker :: String -> String -> Options -> [String] -> [String] -> String -> [RuleToken]
-linker arch compiler opts objs libs bin =
-    [ Str compiler ] 
-    ++ (optLdFlags opts) 
-    ++ 
-    (extraLdFlags opts) 
-    ++ 
-    [ Str "-o", Out arch bin ] 
-    ++ 
+--
+linker :: String -> String -> Options -> [String] -> [String] -> [String] -> String -> [RuleToken]
+linker arch compiler opts objs libs mods bin =
+    [ Str compiler ]
+    ++ (optLdFlags opts)
+    ++
+    (extraLdFlags opts)
+    ++
+    [ Str "-o", Out arch bin ]
+    ++
     [ In BuildTree arch o | o <- objs ]
     ++
     [ In BuildTree arch l | l <- libs ]
-    ++ 
+    ++
+    [Str "-Wl,--whole-archive"] ++ [ In BuildTree arch l | l <- mods ] ++ [Str "-Wl,--no-whole-archive"]
+    ++
     (optLibs opts)
 
+
 --
 -- Link an executable
--- 
-cxxlinker :: String -> String -> Options -> [String] -> [String] -> String -> [RuleToken]
-cxxlinker arch cxxcompiler opts objs libs bin =
-    [ Str cxxcompiler ] 
-    ++ (optLdCxxFlags opts) 
-    ++ 
-    (extraLdFlags opts) 
-    ++ 
-    [ Str "-o", Out arch bin ] 
-    ++ 
+--
+cxxlinker :: String -> String -> Options -> [String] -> [String] -> [String] -> String -> [RuleToken]
+cxxlinker arch cxxcompiler opts objs libs mods bin =
+    [ Str cxxcompiler ]
+    ++ (optLdCxxFlags opts)
+    ++
+    (extraLdFlags opts)
+    ++
+    [ Str "-o", Out arch bin ]
+    ++
     [ In BuildTree arch o | o <- objs ]
     ++
     [ In BuildTree arch l | l <- libs ]
-    ++ 
+    ++
+    [Str "-Wl,--whole-archive"] ++ [ In BuildTree arch l | l <- mods ] ++ [Str "-Wl,--no-whole-archive"]
+    ++
     (optCxxLibs opts)
 
 --
index 50d326a..dcaffdc 100644 (file)
@@ -7,7 +7,7 @@
 -- ETH Zurich D-INFK, Universitaetstasse 6, CH-8092 Zurich. Attn: Systems Group.
 --
 -- Arguments to major Hake targets
--- 
+--
 --------------------------------------------------------------------------
 
 module Args where
@@ -15,7 +15,7 @@ module Args where
 import HakeTypes
 import TreeDB
 
-data Args = Args { 
+data Args = Args {
       buildFunction :: TreeDB -> String -> Args -> HRule,
       target :: String,
       driverType :: String,
@@ -40,6 +40,7 @@ data Args = Args {
       omitIncludes :: [String],
       addLinkFlags :: [String],
       addLibraries :: [String],
+      addModules :: [String],
       addGeneratedDependencies :: [String],
       architectures :: [String],
       sockeyeSchema :: [String],
@@ -51,7 +52,7 @@ data InstallDirs = InstallDirs {
     libdir :: String
 }
 
-defaultArgs = Args { 
+defaultArgs = Args {
       buildFunction = defaultBuildFn,
       target = "",
       driverType = "",
@@ -76,6 +77,7 @@ defaultArgs = Args {
       omitIncludes = [],
       addLinkFlags = [],
       addLibraries = [],
+      addModules = [],
       addGeneratedDependencies = [],
       architectures = allArchitectures,
       sockeyeSchema = [],
@@ -95,12 +97,12 @@ allFlounderBackends
     = [ "lmp", "ump", "ump_ipi", "loopback", "rpcclient", "msgbuf", "multihop", "ahci", "local" ]
 
 defaultBuildFn :: TreeDB -> String -> Args -> HRule
-defaultBuildFn _ f _ = 
+defaultBuildFn _ f _ =
     Error ("Bad use of default Args in " ++ f)
 
 showArgs :: String -> Args -> String
 showArgs prefix a =
-    prefix ++ "Args:" 
+    prefix ++ "Args:"
     ++ "\n  target:                " ++ (show $ target a)
     ++ "\n  cFiles:                " ++ (show $ cFiles a)
     ++ "\n  generatedCFiles:       " ++ (show $ generatedCFiles a)
@@ -121,6 +123,7 @@ showArgs prefix a =
     ++ "\n  omitIncludes:          " ++ (show $ omitIncludes a)
     ++ "\n  addLinkFlags:          " ++ (show $ addLinkFlags a)
     ++ "\n  addLibraries:          " ++ (show $ addLibraries a)
+    ++ "\n  addModules:            " ++ (show $ addModules a)
     ++ "\n  addDeps:               " ++ (show $ addGeneratedDependencies a)
     ++ "\n  architectures:         " ++ (show $ architectures a)
     ++ "\n  sockeyeSchema:         " ++ (show $ sockeyeSchema a)
index 9b954f8..ae5fb9e 100644 (file)
@@ -263,13 +263,13 @@ 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 -> [RuleToken]
-linker opts objs libs bin
-    | optArch opts == "x86_64" = X86_64.linker opts objs libs bin
-    | optArch opts == "k1om" = K1om.linker opts objs libs bin
-    | optArch opts == "x86_32" = X86_32.linker opts objs libs bin
-    | optArch opts == "armv7" = ARMv7.linker opts objs libs bin
-    | optArch opts == "armv8" = ARMv8.linker opts objs libs bin
+linker :: Options -> [String] -> [String] -> [String] -> String -> [RuleToken]
+linker opts objs libs mods bin
+    | optArch opts == "x86_64" = X86_64.linker opts objs libs mods bin
+    | optArch opts == "k1om" = K1om.linker opts objs libs mods bin
+    | optArch opts == "x86_32" = X86_32.linker opts objs libs mods bin
+    | optArch opts == "armv7" = ARMv7.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)) ]
 
 strip :: Options -> String -> String -> String -> [RuleToken]
@@ -290,10 +290,10 @@ 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 -> [RuleToken]
-cxxlinker opts objs libs bin
-    | optArch opts == "x86_64" = X86_64.cxxlinker opts objs libs bin
-    | optArch opts == "k1om" = K1om.cxxlinker opts objs libs bin
+cxxlinker :: Options -> [String] -> [String] -> [String] -> String -> [RuleToken]
+cxxlinker opts objs libs mods bin
+    | optArch opts == "x86_64" = X86_64.cxxlinker opts objs libs mods bin
+    | optArch opts == "k1om" = K1om.cxxlinker opts objs libs mods bin
     | otherwise = [ ErrorMsg ("Can't link C++ executables for " ++ (optArch opts)) ]
 
 --
@@ -407,9 +407,9 @@ archiveLibrary opts name objs libs =
 --
 -- Link an executable
 --
-linkExecutable :: Options -> [String] -> [String] -> String -> [RuleToken]
-linkExecutable opts objs libs bin =
-    linker opts objs libs (applicationPath opts bin)
+linkExecutable :: Options -> [String] -> [String] -> [String] -> String -> [RuleToken]
+linkExecutable opts objs libs mods bin =
+    linker opts objs libs mods (applicationPath opts bin)
 
 --
 -- Strip debug symbols from an executable
@@ -429,9 +429,9 @@ debugExecutable opts src target =
 --
 -- Link a C++ executable
 --
-linkCxxExecutable :: Options -> [String] -> [String] -> String -> [RuleToken]
-linkCxxExecutable opts objs libs bin =
-    cxxlinker opts objs libs (applicationPath opts bin)
+linkCxxExecutable :: Options -> [String] -> [String] -> [String] -> String -> [RuleToken]
+linkCxxExecutable opts objs libs mods bin =
+    cxxlinker opts objs libs mods (applicationPath opts bin)
 
 -------------------------------------------------------------------------
 
@@ -821,12 +821,12 @@ hamletFile opts file =
 --
 -- Link a set of object files and libraries together
 --
-link :: Options -> [String] -> [ String ] -> String -> HRule
-link opts objs libs bin =
+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 full,
+        Rule $ linkExecutable opts objs libs mods full,
         Rule $ debugExecutable opts full debug,
         Rule $ stripExecutable opts full debug bin
     ]
@@ -834,9 +834,9 @@ link opts objs libs bin =
 --
 -- Link a set of C++ object files and libraries together
 --
-linkCxx :: Options -> [String] -> [ String ] -> String -> HRule
-linkCxx opts objs libs bin =
-    Rule (linkCxxExecutable opts objs libs bin)
+linkCxx :: Options -> [String] -> [String] -> [String] -> String -> HRule
+linkCxx opts objs libs mods bin =
+    Rule (linkCxxExecutable opts objs libs mods bin)
 
 --
 -- Link a CPU driver.  This is where it gets distinctly architecture-specific.
@@ -1026,6 +1026,10 @@ 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
@@ -1101,7 +1105,7 @@ appBuildArch tdb tf args arch =
                 compileGeneratedCFiles opts gencsrc,
                 compileGeneratedCxxFiles opts gencxxsrc,
                 assembleSFiles opts (Args.assemblyFiles args),
-                mylink opts (allObjectPaths opts args) (allLibraryPaths opts args)
+                mylink opts (allObjectPaths opts args) (allLibraryPaths opts args) (allModulesPaths opts args)
                        appname,
                 fullTarget opts arch appname
               ]
@@ -1162,7 +1166,7 @@ arrakisAppBuildArch tdb tf args arch =
                 compileGeneratedCFiles opts gencsrc,
                 compileGeneratedCxxFiles opts gencxxsrc,
                 assembleSFiles opts (Args.assemblyFiles args),
-                mylink opts (allObjectPaths opts args) (allLibraryPaths opts args) appname
+                mylink opts (allObjectPaths opts args) (allLibraryPaths opts args) (allModulesPaths opts args) appname
               ]
             )
 
index ca60b3c..dd01bd3 100644 (file)
@@ -7,7 +7,7 @@
 -- ETH Zurich D-INFK, Universitaetstasse 6, CH-8092 Zurich. Attn: Systems Group.
 --
 -- Architectural definitions for Barrelfish on x86_64.
--- 
+--
 --------------------------------------------------------------------------
 
 module X86_64 where
@@ -32,7 +32,7 @@ objcopy     = Config.x86_objcopy
 ourCommonFlags = [ Str "-m64",
                    Str "-mno-red-zone",
                    Str "-fPIE",
-                   Str "-fno-stack-protector", 
+                   Str "-fno-stack-protector",
                    Str "-Wno-unused-but-set-variable",
                    Str "-Wno-packed-bitfield-compat",
                    Str "-Wno-frame-address",
@@ -51,13 +51,14 @@ cDefines = ArchDefaults.cDefines options
 
 ourLdFlags = [ Str "-Wl,-z,max-page-size=0x1000",
                Str "-Wl,--build-id=none",
+               Str "-Wl,--verbose",
                Str "-static",
                Str "-m64" ]
 
 ldFlags = ArchDefaults.ldFlags arch ++ ourLdFlags
 ldCxxFlags = ArchDefaults.ldCxxFlags arch ++ ourLdFlags
 
-options = (ArchDefaults.options arch archFamily) { 
+options = (ArchDefaults.options arch archFamily) {
             optFlags = cFlags,
             optCxxFlags = cxxFlags,
             optDefines = cDefines,
@@ -132,15 +133,15 @@ cxxlinker = ArchDefaults.cxxlinker arch cxxcompiler
 
 --
 -- Link the kernel (CPU Driver)
--- 
+--
 linkKernel :: Options -> [String] -> [String] -> String -> HRule
-linkKernel opts objs libs kbin = 
+linkKernel opts objs libs kbin =
     let linkscript = "/kernel/linker.lds"
     in
       Rules [ Rule ([ Str compiler ] ++
                     map Str Config.cOptFlags ++
                     [ NStr "-T", In BuildTree arch "/kernel/linker.lds",
-                      Str "-o", Out arch kbin 
+                      Str "-o", Out arch kbin
                     ]
                     ++ (optLdFlags opts)
                     ++
@@ -151,15 +152,15 @@ linkKernel opts objs libs kbin =
                     (ArchDefaults.kernelLibs arch)
                     ++
                     [ NL, NStr "bash -c \"echo -e '\\0002'\" | dd of=",
-                      Out arch kbin, 
+                      Out arch kbin,
                       Str "bs=1 seek=16 count=1 conv=notrunc status=noxfer"
                     ]
                    ),
-              Rule [ Str "cpp", 
+              Rule [ Str "cpp",
                      NStr "-I", NoDep SrcTree "src" "/kernel/include/",
-                     Str "-D__ASSEMBLER__", 
+                     Str "-D__ASSEMBLER__",
                      Str "-P", In SrcTree "src" "/kernel/arch/x86_64/linker.lds.in",
-                     Out arch linkscript 
+                     Out arch linkscript
                    ],
               -- Produce a stripped binary
               Rule [ Str objcopy,
index 1ae00dd..181d342 100644 (file)
@@ -14,9 +14,9 @@
 -- This has to be rather low-level, since elver is indeed a module for
 -- x86_64, but is built for 32-bits, so it's easiest to do this rather
 -- explicitly.
--- 
+--
 let arch = "x86_64"
-    opts = (options arch) { 
+    opts = (options arch) {
              optFlags = [ Str s | s <- [ "-fno-builtin",
                                            "-nostdinc",
                                            "-std=gnu99",
@@ -52,20 +52,20 @@ let arch = "x86_64"
                              NoDep BuildTree arch "/include" ],
              optDefines = [],
              optLibs = [],
-             optLdFlags = [ Str s | s <- [ "-m32", 
-                                        "-fno-builtin", 
+             optLdFlags = [ Str s | s <- [ "-m32",
+                                        "-fno-builtin",
                                         "-nostdlib",
                                         "-Wl,--fatal-warnings",
-                                        "-e start", 
+                                        "-e start",
                                         "-Wl,-Ttext,0x100000",
                                         "-static",
                                         "-Wl,--build-id=none" ]],
-             optSuffix = "_for_elver" 
+             optSuffix = "_for_elver"
            }
     objs = [ objectFilePath opts f | f <- [ "boot.S", "elver.c", "lib.c",
                                             "../../lib/elf/elf64.c" ] ]
-in 
+in
   [ compileCFiles opts [ "elver.c", "lib.c", "../../lib/elf/elf64.c" ],
     assembleSFiles opts [ "boot.S" ],
-    link opts objs [] "elver"
+    link opts objs [] [] "elver"
   ]
index 77677ab..4ba28c1 100644 (file)
@@ -11,7 +11,7 @@
 ----------------------------------------------------------------------
 
 let arch = "armv8"
-    opts = (options arch) { 
+    opts = (options arch) {
              optFlags = [ Str s | s <- [ "-fno-builtin",
                                          "-std=gnu99",
 
@@ -31,14 +31,14 @@ let arch = "armv8"
              optDefines = [],
              optLibs = [],
              optLdFlags = [ Str s | s <- [
-                                        "-fno-builtin", 
+                                        "-fno-builtin",
                                         "-pie",
                                         "-nostdlib",
                                         "-Wl,--fatal-warnings",
                                         "-Wl,-N",
                                         "-Wl,--build-id=none" ]] ++
                           [ Str "-T", In SrcTree "src" "shim.lds" ],
-             optSuffix = "" 
+             optSuffix = ""
            }
 in
 [
@@ -54,7 +54,7 @@ in
         [ "/kernel/include" ],
     assembleSFiles opts [ "shim.S" ],
     compileCFiles opts [ "cache.c" ],
-    link opts [ "shim.o", "cache.o" ] [] "fvp_shim",
+    link opts [ "shim.o", "cache.o" ] [] [] "fvp_shim",
     copyFile SrcTree "tools" "/tools/fastmodels/bootdebug.py"
                      "tools" "/fastmodels/bootdebug.py"
 ]
index c74b5d6..78b1e2f 100644 (file)
 -- This has to be rather low-level, since elver is indeed a module for
 -- x86_64, but is built for 32-bits, so it's easiest to do this rather
 -- explicitly.
--- 
+--
 let arch = "k1om"
-    opts = (options arch) { 
+    opts = (options arch) {
              optFlags = [ Str s | s <- [ "-fno-builtin",
                                 "-nostdinc",
                                 "-std=c99",
                                 "-m64",
-                                "-fPIC", 
+                                "-fPIC",
                                 "-e startup_32",
                                 "-mno-red-zone",
                                 "-Wa,-march=k1om+noavx",
@@ -60,10 +60,10 @@ let arch = "k1om"
                                NoDep SrcTree "src" "/include/deputy/nodeputy.h" ],
              optIncludes = [ NoDep SrcTree "src" "/include",
                              NoDep SrcTree "src" "/lib/newlib/newlib/libc/include",
-                             NoDep SrcTree "src" "/include/c", 
+                             NoDep SrcTree "src" "/include/c",
                              NoDep SrcTree "src" "/include/arch/k1om",
-                             NoDep SrcTree "src" "/tools/weever",   
-                             NoDep BuildTree arch "/include", 
+                             NoDep SrcTree "src" "/tools/weever",
+                             NoDep BuildTree arch "/include",
                              NoDep SrcTree "src" "/include/arch/x86_64" ],
              optDefines = [],
              optLibs = [],
@@ -76,15 +76,15 @@ let arch = "k1om"
                                  "-m64 ",
                                  "-e startup_32",
                                  "-Wl,--build-id=none" ] ] ++
-                                 [Str "-T", In SrcTree "src" "/tools/weever/linker.lds"], 
-             optSuffix = "_for_weever" 
+                                 [Str "-T", In SrcTree "src" "/tools/weever/linker.lds"],
+             optSuffix = "_for_weever"
            }
     objs = [ objectFilePath opts f | f <- [ "boot.S", "loader.c", "lib.c", "elf64.c" ] ]
-                                            
-in 
+
+in
   [ compileCFiles opts [ "loader.c", "lib.c", "elf64.c" ],
     assembleSFiles opts [ "boot.S" ],
-    link opts objs [] "weever_elf",
+    link opts objs [] [] "weever_elf",
     Rule [ Str Config.k1om_objcopy,
            Str "-O binary",
            Str "-R .note",
@@ -92,4 +92,3 @@ in
            In BuildTree "k1om" "/sbin/weever_elf",
            Out "k1om" "/sbin/weever" ]
   ]
-