aboutsummaryrefslogtreecommitdiff
path: root/documentation/index.xhtml
diff options
context:
space:
mode:
Diffstat (limited to 'documentation/index.xhtml')
-rw-r--r--documentation/index.xhtml970
1 files changed, 970 insertions, 0 deletions
diff --git a/documentation/index.xhtml b/documentation/index.xhtml
new file mode 100644
index 0000000..afc655c
--- /dev/null
+++ b/documentation/index.xhtml
@@ -0,0 +1,970 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+
+<!--
+
+file : documentation/index.xhtml
+author : Boris Kolpackov <boris@codesynthesis.com>
+copyright : Copyright (c) 2004-2010 Code Synthesis Tools CC
+license : GNU FDL v1.2; http://www.codesynthesis.com/licenses/fdl-1.2.txt
+
+-->
+
+<!--
+@@ maybe background code?
+
+@@ describe all feature that appear in the example.
+-->
+
+<head>
+
+ <title>build/documentation</title>
+
+ <meta name="author" content="Boris Kolpackov"/>
+ <meta name="copyright" content="&copy; 2004-2010 Code Synthesis Tools CC"/>
+ <meta name="keywords" content="build,system,make"/>
+ <meta name="description" content="build/documentation"/>
+
+ <link rel="stylesheet" type="text/css" href="default.css"/>
+
+</head>
+
+<body>
+<div id="content">
+<ul class="toc">
+<li><a href="#introduction">Introduction</a></li>
+<li><a href="#fundamentals">Fundamentals</a></li>
+<li><a href="#first_example">First Example</a>
+ <ul>
+ <li><a href="#invocation">Invocation</a></li>
+ <li><a href="#makefiles">Makefiles</a></li>
+ </ul>
+</li>
+<li><a href="#inter_project_dependencies">Inter-Project Dependencies</a></li>
+<li><a href="#administrivia">Administrivia</a>
+ <ul>
+ <li><a href="#license">License</a></li>
+ <li><a href="#bootstrapping">Bootstrapping</a></li>
+ <li><a href="#versioning">Versioning</a></li>
+ </ul>
+</li>
+</ul>
+
+
+<h1><a name="introduction">Introduction</a></h1>
+
+<p>I hear you saying: "Yeah, yeah, another marvelous make
+replacement with built-in support for various compilers, automatic
+dependency scanning, parallel and distributed builds, and XML instead of
+makefiles!" On the contrary, <em>build</em> is a software build system
+that is implemented on top of GNU make. It defines extensible framework for
+translators, delegates most of its tasks to existing tools, and uses GNU
+make syntax for makefiles. <em>Build</em> was designed with the following
+tasks in mind:</p>
+
+<ul class="multiline">
+ <li>configuration</li>
+ <li>building</li>
+ <li>testing</li>
+ <li>installation</li>
+</ul>
+
+<p>As distribution of software in source code is being replaced by
+precompiled package distributions, greater emphasis was placed on
+development-time conveniences. Some of the features of <em>build</em>
+include:</p>
+
+<ul class="multiline">
+ <li>position-independent makefiles</li>
+
+ <li>non-recursive multi-makefile include-based structure</li>
+
+ <li>leaf makefiles are full-fledged GNU makefiles, not just
+ variable definitions</li>
+
+ <li>complete dependency graph</li>
+
+ <li>inter-project dependency tracking</li>
+</ul>
+
+<p>To understand leaf makefiles in this manual you will need basic
+knowledge of how <code>make</code> works. However, inside, <em>build</em>
+uses some of the more advanced features of GNU make including</p>
+
+<ul class="multiline">
+<li>order-only prerequisites</li>
+<li>pattern and target-specific variables</li>
+<li><code>$(call )</code> and <code>$(eval )</code></li>
+<li>different flavors of <code>include</code> directive</li>
+</ul>
+
+<p>If you find usage of some of the <code>make</code> techniques obscure
+in this text you can always consult with the
+<a href="http://www.gnu.org/software/make/manual/make.html">GNU make
+manual</a>.</p>
+
+
+<h1><a name="fundamentals">Fundamentals</a></h1>
+
+<p><em>Build</em> defines a framework in terms of which user makefiles
+are written. Below is the list of fundamental concepts.</p>
+
+<dl class="multiline">
+<dt>Project</dt>
+<dd>is a separately distributable collection of source files. A more
+intuitive way of defining a project would be to say it's what you
+normally assign a version number to (e.g., <code>libhello-0.0.1</code>)
+and package as a tar ball (e.g., <code>libhello-0.0.1.tar.gz</code>).
+A reasonably complex project usually has a hierarchy of sub-directories
+under its root directory.</dd>
+
+<dt>Component</dt>
+<dd>is part of a project for which you would normally write a
+makefile. For example our <code>libhello</code> could consist of
+two components: the library itself and a test driver.</dd>
+
+<dt>Source root</dt>
+<dd>is a root directory of a project. For example, if we unpack our
+<code>libhello-0.0.1.tar.gz</code> to <code>/tmp</code> and end up with
+a directory <code>/tmp/libhello-0.0.1</code> then that would be this
+project's <em>source root</em>.</dd>
+
+<dt>Source base</dt>
+<dd>is a directory of a component in a project. Continuing our example,
+if our <code>libhello</code> project had a subdirectory <code>test</code>
+then the <em>source base</em> of the <code>test</code> component would be
+<code>/tmp/libhello-0.0.1/test</code>. By definition, any <em>source base</em>
+is a sub-directory of a <em>source root</em> for any particular project.</dd>
+
+<dt>Out root</dt>
+<dd>is a root directory of a project's build (or output) hierarchy. This
+directory signifies where generated files for the project will be placed.
+For example, if we decide to build <code>libhello</code> in
+<code>/tmp/libhello-i686-pc-linux-gnu</code> then that would be one of the
+possible <em>out roots</em>.</dd>
+
+<dt>Out base</dt>
+<dd>is a build (or output) directory of a component in a project.
+If we continue our example, the <em>out base</em> for the <code>test</code>
+component would be <code>/tmp/libhello-i686-pc-linux-gnu/test</code>.</dd>
+</dl>
+
+<p>The <em>build</em> runtime defines four <code>make</code> variables that
+correspond to the last four definitions:</p>
+
+<pre class="make">
+src_root
+src_base
+out_root
+out_base
+</pre>
+
+<p>Below is an example of how you could use some of them.</p>
+
+<pre class="make">
+driver := $(out_base)/driver
+
+$(driver): $(out_base)/driver.o $(out_root)/libhello/libhello.so
+</pre>
+
+<p>Additionally, the <em>build</em> framework defines three more
+variables:</p>
+
+<pre class="make">
+bld_root
+scf_root := $(src_root)/build
+dcf_root := $(out_root)/build
+</pre>
+
+<p><code>bld_root</code> is a root directory of the <em>build</em> runtime.
+Normally you would use it to include one of the <em>build</em>'s files.</p>
+
+<p><code>scf_root</code> stands for static configuration root and
+points to a directory where project's static configuration is kept.
+<code>dcf_root</code> stands for dynamic configuration root and
+points to a directory where project's dynamic configuration is kept.
+We will talk more about those two variables later.</p>
+
+<p>Also note that having <code>src_root</code> the same as
+<code>out_root</code> is perfectly valid and indicates that we
+are building in a source directory.</p>
+
+<h1><a name="first_example">First Example</a></h1>
+
+<p>Now we are ready to examine our first simple example. We
+will skip one-file C-based "hello world", however, because it
+is not very practical and there is not much room for improvement.
+Rather we will start from a <code>libhello</code> library, a test
+driver for it and a <code>hello</code> program that uses the library.
+To make our example even more realistic the <code>libhello</code>
+library and the <code>hello</code> program are two separate projects.
+And, did I mention, they are written in C++. See
+<code>examples/cxx/hello</code>.</p>
+
+<h2><a name="invocation">Invocation</a></h2>
+
+<p>Let's first get some user experience without looking into makefiles.
+Suppose we unpacked <em>build</em> source into <code>/tmp/build-0.1.12</code>.
+First let's try to build <code>libhello</code>:</p>
+
+<pre class="term">
+$ cd /tmp/build-0.1.12/examples/cxx/hello/libhello
+$ make
+
+
+configuring 'libhello'
+
+
+
+Please select the C++ compiler you would like to use:
+
+(1) GNU C++ (g++)
+(2) Intel C++ (icc)
+
+[1]: 1
+
+Would you like the C++ compiler to optimize generated code?
+
+[y]: y
+
+Would you like the C++ compiler to generate debug information?
+
+[y]: y
+
+
+configuring 'libhello'
+
+
+
+Please select the default library type:
+
+(1) archive
+(2) shared object
+
+[2]: 2
+
+
+configuring 'libhello'
+
+
+
+Please enter the g++ binary you would like to use, for example 'g++-3.4',
+'/usr/local/bin/g++' or 'distcc g++'. You can use path auto-completion.
+
+[g++]: g++
+
+Please select the optimization level you would like to use:
+
+(1) -O1 [Tries to reduce code size and execution time, without
+ performing any optimizations that take a great deal of
+ compilation time.]
+(2) -O2 [Performs nearly all supported optimizations that do not
+ involve a space-speed tradeoff.]
+(3) -O3 [Optimize even more.]
+(4) -Os [Optimize for size.]
+
+[2]: 2
+c++ /tmp/build-0.1.12/examples/cxx/hello/libhello/libhello/hello.cxx
+ld /tmp/build-0.1.12/examples/cxx/hello/libhello/libhello/hello.l
+c++ /tmp/build-0.1.12/examples/cxx/hello/libhello/test/driver.cxx
+ld /tmp/build-0.1.12/examples/cxx/hello/libhello/test/driver
+</pre>
+
+<p>Here we were presented with a bunch of configuration questions.
+If you have <code>g++</code> in your default path you can just keep
+hitting enter to select defaults. If you would like to see real commands
+that are being executed (useful when something goes wrong) you can
+say <code>make verbose=1</code>.</p>
+
+<p>From the messages above we can deduce that we have built the
+<code>libhello</code> library (<code>hello.l</code>) and the test driver
+for it (<code>test/driver</code>). So far so good. Now let's try to build
+the <code>hello</code> program:</p>
+
+<pre class="term">
+$ cd /tmp/build-0.1.12/examples/cxx/hello/hello
+$ make
+</pre>
+
+<p>Again you will be asked a bunch of questions you have already seen,
+except these two:</p>
+
+<pre class="term">
+Configuring external dependency on 'libhello' for 'hello driver'.
+
+
+Would you like to configure dependency on the installed
+version as opposed to the development build?
+
+[y]: n
+
+Please enter the out_root for 'libhello'.
+
+[]: ../libhello
+
+Please enter the src_root for 'libhello'.
+
+[]: ../libhello
+</pre>
+
+<p>The <code>hello</code> program depends on <code>libhello</code>. Since
+they are distributed as separate projects <code>hello</code> needs to
+know where to look for <code>libhello</code>. That's why user intervention
+is required. The first question is whether we would like to use an installed
+version of <code>libhello</code> as opposed to the not installed build.
+Since we haven't installed <code>libhello</code> the answer is
+<code>no</code>. The next two questions determine where the
+<code>out_root</code> of the build and the <code>src_root</code> of the source
+code are. Since we built <code>libhello</code> in its source directory both
+become <code>/tmp/build-0.1.12/examples/cxx/hello/libhello</code> or
+<code>../libhello</code> if we are in
+<code>/tmp/build-0.1.12/examples/cxx/hello/hello</code>. After answering
+those questions you will see something like this:</p>
+
+<pre class="term">
+c++ /tmp/build-0.1.12/examples/cxx/hello/hello/hello.cxx
+ld /tmp/build-0.1.12/examples/cxx/hello/hello/hello
+</pre>
+
+<p>And that's it.</p>
+
+<p>One of the nice features of <em>build</em> is that you can have several
+builds in separate directories all from the same source base. Suppose we
+would like to build an <code>-O3</code>-optimized statically-linked version
+of <code>hello</code> without debug information:</p>
+
+<pre class="term">
+$ mkdir /tmp/hello-i686-pc-linux-gnu
+$ cd /tmp/hello-i686-pc-linux-gnu
+$ make -f ../build-0.1.12/examples/cxx/hello/hello/makefile
+
+
+configuring 'hello driver'
+
+
+
+Please select the C++ compiler you would like to use:
+
+(1) GNU C++ (g++)
+(2) Intel C++ (icc)
+
+[1]: 1
+
+Would you like the C++ compiler to optimize generated code?
+
+[y]: y
+
+Would you like the C++ compiler to generate debug information?
+
+[y]: n
+
+
+Configuring external dependency on 'libhello' for 'hello driver'.
+
+
+
+Would you like to configure dependency on the installed
+version as opposed to the development build?
+
+[y]: n
+
+Please enter the out_root for 'libhello'.
+
+[]: /tmp/libhello-i686-pc-linux-gnu
+
+Please enter the src_root for 'libhello'.
+
+[]: ../build-0.1.12/examples/cxx/hello/libhello
+
+
+configuring 'hello driver'
+
+
+
+Please enter the g++ binary you would like to use, for example 'g++-3.4',
+'/usr/local/bin/g++' or 'distcc g++'. You can use path auto-completion.
+
+[g++]: g++
+
+Please select the optimization level you would like to use:
+
+(1) -O1 [Tries to reduce code size and execution time, without
+ performing any optimizations that take a great deal of
+ compilation time.]
+(2) -O2 [Performs nearly all supported optimizations that do not
+ involve a space-speed tradeoff.]
+(3) -O3 [Optimize even more.]
+(4) -Os [Optimize for size.]
+
+[2]: 3
+
+
+configuring 'libhello'
+
+
+
+Please select the C++ compiler you would like to use:
+
+(1) GNU C++ (g++)
+(2) Intel C++ (icc)
+
+[1]: 1
+
+Would you like the C++ compiler to optimize generated code?
+
+[y]: y
+
+Would you like the C++ compiler to generate debug information?
+
+[y]: n
+
+
+configuring 'libhello'
+
+
+
+Please select the default library type:
+
+(1) archive
+(2) shared object
+
+[2]: 1
+
+
+configuring 'libhello'
+
+
+
+Please enter the g++ binary you would like to use, for example 'g++-3.4',
+'/usr/local/bin/g++' or 'distcc g++'. You can use path auto-completion.
+
+[g++]: g++
+
+Please select the optimization level you would like to use:
+
+(1) -O1 [Tries to reduce code size and execution time, without
+ performing any optimizations that take a great deal of
+ compilation time.]
+(2) -O2 [Performs nearly all supported optimizations that do not
+ involve a space-speed tradeoff.]
+(3) -O3 [Optimize even more.]
+(4) -Os [Optimize for size.]
+
+[2]: 3
+c++ /tmp/build-0.1.12/examples/cxx/hello/hello/hello.cxx
+c++ /tmp/build-0.1.12/examples/cxx/hello/libhello/libhello/hello.cxx
+ar /tmp/libhello-i686-pc-linux-gnu/libhello/hello.l
+ld /tmp/hello-i686-pc-linux-gnu/hello
+</pre>
+
+<h2><a name="makefiles">Makefiles</a></h2>
+
+<p>Now let's take a look at the makefiles. We will start from the
+makefile for <code>libhello</code> (<code>hello/libhello/libhello/makefile</code>).
+Note, that I removed support for <code>install</code> target for now.</p>
+
+<pre class="make">
+include $(dir $(lastword $(MAKEFILE_LIST)))../build/bootstrap.make
+
+cxx_tun := hello.cxx
+cxx_obj := $(addprefix $(out_base)/,$(cxx_tun:.cxx=.o))
+cxx_od := $(cxx_obj:.o=.o.d)
+
+hello.l := $(out_base)/hello.l
+hello.l.cpp-options := $(out_base)/hello.l.cpp-options
+
+clean := $(out_base)/.clean
+
+
+# Build.
+#
+$(hello.l): $(cxx_obj)
+
+$(cxx_obj): $(hello.l.cpp-options)
+
+$(hello.l.cpp-options): value := -I$(src_root)
+
+$(call -include,$(cxx_od))
+
+
+# Clean.
+#
+.PHONY: $(clean)
+
+$(clean): $(hello.l).clean \
+ $(addsuffix .clean,$(cxx_obj)) \
+ $(hello.l.cpp-options).clean
+
+
+# Aliases.
+#
+ifdef %interactive%
+
+.PHONY: clean
+
+clean: $(clean)
+
+endif
+
+
+# How to.
+#
+$(call include,$(bld_root)/cxx/o-l.make)
+$(call include,$(bld_root)/cxx/cxx-o.make)
+</pre>
+
+<p>Let's examine this file line-by-line:</p>
+
+<pre class="make">
+include $(dir $(lastword $(MAKEFILE_LIST)))../build/bootstrap.make
+</pre>
+
+<p>Every leaf makefile (i.e., one written to build a component) starts from a
+line that looks like this. Its sole purpose is to bootstrap the build system.
+In our case <code>$(dir $(lastword ...))</code> will expand to something
+like</p>
+
+<pre class="make">
+include .../hello/libhello/libhello/../build/bootstrap.make
+</pre>
+
+<p>Let's take a look at <code>libhello/build/bootstrap.make</code>:</p>
+
+<pre class="make">
+project_name := libhello
+include $(dir $(lastword $(MAKEFILE_LIST))).../build/bootstrap.make
+</pre>
+
+<p>The first line just initializes <code>project_name</code> with the name
+of the project. The second line includes the real <code>bootstrap.make</code>.
+See <a href="#bootstrap">Bootstrapping</a> section for more information on
+various ways of bootstrapping the <em>build</em> runtime.</p>
+
+<p>What does <code>bootstrap.make</code> do? Besides other things (which are
+explained as we encounter them) it sets all those <code>*_root</code> and
+<code>*_base</code> variables.</p>
+
+<p>Let's go back to our <code>libhello/makefile</code>. The first line
+should be clear by now so let's move on:</p>
+
+<pre class="make">
+cxx_tun := hello.cxx
+cxx_obj := $(addprefix $(out_base)/,$(cxx_tun:.cxx=.o))
+cxx_od := $(cxx_obj:.o=.o.d)
+</pre>
+
+<p>This should be pretty straightforward: <code>cxx_tun</code> contains
+a list of translation units, <code>cxx_obj</code> contains a list of
+object files that will be produced from those translation units, and
+<code>cxx_od</code> contains a list of automatically generated dependency
+files for those translation units. After expansion these variables could
+contain the following values (note, in this example <code>out_root</code>
+is the same as <code>src_root</code>):</p>
+
+<pre class="make">
+cxx_tun := hello.cxx
+cxx_obj := .../hello/libhello/libhello/hello.o
+cxx_od := .../hello/libhello/libhello/hello.o.d
+</pre>
+
+<p>Next chunk:</p>
+
+<pre class="make">
+hello.l := $(out_base)/hello.l
+hello.l.cpp-options := $(out_base)/hello.l.cpp-options
+
+clean := $(out_base)/.clean
+</pre>
+
+<p><code>hello.l</code> and <code>clean</code> are two variables that
+store names of targets. You are probably wondering what the heck
+is <code>hello.l</code>? This is a library abstraction the build system
+provides to deal (besides other things) with archives/shared objects
+uniformly. A user who builds your project can specify what type of
+library they want without any additional effort from you. I encourage
+you to take a look inside <code>hello.l</code>.</p>
+
+<p><code>hello.l.cpp-options</code> is a bit trickier.
+<code>$(out_base)/hello.l.cpp-options</code> keeps C preprocessor options
+that are required to compile library files as well as any piece of code
+that uses it. Hopefully, it will become clear once you see the rest of
+the makefile.</p>
+
+<p>Let's move on:</p>
+
+<pre class="make">
+# Build.
+#
+$(hello.l): $(cxx_obj)
+
+$(cxx_obj): $(hello.l.cpp-options)
+
+$(hello.l.cpp-options): value := -I$(src_root)
+
+$(call -include,$(cxx_od))
+</pre>
+
+<p>The first line tells us that <code>hello.l</code> is built from object
+files listed in <code>cxx_obj</code>. The second line establishes dependency
+of object files on C preprocessor options - in order to build an object file
+we will need C++ source file and C preprocessor options - quite logical. The
+third line sets target-specific variable <code>value</code> for
+<code>hello.l.cpp-options</code>: that's how <code>hello.l.cpp-options</code>
+gets its content. You may be wondering why do we need to add this
+<code>-I$(src_root)</code>. The first line of <code>hello.cxx
+</code> should clear things up:</p>
+
+<pre class="cxx">
+#include "libhello/hello.hxx"
+</pre>
+
+<p>And finally the fourth line includes auto-generated dependency
+information for each object file. You can think of
+<code>$(call -include )</code> as being equivalent to <code>-include</code>
+directive for now.</p>
+
+
+<p>Next chunk:</p>
+
+<pre class="make">
+.PHONY: $(clean)
+
+$(clean): $(hello.l).clean \
+ $(addsuffix .clean,$(cxx_obj)) \
+ $(hello.l.cpp-options).clean
+</pre>
+
+<p>Let's concentrate on the last line. There we are essentially saying that
+cleaning <code>libhello</code> consists of cleaning the library, object
+files and C preprocessor options. How does this work? It is done using
+pattern rules. Part of the build system that defines how to build say
+<code>%.l</code> also defines how to clean after it: <code>%.l.clean</code>.
+You may want to look into <code>build/cxx/gnu/o-l.make</code> for details.</p>
+
+<p>Moving on:</p>
+
+<pre class="make">
+# Aliases.
+#
+ifdef %interactive%
+
+.PHONY: clean
+
+clean: $(clean)
+
+endif
+</pre>
+
+<p>In this part we are creating a short alias (<code>clean</code>)
+for its long equivalent (<code>$(out_base)/.clean</code>). <code>
+%interactive%</code> is a <em>system variable</em> defined by
+the framework. It is initialized only if current makefile is
+used in interactive mode as opposed to being included.</p>
+
+<p>And finally:</p>
+
+<pre class="make">
+# How to.
+#
+$(call include,$(bld_root)/cxx/o-l.make)
+$(call include,$(bld_root)/cxx/cxx-o.make)
+</pre>
+
+<p>In this makefile fragment we are including parts of the build
+system that actually know <em>how to build</em>. As you might have
+noticed, all the code that we have examined up until now was dealing
+with <em>what to build</em>. <code>o-l.make</code> defines a pattern
+rule to build libraries from object files. <code>cxx-o.make</code>
+defines a pattern rule to build object files from C++ translation units.</p>
+
+<p>And this concludes our examination of the makefile for
+<code>libhello</code>. Next is the test driver(
+<code>hello/libhello/test/makefile</code>):</p>
+
+<pre class="make">
+include $(dir $(lastword $(MAKEFILE_LIST)))../build/bootstrap.make
+
+cxx_tun := driver.cxx
+cxx_obj := $(addprefix $(out_base)/,$(cxx_tun:.cxx=.o))
+cxx_od := $(cxx_obj:.o=.o.d)
+
+hello.l := $(out_root)/libhello/hello.l
+hello.l.cpp-options := $(out_root)/libhello/hello.l.cpp-options
+
+driver := $(out_base)/driver.e
+clean := $(out_base)/.clean
+test := $(out_base)/.test
+
+
+# Build.
+#
+$(driver): $(cxx_obj) $(hello.l)
+
+$(cxx_obj): $(hello.l.cpp-options)
+
+$(call -include,$(cxx_od))
+
+
+# Test.
+#
+.PHONY: $(test)
+
+$(test): $(driver)
+ $&lt;
+
+
+# Clean.
+#
+.PHONY: $(clean)
+
+$(clean): $(driver).clean $(addsuffix .clean,$(cxx_obj))
+
+
+# Aliases.
+#
+ifdef %interactive%
+
+.PHONY: clean test
+
+test: $(test)
+clean: $(clean)
+
+endif
+
+
+# How to.
+#
+$(call include,$(bld_root)/cxx/o-e.make)
+$(call include,$(bld_root)/cxx/cxx-o.make)
+
+
+# Load build information.
+#
+$(call load,$(src_root)/libhello/makefile)
+</pre>
+
+<p>Do you see anything unknown or strange in this makefile? I hope you don't.
+Just to re-iterate, I will remove everything we definitely saw and leave
+only what's new:</p>
+
+<pre class="make">
+hello.l := $(out_root)/libhello/hello.l
+hello.l.cpp-options := $(out_root)/libhello/hello.l.cpp-options
+
+
+# Build.
+#
+$(driver): $(cxx_obj) $(hello.l)
+
+$(cxx_obj): $(hello.l.cpp-options)
+
+
+# Load build information.
+#
+$(call load,$(src_root)/libhello/makefile)
+</pre>
+
+<p>All of what's left deals in one way or the other with linking
+to <code>libhello</code>. The first two lines define variables that
+hold paths to the library and C preprocessor options (since we are in
+the same project we know what those paths are relative to
+<code>out_root</code>/<code>src_root</code>). The third line declares that
+driver consists of object files and should be linked with
+<code>libhello</code>. The next line says that we need C preprocessor options
+to build object files, just like we did for <code>libhello</code>. And finally
+the last line: what does the <code>load</code> function do? The
+<code>load</code> function loads rules and dependency information from the
+makefile specified. Note that it doesn't make variable definitions from that
+makefile available (or, even worse, override ones we set) - only dependencies
+and rules. The major benefit of doing this is in having complete dependency
+information along with the rules in case something gets out of date. If, for
+example, we change something in <code>libhello</code> and then execute
+<code>make</code> in <code>test</code>, <code>make</code> will be able to
+detect that <code>libhello</code> is out of date and will re-build it before
+building the test driver.</p>
+
+<p>Now let's take a look at the makefile from the <code>hello</code> program
+(<code>hello/hello/makefile</code>). Remember that it is a separate project
+(I removed support for <code>install</code> target again):</p>
+
+
+<pre class="make">
+include $(dir $(lastword $(MAKEFILE_LIST)))build/bootstrap.make
+
+cxx_tun := hello.cxx
+cxx_obj := $(addprefix $(out_base)/,$(cxx_tun:.cxx=.o))
+cxx_od := $(cxx_obj:.o=.o.d)
+
+hello.e := $(out_base)/hello.e
+clean := $(out_base)/.clean
+
+# Secure default target.
+#
+$(hello.e):
+
+
+# Import information about libhello.
+#
+$(call import,libhello,l: hello.l,cpp-options: hello.l.cpp-options)
+
+
+# Build.
+#
+$(hello.e): $(cxx_obj) $(hello.l)
+
+$(cxx_obj): $(hello.l.cpp-options)
+
+$(call -include,$(cxx_od))
+
+
+# Clean.
+#
+.PHONY: $(clean)
+
+$(clean): $(hello.e).clean $(addsuffix .clean,$(cxx_obj))
+
+
+# Aliases.
+#
+ifdef %interactive%
+
+.PHONY: clean
+
+clean: $(clean)
+
+endif
+
+
+# How to.
+#
+$(call include,$(bld_root)/cxx/o-e.make)
+$(call include,$(bld_root)/cxx/cxx-o.make)
+</pre>
+
+<p>Again I will remove all the parts that we are familiar with leaving
+only what's new:</p>
+
+<pre class="make">
+# Secure default target.
+#
+$(hello.e):
+
+
+# Import information about libhello.
+#
+$(call import,libhello,l: hello.l,cpp-options: hello.l.cpp-options)
+</pre>
+
+<p>Let's see what's going on here. I will start from the call to
+the <code>import</code> function. It is similar to the <code>load</code>
+function with a few exceptions. First of all, since we are importing
+build information from a separate project we don't know where to look
+for its parts; this will require dynamic configuration. Secondly, we
+have no way to figure out where <code>hello.l</code> and
+<code>hello.l.cpp-options</code> are. Thus we have
+<code>`l: hello.l'</code> and <code>`cpp-options: hello.l.cpp-options'</code>
+which essentially means "initialize variable <code>hello.l</code> with
+the library path and variable <code>hello.l.cpp-options</code> with
+the C preprocessor options file path".</p>
+
+<p>One side effect of the call to <code>import</code> function is the
+potential loss of the default target. Thus, the first line.</p>
+
+<p>The inter-project dependency importing architecture is probably
+the most complicated part of the build system. It will be described
+in a separate section.</p>
+
+<p>This concludes our step-by-step examination. It was not trivial
+but neither is building real software.</p>
+
+<h1><a name="inter_project_dependencies">Inter-Project Dependencies</a></h1>
+
+<p>To be completed.</p>
+
+
+<h1><a name="administrivia">Administrivia</a></h1>
+
+
+<h2><a name="license">License</a></h2>
+
+<p>The <em>build</em> runtime (makefiles, scripts, etc.) is distributed under
+the terms of the <a href="http://www.codesynthesis.com/licenses/gpl-2.txt">GNU General
+Public License, version 2</a>. <em>Build</em> documentation is distributed
+under the terms of the <a href="http://www.codesynthesis.com/licenses/fdl-1.2.txt">GNU
+Free Documentation License, version 1.2</a>.</p>
+
+<p>In particular, this means that any makefile, script, etc., that
+includes, calls, or otherwise links to the <em>build</em> runtime must
+be covered by a GPL-compatible license, should you decide to distribute
+them.</p>
+
+
+<h2><a name="bootstrapping">Bootstrapping</a></h2>
+
+<p>There are two ways to use the build system: your project can embed
+all necessary files or you can require the <em>build</em> runtime to be
+installed. The first approach allows you to make your project self-content,
+modulo other external dependencies it might have. The disadvantage of this
+approach manifests itself when your project participates in a build with
+inter-project dependencies established: your project and the rest of the
+build could use different (and potentially incompatible) versions of the
+runtime. There is no such problem with the second approach.</p>
+
+<p>My advice is to go with the installed <em>build</em> unless you have
+a compelling reason to do otherwise.</p>
+
+<p>When you go with the embedded runtime you can copy all necessary files
+to your project's <code>build/</code> directory. When you use external
+<em>build</em> your <code>build/bootstrap.make</code> might look something
+like this:</p>
+
+<pre class="make">
+project_name := libhello
+include build-0.1/bootstrap.make
+</pre>
+
+<p>How will <code>make</code> find <code>build-0.1/bootstrap.make</code>?
+There are two ways this can happen: you have the runtime installed (e.g.,
+into <code>/usr/local/include</code>) where <code>make</code> will look
+for it by default or you can tell <code>make</code> where to look using
+<code>-I</code> option in the command line or by setting
+<code>MAKEFLAGS</code> environment variable.</p>
+
+<h2><a name="versioning">Versioning</a></h2>
+
+<p><em>Build</em> uses a three-digit versioning scheme: <code>X.Y.Z</code>.
+<code>X</code> is a generation number; it is incremented when a completely
+new design is implemented. <code>Y</code> is an interface version; two
+<em>build</em> runtimes with different <code>Y</code> have incompatible
+interfaces even though the ideology is the same (if ideology changes
+<code>X</code> will most likely be incremented). Additionally, odd
+<code>Y</code> indicates that it's a development release (similar to
+the linux kernel). Finally, <code>Z</code> signifies a release number.
+Releases with the same <code>X.Y</code> have the same interface.</p>
+
+<p>To allow co-existence of several versions of <em>build</em> on the
+same system, the <code>X.Y</code> pair is made part of the path (e.g.,
+<code>/usr/include/build-0.1</code>) thus when you bootstrap the runtime
+(in a project-specific <code>bootstrap.make</code>) you specify interface
+version:</p>
+
+<pre class="make">
+include build-0.1/bootstrap.make
+</pre>
+</div>
+
+
+<div id="docinfo">
+<p>Copyright &copy; 2004-2010 <a href="http://www.codesynthesis.com">Code Synthesis Tools CC</a>.</p>
+
+<div class="terms">
+Permission is granted to copy, distribute and/or modify this document under
+the terms of the <a href="http://www.codesynthesis.com/licenses/fdl-1.2.txt">GNU Free
+Documentation License, version 1.2</a>; with no Invariant Sections, no
+Front-Cover Texts and no Back-Cover Texts.
+</div>
+</div>
+
+</body>
+</html>