diff options
Diffstat (limited to 'documentation/index.xhtml')
-rw-r--r-- | documentation/index.xhtml | 970 |
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="© 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) + $< + + +# 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 © 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> |