aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2016-01-26 15:35:03 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2016-01-26 15:35:03 +0200
commitfaad206158ae66d9e06a37de610676307a9d6868 (patch)
tree18633edb6a002b47320d2a2f769b6306a6c0fcfc
parentf368c5abcf5eaa2231a1e32ba1dcc57ebe0cd03a (diff)
Add initial version of the build2 toolchain introduction
-rw-r--r--doc/.gitignore3
-rw-r--r--doc/intro.cli930
2 files changed, 933 insertions, 0 deletions
diff --git a/doc/.gitignore b/doc/.gitignore
new file mode 100644
index 0000000..88dbecc
--- /dev/null
+++ b/doc/.gitignore
@@ -0,0 +1,3 @@
+build2-toolchain-intro.ps
+build2-toolchain-intro.pdf
+build2-toolchain-intro.xhtml
diff --git a/doc/intro.cli b/doc/intro.cli
new file mode 100644
index 0000000..3a98922
--- /dev/null
+++ b/doc/intro.cli
@@ -0,0 +1,930 @@
+// file : doc/intro.cli
+// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd
+// license : MIT; see accompanying LICENSE file
+
+"\name=build2-toolchain-intro"
+
+// TODO
+//
+// @@ STL christmass egg?
+// @@ link to --verbose
+// @@ links for commands
+// @@ refs to further docs
+// @@ update for Mac OS in INSTALL
+//
+// STYLE
+//
+// @@ letter spacing
+// @@ links in <code> have underline in spaces.
+// @@ section boundary page breaks (<hr class="page-break"/>)
+// @@ when printed, code background is gone, but spaces still there
+
+// NOTES
+//
+// - Maximum <pre> line is 70 characters.
+//
+
+"
+\h|TL;DR|
+
+\
+$ bpkg create -d hello cxx
+created new configuration in /tmp/hello/
+
+$ cd hello
+$ bpkg add https://build2.org/pkg/1/hello/stable
+added repository build2.org/hello/stable
+
+$ bpkg fetch
+fetching build2.org/hello/stable
+2 package(s) in 1 repository(s)
+
+$ bpkg build hello
+build libhello 1.0.0+1 (required by hello)
+build hello 1.0.0
+continue? [Y/n] y
+libhello-1.0.0+1.tar.gz 100% of 1489 B 983 kBps 00m01s
+fetched libhello 1.0.0+1
+unpacked libhello 1.0.0+1
+hello-1.0.0.tar.gz 100% of 1030 B 6882 kBps 00m01s
+fetched hello 1.0.0
+unpacked hello 1.0.0
+configured libhello 1.0.0+1
+configured hello 1.0.0
+c++ hello-1.0.0/cxx{hello}
+c++ libhello-1.0.0+1/hello/cxx{hello}
+ld libhello-1.0.0+1/hello/libso{hello}
+ld hello-1.0.0/exe{hello}
+updated hello 1.0.0
+\
+"
+
+"
+\h|Warning|
+
+The \c{build2} toolchain \c{0.x.y} series are alpha releases. Interfaces
+\i{will} change in backwards-incompatible ways, guaranteed. Currently, it is
+more of a technology preview rather than anything final. But if you want to
+start playing with it, welcome and join the \l{https://lists.build2.org
+mailing list}!
+
+Our approach to developing \c{build2} is to first get the hard parts (like
+auto-generated source code) right before focusing on completeness. In other
+words, we go depth rather than breadth-first. As a result, there are plenty of
+limitations and missing pieces, especially in the build system. The most
+notable ones are:
+
+\ul|
+
+\li|Limited documentation.|
+
+\li|No C compiler rules.|
+
+\li|No support for Windows/VC++.|
+
+\li|No support for parallel builds.|
+
+\li|No support for custom build system rules/modules.|
+
+|
+"
+
+"
+\h|Introduction|
+
+The \c{build2} toolchain is a set of tools designed for building and packaging
+C++ code (though, if it can handle C++ it can handle anything, right?). The
+toolchain currently includes the \i{build system} (\c{build2}), the \i{package
+manager} (\c{bpkg}), and the \i{repository web interface} (\c{brep}). More
+tools, such as the \i{build robot} (\c{bbot}), are in the works. Then there is
+\l{https://cppget.org/ cppget.org} which we hope will become \i{the C++
+package repository}.
+
+The goal of this document is to give a basic idea of what the \c{build2}
+toolchain can do for you so that you can decide if you are interested and want
+to learn more. Further documentation is referenced at the end of this
+introduction.
+
+The \c{build2} toolchain is self-hosted and self-packaged (and, yes, it is on
+\l{https://cppget.org/ cppget.org}). It could then serve as its own example.
+However, before the toolchain can unpack and build itself, we have to bootstrap
+it (that chicken and egg problem again) and this step wouldn't serve our goal
+of quickly learning what \c{build2} is about. So, instead, we will start with a
+customary \i{\"Hello, World!\"} example which you won't yet be able to try
+yourself (but don't worry, complete terminal output will be shown). If at the
+end you find \c{build2} appealing, the next section provides detailed
+bootstrapping and installation instructions (and, yes, you get to run that
+coveted \c{bpkg update bpkg}). Once the \c{build2} installation is complete,
+you can come back to the \i{\"Hello, World!\"} example and try all the steps
+for yourself.
+
+This introduction explores the \i{consumer} side of the \i{\"Hello, World!\"}
+example. That is, we assume that someone was kind enough to create and package
+the \c{libhello} library and the \c{hello} program and we will learn how to
+obtain and build them as well as keep up with their updates. And so, without
+further ado, let's begin.
+
+The first step in using \c{bpkg} is to create a \i{configuration}. A
+configuration is a directory where packages that require similar compile
+settings will be built. You can create as many configurations as you want: for
+different C++ compilers, debug/release, 32/64-bit, or even for different days
+of the week, if you are so inclined. Say we want a GCC 5 release build:
+
+\
+$ mkdir hello-gcc5-release
+$ cd hello-gcc5-release
+$ bpkg create cxx config.cxx=g++-5 config.cxx.coptions=-O3
+created new configuration in /tmp/hello-gcc5-release/
+\
+
+Let's discuss that last command line: \c{create} is the \c{bpkg} command for
+creating a new configuration. As a side note, if you ever want to get help for
+any \c{bpkg} command, run \c{bpkg help <command>}. To see a list of commands,
+run just \c{bpkg help}. While we are at it, if you ever want to see what
+\c{bpkg} is running underneath, there is the \c{-v} option. And if you really
+want to get under the hood, use \c{--verbose <level>}.
+
+After the command we have \c{cxx} which is the name of the \c{build2} build
+system module. As you might have guessed, \c{cxx} provides support for the C++
+compilation. By specifying this module during the configuration creation we
+configure it (yes, with those \c{config.cxx...} variables that follow) for the
+entire configuration. That is, every package that is built in this
+configuration and that uses the \c{cxx} module inherits the settings that we
+just specified.
+
+The rest of the command line are the configuration variables for the \c{cxx}
+module with \c{coptions} standing for \i{compile options} (there are also
+\c{poptions} for \i{preprocess options}, \c{loptions} for \i{link options}, and
+\c{libs} for extra libraries to link).
+
+Ok, configuration in hand, where can we get some packages? \c{bpkg} packages
+come from \i{repositories}. A repository can be a local filesystem directory
+or a remote URL. Our example packages come from their own remote \i{\"Hello,
+World!\"} repository: \c{https://build2.org/pkg/1/hello/stable/} (go ahead,
+browse it, I will wait).
+
+Instead of scouring repository manifests by hand (I know you couldn't resist),
+we can ask \c{bpkg} to interrogate a repository location for us:
+
+\
+$ bpkg rep-info https://build2.org/pkg/1/hello/stable
+build2.org/hello/stable https://build2.org/pkg/1/hello/stable
+hello 1.0.0
+libhello 1.0.0+1
+\
+
+If we want to use a repository as a source of packages in our configuration, we
+have to first add:
+
+\
+$ bpkg add https://build2.org/pkg/1/hello/stable
+added repository build2.org/hello/stable
+\
+
+If we want to add several repositories, we just execute the \c{add} command for
+each of them. Once this is done, we fetch the list of available packages for
+all the added repositories:
+
+\
+$ bpkg fetch
+fetching build2.org/hello/stable
+2 package(s) in 1 repository(s)
+\
+
+You would normally re-run the \c{fetch} command after you've added another
+repository or to refresh the list of available packages.
+
+Now that \c{bpkg} knows where to get packages, we can finally get down to
+business:
+
+\
+$ bpkg build hello
+build libhello 1.0.0+1 (required by hello)
+build hello 1.0.0
+continue? [Y/n]
+\
+
+Let's see what's going on here. We asked \c{bpkg} to build the \c{hello}
+program which happens to depend on the \c{libhello} library. So \c{bpkg}
+presents us with a \i{plan of action} that it will have to perform in order to
+build us \c{hello} and then asks us to confirm that's what we want to do (you
+can add \c{--yes|-y} to skip the confirmation). Let's answer \i{yes} and see
+what happens:
+
+\
+...
+continue? [Y/n] y
+libhello-1.0.0+1.tar.gz 100% of 1489 B 1364 kBps 00m01s
+fetched libhello 1.0.0+1
+unpacked libhello 1.0.0+1
+hello-1.0.0.tar.gz 100% of 1030 B 20 MBps 00m01s
+fetched hello 1.0.0
+unpacked hello 1.0.0
+configured libhello 1.0.0+1
+configured hello 1.0.0
+c++ hello-1.0.0/cxx{hello}
+c++ libhello-1.0.0+1/hello/cxx{hello}
+ld libhello-1.0.0+1/hello/libso{hello}
+ld hello-1.0.0/exe{hello}
+updated hello 1.0.0
+\
+
+While the output is mostly self-explanatory, in short, \c{bpkg} downloaded,
+unpacked, and configured both packages and then proceeded to building the
+\c{hello} executable which happens to require building of the \c{libhello}
+library. Note that the download progress may look differently on your machine
+depending on which \i{fetch tool} (\c{wget}, \c{curl}, or \c{fetch}) is
+used. If you ever considered giving that \c{-v} option a try, now would be good
+time. But let's first drop the \c{hello} package so that we get the same
+build from scratch:
+
+\
+$ bpkg drop hello
+following prerequisite packages were automatically built and will no
+longer be necessary:
+ libhello
+drop prerequisite packages? [Y/n] y
+drop hello
+drop libhello
+continue? [Y/n] y
+disfigured hello
+disfigured libhello
+purged hello
+purged libhello
+\
+
+Ok, ready for some \c{-v} details? Feel free to skip the following listing
+if not interested.
+
+\
+$ bpkg build -v -y hello
+fetching libhello-1.0.0+1.tar.gz from build2.org/hello/stable
+curl ... https://build2.org/pkg/1/hello/stable/libhello-1.0.0+1.tar.gz
+ % Total % Received Average Speed Time Time Time Current
+ Dload Upload Total Spent Left Speed
+100 1489 100 1489 1121 0 0:00:01 0:00:01 --:--:-- 1122
+fetched libhello 1.0.0+1
+tar -xf libhello-1.0.0+1.tar.gz
+unpacked libhello 1.0.0+1
+fetching hello-1.0.0.tar.gz from build2.org/hello/stable
+curl ... https://build2.org/pkg/1/hello/stable/hello-1.0.0.tar.gz
+ % Total % Received Average Speed Time Time Time Current
+ Dload Upload Total Spent Left Speed
+100 1030 100 1030 773 0 0:00:01 0:00:01 --:--:-- 772
+fetched hello 1.0.0
+tar -xf hello-1.0.0.tar.gz
+unpacked hello 1.0.0
+b -v configure(./libhello-1.0.0+1/)
+config::save libhello-1.0.0+1/build/config.build
+configured libhello 1.0.0+1
+b -v configure(./hello-1.0.0/)
+config::save hello-1.0.0/build/config.build
+configured hello 1.0.0
+hold package hello
+b -v update(./hello-1.0.0/)
+g++-5 -Ilibhello-1.0.0+1 -O3 -std=c++11 -o hello-1.0.0/hello.o -c hell
+o-1.0.0/hello.cxx
+g++-5 -Ilibhello-1.0.0+1 -O3 -std=c++11 -fPIC -o libhello-1.0.0+1/hell
+o/hello-so.o -c libhello-1.0.0+1/hello/hello.cxx
+g++-5 -O3 -std=c++11 -shared -o libhello-1.0.0+1/hello/libhello.so
+g++-5 -O3 -std=c++11 -o hello-1.0.0/hello hello-1.0.0/hello.o libhello
+-1.0.0+1/hello/libhello.so
+updated hello 1.0.0
+\
+
+Another handy \c{bpkg} command is \c{status}. It can be used to examine the
+state of a package in the configuration. Here are a few examples (if you
+absolutely must know what \c{hold_package} means, check the
+\l{bpkg-pkg-status(1)} man page):
+
+\
+$ bpkg status libhello
+configured 1.0.0+1
+
+$ bpkg status hello
+configured 1.0.0 hold_package
+
+$ bpkg drop -y hello
+disfigured hello
+disfigured libhello
+purged hello
+purged libhello
+
+$ bpkg status hello
+available 1.0.0
+
+$ bpkg status libfoobar
+unknown
+\
+
+Let's say we got wind of a new development: the \c{libhello} author released a
+new version of the library. It is such an advance in the state of the
+\i{\"Hello, World!\"} art, it's only currently available from \c{testing}. Of
+course, we must check it out.
+
+Now, what exactly is \c{testing}? You must have noticed that the repository
+location that we've been using so far ended with \c{/stable}. Quite often it is
+useful to split our repository into sub-repositories or \i{sections}. For
+example, to reflect the maturity of packages (say, \c{stable} and \c{testing},
+as in our case) or to divide them into sub-categories (\c{misc} and \c{math})
+or even some combination (\c{math/testing}). Note, however, that to \c{bpkg}
+these sub-repositories or \i{sections} are just normal repositories and there
+is nothing special about them.
+
+We are impatient to try the new version so we will skip interrogating the
+repository with \c{rep-info} and just add it to our configuration. After all,
+we can always check with \c{status} if any upgrades are available for packages
+we are interested in. Here we assume the configuration has \c{hello} built (run
+\c{bpkg build -y hello} to get to that state).
+
+\
+$ bpkg add https://build2.org/pkg/1/hello/testing
+added repository build2.org/hello/testing
+
+$ bpkg fetch
+fetching build2.org/hello/stable
+fetching build2.org/hello/testing
+5 package(s) in 2 repository(s)
+
+$ bpkg status libhello
+configured 1.0.0+1; available 1.1.0
+\
+
+Ok, \c{libhello 1.1.0} is now available. How do we upgrade? We can try to build
+\c{hello} again:
+
+\
+$ bpkg build -y hello
+info: dir{hello-1.0.0/} is up to date
+updated hello 1.0.0
+\
+
+Nothing happens. That's because \c{bpkg} will only upgrade (or downgrade) to a
+new version if we explicitly ask it to. As it is now, all dependencies for
+\c{hello} are satisfied and \c{bpkg} is happy to twiddle its thumbs. Let's tell
+\c{bpkg} to build us \c{libhello} instead:
+
+\
+$ bpkg build libhello
+build libformat 1.0.0 (required by libhello)
+build libprint 1.0.0 (required by libhello)
+upgrade libhello 1.1.0
+reconfigure hello (required by libhello)
+continue? [Y/n]
+\
+
+Ok, now we are getting somewhere. It looks like the new version of \c{libhello}
+went really enterprise-grade (or is it called web-scale these days?). There are
+now two new dependencies (\c{libformat} and \c{libprint}) that we will have to
+build in order to upgrade. Maybe we should answer \i{no} here?
+
+Notice also that \c{reconfigure hello} line. If you think about this, it makes
+sense: we are getting a new version of \c{libhello} and \c{hello} depends on it
+so it might need a chance to make some adjustments to its configuration.
+
+Let's answer \i{yes} if only to see what happens:
+
+\
+...
+continue? [Y/n] y
+disfigured hello 1.0.0
+disfigured libhello 1.0.0+1
+libformat-1.0.0.tar.gz 100% of 1064 B 11 MBps 00m01s
+fetched libformat 1.0.0
+unpacked libformat 1.0.0
+libprint-1.0.0.tar.gz 100% of 1040 B 9 MBps 00m01s
+fetched libprint 1.0.0
+unpacked libprint 1.0.0
+libhello-1.1.0.tar.gz 100% of 1564 B 4672 kBps 00m01s
+fetched libhello 1.1.0
+unpacked libhello 1.1.0
+configured libformat 1.0.0
+configured libprint 1.0.0
+configured libhello 1.1.0
+configured hello 1.0.0
+c++ libhello-1.1.0/hello/cxx{hello}
+c++ libformat-1.0.0/format/cxx{format}
+ld libformat-1.0.0/format/liba{format}
+c++ libprint-1.0.0/print/cxx{print}
+ld libprint-1.0.0/print/liba{print}
+ld libhello-1.1.0/hello/liba{hello}
+c++ libhello-1.1.0/hello/cxx{hello}
+c++ libformat-1.0.0/format/cxx{format}
+ld libformat-1.0.0/format/libso{format}
+c++ libprint-1.0.0/print/cxx{print}
+ld libprint-1.0.0/print/libso{print}
+ld libhello-1.1.0/hello/libso{hello}
+c++ libhello-1.1.0/tests/test/cxx{driver}
+ld libhello-1.1.0/tests/test/exe{driver}
+updated libhello 1.1.0
+\
+
+If you paid really close attention, you might have noticed something
+surprising: the \c{hello} package wasn't \i{updated}. Yes, it was reconfigured,
+but we didn't see any compile or link commands for this project. In fact,
+\c{hello} is now pretty \i{out-of-date}.
+
+While it may seem surprising, \c{bpkg} doesn't try to keep your packages
+\i{up-to-date}. Configured \- yes, but not up-to-date. Trying to guarantee
+up-to-date-ness of packages is in the end futile. For example, if you upgrade
+your compiler or system headers, \c{bpkg} has no way of realizing that some
+packages are now out-of-date. Only the build system, which has the complete
+information about all the dependencies, can make such a realization (and
+correct it).
+
+But it is easy to make sure a package is up-to-date at any given time with
+the \c{bpkg update} command (there is also \c{clean}), for example:
+
+\
+$ bpkg update hello
+c++ hello-1.0.0/cxx{hello.cxx}
+ld hello-1.0.0/exe{hello}
+updated hello 1.0.0
+\
+
+Let's say we really don't like the direction \c{libhello} is going and would
+rather stick to version \c{1.0.0}. Just like upgrades, downgrades are
+explicit except in this case we need to specify the version (you
+can also specify the version for upgrades, in case you are wondering).
+
+\
+$ bpkg build libhello/1.0.0 hello
+downgrade libhello 1.0.0+1
+reconfigure/build hello 1.0.0
+continue? [Y/n] y
+disfigured hello 1.0.0
+disfigured libhello 1.1.0
+libhello-1.0.0+1.tar.gz 100% of 1489 B 983 kBps 00m01s
+fetched libhello 1.0.0+1
+unpacked libhello 1.0.0+1
+configured libhello 1.0.0+1
+configured hello 1.0.0
+c++ libhello-1.0.0+1/hello/cxx{hello}
+ld libhello-1.0.0+1/hello/liba{hello}
+c++ libhello-1.0.0+1/hello/cxx{hello}
+ld libhello-1.0.0+1/hello/libso{hello}
+c++ libhello-1.0.0+1/tests/test/cxx{driver}
+ld libhello-1.0.0+1/tests/test/exe{driver}
+updated libhello 1.0.0+1
+c++ hello-1.0.0/cxx{hello}
+ld hello-1.0.0/exe{hello}
+updated hello 1.0.0
+\
+
+Notice how this time we updated \c{hello} as part of \c{libhello} downgrade \-
+yes, you can do that. Perhaps there should be an option to automatically update
+all the dependents?
+
+Ok, so all this might look nice and all, but we haven't actually seen anything
+of what we've presumably built (it can all be a charade, for all we know). Can
+we see some libraries and run the \c{hello} program?
+
+There are several ways we can do this. If the package provides tests (as all
+good packages should), we can run them with the \c{bpkg test} command:
+
+\
+$ bpkg test libhello hello
+test libhello-1.0.0+1/tests/test/exe{driver}
+test hello-1.0.0/exe{hello}
+tested libhello 1.0.0+1
+tested hello 1.0.0
+\
+
+But that doesn't quite count for seeing libraries and running programs. Well,
+if you insist, let's see what's inside \c{hello-gcc5-release/}. The \c{bpkg}
+configuration (this \c{hello-gcc5-release/} directory) is, in the \c{build2}
+build system terms, an \i{amalgamation} \- a project that contains
+\i{subprojects}. Not surprisingly, the subprojects in this amalgamation are the
+packages that we've built:
+
+\
+$ ls -1F
+build/
+hello-1.0.0/
+libhello-1.0.0+1/
+bpkg.sqlite3
+buildfile
+hello-1.0.0.tar.gz
+libhello-1.0.0+1.tar.gz
+\
+
+And if we look inside \c{hello-1.0.0/} we will see what looks like the
+\c{hello} program:
+
+\
+$ ls -1F hello-1.0.0/
+build/
+buildfile
+hello*
+hello.cxx
+hello.o
+manifest
+test.out
+version
+
+$ hello-1.0.0/hello
+usage: hello <name>...
+
+$ hello-1.0.0/hello World
+Hello, World!
+\
+
+The important point here is that the \c{bpkg} configuration is not some black
+box that you should never look inside. On the contrary, it is a normal building
+block of the build system and if you understand what you are doing, feel free
+to muck around. Now, confess, did you run \c{sqlite3 bpkg.sqlite3 .dump}?
+
+Another way to get hold of a package's goodies is to install it. Let's try
+that:
+
+\
+$ bpkg install config.install.root=/opt/hello \
+config.install.root.sudo=sudo hello
+install /opt/hello/
+install /opt/hello/include/hello/
+install libhello-1.0.0+1/hello/hxx{hello}
+install /opt/hello/lib/
+install libhello-1.0.0+1/hello/libso{hello}
+install /opt/hello/bin/
+install hello-1.0.0/exe{hello}
+install /opt/hello/share/doc/hello/
+install hello-1.0.0/doc{version}
+installed hello 1.0.0
+
+$ tree -F /opt/hello/
+/opt/hello/
+├── bin/
+│ └── hello*
+├── include/
+│ └── hello/
+│ └── hello
+├── lib/
+│ └── libhello.so*
+└── share/
+ └── doc/
+ └── hello/
+ └── version
+
+$ /opt/hello/bin/hello World
+Hello, World!
+\
+
+The \c{config.install.root.sudo} value is the optional \i{sudo}-like program
+that should be used to run the \c{install} commands. For those feeling queasy
+running \c{sudo make install}, here is your answer. If you are wondering
+whether you could have specified those \c{config.install.*} values during the
+configuration creation, the answer is yes, indeed!
+
+What if we wanted to use \c{libhello} in our own project? While the installed
+version is always an option, it may not be convenient when we develop our code.
+We may have multiple builds per project, for example, with GCC and Clang to
+catch all the warnings. We may also want to make sure our application works
+well with various versions of \c{libhello} (and maybe even with that heinous
+\c{1.1.0}). While we can install different configurations into different
+directories, it's hard to deny things are getting a bit hairy: multiple
+configurations, multiple installations... I guess we will have to get our hands
+into that cookie jar, I mean, configuration, again.
+
+In fact, let's just start writing our own version of the \c{hello} program
+and see how it goes:
+
+\
+$ mkdir hello2
+$ cd hello2
+
+$ cat >hello.cpp
+
+#include <hello/hello>
+
+int main ()
+{
+ hello::say (\"World\");
+}
+
+\
+
+What build system will we use? I can't believe you are even asking!
+
+\
+$ mkdir build
+
+$ cat >build/bootstrap.build
+
+project = hello2 # project name
+using config # config module (those config.*)
+
+$ cat >build/root.build
+
+using cxx # c++ module
+cxx{*}: extension = cpp # c++ source file extension
+cxx.std = 11 # c++ standard
+
+$ cat >buildfile
+
+import libs = libhello%lib{hello}
+exe{hello}: cxx{hello} $libs
+
+\
+
+While some of this might not be crystal clear (like why do we have
+\c{bootstrap.build} \i{and} \c{root.build}), I am sure you at least have a
+fuzzy idea of what's going on. And that's enough for what we are after here.
+Completely explaining what's going on here and, more importantly, why it's
+going this way is for another time and place (the \c{build2} build system
+manual).
+
+To recap, these are the contents of our project so far:
+
+\
+$ tree -F
+.
+├── build/
+│   ├── bootstrap.build
+│   └── root.build
+├── buildfile
+└── hello.cpp
+\
+
+Let's try to build it and see what happens \- maybe it will magically work
+(\c{b} is for \c{build2} build system).
+
+\
+$ b
+test g++
+error: unable to import target libhello%lib{hello}
+ info: consider explicitly specifying its project out_root via the
+ config.import.libhello command line variable
+info: while applying rule cxx.compile to update obja{hello}
+info: while applying rule cxx.link to update exe{hello}
+info: while applying rule alias to update dir{./}
+\
+
+No magic but we got a hint: looks like we need to tell \c{build2} where
+\c{libhello} is with \c{config.import.libhello}. Without fretting too much
+about what exactly \c{out_root} means, let's point \c{build2} to our \c{bpkg}
+configuration and see what happens.
+
+\
+$ b config.import.libhello=/tmp/hello-gcc5-release
+test g++
+c++ cxx{hello}
+ld exe{hello}
+\
+
+Almost magic. Let's see what we've got:
+
+\
+$ tree -F
+.
+├── build/
+│   ├── bootstrap.build
+│   └── root.build
+├── buildfile
+├── hello*
+├── hello.cpp
+└── hello.o
+
+$ ./hello
+Hello, World!
+\
+
+Let's change something in our source code and try to update:
+
+\
+$ touch hello.cpp
+
+$ b
+test g++
+error: unable to import target libhello%lib{hello}
+ info: consider explicitly specifying its project out_root via the
+ config.import.libhello command line variable
+info: while applying rule cxx.compile to update obja{hello}
+info: while applying rule cxx.link to update exe{hello}
+info: while applying rule alias to update dir{./}
+\
+
+Looks like we have to keep repeating that \c{config.import.libhello} and who
+wants that? Also, the \c{test g++} line is kind of annoying. To get rid of both
+we have to make our configuration \i{permanent}. Also, seeing that we plan to
+have several of them (GCC/Clang, different version of \c{libhello}), it makes
+sense to create them \i{out of source tree}. Let's get to it.
+
+\
+$ cd ..
+$ mkdir hello2-gcc5-release
+$ ls -1F
+hello2/
+hello2-gcc5-release/
+
+$ b config.cxx=g++-5 config.cxx.coptions=-O3 \
+config.import.libhello=/tmp/hello-gcc5-release \
+'configure(hello2/@hello2-gcc5-release/)'
+test g++-5
+mkdir hello2-gcc5-release/build/
+mkdir hello2-gcc5-release/build/bootstrap/
+save hello2-gcc5-release/build/bootstrap/src-root.build
+save hello2-gcc5-release/build/config.build
+\
+
+Translated, \c{configure(hello2/@hello2-gcc5-release/)} means \i{\"configure
+the \c{hello2/} source directory in the \c{hello2-gcc5-release/} output
+directory\"}. In \c{build2} this \i{source directory} is called \c{src_root}
+and \i{output directory} \- \c{out_root}. Hm, we've already seen \c{out_root}
+mentioned somewhere before...
+
+Once the configuration is saved, we can develop our project without any
+hindrance:
+
+\
+$ b hello2-gcc5-release/
+c++ hello2/cxx{hello}
+ld hello2-gcc5-release/exe{hello}
+
+$ cd hello2-gcc5-release/
+
+$ b
+info: dir{./} is up to date
+
+$ b clean
+rm exe{hello}
+rm obja{hello}
+
+$ b -v
+g++-5 -I/tmp/hello-gcc5-release/libhello-1.0.0+1 -O3 -std=c++11 -o hel
+lo.o -c ../hello2/hello.cpp
+g++-5 -O3 -std=c++11 -o hello hello.o /tmp/hello-gcc5-release/libhello
+-1.0.0+1/hello/libhello.so
+\
+
+Some of you might have noticed that \c{hello2-gcc5-release/} and
+\c{/tmp/hello-gcc5-release/} are awfully similar and are now wondering if we
+could instead build \c{hello2} \i{inside} \c{/tmp/hello-gcc5-release/}? I am
+glad you've asked. In fact, we can just do:
+
+\
+$ cd ..
+$ ls -1F
+hello2/
+hello2-gcc5-release/
+
+$ b 'configure(hello2/@/tmp/hello-gcc5-release/hello2/)'
+mkdir -p /tmp/hello-gcc5-release/hello2/
+mkdir /tmp/hello-gcc5-release/hello2/build/
+mkdir /tmp/hello-gcc5-release/hello2/build/bootstrap/
+save /tmp/hello-gcc5-release/hello2/build/bootstrap/src-root.build
+save /tmp/hello-gcc5-release/hello2/build/config.build
+
+$ b /tmp/hello-gcc5-release/hello2/
+c++ hello2/cxx{hello}
+ld /tmp/hello-gcc5-release/hello2/exe{hello}
+\
+
+Now that might seem like magic, but it's actually pretty logical. Why don't we
+need to specify any of the \c{config.cxx} values this time? Because they are
+inherited from the set specified for \c{/tmp/hello-gcc5-release} when we
+created the configuration with \c{bpkg create}. What about
+\c{config.import.libhello}, don't we need at least that? Nope, \c{libhello}
+will be found automatically since it is part of the same amalgamation as we
+are.
+
+Of course, \c{bpkg} has no idea \c{hello2} is now part of its configuration:
+
+\
+$ bpkg status -d /tmp/hello-gcc5-release/ hello2
+unknown
+\
+
+This is what I meant when I said you can muck around in \c{bpkg}'s back yard as
+long as you understand the implications.
+
+But is there a way to make \c{bpkg} aware of our little project? You seem to
+really have all the right questions today. Actually, there is a very good
+reason why we would want that: if we upgrade \c{libhello} we would want
+\c{bpkg} to automatically reconfigure our project. As it is now, we will have
+to remember and do it ourselves.
+
+The only way to make \c{bpkg} aware of \c{hello2} is to turn it from a
+\c{build2} \i{project} into a \c{build2} \i{package}. While the topic of
+packaging is also for another time and place (the \c{build2} package manager
+manual), we can get away with something as simple as this:
+
+\
+$ cat >hello2/manifest
+: 1
+name: hello2
+version: 1.0.0
+summary: Improved \"Hello World\" program
+license: proprietary
+url: http://example.org/hello2
+email: hello2@example.org
+depends: libhello >= 1.0.0
+\
+
+For our purposes, the only really important value in this manifest is
+\c{depends} since it tells \c{bpkg} which package(s) we need. Let's give it a
+try. But first we will clean up our previous attempt at building \c{hello2}
+inside \c{/tmp/hello-gcc5-release/}:
+
+\
+$ b '{clean disfigure}(/tmp/hello-gcc5-release/hello2/)'
+rm /tmp/hello-gcc5-release/hello2/exe{hello}
+rm /tmp/hello-gcc5-release/hello2/obja{hello}
+rm /tmp/hello-gcc5-release/hello2/build/config.build
+rm /tmp/hello-gcc5-release/hello2/build/bootstrap/src-root.build
+rmdir /tmp/hello-gcc5-release/hello2/build/bootstrap/
+rmdir /tmp/hello-gcc5-release/hello2/build/
+rmdir /tmp/hello-gcc5-release/hello2/
+\
+
+Next, we use the \c{bpkg build} command but instead of giving it a package name
+like we did before, we will point it to our \c{hello2} package directory:
+
+\
+$ bpkg build -d /tmp/hello-gcc5-release/ ./hello2/
+build hello2 1.0.0
+continue? [Y/n] y
+unpacked hello2 1.0.0
+configured hello2 1.0.0
+c++ hello2/cxx{hello}
+ld /tmp/hello-gcc5-release/hello2-1.0.0/exe{hello}
+updated hello2 1.0.0
+\
+
+Let's upgrade \c{libhello} and see what happens:
+
+\
+$ bpkg build -d /tmp/hello-gcc5-release/ libhello
+upgrade libhello 1.1.0
+reconfigure hello2 (required by libhello)
+continue? [Y/n] y
+disfigured hello2 1.0.0
+disfigured libhello 1.0.0+1
+unpacked libhello 1.1.0
+configured libhello 1.1.0
+configured hello2 1.0.0
+mkdir fsdir{/tmp/hello-gcc5-release/libhello-1.1.0/hello/}
+c++ libhello/hello/cxx{hello}
+ld /tmp/hello-gcc5-release/libhello-1.1.0/hello/liba{hello}
+c++ libhello/hello/cxx{hello}
+ld /tmp/hello-gcc5-release/libhello-1.1.0/hello/libso{hello}
+updated libhello 1.1.0
+\
+
+As promised, \c{hello2} got reconfigured. We can now update it and give it a
+try:
+
+\
+$ bpkg update -d /tmp/hello-gcc5-release/ hello2
+c++ hello2/cxx{hello}
+ld /tmp/hello-gcc5-release/hello2-1.0.0/exe{hello}
+updated hello2 1.0.0
+
+$ /tmp/hello-gcc5-release/hello2-1.0.0/hello
+Hello, World!
+\
+
+To finish off, let's see how hard it will be to get a Clang build going:
+
+\
+$ cd /tmp
+$ mkdir hello-clang36-release
+$ cd hello-clang36-release
+
+$ bpkg create cxx config.cxx=clang++-3.6 config.cxx.coptions=-O3
+created new configuration in /tmp/hello-clang36-release/
+
+$ bpkg add https://build2.org/pkg/1/hello/testing
+added repository build2.org/hello/testing
+
+$ bpkg fetch
+fetching build2.org/hello/testing
+fetching build2.org/hello/stable (complements build2.org/hello/testing)
+5 package(s) in 2 repository(s)
+
+$ bpkg build libhello/1.0.0 .../hello2/
+build libhello 1.0.0+1
+build hello2 1.0.0
+continue? [Y/n] y
+libhello-1.0.0+1.tar.gz 100% of 1489 B 983 kBps 00m01s
+fetched libhello 1.0.0+1
+unpacked libhello 1.0.0+1
+unpacked hello2 1.0.0
+configured libhello 1.0.0+1
+configured hello2 1.0.0
+c++ libhello-1.0.0+1/hello/cxx{hello}
+ld libhello-1.0.0+1/hello/liba{hello}
+c++ libhello-1.0.0+1/hello/cxx{hello}
+ld libhello-1.0.0+1/hello/libso{hello}
+c++ libhello-1.0.0+1/tests/test/cxx{driver}
+ld libhello-1.0.0+1/tests/test/exe{driver}
+updated libhello 1.0.0+1
+c++ ~/work/build2/hello/hello2/cxx{hello}
+ld hello2-1.0.0/exe{hello}
+updated hello2 1.0.0
+\
+"
+
+"
+\h|Installation|
+"
+source "../INSTALL.cli";