From ae4a7f8ad474ddeed54d70874438c74d8464e930 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 20 Apr 2018 16:03:42 +0200 Subject: New introduction, first take --- doc/cli.sh | 7 +- doc/intro2.cli | 1158 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1164 insertions(+), 1 deletion(-) create mode 100644 doc/intro2.cli diff --git a/doc/cli.sh b/doc/cli.sh index 8b844c6..6d99c25 100755 --- a/doc/cli.sh +++ b/doc/cli.sh @@ -36,6 +36,9 @@ function gen () # --html-epilogue-file doc-epilogue.xhtml \ --link-regex '%b([-.].+)%../../build2/doc/b$1%' \ --link-regex '%bpkg([-.].+)%../../bpkg/doc/bpkg$1%' \ +--link-regex '%bdep([-.].+)%../../bdep/doc/bdep$1%' \ +--link-regex '%b(#.+)?%../../build2/doc/build2-build-system-manual.xhtml$1%' \ +--link-regex '%bpkg(#.+)?%../../bpkg/doc/build2-package-manager-manual.xhtml$1%' \ --output-prefix build2-toolchain- "${@}" $n.cli html2ps -f doc.html2ps:a4.html2ps -o build2-toolchain-$n-a4.ps build2-toolchain-$n.xhtml @@ -45,10 +48,12 @@ html2ps -f doc.html2ps:letter.html2ps -o build2-toolchain-$n-letter.ps build2-to ps2pdf14 -sPAPERSIZE=letter -dOptimize=true -dEmbedAllFonts=true build2-toolchain-$n-letter.ps build2-toolchain-$n-letter.pdf } +gen intro2 +gen intro + # Auto-heading doesn't work since it is broken into multiple doc strings. # gen install --html-heading-map 2=h2 -gen intro # Generate INSTALL/BOOTSTRAP/UPGRADE file in ../ # diff --git a/doc/intro2.cli b/doc/intro2.cli new file mode 100644 index 0000000..1d62ee6 --- /dev/null +++ b/doc/intro2.cli @@ -0,0 +1,1158 @@ +// file : doc/intro2.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 (
) +// @@ when printed, code background is gone, but spaces still there +// +// PDF +// +// @@ tree output is garbled +// @@ Could we use a nicer font, seeing that we embed them? +// + +// NOTES +// +// - Maximum
 line is 70 characters.
+//
+
+"
+\h1#tldr|TL;DR|
+
+\
+$ git clone ssh://example.org/hello.git
+$ cd hello
+
+$ bdep init --create ../hello-gcc cc config.cxx=g++
+$ b
+
+$ ./hello
+
+$ edit repositories.manifest   # add https://example.org/libhello.git
+$ edit manifest                # add 'depends: libhello ^ 1.0.0'
+$ edit buildfile               # import libhello
+$ edit hello.cxx               # use libhello
+$ b
+
+
+
+$ bdep fetch                   # refresh available versions
+$ bdep status                  # review available versions
+
+
+$ bdep sync libhello           # upgrade to latest
+<...>
+
+$ bdep sync libhello/1.1.0     # downgrade to X.Y.Z
+<...>
+\
+
+\h1#tour|A Tour of The \c{build2} Toolchain|
+
+The aim of this section is to give you a quick tour of the \c{build2}
+toolchain with minimal explanation of the underlying concepts with the
+subsequent sections going into more detail.
+
+All the examples in this document include the relevant command output so that
+you don't have to install the toolchain and run the commands in order to
+follow alone. If at the end you find \c{build2} appealing and would like to
+try the examples for yourself, you can jump straight to
+\l{build2-toolchain-install.xhtml The \c{build2} Toolchain Installation and
+Upgrade}.
+
+The question we will try to answer in this section can be summarized as:
+
+\
+$ git clone .../hello.git && now-what?
+\
+
+That is, we clone an existing C++ project or would like to create a new one
+and then start hacking on it. We want to spend as little time and energy as
+possible on the initial and ongoing infrastructure maintenance: setting up
+build configurations, managing dependencies, continuous integration and
+testing, etc. Or, as one C++ user aptly put it, \"\i{All I want to do is
+program.}\"
+
+\h#tour-hello|Hello, World|
+
+Let's see what programming with \c{build2} feels like by starting with a
+customary \i{\"Hello, World!\"} program:
+
+\
+$ bdep new -t exe -l c++ hello
+\
+
+The \l{bdep-new(1)} command creates a \i{canonical} \c{build2} project. In
+our case it is an executable implemented in C++.
+
+\N|To create a library, pass \c{-t\ lib}. By default \c{new} also initializes
+a \c{git} repository and generates suitable \c{.gitignore} files (pass \c{-s\
+none} if you don't want that).|
+
+Let's take a look inside our new project:
+
+\
+$ tree hello
+hello/
+├── .git/
+├── .bdep/
+├── build/
+├── hello/
+│   ├── buildfile
+│   └── hello.cxx
+├── buildfile
+├── manifest
+└── repositories.manifest
+\
+
+\N|While the canonical project structure is strongly recommended, especially
+for new projects, \c{build2} is flexible enough to allow most commonly used
+arrangements.|
+
+Similar to version control tools, we normally run all \c{build2} tools from
+the project's source directory or one of its subdirectories, so:
+
+\
+$ cd hello
+\
+
+While the project layout is discussed in more detail in later sections, let's
+examine a couple of interesting files to get a sense of what's going on. We
+start with the source file which should look familiar:
+
+\
+$ cat hello/hello.cxx
+
+#include 
+
+int main ()
+{
+  std::cout << \"Hello, World!\" << std::endl;
+}
+\
+
+\N|If you prefer the \c{.?pp} extensions over \c{.?xx} for your C++ source
+files, pass \c{-l\ c++,cpp} to the \c{new} command. See \l{bdep-new(1)} for
+details on this and other customization options.|
+
+Let's take a look at the accompanying \c{buildfile}:
+
+\
+$ cat hello/buildfile
+
+libs =
+#import libs += libhello%lib{hello}
+
+exe{hello}: {hxx ixx txx cxx}{*} $libs
+\
+
+As the name suggests, this file describes how to build things. While its
+content might look a bit cryptic, let's try infer a couple of points without
+going into too much detail (the details are discussed in the following
+sections). That \c{exe{hello\}} on the left of \c{:} is a \i{target}
+(executable named \c{hello}) and what we have on the right are
+\i{prerequisites} (C++ sources files). This \c{buildfile} uses
+\l{b#name-patterns wildcard patterns} (that \c{*}) to automatically locate all
+the source files. This means we don't have to edit our \c{buildfile} every
+time we add a source file to our project. There also appears to be some
+infrastructure for importing (commented out) and linking libraries (that
+\c{libs} variable). We will see how to use it in a moment.
+
+Next up is \c{manifest}:
+
+\
+$ cat manifest
+: 1
+name: hello
+version: 0.1.0-a.0.z
+summary: hello executable project
+license: proprietary
+url: https://example.org/hello
+email: you@example.org
+#depends: libhello >= 1.0.0
+\
+
+The \c{manifest} file is what makes a build system project a \i{package}. It
+contains all the metadata that a user of a package would need to know: its
+name, version, license, dependencies, etc., all in one place.
+
+\N|Refer to \l{bpkg#manifest-format Manifest Format} for the general format of
+\c{build2} manifest files and to \l{bpkg#manifest-package Package Manifest}
+for details on the package manifest values.|
+
+As you can see, a \c{manifest} created by \l{bdep-new(1)} contains some dummy
+values which you would want to adjust before publishing your package. But
+let's resist the urge to adjust that strange looking \c{0.1.0-a.0.z} until we
+discuss package versioning.
+
+\N|Next to \c{manifest} you might have noticed the \c{repositories.manifest}
+file \- we will discuss its function later, when we talk about dependencies
+and where they come from.|
+
+Project in hand, let's build it. Unlike other programming languages, C++
+development usually involves juglling a handful of build configurations:
+several compilers and/or targets (\c{build2} is big on cross-compiling),
+debug/release, different sanitizers and/or static analysis tools, etc. As a
+result, \c{build2} is optimized for multi-configuration usage. However, as we
+will see shortly, one configuration can be designated as the default with
+additional conveniences.
+
+The \l{bdep-init(1)} command is used to initialize a project in a build
+configuration. As a shortcut, it can also create new build configuration in
+the process, which is just what we need here. Let's start with GCC (remember
+we are in the project's root directory):
+
+\
+$ bdep init -C ../hello-gcc @gcc cc config.cxx=g++
+initializing project /tmp/hello/
+created configuration @gcc /tmp/hello-gcc/ (1, default)
+synchronizing:
+  build hello/0.1.0-a.0.19700101000000
+\
+
+The \cb{--create|-C} option instructs \c{init} to create a new configuration
+in the specified directory. To make refering to configurations easire, we can
+give it a name, which is what we do with \c{@gcc}. The next argument (\c{cc},
+stands for \i{C-common}) is the build system module we would like to configure
+with \c{config.cxx=g++} being (one of) its configuration variables. Let's
+ignore that \c{synchronizing:\ ...} bit for now \- it will become clear what's
+going on here in a moment.
+
+Now the same for Clang:
+
+\
+$ bdep init -C ../hello-clang @clang cc config.cxx=clang++
+initializing project /tmp/hello/
+created configuration @clang /tmp/hello-clang/ (2)
+synchronizing:
+  build hello/0.1.0-a.0.19700101000000
+\
+
+If we check the parent directory, we should now see two build configurations
+next to our project:
+
+\
+$ ls ..
+hello/
+hello-gcc/
+hello-clang/
+\
+
+One of the primary goals of the \c{build2} toolchain is to provide a uniform
+interface across all the platforms and compilers. While the examples in this
+document assume a UNIX-like operation system, they will look pretty similar if
+you are on Windows. You just have to use appropriate paths, compilers, and
+options. For example, to initialize our project on Windows with Visual Studio,
+start the Visual Studio development command prompt and then run:
+
+\N|Currently we have to run \c{build2} tools from a suitable Visual Studio
+development command prompt. This requirement will likely be removed in the
+future.|
+
+\
+> bdep init -C ..\hello-debug @debug cc     ^
+  config.cxx=cl                             ^
+  \"config.cc.coptions=/MDd /Z7\"             ^
+  config.cc.loptions=/DEBUG
+
+> bdep init -C ..\hello-release @release cc ^
+  config.cxx=cl                             ^
+  config.cc.coptions=/O2
+\
+
+\N|Besides the \c{coptions} (compile options) and \c{loptions} (link options)
+other commonly used \c{cc} module configuration variables are \c{poptions}
+(preprocess options) and \c{libs} (extra libraries to link). We can also use
+their \c{config.c.*} (C compilation) and \c{config.cxx.*} (C++ compilation)
+variants if we only want them applied only during the respective language
+compilation. For example:
+
+\
+$ bdep init ... cc       \
+  config.cxx=clang++     \
+  config.cc.coptions=-g  \
+  config.cxx.coptions=-stdlib=libc++
+\
+
+|
+
+One difference you might have noticed when creating the \c{gcc} and \c{clang}
+configurations above is that the first one was designated as the default. The
+default configuration is used by \c{bdep} commands if no configuration is
+specified explicitly (see \l{bdep-projects-configs(1)} for details). It is
+also the configuration that is used if we run the build system in the project
+source directory. So, normally, you would make your every day development
+configuration the default. Let's try that:
+
+\
+$ bdep status
+hello configured 0.1.0-a.0.19700101000000
+
+$ b
+<...>
+
+$ hello/hello
+Hello, World!
+\
+
+In contrast, the Clang configuration has to be requested explicitly:
+
+\
+$ bdep status @clang
+hello configured 0.1.0-a.0.19700101000000
+
+$ b ../hello-clang/hello/
+...
+
+$ ../hello-clang/hello/hello/hello
+Hello, World!
+\
+
+\N|To see the actual compilation command lines run \c{b\ -v} and for even
+more details, run \c{b\ -V}. See \l{b(1)} for more information on these
+and other build system options.|
+
+While we are here, let's also check how hard it would be to cross-compile:
+
+\
+$ bdep init -C ../hello-mingw cc config.cxx=x86_64-w64-mingw32-g++
+initializing project /tmp/hello/
+created configuration /tmp/hello-mingw/ (1, default)
+synchronizing:
+  build hello/0.1.0-a.0.19700101000000
+
+$ b
+<...>
+\
+
+As you can see, cross-compiling in \c{build2} is nothing special. In our case,
+on a properly setup GNU/Linux machine (that automatically uses \c{wine} as an
+\c{.exe} interpreter) we can even run tests:
+
+\
+$ b test
+<...>
+\
+
+Let's review what it takes to initialize a project's infrastructure and
+perform the first build. For an exising project:
+
+\
+$ git clone .../hello.git
+$ cd hello
+$ bdep init -C ../hello-gcc @gcc cc config.cxx=g++
+$ b
+\
+
+For a new project:
+
+\
+$ bdep new -t exe -l c++ hello
+$ cd hello
+$ bdep init -C ../hello-gcc @gcc cc config.cxx=g++
+$ b
+\
+
+If you prefer, the \c{new} and \c{init} steps can be combined into a single
+command:
+
+\
+$ bdep new -C hello-gcc @gcc -t exe -l c++ hello cc config.cxx=g++
+\
+
+Now is also a good time to get an overview of the \c{build2} toolchain. After
+all, we have already used two of its tools (\c{bdep} and \c{b}) without a
+clear understanding of what they actually are.
+
+Unlike most other programming languages that encapsulate the build system,
+package dependency manager, and project dependency manager into a single tool
+(such as Rust's \c{cargo} or Go's \c{go}), \c{build2} is a hierarchy of
+several tools that you will be using directly and which together with your
+version control system (VCS) will constitute the core of your development
+toolset.
+
+\N|While \c{build2} can work without a VCS, the resulting functionality will
+be limited significantly.|
+
+At the bottom of the hierarchy is the build system, \l{b(1)}. Next comes the
+package dependency manager, \l{bpkg(1)}. It is primarily used for package
+\i{consumption} and depends on the build system. The top of the hierarchy is
+the project dependency manager, \l{bdep(1)}. It is used for project
+\i{development} and relies on \c{bpkg} to provide backing for building project
+packages and their dependencies.
+
+\N|The main reason for this separation is modularity and the resulting
+flexibility: there are situations where we only need the build system (for
+example, when building a package for a system package manager where all the
+dependencies should be satisfied from the system repository), or only the
+build system and package manager (for example, when a build bot is building a
+package for CI).
+
+Note also that strictly speaking \c{build2} is not C/C++-specific; its build
+system is general enough to handle any DAG-based operations and its
+package/project dependency managers can be used for any compiled language.|
+
+\N|As we will see in moment, \c{build2} also integrates with your VCS in order
+to automate project versioning. Note that currently only \c{git(1)} is
+supported.|
+
+Let's now move on to the reason why there is \i{dep} in the \c{bdep} name:
+dependency management.
+
+
+\h#tour-repositories|Package Repositories|
+
+Say we realized that writing \i{\"Hello, World!\"} programs is a fairly common
+task and that someone must have wrote a library to help with that. So let's
+see if we can find something suitable to use in our project.
+
+Where should we look? That's a good question. But before we can try to answer
+it, we need to understand where \c{build2} can source dependencies. In
+\c{build2} packages come from \i{package repositories}. Two commonly used
+repository types are \i{version control} and \i{archive}-based (@@ link to
+repo type help topic).
+
+As the name suggests, a version control-based repository uses a VCS as its
+ditribution mechanism. \N{Currently only \c{git} is supported.} Such a
+repository normally contains multiple versions of a single package or,
+perhaps, of a few related packages.
+
+An archive-based repository contain multiple, potentially unrelated
+packages/versions as archives along with some meta information (package list,
+prerequisite/complement repositories, signtures, etc) that are all accessible
+via HTTP(S).
+
+Version control and archive-based repositories have different
+tradeoffs. Version control-based repositories are great for package
+developers: With services like GitHub they are trivial to setup. In fact, your
+project's (already existing) VCS repository will normally be the \c{build2}
+package repostiory \- you might need to add a few files, but that's about it.
+
+However, version control-based repositories are not without drawbacks: It will
+be hard for your users to discover your packages (try searching for \"hello
+library\" on GitHub \- most of the results are not even in C++ let alone
+\c{build2} packages). There is also the issue of continous availability: users
+can delete their repositories, services may go out of businese, etc. Version
+control-based repositories also lack repository authentication and package
+signing. Finally, obtainig the available packages list for such repositories
+can be a slow operation.
+
+A central, archive-based repository would addresses all these drawbacks: It
+would be a single place to search for packages. Published packages will never
+disappear and can be easily mirrored. Packages are signed and the repository
+is authenticated (see \l{bpkg-repository-signing(1)} for details). And, last,
+but not least, it would be fast.
+
+\l{https://cppget.org cppget.org} is the \c{build2} community's central
+package repository (which we hope one day will become \i{the C++ package
+repository}). As an added benefit, packages on \l{https://cppget.org
+cppget.org} are continously \l{https://cppget.org/?builds built and tested} on
+all the major platform/compiler combinations with the results available as
+part of the package description.
+
+\N|The main drawback of archive-based repositories is the setup cost. Getting
+a basic repository going is relatively easy \- all you need is an HTTP(S)
+server. Adding a repository web interface like that on \l{https://cppget.org
+cppget.org} will require running \l{https://cppget.org/brep \c{brep}}. And
+adding CI will require running a bunch of build bots
+(\l{https://cppget.org/bbot \c{bbot}}).|
+
+\N|CI support for version control-based repositories is a work in progress.|
+
+To summarize, version control-based repositories are great for package
+developers while a central, archive-based repository is convenient for package
+consumers. A reasonable strategy is then for package developers to publish
+their releases to a central repository. Package consumers can then decide
+which repository to use based on their needs. For example, one could use
+\l{https://cppget.org cppget.org} as a (fast, reliable, and secure) source of
+stable versions but also add, say, \c{git} repositories for select packages
+(perhaps with the \c{#master} fragment filter to imporive download speed) for
+testing development snapshots. In this model the two repository types
+complement each other.
+
+\N|Support for automated publishing of tagged releases to an archive-based
+repository is planned.|
+
+@@ Show using two repos with #master?
+
+\h#tour-add-remove-deps|Adding and Removing Dependencies|
+
+Say we found \c{libhello} that we would like to use in our \c{hello}
+project. First we edit the \c{repositories.manifest} file found in the root
+directory of our project and add \c{libhello} repository as a prerequisite:
+
+\
+role: prerequisite
+location: https://example.org/libhello.git
+\
+
+\N|Refer to \l{bpkg#manifest-repository Repository Manifest} for details on
+the repository manifest values.|
+
+\N|If you are trying the examples for yourself and need a real repository,
+then you can use \c{https://git.build2.org/hello/libhello.git}. Or you can
+create and publish your own:
+
+\
+$ bdep new -t lib -l c++ libhello
+\
+
+|
+
+Next we edit the \c{manifest} file (again, found in the root of our project)
+and specify the version constraint for \c{libhello}:
+
+\
+depends: libhello >= 1.0.0 (@@ ^)
+\
+
+Next we edit \c{hello/buildfile} and import the \c{libhello} library into our
+build:
+
+\
+import libs += libhello%lib{hello}
+\
+
+Finally, we can use the library in our source code:
+
+\
+#include  // Or import hello;
+
+int main ()
+{
+  hello::say_hello (\"World\");
+}
+\
+
+\N|You are probably wondering why we have to specify this often repeating
+information in so many places. Let's start with the source code: we can't
+specify the version constraint and location there because  it will have
+to be repeated in every source file that uses the dependency.
+
+Moving up, \c{buildfile} is also not a good place to specify this information
+for the same reason (a library can be imported in multiple buildfiles) plus
+the build system doesn't really know anything about version constraints or
+repositories which is the purview of the dependency management tools.
+
+Finally, we have to separate the version constraint specification and the
+location specification because the same package can be present in multiple
+repositories. For example, when a package from \i{version control}-based
+repostiroy is published in an \i{archive}-based repository, its
+\c{repositories.manifest} file is ignored and all its dependencies should be
+available from the \i{archive}-based repository itself (or its fixes set of
+prerequisite repositories). In other words, \c{manifest} belongs to a
+package while \c{repositories.manifest} \- to a repository.
+
+Also note that this is unlikely to become burdensome since adding new
+dependencies is not something that happens often. Plus there is a
+possibility this will be automated with a \c{bdep-add(1)} command in
+the future.|
+
+To summarize, these are the files we had to touch to add a dependency
+to your project:
+
+\
+repositories.manifest   # add https://example.org/libhello.git
+manifest                # add 'depends: libhello ^ 1.0.0' (@@ ^)
+buildfile               # import libhello
+hello.cxx               # use libhello
+\
+
+With a new dependency added, let's check status of our project:
+
+\
+$ bdep status
+hello configured 0.1.0-a.0.19700101000000
+      available  0.1.0-a.0.19700101000000#1
+\
+
+The \l{bdep-status(1)} command has detected that the dependency information
+has changed and tells us that a new \i{iteration} of our project (that \c{#1})
+is now available for \i{synchronization} with its build configurations.
+
+To synchronize a project with one or more build configurations we use the
+\l{bdep-sync(1)} command:
+
+\
+$ bdep sync
+synchronizing:
+  build libhello/1.0.0 (required by hello)
+  upgrade hello/0.1.0-a.0.19700101000000#1
+\
+
+Or we could just build the project without an explicit \c{sync} \- if
+necessary, it will be automatically synchronized:
+
+\
+$ b
+synchronizing:
+  build libhello/1.0.0 (required by hello)
+  upgrade hello/0.1.0-a.0.19700101000000#1
+<...>
+c++ ../hello-gcc/libhello-1.0.0/libhello/cxx{hello}
+c++ hello/cxx{hello}@../hello-gcc/hello/hello/
+ld ../hello-gcc/libhello-1.0.0/libhello/libs{hello}
+ld ../hello-gcc/hello/hello/exe{hello}
+\
+
+The synchronization as performed by the \c{sync} command is two-way:
+dependency packages are first added, removed, upgraded, or downgraded in build
+configurations according the project's version constraints and user
+input. Then the actual versions of the dependecies present in the build
+configurations are recorded in the project's \c{lockfile}. \N{The \c{lockfile}
+functionality is not yet implemented.}. For a new dependency the latest
+available version that satisfies the version constraint is used.
+
+\N|Synchronization is also the last of the \l{bdep-init(1)} command's logic.|
+
+Let's now examine the status in all (\c{--all|-a}) build configurations
+including immediate dependencies (\c{--immediate|-i}):
+
+\
+$ bdep status -ai
+in configuration @gcc:
+hello configured 0.1.0-a.0.19700101000000#1
+  libhello configured 1.0.0
+
+in configuration @clang:
+hello configured 0.1.0-a.0.19700101000000
+      available 0.1.0-a.0.19700101000000#1
+\
+
+Since we didn't specify a configuration explicitly, only the default (\c{gcc})
+was synchronized. Normally you would try a new dependency in one
+configuration, make sure everything looks good, then synchronize the rest with
+\c{--all|-a}. Here are a few examples:
+
+\
+$ bdep sync -a
+$ bdep sync @gcc @clang
+$ bdep sync -c ../hello-mingw
+\
+
+To get rid of a dependency, we simply remove it from the two manifest files
+and synchronize the project. For example, assuming \c{libhello} is no longer
+in the manifests:
+
+\
+$ bdep status
+hello configured 0.1.0-a.0.19700101000000#1
+      available  0.1.0-a.0.19700101000000#2
+
+$ bdep sync
+synchronizing:
+  drop libhello/1.0.0 (unused)
+  upgrade hello/0.1.0-a.0.19700101000000#2
+\
+
+
+\h#tour-upgrade-downgrade-deps|Upgrading and Downgrading Dependencies|
+
+Let's say we've heard a new version of \c{libhello} was released and we
+would like to try it out. To refresh the list of available dependency
+versions we use the \l{bdep-fetch(1)} command (or the \c{--fetch|-f}
+option to \c{status}):
+
+\
+$ bdep fetch
+$ bdep status libhello
+libhello configured 1.0.0 available [2.0.0]
+\
+
+To upgrade (or downgrade) dependencies we again use the \l{bdep-sync(1)}
+command. We can upgrade one or more specific dependencies by listing them
+as arguments to \c{sync}:
+
+\
+$ bdep sync libhello
+synchronizing:
+  upgrade libhello/2.0.0
+  reconfigure hello/0.1.0-a.0.19700101000000#3
+\
+
+Without an explicit version or the \c{--patch|-p} option, \c{sync} will
+upgrade the specified dependencies to the latest available versions. For
+example, if we don't like version \c{2.0.0}, we can downgrade it back to
+\c{1.0.0} by specifying the version explicitly (we pass \c{--old-available|-o}
+to \c{status} to see the old versions):
+
+\
+$ bdep status -o libhello
+libhello configured 2.0.0 available [1.0.0] (2.0.0)
+
+$ bdep sync libhello/1.0.0
+synchronizing:
+  downgrade libhello/1.0.0
+  reconfigure hello/0.1.0-a.0.19700101000000#4
+\
+
+Instead of specific dependecies we can also upgrade (\c{--upgrade|-u}) or
+patch (\c{--patch|-p}) immediate (\c{--immediate|-i}) or all
+(\c{--recursive|-r}) dependencies of our project.
+
+As a more realistic example, let's assume our \c{hello} project also depends
+on \c{libformat} and that \c{libhello} in turn depends on \c{libprint}. Here
+is the dependency tree of this project:
+
+\
+$ bdep status -r
+hello configured 0.1.0-a.0.19700101000000#1
+  libhello configured 1.0.0
+    libprint configured 1.0.0
+  libformat configured 1.0.0
+\
+
+A typical conservative dependency management workflow for a our project would
+look like this:
+
+\
+$ bdep status -fi  # refresh and examine immediate dependencies
+hello configured 0.1.0-a.0.19700101000000#1
+  libhello configured 1.0.0 available 1.0.1 1.0.2 1.1.0 2.0.0
+  libformat configured 1.0.0 available 1.0.1 1.0.2 1.1.0 2.0.0
+
+$ bdep sync -pi    # upgrade immediate to latest patch version
+synchronizing:
+  upgrade libhello/1.0.2
+  upgrade libformat/1.0.2
+  reconfigure hello/0.1.0-a.0.19700101000000#2
+continue? [Y/n] y
+\
+
+Notice that in case of such mass upgrades you are prompted for confirmation
+before anything is actually changed (unless you pass \c{--yes|-y}).
+
+In contrast, this would be a fairly agressive workflow where we upgrade
+everything to the latest available version (version constraints permitting):
+
+\
+$ bdep status -fr  # refresh and examine all dependencies
+hello configured 0.1.0-a.0.19700101000000#1
+  libhello configured 1.0.0 available 1.0.1 1.1.0 2.0.0
+    libprint configured 1.0.0 available 1.0.1 1.1.0 2.0.0
+  libformat configured 1.0.0 available 1.0.1 1.1.0 2.0.0
+
+$ bdep sync -ur    # upgrade all to latest available version
+synchronizing:
+  upgrade libprint/2.0.0
+  upgrade libhello/2.0.0
+  upgrade libformat/2.0.0
+  reconfigure hello/0.1.0-a.0.19700101000000#2
+continue? [Y/n] y
+\
+
+We can also have something in between: patch all (\c{sync\ -pr}), upgrade
+immediate (\c{sync\ -ui}), or even upgrade immediate and patch the rest
+(\c{sync\ -ui} followed by \c{sync\ -pr}).
+
+\h#tour-versioning|Versioning and Release Management|
+
+Let's now discuss versioning and release management (and, yes, that
+strange-looking \c{0.1.0-a.0.19700101000000} we keep seeing). While a build
+system project doesn't need a version and a \c{bpkg} package can use custom
+versioning schemes (see \l{bpkg#package-version Package Version}), a project
+managed by \c{bdep} must use \i{standard versioning}. \N{A dependency, which
+is a \c{bpkg} package, need not use standard versioning.}
+
+Standard versioning (\i{stdver}) is a \l{https://semver.org semantic
+versionsing} (\i{semver}) scheme with a more precisely defined pre-release
+component and without any build metadata.
+
+\N|If you believe that \i{semver} is just \c{\i{major}.\i{minor}.\i{patch}},
+then in your worldview \i{stdver} would be the same as \i{semver}. In reality,
+\i{semver} also allows loosly defined pre-release and build metadata
+components. For example, \c{1.2.3-beta.1+build.23456} is a valid \i{semver}.|
+
+A standard version has the following form:
+
+\c{\i{major}\b{.}\i{minor}\b{.}\i{patch}[\b{-}\i{prerel}]}
+
+The \ci{major}, \ci{minor}, and \ci{patch} components have the same semantics
+as in \i{semver}. The \ci{prerel} is used to provide \i{continuous versioning}
+of our project between releases. Specifically, during development of a new
+version we may want to publish several pre-releases, for example, alpha or
+beta. In between those we may also want to publish a number of snapshots, for
+example, for CI. With continuous versioning all these releases, pre-releases,
+and snapshots are assigned unique, properly ordered versions.
+
+\N|Continous versioning is a fundamental building block of the \c{build2}
+project depdendency management. In case of snapshots, an appropriate version
+is assigned automatically in cooperation with your VCS.|
+
+The \ci{prerel} component for a pre-release has the following form:
+
+\c{(\b{a}|\b{b})\b{.}\i{num}}
+
+Here \cb{a} stands for alpha, \cb{b} stands for beta, and \ci{num} is the
+alpha/beta number. For example:
+
+\
+1.1.0        # final              release  for 1.1.0
+1.2.0-a.1    # first  alpha   pre-release  for 1.2.0
+1.2.0-a.1    # second alpha   pre-release  for 1.2.0
+1.2.0-b.2    # first  beta    pre-release  for 1.2.0
+1.2.0        # final              release  for 1.2.0
+\
+
+The \ci{prerel} component for a snapshot has the following form:
+
+\c{(\b{a}|\b{b})\b{.}\i{num}\b{.}\i{snapsn}[\b{.}\i{snapid}]}
+
+Where \ci{snapsn} is the snapshot sequence number and \ci{snapid} is
+the snapshot id. In case of \c{git}, \ci{snapsn} is the commit timestamp
+in the \c{YYYYMMDDhhmmss} form and UTC timezone while \ci{snapid} is
+a 12-character abbreviated commit id. For example:
+
+\
+1.2.3-a.1.20180319215815.26efe301f4a7
+\
+
+Notice also that a snapshot version is ordered \i{after} the corresponding
+pre-release version. That is, \c{1.2.3-a.1\ <\ 1.2.3-a.1.1}. As a result, it
+is customary to start the development of a new version with \c{X.Y.Z-a.0.N},
+that is, a snapshot after the (non-existent) zero'th alpha release. The
+following chronologically-ordered versions illustrate a typical release flow
+of a project that uses \c{git} as its VCS:
+
+\
+0.1.0-a.0.19700101000000               # snapshot (no commits yet)
+0.1.0-a.0.20180319215815.26efe301f4a7  # snapshot (first commit)
+...                                    # more commits/snapshots
+0.1.0-a.1                              # pre-release (first alpha)
+0.1.0-a.1.20180319221826.a6f0f41205b8  # snapshot
+...                                    # more commits/snapshots
+0.1.0-a.2                              # pre-release (second alpha)
+0.1.0-a.2.20180319231937.b701052316c9  # snapshot
+...                                    # more commits/snapshots
+0.1.0-b.1                              # pre-release (first beta)
+0.1.0-b.1.20180319242038.c812163417da  # snapshot
+...                                    # more commits/snapshots
+0.1.0                                  # release
+
+0.2.0-a.0.20180319252139.d923274528eb  # snapshot (first in 0.2.0)
+...
+\
+
+Let's see how this works in practice by publishing a couple of versions for
+our \c{hello} project. For more details on standard versioning and its support
+in \c{build2} refer to \l{b#module-version Version Module}.
+
+By now it should be clear what that \c{0.1.0-a.0.19700101000000} means \- it
+is a first snapshot version of our project. Since there are no commits yet, it
+has the UNIX epoch as its commit timestamp.
+
+As a first step, let's try to commit our project and see what changes:
+
+\
+$ git add .
+$ git commit -m \"Start hello project\"
+
+$ bdep status
+hello configured 0.1.0-a.0.19700101000000
+      available  0.1.0-a.0.20180418054428.4cf95b919a4c
+\
+
+Similar to dependency information, \c{status} has detected that a new
+(snapshot) version of our project is available for synchronization.
+
+\N|Another way to view the project's version (which works even if we are
+not using \c{bdep}) is with the build system's \c{info} operation:
+
+\
+$ bdep info
+project: hello
+version: 0.1.0-a.0.20180418064031.50697bae803c
+summary: hello executable project
+...
+\
+
+|
+
+Let's synchronize with the default build configuration:
+
+\
+$ bdep sync
+synchronizing:
+  upgrade hello/0.1.0-a.0.20180418054428.4cf95b919a4c
+
+$ bdep status
+hello configured 0.1.0-a.0.20180418054428.4cf95b919a4c
+\
+
+\N|Notice that we didn't have to manually change the version anywhere. All we
+had to do is commit our changes and a new snapshot version was automatically
+derived by \c{build2} from the new commit. Without this automation continous
+versioning would be burdensome and hardly impractical.|
+
+If we now make another commit, we will see a similar picture:
+
+\
+$ bdep status
+hello configured 0.1.0-a.0.20180418054428.4cf95b919a4c
+      available  0.1.0-a.0.20180418064031.50697bae803c
+\
+
+\N|Note that you don't need to manually run \c{sync} after every commit. As
+discussed earlier, you can simply run the build system to update your project
+and things will get automatically synchronized if necessary.|
+
+Ok, time for our first release. Let's start with \c{0.1.0-a.1}. Unlike
+snapshots, for pre-release as well as final releases we manually update
+the version in the \c{manifest} file:
+
+\
+version: 0.1.0-a.1
+\
+
+\N|The \c{manifest} file is the singular place where we specify the package
+version with the build system's \l{b#module-version \c{version} module}
+making it available in buildfiles and even source code.|
+
+To ensure continous versioning, this change to version must be the last commit
+for this (pre-)release which itself must be immediately followed by a second
+change to the version starting the development of the next (pre-)release. We
+also recommend that you tag the release commit with a name in the
+\c{\b{v}\i{X}.\i{Y}.\i{Z}} form.
+
+\N|Having regular release tag names with the \cb{v} prefix allows one to
+distinguish them from other tags, for example, with wildcard patterns.|
+
+Here is a workflow for our example:
+
+\
+$ git commit -a -m \"Release version 0.1.0-a.1\"
+$ git tag -a v0.1.0-a.1 -m \"Tag version 0.1.0-a.1\"
+$ git push --follow-tags
+
+# Version 0.1.0-a.1 is now public.
+
+$ edit manifest  # change 'version: 0.1.0-a.1.z'
+$ git commit -a -m \"Change version to 0.1.0-a.1.z\"
+$ git push
+
+# Master is now open for business.
+\
+
+Note that when specifying a snapshot version in \c{manifest} we use the
+special \cb{z} snapshot value (for example, \c{0.1.0-a.1.z}) which is
+recognized and automatically replaced by \c{build2} with, in case of \c{git},
+commit timestamp and id (refer to \l{b#module-version Version Module} for
+details).
+
+Publishing the final release is exactly the same. For completeness, here
+are the commands:
+
+\
+$ edit manifest  # change 'version: 0.1.0'
+$ git commit -a -m \"Release version 0.1.0\"
+$ git tag -a v0.1.0 -m \"Tag version 0.1.0\"
+$ git push --follow-tags
+
+$ edit manifest  # change 'version: 0.2.0-a.0.z'
+$ git commit -a -m \"Change version to 0.2.0-a.0.z\"
+$ git push
+\
+
+\N|One sticky point of continous versioning is choosing the next version.
+For example, above should we continue with \c{0.1.1-a.0}, \c{0.2.0-a.0},
+or \c{1.0.0-a.0}? The important rule to keep in mind is that we can jump
+forward to any further version at any time and without breaking continous
+versioning. But we can never jump backwards.
+
+For example, we can start with \c{0.2.0-a.0} but if we later realize that this
+will actually be a new major release, we can easily change it to
+\c{1.0.0-a.0}. As a result, the general recommendation is to start
+conservatively by either incrementing the patch or the minor version
+component. One reasonable strategy is to incremen the minor component and, if
+required, release patch versions from a separate branch (created by branching
+off from the release commit).|
+
+When publishing the final release you may also want to clean up now
+obsolete pre-release tags. For example:
+
+\
+$ git tag -l 'v0.1.0-*' | xargs git push --delete origin
+$ git tag -l 'v0.1.0-*' | xargs git tag --delete
+\
+
+\N|While at first removing such tags may seem like a bad idea, pre-releases
+are by nature temporary and their use only makes sense until the final release
+is published.
+
+Also note that having a \c{git} repository with a large number of published
+but unused references may result in a significant download overhead.|
+
+
+\h#tour-consume-pkg|Package Consumption|
+
+Ok, now that we have published a few releases of \c{hello}, how would the
+users of our project get them? While they could clone the repository and use
+\c{bdep} just like we did, this is more of a development rather than
+consumption workflow. For consumption it is much easier to use the package
+dependency manager, \l{bpkg(1)}, directly.
+
+First we create a suitable build configuration with the \l{bpkg-cfg-create(1)}
+command. We can use the same place for building all our tools so let's call
+the directory \c{tool-builds/}. Seeing that we are only interested in using
+(rather than developing) such tools, let's build them optimized and also
+configure a suitable installation location:
+
+\
+$ bpkg create -d tool-builds cc  \
+  config.cxx=g++                 \
+  config.cc.coptions=-O3         \
+  config.install.root=/usr/local \
+  config.install.sudo=sudo
+
+$ cd tool-builds
+\
+
+\N|The \c{bdep} build configurations we were creating with \c{init\ -C} are
+actually \c{bpkg} build configurations. In fact, underneath, \l{bdep-init(1)}
+calls \l{bpkg-cfg-create(1)}.|
+
+To fetch and build packages (as well as all their required dependencies)
+we use the \l{bpkg-pkg-build(1)} command:
+
+\
+$ bpkg build https://example.org/hello.git
+<...>
+\
+
+\N|Passing a repository URL to the \c{build} command is a shortcut to the
+following sequence of commands:
+
+\
+$ bpkg add https://example.org/hello.git  # add repository
+$ bpkg fetch                              # fetch available packages
+$ bpkg build hello                        # build package by name
+\
+
+|
+
+Once built, we can install the package to the location that we have specified
+with the \c{config.install.root} variable using the \l{bpkg-pkg-install(1)}
+command:
+
+\
+$ bpkg install hello
+<...>
+\
+
+\N|If on your system the installed executables don't run because of the
+unresolved shared libraries, then the easiest way to fix this is usually to use
+\i{rpath}. Simply add the following configuration variable when creating the
+build configuration (or as an argument to the \c{install} command):
+
+\
+config.bin.rpath=/usr/local/lib
+\
+
+|
+
+If we need to uninstall a previously installed package, there is the
+\l{bpkg-pkg-uninstall(1)} command:
+
+\
+$ bpkg uninstall hello
+<...>
+\
+
+To upgrade or downgrade packages we again use the \c{build} command. Here
+is a typical upgrade workflow:
+
+\
+$ bpkg fetch              # refresh available packages
+$ bpkg status             # see if new versions are available
+
+$ bpkg uninstall hello    # uninstall old version
+$ bpkg build     hello    # upgrade to the latest version
+$ bpkg install   hello    # install new version
+\
+
+Similar to \c{bdep}, to downgrade we have to specify the desired version
+explicitly. There are also the \c{--upgrade|-u} and \c{--patch|-p} as well as
+\c{--immediate|-i} and \c{--recursive|-r} options that allow use to upgrade or
+patch packages that we have built and/or their immediate or all dependencies
+(see \l{bpkg-pkg-build(1)} for details). For example, to make sure everything
+is patched, run:
+
+\
+$ bpkg fetch
+$ bpkg build -pr
+\
+
+If a packages are no longer needed, we can remove it from the configuration
+with \l{bpkg-pkg-drop(1)}:
+
+\
+$ bpkg drop hello
+\
+
+-----------------------------------------------------------------------------
+
+\
+$ git clone https://git.build2.org/hello.git
+$ cd hello/
+
+$ bdep init --empty
+
+$ bdep config create @gcc ../hello-gcc/ cc config.cxx=g++
+$ bdep config create @clang ../hello-clang/ cc config.cxx=clang++
+
+$ bdep init              # in default (gcc)
+$ bdep init @clang       # in clang only
+$ bdep init @clang @gcc  # in clang and gcc
+$ bdep init -a           # in all (clang and gcc)
+
+$ cd ../
+$ bpkg create -d hello-mingw/ cc config.cxx=x86_64-w64-mingw32-g++
+$ bdep init -d hello/ --add hello-mingw/
+
+$ tree -F ./
+...
+
+$ cd hello/
+$ b
+$ ./hello World
+
+$ b ../hello-clang/hello/
+$ ../hello-clang/hello/hello World
+
+$ b ../hello-mingw/hello/
+$ ../hello-mingw/hello/hello.exe World
+
+$ edit ...
+$ bdep sync                     # default (gcc)
+$ bdep sync @clang              # clang only
+$ bdep sync @clang  @gcc        # clang and gcc
+$ bdep sync -c ../hello-mingw/  # mingw
+$ bdep sync -a                  # all (clang, gcc, and mingw)
+
+$ b ../hello-*/hello/
+
+$ bdep fetch                   # default (but can change with @/-a/-c)
+$ bdep status                  # ditto
+$ bdep upgrade libhello/1.1.0  # ditto
+
+$ b
+$ ./hello World
+$ b test
+
+# Looks good so upgrade the rest.
+#
+$ bdep upgrade -f -a libhello/1.1.0
+
+$ b test: ../hello-*/hello/
+\
+"
-- 
cgit v1.1