aboutsummaryrefslogtreecommitdiff
path: root/doc/intro1.cli
diff options
context:
space:
mode:
Diffstat (limited to 'doc/intro1.cli')
-rw-r--r--doc/intro1.cli1169
1 files changed, 1169 insertions, 0 deletions
diff --git a/doc/intro1.cli b/doc/intro1.cli
new file mode 100644
index 0000000..f53544d
--- /dev/null
+++ b/doc/intro1.cli
@@ -0,0 +1,1169 @@
+// file : doc/intro1.cli
+// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd
+// license : MIT; see accompanying LICENSE file
+
+"\name=build2-toolchain-intro"
+"\subject=toolchain"
+"\title=Toolchain Introduction"
+
+// TODO
+//
+// @@ refs to further docs
+//
+// STYLE
+//
+// @@ section boundary page breaks (<hr class="page-break"/>)
+// @@ when printed, code background is gone, but spaces still there
+//
+// PDF
+//
+// @@ tree output is garbled
+// @@ Install list margins missing
+// @@ Could we use a nicer font, seeing that we embed them?
+//
+
+// NOTES
+//
+// - Maximum <pre> line is 70 characters.
+//
+
+"
+\h#tldr|TL;DR|
+
+\
+$ bpkg create -d hello cc
+created new configuration in 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 (required by hello)
+ build hello/1.0.0
+continue? [Y/n] y
+
+libhello-1.0.0.tar.gz 100% of 2428 B 983 kBps 00m01s
+fetched libhello/1.0.0
+unpacked libhello/1.0.0
+
+hello-1.0.0.tar.gz 100% of 1057 B 6882 kBps 00m01s
+fetched hello/1.0.0
+unpacked hello/1.0.0
+
+configured libhello/1.0.0
+configured hello/1.0.0
+
+c++ hello-1.0.0/cxx{hello}
+c++ libhello-1.0.0/hello/cxx{hello}
+ld libhello-1.0.0/hello/libs{hello}
+ld hello-1.0.0/exe{hello}
+
+updated hello/1.0.0
+\
+"
+
+"
+\h#warning|Warning|
+
+The \c{build2} toolchain \c{0.X.Y} series are alpha releases. Interfaces
+\i{will} most likely change in backwards-incompatible ways. 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 right
+before focusing on completeness. So while we might still have no support for
+custom build rules, we do handle auto-generated source code (and, in
+particular, headers) properly. In other words, we go depth rather than
+breadth-first. As a result, there are some limitations and missing pieces,
+especially in the build system. The most notable ones are:
+
+\ul|
+
+\li|Limited documentation.|
+
+\li|No support for custom build system rules/modules.|
+
+|
+"
+
+"
+\h#intro|Introduction|
+
+The \c{build2} toolchain is a set of tools designed for building and packaging
+C and 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} (running \c{brep})
+which we hope will become \i{the C++ package repository}.
+
+The goal of this document is to give you a basic idea of what the \c{build2}
+toolchain can do 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 have served as its own example,
+however, before the toolchain can 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, you can jump straight to
+\l{build2-toolchain-install.xhtml The \c{build2} Toolchain Installation and
+Upgrade} (and, yes, there you get to run that coveted \c{bpkg build bpkg}).
+Once the \c{build2} installation is complete, you can come back to the
+\i{\"Hello, World!\"} example and try all of the steps for yourself.
+
+This introduction explores the \i{consumer} side of \i{\"Hello, World!\"}.
+That is, we assume that someone was kind enough to create and package the
+\c{libhello} library as well as the \c{hello} program and we will learn how to
+obtain and build them as well as keep up with their updates. At the end we
+will also see how to write our own, \c{hello2}, program that depends on
+\c{libhello}. And so, without further ado, let's begin.
+
+Actually, one more thing: if you have a recent enough compiler and would like
+to try the new C++ Modules support, then you can instead use the modularized
+variants of these packages: simply replace \c{hello} with \c{mhello} and
+\c{libhello} with \c{libmhello} in the commands below.
+
+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, targets (\c{build2} is big on cross-compiling),
+debug/release, 32/64-bit, or even for different days of the week, if you are
+so inclined. Say we are in the mood for a GCC 5 release build today:
+
+\
+$ 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/
+\
+
+Or perhaps you are on Windows and prefer Visual Studio (running from the
+Visual Studio Tools Command Prompt):
+
+\
+> mkdir hello-vc14-release
+> cd hello-vc14-release
+> bpkg create cxx config.cxx=cl config.cxx.coptions=/O2
+created new configuration in C:\projects\hello-vc14-release\
+\
+
+One of the primary goals of the \c{build2} toolchain is to provide a uniform
+build interface across all the platforms and compilers. While the following
+examples use the \c{hello-gcc5-release} configuration and assume a UNIX-like
+operation system, everything will work if you use \c{hello-vc14-release} (or
+\c{hello-mingw-release}) on Windows. Just use appropriate paths, compilers,
+and options.
+
+Let's discuss that last command line: \l{bpkg-cfg-create(1) \c{bpkg create}}
+is the 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 \i{<command>}}. To
+see the list of commands, run just \l{bpkg-help(1) \c{bpkg help}} (or see
+\l{bpkg(1)}). While we are at it, if you ever want to see what \c{bpkg} is
+running underneath, there is the \c{-v} (essential commands) and \c{-V} (all
+commands) options. And if you really want to get under the hood, use
+\l{bpkg-common-options(1) \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 when creating the configuration we
+configure it (yes, with those \c{config.cxx.*} variables that follow) for the
+entire configuration. That is, every package that we will build in this
+configuration and that uses the \c{cxx} module will by default inherit these
+settings.
+
+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).
+
+There is also the \c{c} module for the C compilation. So if we were planning
+to build both C and C++ projects, then we could have run:
+
+\
+$ bpkg create c cxx ...
+\
+
+The problem, of course, is that you may not know what mix of languages those
+projects (or their dependencies) might use. For example, the use of C might be
+an implementation detail of a C++ library. To solve this, \c{build2} provides
+another module called \c{cc} which stands for \i{C-common}. So, in this
+context, instead of using the \c{c} and \c{cxx} modules directly, it's a good
+idea to get into the habit of using \c{cc}:
+
+\
+$ bpkg create cc config.cxx=g++-5 config.cc.coptions=-O3
+\
+
+Notice two things about this command line: we don't need to specify the C
+compiler with \c{config.c} \- \c{build2} is smart enough to figure it out
+from \c{config.cxx} (or vice versa). We also used \c{config.cc.coptions}
+instead of \c{config.cxx.coptions} so that the options apply to all the
+C-common languages (we can still use \c{config.{c,cxx\}.*} for the
+language-specific options).
+
+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{\l{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
+warning: authenticity of the certificate for repository build2.org/hello/stable cannot be established
+certificate is for build2.org, \"Code Synthesis\" <admin@build2.org>
+certificate SHA256 fingerprint:
+FF:DF:7D:38:67:4E:C3:82:[...]:30:56:B9:77:B9:F2:01:94
+trust this certificate? [y/n]
+\
+
+The \c{bpkg} repositories are normally signed to prevent tampering with
+packages. If the repository certificate is seen (in this configuration) for
+the first time, \c{bpkg} will ask you to authenticate it. A good way to
+authenticate a certificate is to compare the displayed fingerprint to the one
+you have received earlier, for example, in an email announcement. The
+repository's about page also lists the fingerprint (see the
+\l{https://build2.org/pkg/hello/?about about page} for our repository). For
+more details on repository signing see the \l{bpkg-repository-signing(1)} help
+topic.
+
+If we answer \i{yes}, we will see the basic repository information (its
+\i{canonical name}, location, certificate subject and fingerprint) followed
+by the list of available packages:
+
+\
+build2.org/hello/stable https://build2.org/pkg/1/hello/stable
+CN=build2.org/O=Code Synthesis/admin@build2.org
+FF:DF:7D:38:67:4E:C3:82:[...]:30:56:B9:77:B9:F2:01:94
+
+hello/1.0.0
+libhello/1.0.0
+\
+
+We can also use the repository's web interface (implemented by \c{brep}). Our
+repository has one, check it out: \c{\l{https://build2.org/pkg/hello/}}.
+
+Ok, back to the command line. If we want to use a repository as a source of
+packages in our configuration, we have to first add it:
+
+\
+$ 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 \l{bpkg-rep-add(1)
+\c{bpkg 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)
+\
+
+Note that you would normally re-run the \l{bpkg-rep-fetch(1) \c{bpkg fetch}}
+command after you've added another repository or to refresh the list of
+available packages.
+
+Now that \c{bpkg} knows where to get the packages, we can finally get down to
+business:
+
+\
+$ bpkg build hello
+ build libhello/1.0.0 (required by hello)
+ build hello/1.0.0
+continue? [Y/n]
+\
+
+Let's see what's going on here. We ran \l{bpkg-pkg-build(1) \c{bpkg build}} 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 is, the steps
+it will have to perform in order to build us \c{hello} and then asks us to
+confirm if that's what we want to do (you can add \c{--yes|-y} to skip the
+confirmation). In the real-world usage the plan will be more complex, with
+upgrades/downgrades, reconfigurations, etc.
+
+Let's answer \i{yes} and see what happens:
+
+\
+libhello-1.0.0.tar.gz 100% of 2428 B 1364 kBps 00m01s
+fetched libhello/1.0.0
+unpacked libhello/1.0.0
+hello-1.0.0.tar.gz 100% of 1057 B 20 MBps 00m01s
+fetched hello/1.0.0
+unpacked hello/1.0.0
+configured libhello/1.0.0
+configured hello/1.0.0
+c++ hello-1.0.0/cxx{hello}
+c++ libhello-1.0.0/hello/cxx{hello}
+ld libhello-1.0.0/hello/libs{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 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 a
+good time. But let's first drop (\l{bpkg-pkg-drop(1) \c{bpkg 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 you are not interested.
+
+\
+$ bpkg build -v -y hello
+fetching libhello-1.0.0.tar.gz from build2.org/hello/stable
+curl ... https://build2.org/pkg/1/hello/stable/libhello-1.0.0.tar.gz
+ % Total % Received Average Speed Time Time Time Current
+ Dload Upload Total Spent Left Speed
+100 2428 100 2428 1121 0 0:00:01 0:00:01 --:--:-- 1122
+fetched libhello/1.0.0
+tar -xf libhello-1.0.0.tar.gz
+unpacked libhello/1.0.0
+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 1057 100 1057 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/)
+cat >libhello-1.0.0/build/config.build
+configured libhello/1.0.0
+b -v configure(./hello-1.0.0/)
+cat >hello-1.0.0/build/config.build
+configured hello/1.0.0
+hold package hello
+b -v update(./hello-1.0.0/)
+g++-5 -I libhello-1.0.0 -O3 -std=c++11 -o hello-1.0.0/hello.o -c hello-1.0.0/hello.cxx
+g++-5 -I libhello-1.0.0 -O3 -std=c++11 -fPIC -o libhello-1.0.0/hello/hello.so.o -c libhello-1.0.0/hello/hello.cxx
+g++-5 -O3 -std=c++11 -shared -o libhello-1.0.0/hello/libhello-1.0.so libhello-1.0.0/hello/hello.so.o
+g++-5 -O3 -std=c++11 -o hello-1.0.0/hello hello-1.0.0/hello.o libhello-1.0.0/hello/libhello-1.0.so
+updated hello/1.0.0
+\
+
+Another handy command is \l{bpkg-pkg-status(1) \c{bpkg 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} and \c{sys:?}
+mean, check \l{bpkg-pkg-status(1)}):
+
+\
+$ bpkg status libhello
+configured 1.0.0; available sys:?
+
+$ bpkg status hello
+configured 1.0.0 hold_package; available sys:?
+
+$ bpkg drop -y hello
+disfigured hello
+disfigured libhello
+purged hello
+purged libhello
+
+$ bpkg status hello
+available 1.0.0 sys:?
+
+$ 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 art of \i{\"Hello,
+World!\"}, 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)
+\
+
+Notice that this time we don't see any authentication-related messages or
+prompts since \c{bpkg} remembered (in this configuration) that we trust the
+certificate (\c{testing} naturally uses the same one as \c{stable}).
+
+Let's see what's new:
+
+\
+$ bpkg status libhello
+configured 1.0.0; available 1.1.0 sys:?
+\
+
+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
+\
+
+Why did nothing happen? Because \c{bpkg} will only upgrade (or downgrade)
+to a new version if we explicitly ask it to. As things stand, 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 (dependent of 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:
+
+\
+update dependent packages? [Y/n]
+\
+
+Another question. This one has to do with that \c{reconfigure hello} line we
+just talked about. If you were wondering why we were only offered to
+reconfigure and not actually update the dependent package, you should know
+that \c{bpkg} is a very lazy package manager, it only does what it must do,
+not what might be nice to do. It must reconfigure but it doesn't really have
+to update. And this could be a good thing if, for example, you have a hundred
+dependents in your configuration but right now you only want to build just
+those specific packages. However, quite often, you do want to keep all the
+packages in your configuration up to date and \c{bpkg} graciously offers to
+take care of this task. Ok, let's answer \i{yes} again:
+
+\
+...
+update dependent packages? [Y/n] y
+disfigured hello/1.0.0
+disfigured libhello/1.0.0
+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/libs{format}
+c++ libprint-1.0.0/print/cxx{print}
+ld libprint-1.0.0/print/libs{print}
+ld libhello-1.1.0/hello/libs{hello}
+c++ libhello-1.1.0/tests/test/cxx{driver}
+ld libhello-1.1.0/tests/test/exe{driver}
+c++ hello-1.0.0/cxx{hello}
+ld hello-1.0.0/exe{hello}
+updated libhello/1.1.0
+updated hello/1.0.0
+\
+
+A lot of output but nothing really new. If you were to answer \i{no} to the
+\"update dependent packages?\" question above, it is easy to make sure a
+package is up-to-date at a later time with the \l{bpkg-pkg-update(1) \c{bpkg
+update}} command (there is also \l{bpkg-pkg-clean(1) \c{bpkg clean}}), for
+example:
+
+\
+$ bpkg clean hello
+rm hello-1.0.0/exe{hello}
+rm hello-1.0.0/obje{hello}
+cleaned hello/1.0.0
+
+$ 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
+plus, in this case, we need to specify the version (you can also specify
+the desired version for upgrades).
+
+\
+$ bpkg build libhello/1.0.0
+ downgrade libhello/1.0.0
+ reconfigure hello (dependent of libhello)
+continue? [Y/n] y
+update dependent packages? [Y/n] y
+disfigured hello/1.0.0
+disfigured libhello/1.1.0
+libhello-1.0.0.tar.gz 100% of 2428 B 983 kBps 00m01s
+fetched libhello/1.0.0
+unpacked libhello/1.0.0
+configured libhello/1.0.0
+configured hello/1.0.0
+following prerequisite packages were automatically built and will no longer be necessary:
+ libprint
+ libformat
+drop prerequisite packages? [Y/n] y
+disfigured libprint
+disfigured libformat
+purged libprint
+purged libformat
+c++ libhello-1.0.0/hello/cxx{hello}
+ld libhello-1.0.0/hello/liba{hello}
+c++ libhello-1.0.0/hello/cxx{hello}
+ld libhello-1.0.0/hello/libs{hello}
+c++ libhello-1.0.0/tests/test/cxx{driver}
+ld libhello-1.0.0/tests/test/exe{driver}
+c++ hello-1.0.0/cxx{hello}
+ld hello-1.0.0/exe{hello}
+updated libhello/1.0.0
+updated hello/1.0.0
+\
+
+Notice how \c{bpkg} helpfully offered to get rid of \c{libprint} and
+\c{libformat} which we won't be needing anymore. Note also that while we
+can use \c{--yes|y} as an answer to all the numerous prompts, there are
+also more granular options. For example, this is how we can instruct
+\c{bpkg} to drop prerequisites (\c{--drop-prerequisite|-D}) but leave
+dependents just reconfigured (\c{--leave-dependent|-L}):
+
+\
+$ bpkg build -D -L libhello/1.0.0
+\
+
+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 \l{bpkg-pkg-test(1) \c{bpkg
+test}} command:
+
+\
+$ bpkg test libhello hello
+test libhello-1.0.0/tests/test/exe{driver}
+test hello-1.0.0/exe{hello}
+tested libhello/1.0.0
+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/
+buildfile
+hello-1.0.0.tar.gz
+libhello-1.0.0.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.d
+hello.cxx
+hello.o
+hello.o.d
+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 this: the \c{bpkg} configuration is not some black
+box that you should never look inside of. On the contrary, it is a normal and
+predictable concept of the build system and as long as you understand what you
+are doing, feel free to muck around.
+
+Another way to get hold of a package's goodies is to install it with
+\l{bpkg-pkg-install(1) \c{bpkg install}}. Let's try that:
+
+\
+$ bpkg install \
+ config.install.root=/opt/hello \
+ config.install.sudo=sudo \
+ hello
+
+install /opt/hello/
+install /opt/hello/include/
+install /opt/hello/include/hello/
+install libhello-1.0.0/hello/hxx{hello}
+install libhello-1.0.0/hello/hxx{export}
+install /opt/hello/lib/
+install libhello-1.0.0/hello/libs{hello}
+install /opt/hello/bin/
+install hello-1.0.0/exe{hello}
+install /opt/hello/share/
+install /opt/hello/share/doc/
+install /opt/hello/share/doc/hello/
+install hello-1.0.0/doc{version}
+installed hello/1.0.0
+\
+
+The \c{config.install.sudo} value is the optional \i{sudo}-like program
+that should be used to run the \c{install} program. 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!
+
+Let's see what we've got:
+
+\
+$ tree -F /opt/hello/
+/opt/hello/
+├── bin/
+│ └── hello*
+├── include/
+│ └── libhello/
+│ ├── export
+│ └── hello
+├── lib/
+│ ├── libhello-1.0.so*
+│ └── libhello.so -> libhello-1.0.so*
+└── share/
+ └── doc/
+ └── hello/
+ └── version
+\
+
+We can also try to run the installed program:
+
+\
+$ /opt/hello/bin/hello World
+/opt/hello/bin/hello: error while loading shared libraries: libhello-1.0.so: cannot open shared object file: No such file or directory
+\
+
+Not what we hoped to see. Note to the Windows users: this will actually work
+since \c{hello-1.0.dll} will be installed into \c{bin\\}, next to the
+executable; for once things are working better on Windows.
+
+The problem is with our installation location: the runtime linker won't look
+for \c{libhello-1.0.so} in \c{/opt/hello/lib} unless we somehow tell it to
+(for example, using \c{LD_LIBRARY_PATH} or equivalent). There are several
+ways we can resolve this. We could give up on shared libraries and link our
+prerequisite libraries statically (\c{config.bin.exe.lib=static}). Or we could
+use the \i{rpath} mechanism:
+
+\
+$ bpkg install \
+ config.install.root=/opt/hello \
+ config.install.sudo=sudo \
+ config.bin.rpath=/opt/hello/lib \
+ hello
+
+ld hello-1.0.0/exe{hello}
+install /opt/hello/
+install /opt/hello/include/
+install /opt/hello/include/hello/
+install libhello-1.0.0/hello/hxx{hello}
+install libhello-1.0.0/hello/hxx{export}
+install /opt/hello/lib/
+install libhello-1.0.0/hello/libs{hello}
+install /opt/hello/bin/
+install hello-1.0.0/exe{hello}
+install /opt/hello/share/
+install /opt/hello/share/doc/
+install /opt/hello/share/doc/hello/
+install hello-1.0.0/doc{version}
+installed hello/1.0.0
+
+$ /opt/hello/bin/hello World
+Hello, World!
+\
+
+Notice that \c{ld} line above \- this is where our executable is re-linked
+with the \c{-rpath} option.
+
+We can also uninstall what we have installed with \l{bpkg-pkg-uninstall(1)
+\c{bpkg uninstall}}:
+
+\
+$ bpkg uninstall \
+ config.install.root=/opt/hello \
+ config.install.sudo=sudo \
+ hello
+
+uninstall hello-1.0.0/doc{version}
+uninstall /opt/hello/share/doc/hello/
+uninstall /opt/hello/share/doc/
+uninstall /opt/hello/share/
+uninstall hello-1.0.0/exe{hello}
+uninstall /opt/hello/bin/
+uninstall libhello-1.0.0/hello/libs{hello}
+uninstall /opt/hello/lib/
+uninstall libhello-1.0.0/hello/hxx{export}
+uninstall libhello-1.0.0/hello/hxx{hello}
+uninstall /opt/hello/include/hello/
+uninstall /opt/hello/include/
+uninstall /opt/hello/
+uninstalled hello/1.0.0
+
+$ ls /opt/hello
+ls: cannot access /opt/hello: No such file or directory
+\
+
+What if we wanted to use \c{libhello} in our own project? While installing it
+is always an option, this 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 several versions of \c{libhello} (and maybe even with that heinous
+\c{1.1.X}). 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 <libhello/hello>
+
+int main ()
+{
+ hello::say (\"World\");
+}
+
+\
+
+What build system shall we use? I can't believe you are even asking this
+question...
+
+\
+$ mkdir build
+
+$ cat >build/bootstrap.build
+
+project = hello2 # project name
+using config # config module (those config.*)
+
+$ cat >build/root.build
+
+cxx.std = 11 # C++ standard
+using cxx # C++ module
+cxx{*}: extension = cpp # C++ source file extension
+
+$ 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, \i{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
+(\l{b(1)} is the \c{build2} build system driver).
+
+\
+$ b config.cxx=g++-5
+error: unable to import target libhello%lib{hello}
+ info: use config.import.libhello command line variable to specifying its project out_root
+ info: while applying rule cxx.link to update exe{hello}
+ info: while applying rule alias to update dir{./}
+\
+
+No magic, unfortunately (or fortunately). But we got a hint: looks like we
+need to tell \c{build2} where \c{libhello} is using
+\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. After all, that's where, more or less, our \i{out}-put for
+\c{libhello} is.
+
+\
+$ b config.cxx=g++-5 \
+ config.import.libhello=/tmp/hello-gcc5-release
+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.d
+├── hello.cpp
+├── hello.o
+└── hello.o.d
+
+$ ./hello
+Hello, World!
+\
+
+Let's change something in our source code and try to update:
+
+\
+$ touch hello.cpp
+
+$ b
+error: unable to import target libhello%lib{hello}
+ info: use config.import.libhello command line variable to specifying its project out_root
+ 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 those \c{config.*} values and who wants
+that? To get rid of this annoyance 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.cc.coptions=-O3 \
+ config.import.libhello=/tmp/hello-gcc5-release \
+ 'configure(hello2/@hello2-gcc5-release/)'
+
+mkdir -p hello2-gcc5-release/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 heard \c{out_root}
+mentioned somewhere before...
+
+Once the configuration is saved, we can develop our project without any
+annoyance:
+
+\
+$ 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 obje{hello}
+
+$ b -v
+g++-5 -I/tmp/hello-gcc5-release/libhello-1.0.0 -O3 -std=c++11 -o hello.o -c ../hello2/hello.cpp
+g++-5 -O3 -std=c++11 -o hello hello.o /tmp/hello-gcc5-release/libhello-1.0.0/hello/libhello-1.0.so
+\
+
+Some of you might have noticed that \c{hello2-gcc5-release/} and
+\c{/tmp/hello-gcc5-release/} look 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/build/
+save /tmp/hello-gcc5-release/hello2/build/config.build
+
+$ b /tmp/hello-gcc5-release/hello2/
+c++ hello2/cxx{hello}@/tmp/hello-gcc5-release/hello2/
+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.c*} values this time? Because they are
+inherited from those 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? Not really \- \c{libhello} will be found
+automatically since it is part of the same amalgamation.
+
+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 merely 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/obje{hello}
+rm /tmp/hello-gcc5-release/hello2/build/config.build
+rmdir /tmp/hello-gcc5-release/hello2/
+\
+
+Next, we use the \l{bpkg-pkg-build(1) \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 (\c{bpkg} can fetch packages or it can build local package
+archives or package directories):
+
+\
+$ 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}@/tmp/hello-gcc5-release/hello2-1.0.0/
+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/ -L libhello
+ build libformat/1.0.0 (required by libhello)
+ build libprint/1.0.0 (required by libhello)
+ upgrade libhello/1.1.0
+ reconfigure hello2 (dependent of libhello)
+continue? [Y/n] y
+disfigured hello2/1.0.0
+disfigured libhello/1.0.0
+[ ... fetching & unpacking ... ]
+configured libformat/1.0.0
+configured libprint/1.0.0
+configured libhello/1.1.0
+configured hello2/1.0.0
+[ ... updating libprint, libformat, and libhello ... ]
+updated libhello/1.1.0
+\
+
+As promised, \c{hello2} got reconfigured (it didn't get updated because of the
+\c{-L} option). We can now update it and give it a try:
+
+\
+$ bpkg update -d /tmp/hello-gcc5-release/ hello2
+c++ hello2/cxx{hello}@/tmp/hello-gcc5-release/hello2-1.0.0/
+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 cc config.cxx=clang++-3.6 config.cc.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
+[... certificate authentication ...]
+fetching build2.org/hello/stable (complements build2.org/hello/testing)
+5 package(s) in 2 repository(s)
+
+$ bpkg build libhello/1.0.0 path/to/hello2/
+ build libhello/1.0.0
+ build hello2/1.0.0
+continue? [Y/n] y
+libhello-1.0.0.tar.gz 100% of 2428 B 983 kBps 00m01s
+fetched libhello/1.0.0
+unpacked libhello/1.0.0
+unpacked hello2/1.0.0
+configured libhello/1.0.0
+configured hello2/1.0.0
+c++ libhello-1.0.0/hello/cxx{hello}
+ld libhello-1.0.0/hello/liba{hello}
+c++ libhello-1.0.0/hello/cxx{hello}
+ld libhello-1.0.0/hello/libs{hello}
+c++ libhello-1.0.0/tests/test/cxx{driver}
+ld libhello-1.0.0/tests/test/exe{driver}
+c++ /path/to/hello2/cxx{hello}@hello2-1.0.0/
+ld hello2-1.0.0/exe{hello}
+updated libhello/1.0.0
+updated hello2/1.0.0
+\
+
+Are you still there? Ok, one last example. Let's see how hard it is to
+cross-compile.
+
+\
+$ mkdir hello-mingw64
+$ cd hello-mingw64
+
+$ bpkg create cc config.cxx=x86_64-w64-mingw32-g++
+created new configuration in /tmp/hello-mingw64/
+
+$ bpkg add https://build2.org/pkg/1/hello/stable
+added repository build2.org/hello/stable
+
+$ bpkg fetch
+fetching build2.org/hello/stable
+[... certificate authentication ...]
+2 package(s) in 1 repository(s)
+
+$ bpkg build -y hello
+libhello-1.0.0.tar.gz 100% of 2428 B 983 kBps 00m01s
+fetched libhello/1.0.0
+unpacked libhello/1.0.0
+hello-1.0.0.tar.gz 100% of 1057 B 6882 kBps 00m01s
+fetched hello/1.0.0
+unpacked hello/1.0.0
+configured libhello/1.0.0
+configured hello/1.0.0
+c++ hello-1.0.0/cxx{hello}
+c++ libhello-1.0.0/hello/cxx{hello}
+ld libhello-1.0.0/hello/libs{hello}
+ld hello-1.0.0/exe{hello}
+updated hello/1.0.0
+
+$ wine hello-1.0.0/hello.exe Windows
+Hello, Windows!
+\
+
+In fact, on a properly setup GNU/Linux machine (that automatically uses
+\c{wine} as an \c{.exe} interpreter) we can even run tests:
+
+\
+$ bpkg test libhello hello
+c++ libhello-1.0.0/tests/test/cxx{driver}
+ld libhello-1.0.0/tests/test/exe{driver}
+test libhello-1.0.0/tests/test/exe{driver}
+test hello-1.0.0/exe{hello}
+tested libhello/1.0.0
+tested hello/1.0.0
+\
+"