aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitattributes3
-rw-r--r--.gitignore6
-rw-r--r--.gitmodules17
-rw-r--r--BOOTSTRAP-UNIX.cli123
-rw-r--r--BOOTSTRAP-WINDOWS-CLANG.cli111
-rw-r--r--BOOTSTRAP-WINDOWS-MINGW.cli95
-rw-r--r--BOOTSTRAP-WINDOWS-MSVC.cli91
-rw-r--r--LICENSE2
-rw-r--r--README-GIT4
-rw-r--r--UPGRADE.cli91
m---------bdep0
m---------bpkg0
-rw-r--r--build-clang.bat388
-rw-r--r--build-clang.bat.in714
-rw-r--r--build-mingw.bat398
-rw-r--r--build-mingw.bat.in716
-rw-r--r--build-msvc.bat361
-rw-r--r--build-msvc.bat.in670
-rwxr-xr-xbuild.sh414
-rw-r--r--build.sh.in780
-rw-r--r--build/bootstrap.build11
m---------build20
-rw-r--r--buildfile104
-rw-r--r--doc/.gitignore6
-rw-r--r--doc/buildfile2
-rwxr-xr-xdoc/cli.sh8
-rw-r--r--doc/intro.cli999
-rw-r--r--doc/packaging.cli5392
m---------doc/style0
m---------libbpkg0
l---------libbuild2-autoconf1
l---------libbuild2-kconfig1
m---------libbutl0
m---------libodb0
m---------libodb-sqlite0
l---------libpkg-config1
l---------libpkgconf1
l---------libsqlite32
-rw-r--r--manifest6
m---------pkgconf0
m---------sqlite0
m---------submodules/libbuild2-autoconf0
m---------submodules/libbuild2-kconfig0
m---------submodules/libpkg-config0
m---------submodules/sqlite0
-rw-r--r--tests/README2
l---------tests/libbuild2-autoconf-tests1
l---------tests/libbuild2-kconfig-tests1
48 files changed, 9644 insertions, 1878 deletions
diff --git a/.gitattributes b/.gitattributes
index 1631641..9a79d3b 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -7,7 +7,8 @@
# Use `eol=crlf` for files that should have the CRLF line ending both in the
# working tree (even on Unix) and in the repository.
#
-#*.bat text eol=crlf
+*.bat text eol=crlf
+*.bat.in text eol=crlf
# Use `eol=lf` for files that should have the LF line ending both in the
# working tree (even on Windows) and in the repository.
diff --git a/.gitignore b/.gitignore
index 68e3c03..a18d885 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,9 @@ INSTALL
UPGRADE
BOOTSTRAP-*
!BOOTSTRAP-*.cli
+
+# Building output.
+#
+*.d
+build.sh
+build-*.bat
diff --git a/.gitmodules b/.gitmodules
index 923e17b..b95cbe3 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -24,11 +24,16 @@
path = libodb-sqlite
url = https://scm.codesynthesis.com/odb/libodb-sqlite.git
update = none
-[submodule "sqlite"]
- path = sqlite
+[submodule "submodules/sqlite"]
+ path = submodules/sqlite
url = https://git.build2.org/packaging/sqlite/sqlite.git
update = none
-[submodule "pkgconf"]
- path = pkgconf
- url = https://git.build2.org/packaging/pkgconf/pkgconf.git
- update = none
+[submodule "submodules/libbuild2-kconfig"]
+ path = submodules/libbuild2-kconfig
+ url = https://github.com/build2/libbuild2-kconfig.git
+[submodule "submodules/libbuild2-autoconf"]
+ path = submodules/libbuild2-autoconf
+ url = https://github.com/build2/libbuild2-autoconf.git
+[submodule "submodules/libpkg-config"]
+ path = submodules/libpkg-config
+ url = https://github.com/build2/libpkg-config.git
diff --git a/BOOTSTRAP-UNIX.cli b/BOOTSTRAP-UNIX.cli
index f0ff600..aee6fd9 100644
--- a/BOOTSTRAP-UNIX.cli
+++ b/BOOTSTRAP-UNIX.cli
@@ -97,7 +97,7 @@ versions. It can also be used to uninstall the toolchain:
\
$ cd build2-toolchain-X.Y
-$ bpkg uninstall build2 bpkg bdep
+$ bpkg uninstall --all
\
\N|Note that in both cases (manual or scripted bootstrap), if something goes
@@ -118,7 +118,7 @@ file for details.
\
$ cd build2
-$ ./bootstrap.sh g++
+$ ./bootstrap.sh g++ -w
$ build2/b-boot --version
\
@@ -128,7 +128,7 @@ in parallel:
\
$ cd build2
-$ make -f bootstrap.gmake -j 8 CXX=g++
+$ make -f bootstrap.gmake -j 8 CXX=g++ CXXFLAGS=-w
$ build2/b-boot --version
\
@@ -177,6 +177,28 @@ $ build2/build2/b-boot configure \
$ build2/build2/b-boot install: build2/ bpkg/
\
+\N|The above command will build all the dependencies of \c{build2} and
+\c{bpkg} from sources bundled with \c{build2-toolchain}. If instead you would
+like to use system-installed versions for some of them, then you can specify
+empty \c{config.import.*} values to disable the use of the bundled versions.
+For example, to use the system-installed SQLite:
+
+\
+$ build2/build2/b-boot configure \
+ ... \
+ config.import.libsqlite3=
+\
+
+If performing an installation with the \c{build.sh} script, then to use the
+system-installed dependencies pass the \c{--system} option, specifying such
+dependencies as a comma-separated list. For example:
+
+\
+$ ./build.sh --system libsqlite3,libpkg-config g++
+\
+
+|
+
The strange-looking \c{config.install.data_root=root/stage} means install
data files (as opposed to executable files) into the \c{stage/} subdirectory
of wherever \c{config.install.root} points to (so in our case it will be
@@ -215,13 +237,19 @@ subdirectory is in \c{PATH}.
At the next step we will use \c{bpkg} to build and install the entire
toolchain. If for some reason you prefer not to build from packages (for
example, because the machine is offline), then you can convert this step into
-a local installation and skip the rest. For this you will need to change
-the \c{configure} and \c{install} command lines above along these lines (see
-also notes on the following step about only building shared libraries and
-private installation subdirectory):
+a local installation and skip the rest of the steps.
+
+\N|To perform a local installation with the \c{build.sh} script, pass the
+\c{--local} option.|
+
+To perform a local installation you will need to change the \c{configure} and
+\c{install} command lines above along these lines (see also notes on the
+following step about only building shared libraries, private installation
+subdirectory, toolchain executables prefix/suffix, etc):
\
$ build2/build2/b-boot configure \
+ config.config.hermetic=true \
config.cxx=g++ \
config.cc.coptions=-O3 \
config.bin.lib=shared \
@@ -233,13 +261,25 @@ $ build2/build2/b-boot configure \
$ build2/build2/b-boot install: build2/ bpkg/ bdep/
\
-\N|To perform a local installation with the \c{build.sh} script, pass the
-\c{--local} option.|
+You will also need to build and install the standard build system modules:
+
+\
+$ b install: '!config.install.scope=project' libbuild2-*/
+\
+
+\N|To verify the build system modules installation you can load them with the
+following command:
+
+\
+$ b noop: tests/libbuild2-*/
+\
+
+|
To uninstall such a local installation, run:
\
-$ b uninstall: build2/ bpkg/ bdep/
+$ b uninstall: build2/ bpkg/ bdep/ libbuild2-*/
\
|
@@ -259,6 +299,7 @@ $ cd build2-toolchain-X.Y
$ bpkg-stage create \
cc \
+ config.config.hermetic=true \
config.cxx=g++ \
config.cc.coptions=-O3 \
config.bin.lib=shared \
@@ -280,16 +321,49 @@ and that any further such installations won't interfere with \c{build2}. If,
however, you are installing into a private location, such as \c{/opt/build2/},
then you can remove \c{config.install.private=build2}.|
+\N|To add a custom prefix/suffix to the toolchain executables names, add
+\c{config.bin.exe.prefix=...} and/or \c{config.bin.exe.suffix=...}.|
+
+\N|The \c{config.config.hermetic=true} configuration variable in the above
+command makes sure the embedded \c{~host} and \c{~build2} configurations
+include the current environment. This is especially important for \c{~build2}
+which is used to dynamically build and load ad hoc recipes and build system
+modules and must therefore match the environment that was used to build the
+build system itself.|
+
Next, we add the package repository, build, and install:
\
$ bpkg-stage add https://pkg.cppget.org/1/alpha
$ bpkg-stage fetch
$ bpkg-stage build --for install build2 bpkg bdep
-$ bpkg-stage install build2 bpkg bdep
+$ bpkg-stage install --all
\
-Finally, we verify the result:
+\N|The above command will build all the dependencies of \c{build2}, \c{bpkg},
+and \c{bdep} from source packages. If instead you would like to use
+system-installed versions for some of them, then you can list them with the
+\c{sys} scheme to make \c{bpkg-stage} treat them as available from the system
+rather than building them from source. For example, to use the
+system-installed SQLite:
+
+\
+$ bpkg-stage build --for install build2 bpkg bdep ?sys:libsqlite3
+\
+
+|
+
+\N|By default \c{bpkg} will build the latest available version of each
+package. You can, however, specify the desired versions explicitly, for
+example:
+
+\
+$ bpkg-stage build --for install build2/X.Y.Z bpkg/X.Y.Z bdep/X.Y.Z
+\
+
+|
+
+To verify the result, run:
\
$ which b
@@ -306,8 +380,33 @@ $ bpkg --version
$ bdep --version
\
+Finally, we build and install the standard build system modules:
+
+\
+$ bpkg build --for install libbuild2-autoconf libbuild2-kconfig
+$ bpkg install '!config.install.scope=project' \
+ --all-pattern=libbuild2-*
+\
+
+\N|To get a list of the standard pre-installed build system modules in a
+specific version of the toolchain, run:
+
+\
+$ cd ../build2-toolchain-X.Y.Z
+$ ls -d libbuild2-*
+\
+
|
+\N|To verify the build system modules installation you can load them with the
+following command:
+
+\
+$ b noop: ../build2-toolchain-X.Y.Z/tests/libbuild2-*/
+\
+
+||
+
\li|\n\b{5. Clean}\n
The last thing we need to do is uninstall the staged tools:
diff --git a/BOOTSTRAP-WINDOWS-CLANG.cli b/BOOTSTRAP-WINDOWS-CLANG.cli
index f35c212..3429c5a 100644
--- a/BOOTSTRAP-WINDOWS-CLANG.cli
+++ b/BOOTSTRAP-WINDOWS-CLANG.cli
@@ -48,7 +48,7 @@ versions. It can also be used to uninstall the toolchain:
\
> cd build2-toolchain-X.Y
-> bpkg uninstall build2 bpkg bdep
+> bpkg uninstall --all
\
\N|Note that in both cases (manual or scripted bootstrap), if something goes
@@ -69,7 +69,7 @@ compile options; run \c{bootstrap-clang.bat /?} and see the
\
> cd build2
-> .\bootstrap-clang.bat clang++
+> .\bootstrap-clang.bat clang++ -m64 -w
> build2\b-boot --version
\
@@ -79,7 +79,7 @@ in parallel:
\
> cd build2
-> mingw32-make -f bootstrap.gmake -j 8 CXX=clang++
+> mingw32-make -f bootstrap.gmake -j 8 CXX=clang++ \"CXXFLAGS=-m64 -w\"
> build2\b-boot --version
\
@@ -92,10 +92,9 @@ Then, we rebuild the build system with the result of Phase 1 linking libraries
statically.
\
-> build2\b-boot ^
- config.cxx=clang++ ^
- config.cc.coptions=-m64 ^
- config.bin.lib=static ^
+> build2\b-boot ^
+ \"config.cxx=clang++ -m64\" ^
+ config.bin.lib=static ^
build2\exe{b}
> move /y build2\b.exe build2\b-boot.exe
@@ -114,14 +113,13 @@ libraries and then staged:
> cd .. # Back to build2-toolchain-X.Y.Z\
> build2\build2\b-boot configure ^
- config.cxx=clang++ ^
- config.cc.coptions=-m64 ^
+ \"config.cxx=clang++ -m64\" ^
config.bin.lib=shared ^
config.bin.suffix=-stage ^
config.install.root=C:\build2 ^
config.install.data_root=root\stage
-> build2\build2\b-boot install: build2/ bpkg/
+> build2\build2\b-boot install: build2\ bpkg\
\
The strange-looking \c{config.install.data_root=root\\stage} means install
@@ -147,27 +145,46 @@ C:\build2\bin\bpkg-stage.exe
At the next step we will use \c{bpkg} to build and install the entire
toolchain. If for some reason you prefer not to build from packages (for
example, because the machine is offline), then you can convert this step into
-a local installation and skip the rest. For this you will need to change
-the \c{configure} and \c{install} command lines above along these lines (see
-also a note on the following step about only building shared libraries):
+a local installation and skip the rest of the steps.
+
+\N|To perform a local installation with the \c{build-clang.bat} batch file,
+pass the \c{--local} option.|
+
+To perform a local installation you will need to change the \c{configure} and
+\c{install} command lines above along these lines (see also a note on the
+following step about only building shared libraries, toolchain executables
+prefix/suffix, etc):
\
> build2\build2\b-boot configure ^
- config.cxx=clang++ ^
- \"config.cc.coptions=-m64 -O3\" ^
+ config.config.hermetic=true ^
+ \"config.cxx=clang++ -m64\" ^
+ config.cc.coptions=-O2 ^
config.bin.lib=shared ^
config.install.root=C:\build2
-> build2\build2\b-boot install: build2/ bpkg/ bdep/
+> build2\build2\b-boot install: build2\ bpkg\ bdep\
\
-\N|To perform a local installation with the \c{build-clang.bat} batch file,
-pass the \c{--local} option.|
+You will also need to build and install the standard build system modules:
+
+\
+> b install: !config.install.scope=project libbuild2-*\
+\
+
+\N|To verify the build system modules installation you can load them with the
+following command:
+
+\
+> b noop: tests\libbuild2-*\
+\
+
+|
To uninstall such a local installation, run:
\
-> b uninstall: build2/ bpkg/ bdep/
+> b uninstall: build2\ bpkg\ bdep\ libbuild2-*\
\
|
@@ -186,8 +203,9 @@ previous step and you may want/need to make similar adjustments.
> bpkg-stage create ^
cc ^
- config.cxx=clang++ ^
- \"config.cc.coptions=-m64 -O3\" ^
+ config.config.hermetic=true ^
+ \"config.cxx=clang++ -m64\" ^
+ config.cc.coptions=-O2 ^
config.bin.lib=shared ^
config.install.root=C:\build2
\
@@ -195,16 +213,36 @@ previous step and you may want/need to make similar adjustments.
\N|The above configuration will only build shared libraries. If you would like
to build both shared and static, remove \c{config.bin.lib=shared}.|
+\N|To add a custom prefix/suffix to the toolchain executables names, add
+\c{config.bin.exe.prefix=...} and/or \c{config.bin.exe.suffix=...}.|
+
+\N|The \c{config.config.hermetic=true} configuration variable in the above
+command makes sure the embedded \c{~host} and \c{~build2} configurations
+include the current environment. This is especially important for \c{~build2}
+which is used to dynamically build and load ad hoc recipes and build system
+modules and must therefore match the environment that was used to build the
+build system itself.|
+
Next, we add the package repository, build, and install:
\
> bpkg-stage add https://pkg.cppget.org/1/alpha
> bpkg-stage fetch
> bpkg-stage build --for install build2 bpkg bdep
-> bpkg-stage install build2 bpkg bdep
+> bpkg-stage install --all
\
-Finally, we verify the result:
+\N|By default \c{bpkg} will build the latest available version of each
+package. You can, however, specify the desired versions explicitly, for
+example:
+
+\
+> bpkg-stage build --for install build2/X.Y.Z bpkg/X.Y.Z bdep/X.Y.Z
+\
+
+|
+
+To verify the result, run:
\
> where b
@@ -221,15 +259,40 @@ C:\build2\bin\bdep.exe
> bdep --version
\
+Finally, we build and install the standard build system modules:
+
+\
+> bpkg build --for install libbuild2-autoconf libbuild2-kconfig
+> bpkg install !config.install.scope=project ^
+ --all-pattern=libbuild2-*
+\
+
+\N|To get a list of the standard pre-installed build system modules in a
+specific version of the toolchain, run:
+
+\
+> cd ..\build2-toolchain-X.Y.Z
+> dir /B libbuild2-*
+\
+
|
+\N|To verify the build system modules installation you can load them with the
+following command:
+
+\
+> b noop: ..\build2-toolchain-X.Y.Z\tests\libbuild2-*\
+\
+
+||
+
\li|\n\b{5. Clean}\n
The last thing we need to do is uninstall the staged tools:
\
> cd ..\build2-toolchain-X.Y.Z # Back to bootstrap.
-> b uninstall: build2/ bpkg/
+> b uninstall: build2\ bpkg\
\
||
diff --git a/BOOTSTRAP-WINDOWS-MINGW.cli b/BOOTSTRAP-WINDOWS-MINGW.cli
index 852b80b..39c2581 100644
--- a/BOOTSTRAP-WINDOWS-MINGW.cli
+++ b/BOOTSTRAP-WINDOWS-MINGW.cli
@@ -56,7 +56,7 @@ versions. It can also be used to uninstall the toolchain:
\
> cd build2-toolchain-X.Y
-> bpkg uninstall build2 bpkg bdep
+> bpkg uninstall --all
\
\N|Note that in both cases (manual or scripted bootstrap), if something goes
@@ -77,7 +77,7 @@ compile options; run \c{bootstrap-mingw.bat /?} and see the
\
> cd build2
-> .\bootstrap-mingw.bat g++ -static
+> .\bootstrap-mingw.bat g++ -w -static
> build2\b-boot --version
\
@@ -87,7 +87,7 @@ in parallel:
\
> cd build2
-> mingw32-make -f bootstrap.gmake -j 8 CXX=g++ LDFLAGS=-static
+> mingw32-make -f bootstrap.gmake -j 8 CXX=g++ CXXFLAGS=-w LDFLAGS=-static
> build2\b-boot --version
\
@@ -123,7 +123,7 @@ libraries and then staged:
config.install.root=C:\build2 ^
config.install.data_root=root\stage
-> build2\build2\b-boot install: build2/ bpkg/
+> build2\build2\b-boot install: build2\ bpkg\
\
The strange-looking \c{config.install.data_root=root\\stage} means install
@@ -149,27 +149,46 @@ C:\build2\bin\bpkg-stage.exe
At the next step we will use \c{bpkg} to build and install the entire
toolchain. If for some reason you prefer not to build from packages (for
example, because the machine is offline), then you can convert this step into
-a local installation and skip the rest. For this you will need to change
-the \c{configure} and \c{install} command lines above along these lines (see
-also a note on the following step about only building shared libraries):
+a local installation and skip the rest of the steps.
+
+\N|To perform a local installation with the \c{build-mingw.bat} batch file,
+pass the \c{--local} option.|
+
+To perform a local installation you will need to change the \c{configure} and
+\c{install} command lines above along these lines (see also a note on the
+following step about only building shared libraries, toolchain executables
+prefix/suffix, etc):
\
> build2\build2\b-boot configure ^
+ config.config.hermetic=true ^
config.cxx=g++ ^
config.cc.coptions=-O3 ^
config.bin.lib=shared ^
config.install.root=C:\build2
-> build2\build2\b-boot install: build2/ bpkg/ bdep/
+> build2\build2\b-boot install: build2\ bpkg\ bdep\
\
-\N|To perform a local installation with the \c{build-mingw.bat} batch file,
-pass the \c{--local} option.|
+You will also need to build and install the standard build system modules:
+
+\
+> b install: !config.install.scope=project libbuild2-*\
+\
+
+\N|To verify the build system modules installation you can load them with the
+following command:
+
+\
+> b noop: tests\libbuild2-*\
+\
+
+|
To uninstall such a local installation, run:
\
-> b uninstall: build2/ bpkg/ bdep/
+> b uninstall: build2\ bpkg\ bdep\ libbuild2-*\
\
|
@@ -188,6 +207,7 @@ previous step and you may want/need to make similar adjustments.
> bpkg-stage create ^
cc ^
+ config.config.hermetic=true ^
config.cxx=g++ ^
config.cc.coptions=-O3 ^
config.bin.lib=shared ^
@@ -197,17 +217,37 @@ previous step and you may want/need to make similar adjustments.
\N|The above configuration will only build shared libraries. If you would like
to build both shared and static, remove \c{config.bin.lib=shared}.|
+\N|To add a custom prefix/suffix to the toolchain executables names, add
+\c{config.bin.exe.prefix=...} and/or \c{config.bin.exe.suffix=...}.|
+
+\N|The \c{config.config.hermetic=true} configuration variable in the above
+command makes sure the embedded \c{~host} and \c{~build2} configurations
+include the current environment. This is especially important for \c{~build2}
+which is used to dynamically build and load ad hoc recipes and build system
+modules and must therefore match the environment that was used to build the
+build system itself.|
+
Next, we add the package repository, build, and install:
\
> bpkg-stage add https://pkg.cppget.org/1/alpha
> bpkg-stage fetch
> bpkg-stage build --for install build2 bpkg bdep
-> bpkg-stage install build2 bpkg bdep
+> bpkg-stage install --all
\
-Finally, we verify the result (note that the \c{where} command is not
-available on Windows XP without the Resource Kit installed):
+\N|By default \c{bpkg} will build the latest available version of each
+package. You can, however, specify the desired versions explicitly, for
+example:
+
+\
+> bpkg-stage build --for install build2/X.Y.Z bpkg/X.Y.Z bdep/X.Y.Z
+\
+
+|
+
+To verify the result, run (note that the \c{where} command is not available on
+Windows XP without the Resource Kit installed):
\
> where b
@@ -224,15 +264,40 @@ C:\build2\bin\bdep.exe
> bdep --version
\
+Finally, we build and install the standard build system modules:
+
+\
+> bpkg build --for install libbuild2-autoconf libbuild2-kconfig
+> bpkg install !config.install.scope=project ^
+ --all-pattern=libbuild2-*
+\
+
+\N|To get a list of the standard pre-installed build system modules in a
+specific version of the toolchain, run:
+
+\
+> cd ..\build2-toolchain-X.Y.Z
+> dir /B libbuild2-*
+\
+
|
+\N|To verify the build system modules installation you can load them with the
+following command:
+
+\
+> b noop: ..\build2-toolchain-X.Y.Z\tests\libbuild2-*\
+\
+
+||
+
\li|\n\b{5. Clean}\n
The last thing we need to do is uninstall the staged tools:
\
> cd ..\build2-toolchain-X.Y.Z # Back to bootstrap.
-> b uninstall: build2/ bpkg/
+> b uninstall: build2\ bpkg\
\
||
diff --git a/BOOTSTRAP-WINDOWS-MSVC.cli b/BOOTSTRAP-WINDOWS-MSVC.cli
index b162ad9..49a84c0 100644
--- a/BOOTSTRAP-WINDOWS-MSVC.cli
+++ b/BOOTSTRAP-WINDOWS-MSVC.cli
@@ -38,7 +38,7 @@ versions. It can also be used to uninstall the toolchain:
\
> cd build2-toolchain-X.Y
-> bpkg uninstall build2 bpkg bdep
+> bpkg uninstall --all
\
\N|Note that in both cases (manual or scripted bootstrap), if something goes
@@ -59,7 +59,7 @@ file for details.
\
> cd build2
-> .\bootstrap-msvc.bat cl
+> .\bootstrap-msvc.bat cl /w /MP8
> build2\b-boot --version
\
@@ -95,7 +95,7 @@ libraries and then staged:
config.install.root=C:\build2 ^
config.install.data_root=root\stage
-> build2\build2\b-boot install: build2/ bpkg/
+> build2\build2\b-boot install: build2\ bpkg\
\
The strange-looking \c{config.install.data_root=root\\stage} means install
@@ -121,27 +121,46 @@ C:\build2\bin\bpkg-stage.exe
At the next step we will use \c{bpkg} to build and install the entire
toolchain. If for some reason you prefer not to build from packages (for
example, because the machine is offline), then you can convert this step into
-a local installation and skip the rest. For this you will need to change
-the \c{configure} and \c{install} command lines above along these lines (see
-also a note on the following step about only building shared libraries):
+a local installation and skip the rest of the steps.
+
+\N|To perform a local installation with the \c{build-msvc.bat} batch file,
+pass the \c{--local} option.|
+
+To perform a local installation you will need to change the \c{configure} and
+\c{install} command lines above along these lines (see also a note on the
+following step about only building shared libraries, toolchain executables
+prefix/suffix, etc):
\
> build2\build2\b-boot configure ^
+ config.config.hermetic=true ^
config.cxx=cl ^
config.cc.coptions=/O2 ^
config.bin.lib=shared ^
config.install.root=C:\build2
-> build2\build2\b-boot install: build2/ bpkg/ bdep/
+> build2\build2\b-boot install: build2\ bpkg\ bdep\
\
-\N|To perform a local installation with the \c{build-msvc.bat} batch file,
-pass the \c{--local} option.|
+You will also need to build and install the standard build system modules:
+
+\
+> b install: !config.install.scope=project libbuild2-*\
+\
+
+\N|To verify the build system modules installation you can load them with the
+following command:
+
+\
+> b noop: tests\libbuild2-*\
+\
+
+|
To uninstall such a local installation, run:
\
-> b uninstall: build2/ bpkg/ bdep/
+> b uninstall: build2\ bpkg\ bdep\ libbuild2-*\
\
|
@@ -160,6 +179,7 @@ previous step and you may want/need to make similar adjustments.
> bpkg-stage create ^
cc ^
+ config.config.hermetic=true ^
config.cxx=cl ^
config.cc.coptions=/O2 ^
config.bin.lib=shared ^
@@ -169,16 +189,36 @@ previous step and you may want/need to make similar adjustments.
\N|The above configuration will only build shared libraries. If you would like
to build both shared and static, remove \c{config.bin.lib=shared}.|
+\N|To add a custom prefix/suffix to the toolchain executables names, add
+\c{config.bin.exe.prefix=...} and/or \c{config.bin.exe.suffix=...}.|
+
+\N|The \c{config.config.hermetic=true} configuration variable in the above
+command makes sure the embedded \c{~host} and \c{~build2} configurations
+include the current environment. This is especially important for \c{~build2}
+which is used to dynamically build and load ad hoc recipes and build system
+modules and must therefore match the environment that was used to build the
+build system itself.|
+
Next, we add the package repository, build, and install:
\
> bpkg-stage add https://pkg.cppget.org/1/alpha
> bpkg-stage fetch
> bpkg-stage build --for install build2 bpkg bdep
-> bpkg-stage install build2 bpkg bdep
+> bpkg-stage install --all
\
-Finally, we verify the result:
+\N|By default \c{bpkg} will build the latest available version of each
+package. You can, however, specify the desired versions explicitly, for
+example:
+
+\
+> bpkg-stage build --for install build2/X.Y.Z bpkg/X.Y.Z bdep/X.Y.Z
+\
+
+|
+
+To verify the result, run:
\
> where b
@@ -195,15 +235,40 @@ C:\build2\bin\bdep.exe
> bdep --version
\
+Finally, we build and install the standard build system modules:
+
+\
+> bpkg build --for install libbuild2-autoconf libbuild2-kconfig
+> bpkg install !config.install.scope=project ^
+ --all-pattern=libbuild2-*
+\
+
+\N|To get a list of the standard pre-installed build system modules in a
+specific version of the toolchain, run:
+
+\
+> cd ..\build2-toolchain-X.Y.Z
+> dir /B libbuild2-*
+\
+
|
+\N|To verify the build system modules installation you can load them with the
+following command:
+
+\
+> b noop: ..\build2-toolchain-X.Y.Z\tests\libbuild2-*\
+\
+
+||
+
\li|\n\b{5. Clean}\n
The last thing we need to do is uninstall the staged tools:
\
> cd ..\build2-toolchain-X.Y.Z # Back to bootstrap.
-> b uninstall: build2/ bpkg/
+> b uninstall: build2\ bpkg\
\
||
diff --git a/LICENSE b/LICENSE
index 8c473f0..7e89b74 100644
--- a/LICENSE
+++ b/LICENSE
@@ -4,7 +4,7 @@ The rest:
MIT License
-Copyright (c) 2014-2020 the build2 authors (see the AUTHORS file).
+Copyright (c) 2014-2024 the build2 authors (see the AUTHORS file).
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/README-GIT b/README-GIT
index 7a2cae1..ef48a70 100644
--- a/README-GIT
+++ b/README-GIT
@@ -25,7 +25,7 @@ A few additional notes:
commits)' next to submodules (i.e., git "thinks" you have modified the
member project by "setting back" its subproject commit).
-2. The pkgconf, sqlite and libodb* submodules are not updated by default
+2. The libpkg-config, sqlite and libodb* submodules are not updated by default
(e.g., with the above command). This is achieved with:
git config --file .gitmodules submodule.sqlite.update none
@@ -33,7 +33,7 @@ A few additional notes:
Instead, their updates (normally to something tagged) must be requested
explicitly:
- git submodule update --remote --checkout sqlite
+ git submodule update --remote --checkout submodules/sqlite
Note that you need a fairly recent git (e.g., 2.9) for this enforcement
to work.
diff --git a/UPGRADE.cli b/UPGRADE.cli
index d76eb41..f5fcc65 100644
--- a/UPGRADE.cli
+++ b/UPGRADE.cli
@@ -23,9 +23,9 @@ toolchain (similar to what we did during bootstrap), test it, uninstall the
old toolchain, install the new toolchain as \"final\", and finally uninstall
\c{-stage}.
-We recommend that you use a dirty upgrade for patch releases with the same
-\c{X.Y} (\c{MAJOR.MINOR}) version and a staged upgrade otherwise. With patch
-releases we guarantee not to alter the installation file set.
+We recommend that you use a dirty upgrade for toolchain patch releases with
+the same \c{X.Y} (\c{MAJOR.MINOR}) version and a staged upgrade otherwise.
+With patch releases we guarantee not to alter the installation file set.
\N|Without periodic upgrades your version of the toolchain may become too old
to be able to upgrade itself. In this case you will have to fall back onto the
@@ -37,31 +37,43 @@ Windows} for details). We recommend using the bootstrap process to upgrade
these packages since all the straightforward upgrade sequences would lead to
either the old toolchain using the new utilities or vice versa.|
+\N|For both ways of upgrading we need to make sure that the build system
+modules are built and installed with the new version of the toolchain. The set
+of build system modules can also change from version to version.|
+
+\N|If using the Windows command prompt, the \c{!config.install.scope=project}
+command line argument should not be quoted.|
+
The dirty upgrade is straightforward:
\
$ cd build2-toolchain-X.Y
+$ bpkg uninstall '!config.install.scope=project' \
+ --all-pattern=libbuild2-*
+$ bpkg drop --all-pattern=libbuild2-*
$ bpkg fetch
-$ bpkg build --for install -ur build2 bpkg bdep
-$ bpkg install build2 bpkg bdep
+$ bpkg build --for install -pr
+$ bpkg install --all
+$ bpkg build --for install libbuild2-autoconf libbuild2-kconfig
+$ bpkg install '!config.install.scope=project' \
+ --all-pattern=libbuild2-*
\
-\N|The \c{-ur} options stands for \c{--upgrade} and \c{--recursive} \- upgrade
-the listed packages and their dependencies, recursively. See
-\l{bpkg-pkg-build(1)} for details.|
+\N|The \c{-pr} options stands for \c{--patch} and \c{--recursive} \- upgrade
+the built packages and their dependencies to the latest patch version,
+recursively. See \l{bpkg-pkg-build(1)} for details.|
-You may also want to issue the \c{status} command after \c{fetch} to examine
-which versions are available. By default \c{bpkg} will upgrade to the latest
-available but you can override this by specifying the desired version
-explicitly, for example:
+You can also issue the \c{status} command after \c{fetch} to examine which
+versions are available. The above \c{build} command will upgrade all the
+packages to the latest available patch versions but you can override this by
+specifying the desired packages and/or versions explicitly, for example:
\
-$ bpkg status build2 bpkg bdep
-!build2 configured 1.0.0 available 1.0.1 2.0.0
-!bpkg configured 1.0.0 available 1.0.1 2.0.0
-!bdep configured 1.0.0 available 1.0.1 2.0.0
+$ bpkg status
+!build2 configured 1.0.0 available 1.0.1 1.0.2 2.0.0
+...
-$ bpkg build --for install build2/1.0.1 bpkg/1.0.1 bdep/1.0.1
+$ bpkg build --for install build2/1.0.1
\
The staged upgrade consists of several steps:
@@ -106,19 +118,33 @@ Or, using Windows command prompt:
\li|\n\b{2. Build and Install as \c{-stage}}\n
-This step is similar to the dirty upgrade except we use the copied
-configuration and install the new toolchain with the \c{-stage} suffix:
+This step is similar to the dirty upgrade except that we use the copied
+configuration, upgrade (\c{--upgrade|-u}) instead of patching
+(\c{--patch|-p}), and install the new toolchain with the \c{-stage} suffix:
\
$ cd build2-toolchain-X.Z
-$ bpkg build --for install -ur build2 bpkg bdep
+$ bpkg drop --all-pattern=libbuild2-*
+$ bpkg build --for install -ur
+\
+
+Once this is done, we can proceed to installing:
+
+\
$ bpkg install \
config.bin.suffix=-stage \
config.install.data_root=root/stage \
- build2 bpkg bdep
+ --all
\
-|
+\N|If during installation you have added a custom prefix/suffix to the
+toolchain executables names with \c{config.bin.exe.prefix} and/or
+\c{config.bin.exe.suffix}, add \c{config.bin.exe.prefix=[null]} and/or
+\c{config.bin.exe.suffix=[null]} to suppress them in the executables being
+staged.|
+
+You can also specify the desired packages and/or versions explicitly, again,
+similar to the dirty upgrade.|
\li|\n\b{3. Test Staged}\n
@@ -141,10 +167,13 @@ one and install the new one:
\
$ cd ../build2-toolchain-X.Y
-$ bpkg uninstall build2 bpkg bdep
+$ bpkg uninstall --all
$ cd ../build2-toolchain-X.Z
-$ bpkg-stage install build2 bpkg bdep
+$ bpkg-stage install --all
+$ bpkg build --for install libbuild2-autoconf libbuild2-kconfig
+$ bpkg install '!config.install.scope=project' \
+ --all-pattern=libbuild2-*
\
|
@@ -153,13 +182,14 @@ $ bpkg-stage install build2 bpkg bdep
Finally, we clean up by removing the staged toolchain (hint: use the command
line history to find the corresponding \c{install} command and change it to
-\c{uninstall}):
+\c{uninstall}; see also a note at step 2 about toolchain executables
+prefix/suffix):
\
$ bpkg uninstall \
config.bin.suffix=-stage \
config.install.data_root=root/stage \
- build2 bpkg bdep
+ --all
\
You can also remove the old configuration in \c{build2-toolchain-X.Y/} if you
@@ -176,11 +206,13 @@ For UNIX-like operating systems (GNU/Linux, Mac OS X, FreeBSD, etc):
\
$ bpkg-stage create \
cc \
+config.config.hermetic=true \
config.cxx=g++ \
config.cc.coptions=-O3 \
config.bin.lib=shared \
config.bin.rpath=/usr/local/lib \
config.install.root=/usr/local \
+config.install.private=build2 \
config.install.sudo=sudo
\
@@ -190,6 +222,7 @@ Prompt\"):
\
> bpkg-stage create ^
cc ^
+ config.config.hermetic=true ^
config.cxx=cl ^
config.cc.coptions=/O2 ^
config.bin.lib=shared ^
@@ -202,8 +235,9 @@ For Windows with Clang (from a suitable command prompt, see
\
> bpkg-stage create ^
cc ^
- config.cxx=clang++ ^
- \"config.cc.coptions=-m64 -O3\" ^
+ config.config.hermetic=true ^
+ \"config.cxx=clang++ -m64\" ^
+ config.cc.coptions=-O2 ^
config.bin.lib=shared ^
config.install.root=C:\build2
\
@@ -213,6 +247,7 @@ For Windows with MinGW (from the command prompt):
\
> bpkg-stage create ^
cc ^
+ config.config.hermetic=true ^
config.cxx=g++ ^
config.cc.coptions=-O3 ^
config.bin.lib=shared ^
diff --git a/bdep b/bdep
-Subproject 0aa9086aa2e3c90c1e6142e2d3f3199132009e1
+Subproject 2d9112e84d735e1948313240df8d5140364cca0
diff --git a/bpkg b/bpkg
-Subproject 30b37545ea821bd5a73bdc0a41d5b37c1c002a3
+Subproject 380cb54ab94a502d2d7ff5d47f21839ee9e4f1e
diff --git a/build-clang.bat b/build-clang.bat
deleted file mode 100644
index a2a8c90..0000000
--- a/build-clang.bat
+++ /dev/null
@@ -1,388 +0,0 @@
-@echo off
-
-rem file : build-clang.bat
-rem license : MIT; see accompanying LICENSE file
-
-setlocal EnableDelayedExpansion
-goto start
-
-:usage
-echo.
-echo Usage: %0 [/?] [^<options^>] [^<clang++-compiler^>]
-echo Options:
-echo --local Don't build from packages, only from local source.
-echo --install-dir ^<dir^> Alternative installation directory.
-echo --repo ^<loc^> Alternative package repository location.
-echo --trust ^<fp^> Repository certificate fingerprint to trust.
-echo --timeout ^<sec^> Network operations timeout in seconds.
-echo --make ^<arg^> Bootstrap using GNU make instead of batch file.
-echo --verbose ^<level^> Diagnostics verbosity level between 0 and 6.
-echo.
-echo By default the batch file will use clang++.exe as the C++ compiler and
-echo install into C:\build2. It also expects to find the base utilities in the
-echo bin\ subdirectory of the installation directory ^(C:\build2\bin\ by
-echo default^).
-echo.
-echo The --trust option recognizes two special values: 'yes' ^(trust everything^)
-echo and 'no' (trust nothing).
-echo.
-echo The --make option can be used to bootstrap using GNU make. The first
-echo --make value should specify the make executable optionally followed by
-echo additional make options, for example:
-echo.
-echo %0 --make mingw32-make --make -j8
-echo.
-echo See the BOOTSTRAP-WINDOWS-CLANG file for details.
-echo.
-goto end
-
-:start
-
-set "owd=%CD%"
-
-rem Package repository URL (or path).
-rem
-if "_%BUILD2_REPO%_" == "__" (
- set "BUILD2_REPO=https://stage.build2.org/1"
-rem set "BUILD2_REPO=https://pkg.cppget.org/1/queue/alpha"
-rem set "BUILD2_REPO=https://pkg.cppget.org/1/alpha"
-)
-
-rem The bpkg configuration directory.
-rem
-set "cver=0.13-a.0"
-set "cdir=build2-toolchain-%cver%"
-
-rem Parse options.
-rem
-set "local="
-set "idir=C:\build2"
-set "trust="
-set "timeout="
-set "make="
-set "verbose="
-
-:options
-if "_%~1_" == "_/?_" goto usage
-if "_%~1_" == "_-h_" goto usage
-if "_%~1_" == "_--help_" goto usage
-
-if "_%~1_" == "_--local_" (
- set "local=true"
- shift
- goto options
-)
-
-if "_%~1_" == "_--install-dir_" (
- if "_%~2_" == "__" (
- echo error: installation directory expected after --install-dir
- goto error
- )
- set "idir=%~2"
- shift
- shift
- goto options
-)
-
-if "_%~1_" == "_--trust_" (
- if "_%~2_" == "__" (
- echo error: certificate fingerprint expected after --trust
- goto error
- )
- set "trust=%~2"
- shift
- shift
- goto options
-)
-
-if "_%~1_" == "_--repo_" (
- if "_%~2_" == "__" (
- echo error: repository location expected after --repo
- goto error
- )
- set "BUILD2_REPO=%~2"
- shift
- shift
- goto options
-)
-
-if "_%~1_" == "_--timeout_" (
- if "_%~2_" == "__" (
- echo error: value in seconds expected after --timeout
- goto error
- )
- set "timeout=%~2"
- shift
- shift
- goto options
-)
-
-if "_%~1_" == "_--make_" (
- if "_%~2_" == "__" (
- echo error: argument expected after --make
- goto error
- )
- set "make=%make% %~2"
- shift
- shift
- goto options
-)
-
-if "_%~1_" == "_--verbose_" (
- if "_%~2_" == "__" (
- echo error: diagnostics level between 0 and 6 expected after --verbose
- goto error
- )
- set "verbose=%~2"
- shift
- shift
- goto options
-)
-
-if "_%~1_" == "_--_" shift
-
-rem Validate options and arguments.
-rem
-
-rem Compiler.
-rem
-if "_%1_" == "__" (
- set "cxx=clang++"
-) else (
- set "cxx=%1"
-)
-
-rem Certificate to trust.
-rem
-if not "_%trust%_" == "__" (
- if "_%trust%_" == "_yes_" (
- set "trust=--trust-yes"
- ) else (
- if "_%trust%_" == "_no_" (
- set "trust=--trust-no"
- ) else (
- set "trust=--trust %trust%"
- )
- )
-)
-
-rem Network timeout.
-rem
-if not "_%timeout%_" == "__" (
- set "timeout=--fetch-timeout %timeout%"
-)
-
-rem Diagnostics verbosity.
-rem
-if not "_%verbose%_" == "__" (
- set "verbose=--verbose %verbose%"
-)
-
-if not exist %idir%\bin\ (
- echo error: %idir%\bin\ does not exist
- goto error
-)
-
-if exist build\config.build (
- echo error: current directory already configured, start with clean source
- goto error
-)
-
-if "_%local%_" == "__" (
- if exist ..\%cdir%\ (
- echo error: ..\%cdir%\ bpkg configuration directory already exists, remove it
- goto error
- )
-)
-
-set "PATH=%idir%\bin;%PATH%"
-
-rem Show the steps we are performing.
-rem
-@echo on
-
-@rem Verify the compiler works.
-@rem
-%cxx% --version
-@if errorlevel 1 goto error
-
-@rem Bootstrap.
-@rem
-cd build2
-
-@if "_%make%_" == "__" (
- goto batchfile
-) else (
- goto makefile
-)
-
-:batchfile
-@rem Execute in a separate cmd.exe to preserve the echo mode.
-@rem
-cmd /C bootstrap-clang.bat %cxx%
-@if errorlevel 1 goto error
-@goto endfile
-
-:makefile
-%make% -f bootstrap.gmake CXX=%cxx%
-@if errorlevel 1 goto error
-@goto endfile
-
-:endfile
-build2\b-boot --version
-@if errorlevel 1 goto error
-
-build2\b-boot %verbose% config.cxx=%cxx% config.cc.coptions=-m64 config.bin.lib=static build2\exe{b}
-@if errorlevel 1 goto error
-
-move /y build2\b.exe build2\b-boot.exe
-@if errorlevel 1 goto error
-
-build2\b-boot --version
-@if errorlevel 1 goto error
-
-cd ..
-
-@rem Local installation early return.
-@rem
-@if "_%local%_" == "__" goto stage
-
-build2\build2\b-boot %verbose% configure^
- config.cxx=%cxx%^
- "config.cc.coptions=-m64 -O3"^
- config.bin.lib=shared^
- config.install.root=%idir%
-@if errorlevel 1 goto error
-
-build2\build2\b-boot %verbose% install: build2\ bpkg\ bdep\
-@if errorlevel 1 goto error
-
-where b
-@if errorlevel 1 goto error
-
-where bpkg
-@if errorlevel 1 goto error
-
-where bdep
-@if errorlevel 1 goto error
-
-b --version
-@if errorlevel 1 goto error
-
-bpkg --version
-@if errorlevel 1 goto error
-
-bdep --version
-@if errorlevel 1 goto error
-
-@echo off
-
-echo.
-echo Toolchain installation: %idir%\bin
-echo Build configuration: %owd%
-echo.
-
-goto end
-
-@rem Build and stage the build system and the package manager.
-@rem
-:stage
-
-build2\build2\b-boot %verbose% configure^
- config.cxx=%cxx%^
- config.cc.coptions=-m64^
- config.bin.lib=shared^
- config.bin.suffix=-stage^
- config.install.root=%idir%^
- config.install.data_root=root\stage
-@if errorlevel 1 goto error
-
-build2\build2\b-boot %verbose% install: build2\ bpkg\
-@if errorlevel 1 goto error
-
-where b-stage
-@if errorlevel 1 goto error
-
-where bpkg-stage
-@if errorlevel 1 goto error
-
-b-stage --version
-@if errorlevel 1 goto error
-
-bpkg-stage --version
-@if errorlevel 1 goto error
-
-@rem Build the entire toolchain from packages.
-@rem
-cd ..
-
-md %cdir%
-@if errorlevel 1 goto error
-
-cd %cdir%
-
-@rem Save full path for later.
-@rem
-@set "cdir=%CD%"
-
-bpkg-stage %verbose% create^
- cc^
- config.cxx=%cxx%^
- "config.cc.coptions=-m64 -O3"^
- config.bin.lib=shared^
- config.install.root=%idir%
-@if errorlevel 1 goto error
-
-bpkg-stage %verbose% add %BUILD2_REPO%
-@if errorlevel 1 goto error
-
-bpkg-stage %verbose% %timeout% %trust% fetch
-@if errorlevel 1 goto error
-
-bpkg-stage %verbose% %timeout% build --for install --yes --plan= build2 bpkg bdep
-@if errorlevel 1 goto error
-
-bpkg-stage %verbose% install build2 bpkg bdep
-@if errorlevel 1 goto error
-
-where b
-@if errorlevel 1 goto error
-
-where bpkg
-@if errorlevel 1 goto error
-
-where bdep
-@if errorlevel 1 goto error
-
-b --version
-@if errorlevel 1 goto error
-
-bpkg --version
-@if errorlevel 1 goto error
-
-bdep --version
-@if errorlevel 1 goto error
-
-@rem Clean up stage.
-@rem
-cd %owd%
-b %verbose% uninstall: build2/ bpkg/
-@if errorlevel 1 goto error
-
-@echo off
-
-echo.
-echo Toolchain installation: %idir%\bin
-echo Build configuration: %cdir%
-echo.
-
-goto end
-
-:error
-@echo off
-cd %owd%
-endlocal
-exit /b 1
-
-:end
-endlocal
diff --git a/build-clang.bat.in b/build-clang.bat.in
new file mode 100644
index 0000000..dd38fc3
--- /dev/null
+++ b/build-clang.bat.in
@@ -0,0 +1,714 @@
+@echo off
+
+rem file : build-clang.bat.in
+rem license : MIT; see accompanying LICENSE file
+
+setlocal EnableDelayedExpansion
+goto start
+
+:usage
+echo.
+echo Usage: %0 [/?] [^<options^>] [--] [^<clang++-compiler^>] [^<compile-options^>] [-- ^<link-options^>]
+echo Options:
+echo --local Don't build from packages, only from local source.
+echo --no-bpkg Don't install bpkg nor bdep ^(requires --local^).
+echo --no-bdep Don't install bdep.
+echo --no-modules Don't install standard build system modules.
+echo --modules "<list>" Install only specified standard build system modules.
+echo --install-dir ^<dir^> Alternative installation directory.
+echo --exe-prefix ^<pfx^> Toolchain executables name prefix.
+echo --exe-suffix ^<sfx^> Toolchain executables name suffix.
+echo --stage-suffix ^<sfx^> Staged executables name suffix ^('-stage' by default^).
+echo --jobs^|-j ^<num^> Number of jobs to perform in parallel.
+echo --repo ^<loc^> Alternative package repository location.
+echo --trust ^<fp^> Repository certificate fingerprint to trust.
+echo --timeout ^<sec^> Network operations timeout in seconds.
+echo --make ^<arg^> Bootstrap using GNU make instead of batch file.
+echo --verbose ^<level^> Diagnostics verbosity level between 0 and 6.
+echo.
+echo By default the batch file will use clang++.exe as the C++ compiler and
+echo install into C:\build2. It also expects to find the base utilities in the
+echo bin\ subdirectory of the installation directory ^(C:\build2\bin\ by
+echo default^).
+echo.
+echo If --jobs^|-j is unspecified, then the bootstrap step is performed
+echo serially with the rest of the process using the number of available
+echo hardware threads.
+echo.
+echo The --trust option recognizes two special values: 'yes' ^(trust everything^)
+echo and 'no' ^(trust nothing^).
+echo.
+echo The --make option can be used to bootstrap using GNU make. The first
+echo --make value should specify the make executable optionally followed by
+echo additional make options, for example:
+echo.
+echo %0 --make mingw32-make --make -j8
+echo.
+echo If --jobs^|-j is specified, then its value is passed to make before
+echo any additional options.
+echo.
+echo The script by default installs the following standard build system
+echo modules:
+echo.
+echo %standard_modules%
+echo.
+echo Use --no-modules to suppress installing build system modules or
+echo --modules "<list>" to specify a comma-separated subset to install.
+echo.
+echo See the BOOTSTRAP-WINDOWS-CLANG file for details.
+echo.
+goto end
+
+:start
+
+set "owd=%CD%"
+
+rem Package repository URL (or path).
+rem
+if "_%BUILD2_REPO%_" == "__" (
+ set "BUILD2_REPO=@BUILD2_REPO@"
+)
+
+rem Package versions.
+rem
+set "build2_ver=@BUILD2_VERSION@"
+set "bpkg_ver=@BPKG_VERSION@"
+set "bdep_ver=@BDEP_VERSION@"
+
+rem Standard modules comma-separated list and versions.
+rem
+rem NOTE: we currently print the list as a single line and will need to
+rem somehow change that when it becomes too long.
+rem
+set "standard_modules=autoconf, kconfig"
+set "autoconf_ver=@AUTOCONF_VERSION@"
+set "kconfig_ver=@KCONFIG_VERSION@"
+
+rem The bpkg configuration directory.
+rem
+set "cver=@CONFIG_VER@"
+set "cdir=build2-toolchain-%cver%"
+
+rem Parse options.
+rem
+set "local="
+set "bpkg_install=true"
+set "bdep_install=true"
+set "modules=%standard_modules%"
+set "idir=C:\build2"
+set "exe_prefix="
+set "exe_suffix="
+set "stage_suffix=-stage"
+set "jobs="
+set "trust="
+set "timeout="
+set "make="
+set "make_options="
+set "verbose="
+
+:options
+if "_%~1_" == "_/?_" goto usage
+if "_%~1_" == "_-h_" goto usage
+if "_%~1_" == "_--help_" goto usage
+
+if "_%~1_" == "_--local_" (
+ set "local=true"
+ shift
+ goto options
+)
+
+if "_%~1_" == "_--no-bpkg_" (
+ set "bpkg_install="
+ shift
+ goto options
+)
+
+if "_%~1_" == "_--no-bdep_" (
+ set "bdep_install="
+ shift
+ goto options
+)
+
+if "_%~1_" == "_--no-modules_" (
+ set "modules="
+ shift
+ goto options
+)
+
+if "_%~1_" == "_--modules_" (
+ set "modules=%~2"
+ shift
+ shift
+ goto options
+)
+
+if "_%~1_" == "_--install-dir_" (
+ if "_%~2_" == "__" (
+ echo error: installation directory expected after --install-dir
+ goto error
+ )
+ set "idir=%~2"
+ shift
+ shift
+ goto options
+)
+
+if "_%~1_" == "_--exe-prefix_" (
+ if "_%~2_" == "__" (
+ echo error: executables name prefix expected after --exe-prefix
+ goto error
+ )
+ set "exe_prefix=%~2"
+ shift
+ shift
+ goto options
+)
+
+if "_%~1_" == "_--exe-suffix_" (
+ if "_%~2_" == "__" (
+ echo error: executables name suffix expected after --exe-suffix
+ goto error
+ )
+ set "exe_suffix=%~2"
+ shift
+ shift
+ goto options
+)
+
+if "_%~1_" == "_--stage-suffix_" (
+ if "_%~2_" == "__" (
+ echo error: staged executables name suffix expected after --stage-suffix
+ goto error
+ )
+ set "stage_suffix=%~2"
+ shift
+ shift
+ goto options
+)
+
+set "jo="
+if "_%~1_" == "_-j_" set "jo=true"
+if "_%~1_" == "_--jobs_" set "jo=true"
+
+if "_%jo%_" == "_true_" (
+ if "_%~2_" == "__" (
+ echo error: number of jobs expected after --jobs^|-j
+ goto error
+ )
+ set "jobs=-j %~2"
+ shift
+ shift
+ goto options
+)
+
+if "_%~1_" == "_--trust_" (
+ if "_%~2_" == "__" (
+ echo error: certificate fingerprint expected after --trust
+ goto error
+ )
+ set "trust=%~2"
+ shift
+ shift
+ goto options
+)
+
+if "_%~1_" == "_--repo_" (
+ if "_%~2_" == "__" (
+ echo error: repository location expected after --repo
+ goto error
+ )
+ set "BUILD2_REPO=%~2"
+ shift
+ shift
+ goto options
+)
+
+if "_%~1_" == "_--timeout_" (
+ if "_%~2_" == "__" (
+ echo error: value in seconds expected after --timeout
+ goto error
+ )
+ set "timeout=%~2"
+ shift
+ shift
+ goto options
+)
+
+if "_%~1_" == "_--make_" (
+ if "_%~2_" == "__" (
+ echo error: argument expected after --make
+ goto error
+ )
+
+ if "_%make%_" == "__" (
+ set "make=%~2"
+ ) else (
+ set "make_options=%make_options% %~2"
+ )
+ shift
+ shift
+ goto options
+)
+
+if "_%~1_" == "_--verbose_" (
+ if "_%~2_" == "__" (
+ echo error: diagnostics level between 0 and 6 expected after --verbose
+ goto error
+ )
+ set "verbose=%~2"
+ shift
+ shift
+ goto options
+)
+
+if "_%~1_" == "_--_" shift
+
+rem Compiler.
+rem
+if "_%1_" == "__" (
+ set "cxx=clang++"
+) else (
+ set "cxx=%~1"
+ shift
+)
+
+rem Compile and link options.
+rem
+set "compile_ops="
+set "link_ops="
+
+:compile_options
+if not "_%1_" == "__" (
+ if not "_%~1_" == "_--_" (
+ set "compile_ops=%compile_ops% %~1"
+ shift
+ goto compile_options
+ ) else (
+ shift
+ )
+)
+
+:link_options
+if not "_%1_" == "__" (
+ set "link_ops=%link_ops% %~1"
+ shift
+ goto link_options
+)
+
+if not "_%compile_ops%_" == "__" (
+ set coptions="config.cc.coptions=%compile_ops:~1%"
+) else (
+ set coptions="config.cc.coptions=-O2"
+)
+
+if not "_%link_ops%_" == "__" (
+ set loptions="config.cc.loptions=%link_ops:~1%"
+) else (
+ set "loptions="
+)
+
+rem Merge jobs and make_options into make.
+rem
+if not "_%make%_" == "__" (
+ if not "_%jobs%_" == "__" set "make=%make% %jobs%"
+
+ rem Already has leading space.
+ rem
+ if not "_%make_options%_" == "__" set "make=!make!%make_options%"
+)
+
+rem Validate options and arguments.
+rem
+
+rem If --no-bpkg is specified, then we require --local to also be specified
+rem since it won't be possible to build things from packages without bpkg.
+rem Also imply --no-bdep in this case, since bdep is pretty much useless
+rem without bpkg.
+rem
+if "_%bpkg_install%_" == "__" (
+ if "_%local%_" == "__" (
+ echo error: --no-bpkg can only be used for local installation
+ echo info: additionally specify --local
+ goto error
+ )
+
+ set "bdep_install="
+)
+
+for %%m in (%modules%) do (
+ if "_!%%m_ver!_" == "__" (
+ echo error: unknown standard build system module '%%m'
+ echo info: available standard modules: %standard_modules%
+ goto error
+ )
+)
+
+rem Convert a relative path to an absolute.
+rem
+for /F "delims=|" %%D in ("%idir%") do set "idir=%%~dpnxD"
+
+rem Certificate to trust.
+rem
+if not "_%trust%_" == "__" (
+ if "_%trust%_" == "_yes_" (set "trust=--trust-yes"
+ ) else (if "_%trust%_" == "_no_" (set "trust=--trust-no"
+ ) else (set "trust=--trust %trust%"))
+)
+
+rem Network timeout.
+rem
+if not "_%timeout%_" == "__" (
+ set "timeout=--fetch-timeout %timeout%"
+)
+
+rem Diagnostics verbosity.
+rem
+if not "_%verbose%_" == "__" (
+ set "verbose=--verbose %verbose%"
+)
+
+if not exist %idir%\bin\ (
+ echo error: %idir%\bin\ does not exist
+ goto error
+)
+
+rem Derive the to be installed executables names based on
+rem --exe-{prefix,suffix}. Unless the installation is local, also derive the
+rem staged executables names based on --stage-suffix and verify that they
+rem don't clash with existing filesystem entries as well as the executables
+rem being installed.
+rem
+set "b=%exe_prefix%b%exe_suffix%"
+set "bpkg=%exe_prefix%bpkg%exe_suffix%"
+set "bdep=%exe_prefix%bdep%exe_suffix%"
+
+if "_%local%_" == "__" (
+ set "b_stage=b%stage_suffix%"
+ set "bpkg_stage=bpkg%stage_suffix%"
+
+ if exist %idir%\bin\!b_stage!.exe (
+ echo error: staged executable name '!b_stage!' clashes with existing %idir%\bin\!b_stage!.exe
+ echo info: specify alternative staged executables name suffix with --stage-suffix
+ goto error
+ )
+
+ if exist %idir%\bin\!bpkg_stage!.exe (
+ echo error: staged executable name '!bpkg_stage!' clashes with existing %idir%\bin\!bpkg_stage!.exe
+ echo info: specify alternative staged executables name suffix with --stage-suffix
+ goto error
+ )
+
+ if "_%stage_suffix%_" == "_%exe_suffix%_" (
+ if "_%exe_prefix%_" == "__" (
+ echo error: suffix '%exe_suffix%' is used for both final and staged executables
+ echo info: specify alternative staged executables name suffix with --stage-suffix
+ goto error
+ )
+ )
+)
+
+set "conf_exe_affixes="
+
+if not "_%exe_prefix%_" == "__" (
+ set "conf_exe_affixes=config.bin.exe.prefix=%exe_prefix%"
+)
+
+if not "_%exe_suffix%_" == "__" (
+ set "conf_exe_affixes=%conf_exe_affixes% config.bin.exe.suffix=%exe_suffix%"
+)
+
+if exist build\config.build (
+ echo error: current directory already configured, start with clean source
+ goto error
+)
+
+if "_%local%_" == "__" (
+ if exist ..\%cdir%\ (
+ echo error: ..\%cdir%\ bpkg configuration directory already exists, remove it
+ goto error
+ )
+)
+
+set "PATH=%idir%\bin;%PATH%"
+
+rem Show the steps we are performing.
+rem
+@echo on
+
+@rem Verify the compiler works.
+@rem
+%cxx% --version
+@if errorlevel 1 goto error
+
+@rem Suppress loading of default options files.
+@rem
+set "BUILD2_DEF_OPT=0"
+set "BPKG_DEF_OPT=0"
+set "BDEP_DEF_OPT=0"
+
+@rem Bootstrap.
+@rem
+@rem Note: disable all warnings since we cannot do anything more granular
+@rem during bootstrap stage 1.
+@rem
+cd build2
+
+@if "_%make%_" == "__" (
+ goto batchfile
+) else (
+ goto makefile
+)
+
+:batchfile
+@rem Execute in a separate cmd.exe to preserve the echo mode.
+@rem
+cmd /C bootstrap-clang.bat %cxx% -m64 -w
+@if errorlevel 1 goto error
+@goto endfile
+
+:makefile
+%make% -f bootstrap.gmake CXX=%cxx% "CXXFLAGS=-m64 -w"
+@if errorlevel 1 goto error
+@goto endfile
+
+:endfile
+build2\b-boot --version
+@if errorlevel 1 goto error
+
+build2\b-boot %verbose% %jobs% "config.cxx=%cxx% -m64" config.bin.lib=static build2\exe{b}
+@if errorlevel 1 goto error
+
+move /y build2\b.exe build2\b-boot.exe
+@if errorlevel 1 goto error
+
+build2\b-boot --version
+@if errorlevel 1 goto error
+
+cd ..
+
+@rem Local installation early return.
+@rem
+@if "_%local%_" == "__" goto stage
+
+build2\build2\b-boot %verbose% configure^
+ config.config.hermetic=true^
+ "config.cxx=%cxx% -m64"^
+ %coptions%^
+ %loptions%^
+ config.bin.lib=shared^
+ config.install.root=%idir%^
+ %conf_exe_affixes%
+@if errorlevel 1 goto error
+
+@rem Install toolchain.
+@rem
+@set "projects=build2\"
+
+@if "_%bpkg_install%_" == "_true_" (
+ set "projects=%projects% bpkg\"
+)
+
+@if "_%bdep_install%_" == "_true_" (
+ set "projects=%projects% bdep\"
+)
+
+build2\build2\b-boot %verbose% %jobs% install: %projects%
+@if errorlevel 1 goto error
+
+where %b%
+@if errorlevel 1 goto error
+
+%b% --version
+@if errorlevel 1 goto error
+
+@if "_%bpkg_install%_" == "__" goto bpkg_vle
+
+where %bpkg%
+@if errorlevel 1 goto error
+
+%bpkg% --version
+@if errorlevel 1 goto error
+
+:bpkg_vle
+
+@if "_%bdep_install%_" == "__" goto bdep_vle
+
+where %bdep%
+@if errorlevel 1 goto error
+
+%bdep% --version
+@if errorlevel 1 goto error
+
+:bdep_vle
+
+@rem Install modules.
+@rem
+@set "projects="
+@set "tests="
+
+@for %%m in (%modules%) do @(
+ set "projects=!projects! libbuild2-%%m\"
+ set "tests=!tests! tests\libbuild2-%%m-tests\"
+)
+
+@if "_%projects%_" == "__" goto mods_ile
+
+%b% %verbose% %jobs% install: ^^!config.install.scope=project %projects:~1%
+@if errorlevel 1 goto error
+
+%b% %verbose% noop: %tests:~1%
+@if errorlevel 1 goto error
+
+:mods_ile
+
+@echo off
+
+echo.
+echo Toolchain installation: %idir%\bin
+echo Build configuration: %owd%
+echo.
+
+goto end
+
+@rem Build and stage the build system and the package manager.
+@rem
+:stage
+
+build2\build2\b-boot %verbose% configure^
+ "config.cxx=%cxx% -m64"^
+ config.bin.lib=shared^
+ config.bin.suffix=%stage_suffix%^
+ config.install.root=%idir%^
+ config.install.data_root=root\stage
+@if errorlevel 1 goto error
+
+build2\build2\b-boot %verbose% %jobs% install: build2\ bpkg\
+@if errorlevel 1 goto error
+
+where %b_stage%
+@if errorlevel 1 goto error
+
+%b_stage% --version
+@if errorlevel 1 goto error
+
+where %bpkg_stage%
+@if errorlevel 1 goto error
+
+%bpkg_stage% --version
+@if errorlevel 1 goto error
+
+@rem Build the entire toolchain from packages.
+@rem
+cd ..
+
+md %cdir%
+@if errorlevel 1 goto error
+
+cd %cdir%
+
+@rem Save full path for later.
+@rem
+@set "cdir=%CD%"
+
+%bpkg_stage% %verbose% create^
+ cc^
+ config.config.hermetic=true^
+ "config.cxx=%cxx% -m64"^
+ %coptions%^
+ %loptions%^
+ config.bin.lib=shared^
+ config.install.root=%idir%^
+ %conf_exe_affixes%
+@if errorlevel 1 goto error
+
+@set "packages=build2/%build2_ver% bpkg/%bpkg_ver%"
+
+@if "_%bdep_install%_" == "_true_" (
+ set "packages=%packages% bdep/%bdep_ver%"
+)
+
+%bpkg_stage% %verbose% add %BUILD2_REPO%
+@if errorlevel 1 goto error
+
+%bpkg_stage% %verbose% %timeout% %trust% fetch
+@if errorlevel 1 goto error
+
+%bpkg_stage% %verbose% %jobs% %timeout% build --for install --yes --plan= %packages%
+@if errorlevel 1 goto error
+
+%bpkg_stage% %verbose% %jobs% install --all
+@if errorlevel 1 goto error
+
+where %b%
+@if errorlevel 1 goto error
+
+%b% --version
+@if errorlevel 1 goto error
+
+where %bpkg%
+@if errorlevel 1 goto error
+
+%bpkg% --version
+@if errorlevel 1 goto error
+
+@if "_%bdep_install%_" == "__" goto bdep_vpe
+
+where %bdep%
+@if errorlevel 1 goto error
+
+%bdep% --version
+@if errorlevel 1 goto error
+
+:bdep_vpe
+
+@rem Build, install, and verify the build system modules.
+@rem
+@set "packages="
+@set "tests="
+
+@for %%m in (%modules%) do @(
+ set "packages=!packages! libbuild2-%%m/!%%m_ver!"
+ set "tests=!tests! tests\libbuild2-%%m-tests\"
+)
+
+@if "_%packages%_" == "__" goto mods_ipe
+
+%bpkg% %verbose% %jobs% %timeout% build --for install %packages:~1%
+@if errorlevel 1 goto error
+
+%bpkg% %verbose% %jobs% install ^^!config.install.scope=project --all-pattern=libbuild2-*
+@if errorlevel 1 goto error
+
+:mods_ipe
+
+cd %owd%
+
+@if "_%tests%_" == "__" goto mods_lpe
+
+%b% %verbose% noop: %tests:~1%
+@if errorlevel 1 goto error
+
+:mods_lpe
+
+@rem Clean up stage.
+@rem
+%b% %verbose% %jobs% uninstall: build2\ bpkg\
+@if errorlevel 1 goto error
+
+@echo off
+
+echo.
+echo Toolchain installation: %idir%\bin
+echo Build configuration: %cdir%
+echo.
+
+goto end
+
+:error
+@echo off
+cd %owd%
+endlocal
+exit /b 1
+
+:end
+endlocal
diff --git a/build-mingw.bat b/build-mingw.bat
deleted file mode 100644
index 7173087..0000000
--- a/build-mingw.bat
+++ /dev/null
@@ -1,398 +0,0 @@
-@echo off
-
-rem file : build-mingw.bat
-rem license : MIT; see accompanying LICENSE file
-
-setlocal EnableDelayedExpansion
-goto start
-
-:usage
-echo.
-echo Usage: %0 [/?] [^<options^>] ^<c++-compiler^>
-echo Options:
-echo --local Don't build from packages, only from local source.
-echo --install-dir ^<dir^> Alternative installation directory.
-echo --repo ^<loc^> Alternative package repository location.
-echo --trust ^<fp^> Repository certificate fingerprint to trust.
-echo --timeout ^<sec^> Network operations timeout in seconds.
-echo --make ^<arg^> Bootstrap using GNU make instead of batch file.
-echo --verbose ^<level^> Diagnostics verbosity level between 0 and 6.
-echo.
-echo By default the batch file will install into C:\build2. It also expects
-echo to find the base utilities in the bin\ subdirectory of the installation
-echo directory ^(C:\build2\bin\ by default^).
-echo.
-echo The --trust option recognizes two special values: 'yes' ^(trust everything^)
-echo and 'no' (trust nothing).
-echo.
-echo The --make option can be used to bootstrap using GNU make. The first
-echo --make value should specify the make executable optionally followed by
-echo additional make options, for example:
-echo.
-echo %0 --make mingw32-make --make -j8 g++
-echo.
-echo See the BOOTSTRAP-WINDOWS-MINGW file for details.
-echo.
-goto end
-
-:start
-
-set "owd=%CD%"
-
-rem Package repository URL (or path).
-rem
-if "_%BUILD2_REPO%_" == "__" (
- set "BUILD2_REPO=https://stage.build2.org/1"
-rem set "BUILD2_REPO=https://pkg.cppget.org/1/queue/alpha"
-rem set "BUILD2_REPO=https://pkg.cppget.org/1/alpha"
-)
-
-rem The bpkg configuration directory.
-rem
-set "cver=0.13-a.0"
-set "cdir=build2-toolchain-%cver%"
-
-rem Parse options.
-rem
-set "local="
-set "idir=C:\build2"
-set "trust="
-set "timeout="
-set "make="
-set "verbose="
-
-:options
-if "_%~1_" == "_/?_" goto usage
-if "_%~1_" == "_-h_" goto usage
-if "_%~1_" == "_--help_" goto usage
-
-if "_%~1_" == "_--local_" (
- set "local=true"
- shift
- goto options
-)
-
-if "_%~1_" == "_--install-dir_" (
- if "_%~2_" == "__" (
- echo error: installation directory expected after --install-dir
- goto error
- )
- set "idir=%~2"
- shift
- shift
- goto options
-)
-
-if "_%~1_" == "_--trust_" (
- if "_%~2_" == "__" (
- echo error: certificate fingerprint expected after --trust
- goto error
- )
- set "trust=%~2"
- shift
- shift
- goto options
-)
-
-if "_%~1_" == "_--repo_" (
- if "_%~2_" == "__" (
- echo error: repository location expected after --repo
- goto error
- )
- set "BUILD2_REPO=%~2"
- shift
- shift
- goto options
-)
-
-if "_%~1_" == "_--timeout_" (
- if "_%~2_" == "__" (
- echo error: value in seconds expected after --timeout
- goto error
- )
- set "timeout=%~2"
- shift
- shift
- goto options
-)
-
-if "_%~1_" == "_--make_" (
- if "_%~2_" == "__" (
- echo error: argument expected after --make
- goto error
- )
- set "make=%make% %~2"
- shift
- shift
- goto options
-)
-
-if "_%~1_" == "_--verbose_" (
- if "_%~2_" == "__" (
- echo error: diagnostics level between 0 and 6 expected after --verbose
- goto error
- )
- set "verbose=%~2"
- shift
- shift
- goto options
-)
-
-if "_%~1_" == "_--_" shift
-
-rem Validate options and arguments.
-rem
-
-rem Compiler.
-rem
-if "_%1_" == "__" (
- echo error: compiler executable expected, run %0 /? for details
- goto error
-) else (
- set "cxx=%1"
-)
-
-rem @@ Temporarily retained for backwards compatibility.
-rem
-if not "_%2_" == "__" (
- set "idir=%2"
-)
-if not "_%3_" == "__" (
- set "trust=%3"
-)
-
-rem Certificate to trust.
-rem
-if not "_%trust%_" == "__" (
- if "_%trust%_" == "_yes_" (
- set "trust=--trust-yes"
- ) else (
- if "_%trust%_" == "_no_" (
- set "trust=--trust-no"
- ) else (
- set "trust=--trust %trust%"
- )
- )
-)
-
-rem Network timeout.
-rem
-if not "_%timeout%_" == "__" (
- set "timeout=--fetch-timeout %timeout%"
-)
-
-rem Diagnostics verbosity.
-rem
-if not "_%verbose%_" == "__" (
- set "verbose=--verbose %verbose%"
-)
-
-if not exist %idir%\bin\ (
- echo error: %idir%\bin\ does not exist
- goto error
-)
-
-if exist build\config.build (
- echo error: current directory already configured, start with clean source
- goto error
-)
-
-if "_%local%_" == "__" (
- if exist ..\%cdir%\ (
- echo error: ..\%cdir%\ bpkg configuration directory already exists, remove it
- goto error
- )
-)
-
-set "PATH=%idir%\bin;%PATH%"
-
-rem Show the steps we are performing.
-rem
-@echo on
-
-@rem Verify the compiler works.
-@rem
-%cxx% --version
-@if errorlevel 1 goto error
-
-@rem Bootstrap.
-@rem
-cd build2
-
-@if "_%make%_" == "__" (
- goto batchfile
-) else (
- goto makefile
-)
-
-:batchfile
-@rem Execute in a separate cmd.exe to preserve the echo mode.
-@rem
-cmd /C bootstrap-mingw.bat %cxx% -static
-@if errorlevel 1 goto error
-@goto endfile
-
-:makefile
-%make% -f bootstrap.gmake CXX=%cxx% LDFLAGS=-static
-@if errorlevel 1 goto error
-@goto endfile
-
-:endfile
-build2\b-boot --version
-@if errorlevel 1 goto error
-
-build2\b-boot %verbose% config.cxx=%cxx% config.bin.lib=static build2\exe{b}
-@if errorlevel 1 goto error
-
-move /y build2\b.exe build2\b-boot.exe
-@if errorlevel 1 goto error
-
-build2\b-boot --version
-@if errorlevel 1 goto error
-
-cd ..
-
-@rem Local installation early return.
-@rem
-@if "_%local%_" == "__" goto stage
-
-build2\build2\b-boot %verbose% configure^
- config.cxx=%cxx%^
- config.cc.coptions=-O3^
- config.bin.lib=shared^
- config.install.root=%idir%
-@if errorlevel 1 goto error
-
-build2\build2\b-boot %verbose% install: build2\ bpkg\ bdep\
-@if errorlevel 1 goto error
-
-where b
-@if errorlevel 1 goto error
-
-where bpkg
-@if errorlevel 1 goto error
-
-where bdep
-@if errorlevel 1 goto error
-
-b --version
-@if errorlevel 1 goto error
-
-bpkg --version
-@if errorlevel 1 goto error
-
-bdep --version
-@if errorlevel 1 goto error
-
-@echo off
-
-echo.
-echo Toolchain installation: %idir%\bin
-echo Build configuration: %owd%
-echo.
-
-goto end
-
-@rem Build and stage the build system and the package manager.
-@rem
-:stage
-
-build2\build2\b-boot %verbose% configure^
- config.cxx=%cxx%^
- config.bin.lib=shared^
- config.bin.suffix=-stage^
- config.install.root=%idir%^
- config.install.data_root=root\stage
-@if errorlevel 1 goto error
-
-build2\build2\b-boot %verbose% install: build2\ bpkg\
-@if errorlevel 1 goto error
-
-@rem The where command is not available on XP without the resource kit.
-@rem
-where b-stage
-@rem @if errorlevel 1 goto error
-
-where bpkg-stage
-@rem @if errorlevel 1 goto error
-
-b-stage --version
-@if errorlevel 1 goto error
-
-bpkg-stage --version
-@if errorlevel 1 goto error
-
-@rem Build the entire toolchain from packages.
-@rem
-cd ..
-
-md %cdir%
-@if errorlevel 1 goto error
-
-cd %cdir%
-
-@rem Save full path for later.
-@rem
-@set "cdir=%CD%"
-
-bpkg-stage %verbose% create^
- cc^
- config.cxx=%cxx%^
- config.cc.coptions=-O3^
- config.bin.lib=shared^
- config.install.root=%idir%
-@if errorlevel 1 goto error
-
-bpkg-stage %verbose% add %BUILD2_REPO%
-@if errorlevel 1 goto error
-
-bpkg-stage %verbose% %timeout% %trust% fetch
-@if errorlevel 1 goto error
-
-bpkg-stage %verbose% %timeout% build --for install --yes --plan= build2 bpkg bdep
-@if errorlevel 1 goto error
-
-bpkg-stage %verbose% install build2 bpkg bdep
-@if errorlevel 1 goto error
-
-where b
-@rem @if errorlevel 1 goto error
-
-where bpkg
-@rem @if errorlevel 1 goto error
-
-where bdep
-@rem @if errorlevel 1 goto error
-
-b --version
-@if errorlevel 1 goto error
-
-bpkg --version
-@if errorlevel 1 goto error
-
-bdep --version
-@if errorlevel 1 goto error
-
-@rem Clean up stage.
-@rem
-cd %owd%
-b %verbose% uninstall: build2\ bpkg\
-@if errorlevel 1 goto error
-
-@echo off
-
-echo.
-echo Toolchain installation: %idir%\bin
-echo Build configuration: %cdir%
-echo.
-
-goto end
-
-:error
-@echo off
-cd %owd%
-endlocal
-exit /b 1
-
-:end
-endlocal
diff --git a/build-mingw.bat.in b/build-mingw.bat.in
new file mode 100644
index 0000000..8982f84
--- /dev/null
+++ b/build-mingw.bat.in
@@ -0,0 +1,716 @@
+@echo off
+
+rem file : build-mingw.bat.in
+rem license : MIT; see accompanying LICENSE file
+
+setlocal EnableDelayedExpansion
+goto start
+
+:usage
+echo.
+echo Usage: %0 [/?] [^<options^>] [--] ^<c++-compiler^> [^<compile-options^>] [-- ^<link-options^>]
+echo Options:
+echo --local Don't build from packages, only from local source.
+echo --no-bpkg Don't install bpkg nor bdep ^(requires --local^).
+echo --no-bdep Don't install bdep.
+echo --no-modules Don't install standard build system modules.
+echo --modules "<list>" Install only specified standard build system modules.
+echo --install-dir ^<dir^> Alternative installation directory.
+echo --exe-prefix ^<pfx^> Toolchain executables name prefix.
+echo --exe-suffix ^<sfx^> Toolchain executables name suffix.
+echo --stage-suffix ^<sfx^> Staged executables name suffix ^('-stage' by default^).
+echo --jobs^|-j ^<num^> Number of jobs to perform in parallel.
+echo --repo ^<loc^> Alternative package repository location.
+echo --trust ^<fp^> Repository certificate fingerprint to trust.
+echo --timeout ^<sec^> Network operations timeout in seconds.
+echo --make ^<arg^> Bootstrap using GNU make instead of batch file.
+echo --verbose ^<level^> Diagnostics verbosity level between 0 and 6.
+echo.
+echo By default the batch file will install into C:\build2. It also expects
+echo to find the base utilities in the bin\ subdirectory of the installation
+echo directory ^(C:\build2\bin\ by default^).
+echo.
+echo If --jobs^|-j is unspecified, then the bootstrap step is performed
+echo serially with the rest of the process using the number of available
+echo hardware threads.
+echo.
+echo The --trust option recognizes two special values: 'yes' ^(trust everything^)
+echo and 'no' ^(trust nothing^).
+echo.
+echo The --make option can be used to bootstrap using GNU make. The first
+echo --make value should specify the make executable optionally followed by
+echo additional make options, for example:
+echo.
+echo %0 --make mingw32-make --make -j8 g++
+echo.
+echo If --jobs^|-j is specified, then its value is passed to make before
+echo any additional options.
+echo.
+echo The script by default installs the following standard build system
+echo modules:
+echo.
+echo %standard_modules%
+echo.
+echo Use --no-modules to suppress installing build system modules or
+echo --modules "<list>" to specify a comma-separated subset to install.
+echo.
+echo See the BOOTSTRAP-WINDOWS-MINGW file for details.
+echo.
+goto end
+
+:start
+
+set "owd=%CD%"
+
+rem Package repository URL (or path).
+rem
+if "_%BUILD2_REPO%_" == "__" (
+ set "BUILD2_REPO=@BUILD2_REPO@"
+)
+
+rem Package versions.
+rem
+set "build2_ver=@BUILD2_VERSION@"
+set "bpkg_ver=@BPKG_VERSION@"
+set "bdep_ver=@BDEP_VERSION@"
+
+rem Standard modules comma-separated list and versions.
+rem
+rem NOTE: we currently print the list as a single line and will need to
+rem somehow change that when it becomes too long.
+rem
+set "standard_modules=autoconf, kconfig"
+set "autoconf_ver=@AUTOCONF_VERSION@"
+set "kconfig_ver=@KCONFIG_VERSION@"
+
+rem The bpkg configuration directory.
+rem
+set "cver=@CONFIG_VER@"
+set "cdir=build2-toolchain-%cver%"
+
+rem Parse options.
+rem
+set "local="
+set "bpkg_install=true"
+set "bdep_install=true"
+set "modules=%standard_modules%"
+set "idir=C:\build2"
+set "exe_prefix="
+set "exe_suffix="
+set "stage_suffix=-stage"
+set "jobs="
+set "trust="
+set "timeout="
+set "make="
+set "make_options="
+set "verbose="
+
+:options
+if "_%~1_" == "_/?_" goto usage
+if "_%~1_" == "_-h_" goto usage
+if "_%~1_" == "_--help_" goto usage
+
+if "_%~1_" == "_--local_" (
+ set "local=true"
+ shift
+ goto options
+)
+
+if "_%~1_" == "_--no-bpkg_" (
+ set "bpkg_install="
+ shift
+ goto options
+)
+
+if "_%~1_" == "_--no-bdep_" (
+ set "bdep_install="
+ shift
+ goto options
+)
+
+if "_%~1_" == "_--no-modules_" (
+ set "modules="
+ shift
+ goto options
+)
+
+if "_%~1_" == "_--modules_" (
+ set "modules=%~2"
+ shift
+ shift
+ goto options
+)
+
+if "_%~1_" == "_--install-dir_" (
+ if "_%~2_" == "__" (
+ echo error: installation directory expected after --install-dir
+ goto error
+ )
+ set "idir=%~2"
+ shift
+ shift
+ goto options
+)
+
+if "_%~1_" == "_--exe-prefix_" (
+ if "_%~2_" == "__" (
+ echo error: executables name prefix expected after --exe-prefix
+ goto error
+ )
+ set "exe_prefix=%~2"
+ shift
+ shift
+ goto options
+)
+
+if "_%~1_" == "_--exe-suffix_" (
+ if "_%~2_" == "__" (
+ echo error: executables name suffix expected after --exe-suffix
+ goto error
+ )
+ set "exe_suffix=%~2"
+ shift
+ shift
+ goto options
+)
+
+if "_%~1_" == "_--stage-suffix_" (
+ if "_%~2_" == "__" (
+ echo error: staged executables name suffix expected after --stage-suffix
+ goto error
+ )
+ set "stage_suffix=%~2"
+ shift
+ shift
+ goto options
+)
+
+set "jo="
+if "_%~1_" == "_-j_" set "jo=true"
+if "_%~1_" == "_--jobs_" set "jo=true"
+
+if "_%jo%_" == "_true_" (
+ if "_%~2_" == "__" (
+ echo error: number of jobs expected after --jobs^|-j
+ goto error
+ )
+ set "jobs=-j %~2"
+ shift
+ shift
+ goto options
+)
+
+if "_%~1_" == "_--trust_" (
+ if "_%~2_" == "__" (
+ echo error: certificate fingerprint expected after --trust
+ goto error
+ )
+ set "trust=%~2"
+ shift
+ shift
+ goto options
+)
+
+if "_%~1_" == "_--repo_" (
+ if "_%~2_" == "__" (
+ echo error: repository location expected after --repo
+ goto error
+ )
+ set "BUILD2_REPO=%~2"
+ shift
+ shift
+ goto options
+)
+
+if "_%~1_" == "_--timeout_" (
+ if "_%~2_" == "__" (
+ echo error: value in seconds expected after --timeout
+ goto error
+ )
+ set "timeout=%~2"
+ shift
+ shift
+ goto options
+)
+
+if "_%~1_" == "_--make_" (
+ if "_%~2_" == "__" (
+ echo error: argument expected after --make
+ goto error
+ )
+
+ if "_%make%_" == "__" (
+ set "make=%~2"
+ ) else (
+ set "make_options=%make_options% %~2"
+ )
+ shift
+ shift
+ goto options
+)
+
+if "_%~1_" == "_--verbose_" (
+ if "_%~2_" == "__" (
+ echo error: diagnostics level between 0 and 6 expected after --verbose
+ goto error
+ )
+ set "verbose=%~2"
+ shift
+ shift
+ goto options
+)
+
+if "_%~1_" == "_--_" shift
+
+rem Compiler.
+rem
+if "_%1_" == "__" (
+ echo error: compiler executable expected, run %0 /? for details
+ goto error
+) else (
+ set "cxx=%~1"
+ shift
+)
+
+rem Compile and link options.
+rem
+set "compile_ops="
+set "link_ops="
+
+:compile_options
+if not "_%1_" == "__" (
+ if not "_%~1_" == "_--_" (
+ set "compile_ops=%compile_ops% %~1"
+ shift
+ goto compile_options
+ ) else (
+ shift
+ )
+)
+
+:link_options
+if not "_%1_" == "__" (
+ set "link_ops=%link_ops% %~1"
+ shift
+ goto link_options
+)
+
+if not "_%compile_ops%_" == "__" (
+ set coptions="config.cc.coptions=%compile_ops:~1%"
+) else (
+ set "coptions=config.cc.coptions=-O2"
+)
+
+if not "_%link_ops%_" == "__" (
+ set loptions="config.cc.loptions=%link_ops:~1%"
+) else (
+ set "loptions="
+)
+
+rem Merge jobs and make_options into make.
+rem
+if not "_%make%_" == "__" (
+ if not "_%jobs%_" == "__" set "make=%make% %jobs%"
+
+ rem Already has leading space.
+ rem
+ if not "_%make_options%_" == "__" set "make=!make!%make_options%"
+)
+
+rem Validate options and arguments.
+rem
+
+rem If --no-bpkg is specified, then we require --local to also be specified
+rem since it won't be possible to build things from packages without bpkg.
+rem Also imply --no-bdep in this case, since bdep is pretty much useless
+rem without bpkg.
+rem
+if "_%bpkg_install%_" == "__" (
+ if "_%local%_" == "__" (
+ echo error: --no-bpkg can only be used for local installation
+ echo info: additionally specify --local
+ goto error
+ )
+
+ set "bdep_install="
+)
+
+for %%m in (%modules%) do (
+ if "_!%%m_ver!_" == "__" (
+ echo error: unknown standard build system module '%%m'
+ echo info: available standard modules: %standard_modules%
+ goto error
+ )
+)
+
+rem Convert a relative path to an absolute.
+rem
+for /F "delims=|" %%D in ("%idir%") do set "idir=%%~dpnxD"
+
+rem Certificate to trust.
+rem
+if not "_%trust%_" == "__" (
+ if "_%trust%_" == "_yes_" (set "trust=--trust-yes"
+ ) else (if "_%trust%_" == "_no_" (set "trust=--trust-no"
+ ) else (set "trust=--trust %trust%"))
+)
+
+rem Network timeout.
+rem
+if not "_%timeout%_" == "__" (
+ set "timeout=--fetch-timeout %timeout%"
+)
+
+rem Diagnostics verbosity.
+rem
+if not "_%verbose%_" == "__" (
+ set "verbose=--verbose %verbose%"
+)
+
+if not exist %idir%\bin\ (
+ echo error: %idir%\bin\ does not exist
+ goto error
+)
+
+rem Derive the to be installed executables names based on
+rem --exe-{prefix,suffix}. Unless the installation is local, also derive the
+rem staged executables names based on --stage-suffix and verify that they
+rem don't clash with existing filesystem entries as well as the executables
+rem being installed.
+rem
+set "b=%exe_prefix%b%exe_suffix%"
+set "bpkg=%exe_prefix%bpkg%exe_suffix%"
+set "bdep=%exe_prefix%bdep%exe_suffix%"
+
+if "_%local%_" == "__" (
+ set "b_stage=b%stage_suffix%"
+ set "bpkg_stage=bpkg%stage_suffix%"
+
+ if exist %idir%\bin\!b_stage!.exe (
+ echo error: staged executable name '!b_stage!' clashes with existing %idir%\bin\!b_stage!.exe
+ echo info: specify alternative staged executables name suffix with --stage-suffix
+ goto error
+ )
+
+ if exist %idir%\bin\!bpkg_stage!.exe (
+ echo error: staged executable name '!bpkg_stage!' clashes with existing %idir%\bin\!bpkg_stage!.exe
+ echo info: specify alternative staged executables name suffix with --stage-suffix
+ goto error
+ )
+
+ if "_%stage_suffix%_" == "_%exe_suffix%_" (
+ if "_%exe_prefix%_" == "__" (
+ echo error: suffix '%exe_suffix%' is used for both final and staged executables
+ echo info: specify alternative staged executables name suffix with --stage-suffix
+ goto error
+ )
+ )
+)
+
+set "conf_exe_affixes="
+
+if not "_%exe_prefix%_" == "__" (
+ set "conf_exe_affixes=config.bin.exe.prefix=%exe_prefix%"
+)
+
+if not "_%exe_suffix%_" == "__" (
+ set "conf_exe_affixes=%conf_exe_affixes% config.bin.exe.suffix=%exe_suffix%"
+)
+
+if exist build\config.build (
+ echo error: current directory already configured, start with clean source
+ goto error
+)
+
+if "_%local%_" == "__" (
+ if exist ..\%cdir%\ (
+ echo error: ..\%cdir%\ bpkg configuration directory already exists, remove it
+ goto error
+ )
+)
+
+set "PATH=%idir%\bin;%PATH%"
+
+rem Show the steps we are performing.
+rem
+@echo on
+
+@rem Verify the compiler works.
+@rem
+%cxx% --version
+@if errorlevel 1 goto error
+
+@rem Suppress loading of default options files.
+@rem
+set "BUILD2_DEF_OPT=0"
+set "BPKG_DEF_OPT=0"
+set "BDEP_DEF_OPT=0"
+
+@rem Bootstrap.
+@rem
+@rem Note: disable all warnings since we cannot do anything more granular
+@rem during bootstrap stage 1.
+@rem
+cd build2
+
+@if "_%make%_" == "__" (
+ goto batchfile
+) else (
+ goto makefile
+)
+
+:batchfile
+@rem Execute in a separate cmd.exe to preserve the echo mode.
+@rem
+cmd /C bootstrap-mingw.bat %cxx% -w -static
+@if errorlevel 1 goto error
+@goto endfile
+
+:makefile
+%make% -f bootstrap.gmake CXX=%cxx% CXXFLAGS=-w LDFLAGS=-static
+@if errorlevel 1 goto error
+@goto endfile
+
+:endfile
+build2\b-boot --version
+@if errorlevel 1 goto error
+
+build2\b-boot %verbose% %jobs% config.cxx=%cxx% config.bin.lib=static build2\exe{b}
+@if errorlevel 1 goto error
+
+move /y build2\b.exe build2\b-boot.exe
+@if errorlevel 1 goto error
+
+build2\b-boot --version
+@if errorlevel 1 goto error
+
+cd ..
+
+@rem Local installation early return.
+@rem
+@if "_%local%_" == "__" goto stage
+
+build2\build2\b-boot %verbose% configure^
+ config.config.hermetic=true^
+ config.cxx=%cxx%^
+ %coptions%^
+ %loptions%^
+ config.bin.lib=shared^
+ config.install.root=%idir%^
+ %conf_exe_affixes%
+@if errorlevel 1 goto error
+
+@rem Install toolchain.
+@rem
+@set "projects=build2\"
+
+@if "_%bpkg_install%_" == "_true_" (
+ set "projects=%projects% bpkg\"
+)
+
+@if "_%bdep_install%_" == "_true_" (
+ set "projects=%projects% bdep\"
+)
+
+build2\build2\b-boot %verbose% %jobs% install: %projects%
+@if errorlevel 1 goto error
+
+@rem The where command is not available on XP without the resource kit.
+@rem
+where %b%
+@rem @if errorlevel 1 goto error
+
+%b% --version
+@if errorlevel 1 goto error
+
+@if "_%bpkg_install%_" == "__" goto bpkg_vle
+
+where %bpkg%
+@rem @if errorlevel 1 goto error
+
+%bpkg% --version
+@if errorlevel 1 goto error
+
+:bpkg_vle
+
+@if "_%bdep_install%_" == "__" goto bdep_vle
+
+where %bdep%
+@rem @if errorlevel 1 goto error
+
+%bdep% --version
+@if errorlevel 1 goto error
+
+:bdep_vle
+
+@rem Install modules.
+@rem
+@set "projects="
+@set "tests="
+
+@for %%m in (%modules%) do @(
+ set "projects=!projects! libbuild2-%%m\"
+ set "tests=!tests! tests\libbuild2-%%m-tests\"
+)
+
+@if "_%projects%_" == "__" goto mods_ile
+
+%b% %verbose% %jobs% install: ^^!config.install.scope=project %projects:~1%
+@if errorlevel 1 goto error
+
+%b% %verbose% noop: %tests:~1%
+@if errorlevel 1 goto error
+
+:mods_ile
+
+@echo off
+
+echo.
+echo Toolchain installation: %idir%\bin
+echo Build configuration: %owd%
+echo.
+
+goto end
+
+@rem Build and stage the build system and the package manager.
+@rem
+:stage
+
+build2\build2\b-boot %verbose% configure^
+ config.cxx=%cxx%^
+ config.bin.lib=shared^
+ config.bin.suffix=%stage_suffix%^
+ config.install.root=%idir%^
+ config.install.data_root=root\stage
+@if errorlevel 1 goto error
+
+build2\build2\b-boot %verbose% %jobs% install: build2\ bpkg\
+@if errorlevel 1 goto error
+
+where %b_stage%
+@rem @if errorlevel 1 goto error
+
+%b_stage% --version
+@if errorlevel 1 goto error
+
+where %bpkg_stage%
+@rem @if errorlevel 1 goto error
+
+%bpkg_stage% --version
+@if errorlevel 1 goto error
+
+@rem Build the entire toolchain from packages.
+@rem
+cd ..
+
+md %cdir%
+@if errorlevel 1 goto error
+
+cd %cdir%
+
+@rem Save full path for later.
+@rem
+@set "cdir=%CD%"
+
+%bpkg_stage% %verbose% create^
+ cc^
+ config.config.hermetic=true^
+ config.cxx=%cxx%^
+ %coptions%^
+ %loptions%^
+ config.bin.lib=shared^
+ config.install.root=%idir%^
+ %conf_exe_affixes%
+@if errorlevel 1 goto error
+
+@set "packages=build2/%build2_ver% bpkg/%bpkg_ver%"
+
+@if "_%bdep_install%_" == "_true_" (
+ set "packages=%packages% bdep/%bdep_ver%"
+)
+
+%bpkg_stage% %verbose% add %BUILD2_REPO%
+@if errorlevel 1 goto error
+
+%bpkg_stage% %verbose% %timeout% %trust% fetch
+@if errorlevel 1 goto error
+
+%bpkg_stage% %verbose% %jobs% %timeout% build --for install --yes --plan= %packages%
+@if errorlevel 1 goto error
+
+%bpkg_stage% %verbose% %jobs% install --all
+@if errorlevel 1 goto error
+
+where %b%
+@rem @if errorlevel 1 goto error
+
+%b% --version
+@if errorlevel 1 goto error
+
+where %bpkg%
+@rem @if errorlevel 1 goto error
+
+%bpkg% --version
+@if errorlevel 1 goto error
+
+@if "_%bdep_install%_" == "__" goto bdep_vpe
+
+where %bdep%
+@rem @if errorlevel 1 goto error
+
+%bdep% --version
+@if errorlevel 1 goto error
+
+:bdep_vpe
+
+@rem Build, install, and verify the build system modules.
+@rem
+@set "packages="
+@set "tests="
+
+@for %%m in (%modules%) do @(
+ set "packages=!packages! libbuild2-%%m/!%%m_ver!"
+ set "tests=!tests! tests\libbuild2-%%m-tests\"
+)
+
+@if "_%packages%_" == "__" goto mods_ipe
+
+%bpkg% %verbose% %jobs% %timeout% build --for install %packages:~1%
+@if errorlevel 1 goto error
+
+%bpkg% %verbose% %jobs% install ^^!config.install.scope=project --all-pattern=libbuild2-*
+@if errorlevel 1 goto error
+
+:mods_ipe
+
+cd %owd%
+
+@if "_%tests%_" == "__" goto mods_lpe
+
+%b% %verbose% noop: %tests:~1%
+@if errorlevel 1 goto error
+
+:mods_lpe
+
+@rem Clean up stage.
+@rem
+%b% %verbose% %jobs% uninstall: build2\ bpkg\
+@if errorlevel 1 goto error
+
+@echo off
+
+echo.
+echo Toolchain installation: %idir%\bin
+echo Build configuration: %cdir%
+echo.
+
+goto end
+
+:error
+@echo off
+cd %owd%
+endlocal
+exit /b 1
+
+:end
+endlocal
diff --git a/build-msvc.bat b/build-msvc.bat
deleted file mode 100644
index 495f2ac..0000000
--- a/build-msvc.bat
+++ /dev/null
@@ -1,361 +0,0 @@
-@echo off
-
-rem file : build-msvc.bat
-rem license : MIT; see accompanying LICENSE file
-
-setlocal EnableDelayedExpansion
-goto start
-
-:usage
-echo.
-echo Usage: %0 [/?] [^<options^>] [^<cl-compiler^>]
-echo Options:
-echo --local Don't build from packages, only from local source.
-echo --install-dir ^<dir^> Alternative installation directory.
-echo --repo ^<loc^> Alternative package repository location.
-echo --trust ^<fp^> Repository certificate fingerprint to trust.
-echo --timeout ^<sec^> Network operations timeout in seconds.
-echo --verbose ^<level^> Diagnostics verbosity level between 0 and 6.
-echo.
-echo By default the batch file will use cl.exe as the C++ compiler and install
-echo into C:\build2. It also expects to find the base utilities in the bin\
-echo subdirectory of the installation directory ^(C:\build2\bin\ by default^).
-echo.
-echo The --trust option recognizes two special values: 'yes' ^(trust everything^)
-echo and 'no' (trust nothing).
-echo.
-echo See the BOOTSTRAP-WINDOWS-MSVC file for details.
-echo.
-goto end
-
-:start
-
-set "owd=%CD%"
-
-rem Package repository URL (or path).
-rem
-if "_%BUILD2_REPO%_" == "__" (
- set "BUILD2_REPO=https://stage.build2.org/1"
-rem set "BUILD2_REPO=https://pkg.cppget.org/1/queue/alpha"
-rem set "BUILD2_REPO=https://pkg.cppget.org/1/alpha"
-)
-
-rem The bpkg configuration directory.
-rem
-set "cver=0.13-a.0"
-set "cdir=build2-toolchain-%cver%"
-
-rem Parse options.
-rem
-set "local="
-set "idir=C:\build2"
-set "trust="
-set "timeout="
-set "verbose="
-
-:options
-if "_%~1_" == "_/?_" goto usage
-if "_%~1_" == "_-h_" goto usage
-if "_%~1_" == "_--help_" goto usage
-
-if "_%~1_" == "_--local_" (
- set "local=true"
- shift
- goto options
-)
-
-if "_%~1_" == "_--install-dir_" (
- if "_%~2_" == "__" (
- echo error: installation directory expected after --install-dir
- goto error
- )
- set "idir=%~2"
- shift
- shift
- goto options
-)
-
-if "_%~1_" == "_--trust_" (
- if "_%~2_" == "__" (
- echo error: certificate fingerprint expected after --trust
- goto error
- )
- set "trust=%~2"
- shift
- shift
- goto options
-)
-
-if "_%~1_" == "_--repo_" (
- if "_%~2_" == "__" (
- echo error: repository location expected after --repo
- goto error
- )
- set "BUILD2_REPO=%~2"
- shift
- shift
- goto options
-)
-
-if "_%~1_" == "_--timeout_" (
- if "_%~2_" == "__" (
- echo error: value in seconds expected after --timeout
- goto error
- )
- set "timeout=%~2"
- shift
- shift
- goto options
-)
-
-if "_%~1_" == "_--verbose_" (
- if "_%~2_" == "__" (
- echo error: diagnostics level between 0 and 6 expected after --verbose
- goto error
- )
- set "verbose=%~2"
- shift
- shift
- goto options
-)
-
-if "_%~1_" == "_--_" shift
-
-rem Validate options and arguments.
-rem
-
-rem @@ Temporarily retained for backwards compatibility.
-rem
-if not "_%1_" == "__" (
- set "idir=%1"
-)
-if not "_%2_" == "__" (
- set "trust=%2"
-)
-rem Compiler.
-rem
-rem if "_%1_" == "__" (
- set "cxx=cl"
-rem ) else (
-rem set "cxx=%1"
-rem )
-
-rem Certificate to trust.
-rem
-if not "_%trust%_" == "__" (
- if "_%trust%_" == "_yes_" (
- set "trust=--trust-yes"
- ) else (
- if "_%trust%_" == "_no_" (
- set "trust=--trust-no"
- ) else (
- set "trust=--trust %trust%"
- )
- )
-)
-
-rem Network timeout.
-rem
-if not "_%timeout%_" == "__" (
- set "timeout=--fetch-timeout %timeout%"
-)
-
-rem Diagnostics verbosity.
-rem
-if not "_%verbose%_" == "__" (
- set "verbose=--verbose %verbose%"
-)
-
-if not exist %idir%\bin\ (
- echo error: %idir%\bin\ does not exist
- goto error
-)
-
-if exist build\config.build (
- echo error: current directory already configured, start with clean source
- goto error
-)
-
-if "_%local%_" == "__" (
- if exist ..\%cdir%\ (
- echo error: ..\%cdir%\ bpkg configuration directory already exists, remove it
- goto error
- )
-)
-
-set "PATH=%idir%\bin;%PATH%"
-
-rem Show the steps we are performing.
-rem
-@echo on
-
-@rem Verify the compiler works.
-@rem
-%cxx%
-@if errorlevel 1 goto error
-
-@rem Bootstrap.
-@rem
-cd build2
-
-@rem Execute in a separate cmd.exe to preserve the echo mode.
-@rem
-cmd /C bootstrap-msvc.bat %cxx%
-@if errorlevel 1 goto error
-
-build2\b-boot --version
-@if errorlevel 1 goto error
-
-build2\b-boot %verbose% config.cxx=%cxx% config.bin.lib=static build2\exe{b}
-@if errorlevel 1 goto error
-
-move /y build2\b.exe build2\b-boot.exe
-@if errorlevel 1 goto error
-
-build2\b-boot --version
-@if errorlevel 1 goto error
-
-cd ..
-
-@rem Local installation early return.
-@rem
-@if "_%local%_" == "__" goto stage
-
-build2\build2\b-boot %verbose% configure^
- config.cxx=%cxx%^
- config.cc.coptions=/O2^
- config.bin.lib=shared^
- config.install.root=%idir%
-@if errorlevel 1 goto error
-
-build2\build2\b-boot %verbose% install: build2\ bpkg\ bdep\
-@if errorlevel 1 goto error
-
-where b
-@if errorlevel 1 goto error
-
-where bpkg
-@if errorlevel 1 goto error
-
-where bdep
-@if errorlevel 1 goto error
-
-b --version
-@if errorlevel 1 goto error
-
-bpkg --version
-@if errorlevel 1 goto error
-
-bdep --version
-@if errorlevel 1 goto error
-
-@echo off
-
-echo.
-echo Toolchain installation: %idir%\bin
-echo Build configuration: %owd%
-echo.
-
-goto end
-
-@rem Build and stage the build system and the package manager.
-@rem
-:stage
-
-build2\build2\b-boot %verbose% configure^
- config.cxx=%cxx%^
- config.bin.lib=shared^
- config.bin.suffix=-stage^
- config.install.root=%idir%^
- config.install.data_root=root\stage
-@if errorlevel 1 goto error
-
-build2\build2\b-boot %verbose% install: build2\ bpkg\
-@if errorlevel 1 goto error
-
-where b-stage
-@if errorlevel 1 goto error
-
-where bpkg-stage
-@if errorlevel 1 goto error
-
-b-stage --version
-@if errorlevel 1 goto error
-
-bpkg-stage --version
-@if errorlevel 1 goto error
-
-@rem Build the entire toolchain from packages.
-@rem
-cd ..
-
-md %cdir%
-@if errorlevel 1 goto error
-
-cd %cdir%
-
-@rem Save full path for later.
-@rem
-@set "cdir=%CD%"
-
-bpkg-stage %verbose% create^
- cc^
- config.cxx=%cxx%^
- config.cc.coptions=/O2^
- config.bin.lib=shared^
- config.install.root=%idir%
-@if errorlevel 1 goto error
-
-bpkg-stage %verbose% add %BUILD2_REPO%
-@if errorlevel 1 goto error
-
-bpkg-stage %verbose% %timeout% %trust% fetch
-@if errorlevel 1 goto error
-
-bpkg-stage %verbose% %timeout% build --for install --yes --plan= build2 bpkg bdep
-@if errorlevel 1 goto error
-
-bpkg-stage %verbose% install build2 bpkg bdep
-@if errorlevel 1 goto error
-
-where b
-@if errorlevel 1 goto error
-
-where bpkg
-@if errorlevel 1 goto error
-
-where bdep
-@if errorlevel 1 goto error
-
-b --version
-@if errorlevel 1 goto error
-
-bpkg --version
-@if errorlevel 1 goto error
-
-bdep --version
-@if errorlevel 1 goto error
-
-@rem Clean up stage.
-@rem
-cd %owd%
-b %verbose% uninstall: build2/ bpkg/
-@if errorlevel 1 goto error
-
-@echo off
-
-echo.
-echo Toolchain installation: %idir%\bin
-echo Build configuration: %cdir%
-echo.
-
-goto end
-
-:error
-@echo off
-cd %owd%
-endlocal
-exit /b 1
-
-:end
-endlocal
diff --git a/build-msvc.bat.in b/build-msvc.bat.in
new file mode 100644
index 0000000..b3035b4
--- /dev/null
+++ b/build-msvc.bat.in
@@ -0,0 +1,670 @@
+@echo off
+
+rem file : build-msvc.bat.in
+rem license : MIT; see accompanying LICENSE file
+
+setlocal EnableDelayedExpansion
+goto start
+
+:usage
+echo.
+echo Usage: %0 [/?] [^<options^>] [--] [^<cl-compiler^>] [^<compile-options^>] [-- ^<link-options^>]
+echo Options:
+echo --local Don't build from packages, only from local source.
+echo --no-bpkg Don't install bpkg nor bdep ^(requires --local^).
+echo --no-bdep Don't install bdep.
+echo --no-modules Don't install standard build system modules.
+echo --modules "<list>" Install only specified standard build system modules.
+echo --install-dir ^<dir^> Alternative installation directory.
+echo --exe-prefix ^<pfx^> Toolchain executables name prefix.
+echo --exe-suffix ^<sfx^> Toolchain executables name suffix.
+echo --stage-suffix ^<sfx^> Staged executables name suffix ^('-stage' by default^).
+echo --jobs^|-j ^<num^> Number of jobs to perform in parallel.
+echo --repo ^<loc^> Alternative package repository location.
+echo --trust ^<fp^> Repository certificate fingerprint to trust.
+echo --timeout ^<sec^> Network operations timeout in seconds.
+echo --verbose ^<level^> Diagnostics verbosity level between 0 and 6.
+echo.
+echo By default the batch file will use cl.exe as the C++ compiler and install
+echo into C:\build2. It also expects to find the base utilities in the bin\
+echo subdirectory of the installation directory ^(C:\build2\bin\ by default^).
+echo.
+echo If --jobs^|-j is unspecified, then the number of available hardware
+echo threads is used.
+echo.
+echo The --trust option recognizes two special values: 'yes' ^(trust everything^)
+echo and 'no' ^(trust nothing^).
+echo.
+echo The script by default installs the following standard build system
+echo modules:
+echo.
+echo %standard_modules%
+echo.
+echo Use --no-modules to suppress installing build system modules or
+echo --modules "<list>" to specify a comma-separated subset to install.
+echo.
+echo See the BOOTSTRAP-WINDOWS-MSVC file for details.
+echo.
+goto end
+
+:start
+
+set "owd=%CD%"
+
+rem Package repository URL (or path).
+rem
+if "_%BUILD2_REPO%_" == "__" (
+ set "BUILD2_REPO=@BUILD2_REPO@"
+)
+
+rem Package versions.
+rem
+set "build2_ver=@BUILD2_VERSION@"
+set "bpkg_ver=@BPKG_VERSION@"
+set "bdep_ver=@BDEP_VERSION@"
+
+rem Standard modules comma-separated list and versions.
+rem
+rem NOTE: we currently print the list as a single line and will need to
+rem somehow change that when it becomes too long.
+rem
+set "standard_modules=autoconf, kconfig"
+set "autoconf_ver=@AUTOCONF_VERSION@"
+set "kconfig_ver=@KCONFIG_VERSION@"
+
+rem The bpkg configuration directory.
+rem
+set "cver=@CONFIG_VER@"
+set "cdir=build2-toolchain-%cver%"
+
+rem Parse options.
+rem
+set "local="
+set "bpkg_install=true"
+set "bdep_install=true"
+set "modules=%standard_modules%"
+set "idir=C:\build2"
+set "exe_prefix="
+set "exe_suffix="
+set "stage_suffix=-stage"
+set "jobs="
+set "trust="
+set "timeout="
+set "verbose="
+
+:options
+if "_%~1_" == "_/?_" goto usage
+if "_%~1_" == "_-h_" goto usage
+if "_%~1_" == "_--help_" goto usage
+
+if "_%~1_" == "_--local_" (
+ set "local=true"
+ shift
+ goto options
+)
+
+if "_%~1_" == "_--no-bpkg_" (
+ set "bpkg_install="
+ shift
+ goto options
+)
+
+if "_%~1_" == "_--no-bdep_" (
+ set "bdep_install="
+ shift
+ goto options
+)
+
+if "_%~1_" == "_--no-modules_" (
+ set "modules="
+ shift
+ goto options
+)
+
+if "_%~1_" == "_--modules_" (
+ set "modules=%~2"
+ shift
+ shift
+ goto options
+)
+
+if "_%~1_" == "_--install-dir_" (
+ if "_%~2_" == "__" (
+ echo error: installation directory expected after --install-dir
+ goto error
+ )
+ set "idir=%~2"
+ shift
+ shift
+ goto options
+)
+
+if "_%~1_" == "_--exe-prefix_" (
+ if "_%~2_" == "__" (
+ echo error: executables name prefix expected after --exe-prefix
+ goto error
+ )
+ set "exe_prefix=%~2"
+ shift
+ shift
+ goto options
+)
+
+if "_%~1_" == "_--exe-suffix_" (
+ if "_%~2_" == "__" (
+ echo error: executables name suffix expected after --exe-suffix
+ goto error
+ )
+ set "exe_suffix=%~2"
+ shift
+ shift
+ goto options
+)
+
+if "_%~1_" == "_--stage-suffix_" (
+ if "_%~2_" == "__" (
+ echo error: staged executables name suffix expected after --stage-suffix
+ goto error
+ )
+ set "stage_suffix=%~2"
+ shift
+ shift
+ goto options
+)
+
+set "jo="
+if "_%~1_" == "_-j_" set "jo=true"
+if "_%~1_" == "_--jobs_" set "jo=true"
+
+if "_%jo%_" == "_true_" (
+ if "_%~2_" == "__" (
+ echo error: number of jobs expected after --jobs^|-j
+ goto error
+ )
+ set "jobs=%~2"
+ shift
+ shift
+ goto options
+)
+
+if "_%~1_" == "_--trust_" (
+ if "_%~2_" == "__" (
+ echo error: certificate fingerprint expected after --trust
+ goto error
+ )
+ set "trust=%~2"
+ shift
+ shift
+ goto options
+)
+
+if "_%~1_" == "_--repo_" (
+ if "_%~2_" == "__" (
+ echo error: repository location expected after --repo
+ goto error
+ )
+ set "BUILD2_REPO=%~2"
+ shift
+ shift
+ goto options
+)
+
+if "_%~1_" == "_--timeout_" (
+ if "_%~2_" == "__" (
+ echo error: value in seconds expected after --timeout
+ goto error
+ )
+ set "timeout=%~2"
+ shift
+ shift
+ goto options
+)
+
+if "_%~1_" == "_--verbose_" (
+ if "_%~2_" == "__" (
+ echo error: diagnostics level between 0 and 6 expected after --verbose
+ goto error
+ )
+ set "verbose=%~2"
+ shift
+ shift
+ goto options
+)
+
+if "_%~1_" == "_--_" shift
+
+rem Compiler.
+rem
+if "_%1_" == "__" (
+ set "cxx=cl"
+) else (
+ set "cxx=%~1"
+ shift
+)
+
+rem Compile and link options.
+rem
+set "compile_ops="
+set "link_ops="
+
+:compile_options
+if not "_%1_" == "__" (
+ if not "_%~1_" == "_--_" (
+ set "compile_ops=%compile_ops% %~1"
+ shift
+ goto compile_options
+ ) else (
+ shift
+ )
+)
+
+:link_options
+if not "_%1_" == "__" (
+ set "link_ops=%link_ops% %~1"
+ shift
+ goto link_options
+)
+
+if not "_%compile_ops%_" == "__" (
+ set coptions="config.cc.coptions=%compile_ops:~1%"
+) else (
+ set "coptions=config.cc.coptions=/O2"
+)
+
+if not "_%link_ops%_" == "__" (
+ set loptions="config.cc.loptions=%link_ops:~1%"
+) else (
+ set "loptions="
+)
+
+rem Validate options and arguments.
+rem
+
+rem If --no-bpkg is specified, then we require --local to also be specified
+rem since it won't be possible to build things from packages without bpkg.
+rem Also imply --no-bdep in this case, since bdep is pretty much useless
+rem without bpkg.
+rem
+if "_%bpkg_install%_" == "__" (
+ if "_%local%_" == "__" (
+ echo error: --no-bpkg can only be used for local installation
+ echo info: additionally specify --local
+ goto error
+ )
+
+ set "bdep_install="
+)
+
+for %%m in (%modules%) do (
+ if "_!%%m_ver!_" == "__" (
+ echo error: unknown standard build system module '%%m'
+ echo info: available standard modules: %standard_modules%
+ goto error
+ )
+)
+
+rem Convert a relative path to an absolute.
+rem
+for /F "delims=|" %%D in ("%idir%") do set "idir=%%~dpnxD"
+
+rem Translate the number of jobs into the bootstrap script and build2/bpkg
+rem options.
+rem
+if not "_%jobs%_" == "__" (
+ set "ops=/MP%jobs%"
+ set "jobs=-j %jobs%"
+) else (
+ set "ops="
+)
+
+rem Certificate to trust.
+rem
+if not "_%trust%_" == "__" (
+ if "_%trust%_" == "_yes_" (set "trust=--trust-yes"
+ ) else (if "_%trust%_" == "_no_" (set "trust=--trust-no"
+ ) else (set "trust=--trust %trust%"))
+)
+
+rem Network timeout.
+rem
+if not "_%timeout%_" == "__" (
+ set "timeout=--fetch-timeout %timeout%"
+)
+
+rem Diagnostics verbosity.
+rem
+if not "_%verbose%_" == "__" (
+ set "verbose=--verbose %verbose%"
+)
+
+if not exist %idir%\bin\ (
+ echo error: %idir%\bin\ does not exist
+ goto error
+)
+
+rem Derive the to be installed executables names based on
+rem --exe-{prefix,suffix}. Unless the installation is local, also derive the
+rem staged executables names based on --stage-suffix and verify that they
+rem don't clash with existing filesystem entries as well as the executables
+rem being installed.
+rem
+set "b=%exe_prefix%b%exe_suffix%"
+set "bpkg=%exe_prefix%bpkg%exe_suffix%"
+set "bdep=%exe_prefix%bdep%exe_suffix%"
+
+if "_%local%_" == "__" (
+ set "b_stage=b%stage_suffix%"
+ set "bpkg_stage=bpkg%stage_suffix%"
+
+ if exist %idir%\bin\!b_stage!.exe (
+ echo error: staged executable name '!b_stage!' clashes with existing %idir%\bin\!b_stage!.exe
+ echo info: specify alternative staged executables name suffix with --stage-suffix
+ goto error
+ )
+
+ if exist %idir%\bin\!bpkg_stage!.exe (
+ echo error: staged executable name '!bpkg_stage!' clashes with existing %idir%\bin\!bpkg_stage!.exe
+ echo info: specify alternative staged executables name suffix with --stage-suffix
+ goto error
+ )
+
+ if "_%stage_suffix%_" == "_%exe_suffix%_" (
+ if "_%exe_prefix%_" == "__" (
+ echo error: suffix '%exe_suffix%' is used for both final and staged executables
+ echo info: specify alternative staged executables name suffix with --stage-suffix
+ goto error
+ )
+ )
+)
+
+set "conf_exe_affixes="
+
+if not "_%exe_prefix%_" == "__" (
+ set "conf_exe_affixes=config.bin.exe.prefix=%exe_prefix%"
+)
+
+if not "_%exe_suffix%_" == "__" (
+ set "conf_exe_affixes=%conf_exe_affixes% config.bin.exe.suffix=%exe_suffix%"
+)
+
+if exist build\config.build (
+ echo error: current directory already configured, start with clean source
+ goto error
+)
+
+if "_%local%_" == "__" (
+ if exist ..\%cdir%\ (
+ echo error: ..\%cdir%\ bpkg configuration directory already exists, remove it
+ goto error
+ )
+)
+
+set "PATH=%idir%\bin;%PATH%"
+
+rem Show the steps we are performing.
+rem
+@echo on
+
+@rem Verify the compiler works.
+@rem
+%cxx%
+@if errorlevel 1 goto error
+
+@rem Suppress loading of default options files.
+@rem
+set "BUILD2_DEF_OPT=0"
+set "BPKG_DEF_OPT=0"
+set "BDEP_DEF_OPT=0"
+
+@rem Bootstrap.
+@rem
+@rem Note: disable all warnings since we cannot do anything more granular
+@rem during bootstrap stage 1.
+@rem
+cd build2
+
+@rem Execute in a separate cmd.exe to preserve the echo mode.
+@rem
+cmd /C bootstrap-msvc.bat %cxx% /w %ops%
+@if errorlevel 1 goto error
+
+build2\b-boot --version
+@if errorlevel 1 goto error
+
+build2\b-boot %verbose% %jobs% config.cxx=%cxx% config.bin.lib=static build2\exe{b}
+@if errorlevel 1 goto error
+
+move /y build2\b.exe build2\b-boot.exe
+@if errorlevel 1 goto error
+
+build2\b-boot --version
+@if errorlevel 1 goto error
+
+cd ..
+
+@rem Local installation early return.
+@rem
+@if "_%local%_" == "__" goto stage
+
+build2\build2\b-boot %verbose% configure^
+ config.config.hermetic=true^
+ config.cxx=%cxx%^
+ %coptions%^
+ %loptions%^
+ config.bin.lib=shared^
+ config.install.root=%idir%^
+ %conf_exe_affixes%
+@if errorlevel 1 goto error
+
+@rem Install toolchain.
+@rem
+@set "projects=build2\"
+
+@if "_%bpkg_install%_" == "_true_" (
+ set "projects=%projects% bpkg\"
+)
+
+@if "_%bdep_install%_" == "_true_" (
+ set "projects=%projects% bdep\"
+)
+
+build2\build2\b-boot %verbose% %jobs% install: %projects%
+@if errorlevel 1 goto error
+
+where %b%
+@if errorlevel 1 goto error
+
+%b% --version
+@if errorlevel 1 goto error
+
+@if "_%bpkg_install%_" == "__" goto bpkg_vle
+
+where %bpkg%
+@if errorlevel 1 goto error
+
+%bpkg% --version
+@if errorlevel 1 goto error
+
+:bpkg_vle
+
+@if "_%bdep_install%_" == "__" goto bdep_vle
+
+where %bdep%
+@if errorlevel 1 goto error
+
+%bdep% --version
+@if errorlevel 1 goto error
+
+:bdep_vle
+
+@rem Install modules.
+@rem
+@set "projects="
+@set "tests="
+
+@for %%m in (%modules%) do @(
+ set "projects=!projects! libbuild2-%%m\"
+ set "tests=!tests! tests\libbuild2-%%m-tests\"
+)
+
+@if "_%projects%_" == "__" goto mods_ile
+
+%b% %verbose% %jobs% install: ^^!config.install.scope=project %projects:~1%
+@if errorlevel 1 goto error
+
+%b% %verbose% noop: %tests:~1%
+@if errorlevel 1 goto error
+
+:mods_ile
+
+@echo off
+
+echo.
+echo Toolchain installation: %idir%\bin
+echo Build configuration: %owd%
+echo.
+
+goto end
+
+@rem Build and stage the build system and the package manager.
+@rem
+:stage
+
+build2\build2\b-boot %verbose% configure^
+ config.cxx=%cxx%^
+ config.bin.lib=shared^
+ config.bin.suffix=%stage_suffix%^
+ config.install.root=%idir%^
+ config.install.data_root=root\stage
+@if errorlevel 1 goto error
+
+build2\build2\b-boot %verbose% %jobs% install: build2\ bpkg\
+@if errorlevel 1 goto error
+
+where %b_stage%
+@if errorlevel 1 goto error
+
+%b_stage% --version
+@if errorlevel 1 goto error
+
+where %bpkg_stage%
+@if errorlevel 1 goto error
+
+%bpkg_stage% --version
+@if errorlevel 1 goto error
+
+@rem Build the entire toolchain from packages.
+@rem
+cd ..
+
+md %cdir%
+@if errorlevel 1 goto error
+
+cd %cdir%
+
+@rem Save full path for later.
+@rem
+@set "cdir=%CD%"
+
+%bpkg_stage% %verbose% create^
+ cc^
+ config.config.hermetic=true^
+ config.cxx=%cxx%^
+ %coptions%^
+ %loptions%^
+ config.bin.lib=shared^
+ config.install.root=%idir%^
+ %conf_exe_affixes%
+@if errorlevel 1 goto error
+
+@set "packages=build2/%build2_ver% bpkg/%bpkg_ver%"
+
+@if "_%bdep_install%_" == "_true_" (
+ set "packages=%packages% bdep/%bdep_ver%"
+)
+
+%bpkg_stage% %verbose% add %BUILD2_REPO%
+@if errorlevel 1 goto error
+
+%bpkg_stage% %verbose% %timeout% %trust% fetch
+@if errorlevel 1 goto error
+
+%bpkg_stage% %verbose% %jobs% %timeout% build --for install --yes --plan= %packages%
+@if errorlevel 1 goto error
+
+%bpkg_stage% %verbose% %jobs% install --all
+@if errorlevel 1 goto error
+
+where %b%
+@if errorlevel 1 goto error
+
+%b% --version
+@if errorlevel 1 goto error
+
+where %bpkg%
+@if errorlevel 1 goto error
+
+%bpkg% --version
+@if errorlevel 1 goto error
+
+@if "_%bdep_install%_" == "__" goto bdep_vpe
+
+where %bdep%
+@if errorlevel 1 goto error
+
+%bdep% --version
+@if errorlevel 1 goto error
+
+:bdep_vpe
+
+@rem Build, install, and verify the build system modules.
+@rem
+@set "packages="
+@set "tests="
+
+@for %%m in (%modules%) do @(
+ set "packages=!packages! libbuild2-%%m/!%%m_ver!"
+ set "tests=!tests! tests\libbuild2-%%m-tests\"
+)
+
+@if "_%packages%_" == "__" goto mods_ipe
+
+%bpkg% %verbose% %jobs% %timeout% build --for install %packages:~1%
+@if errorlevel 1 goto error
+
+%bpkg% %verbose% %jobs% install ^^!config.install.scope=project --all-pattern=libbuild2-*
+@if errorlevel 1 goto error
+
+:mods_ipe
+
+cd %owd%
+
+@if "_%tests%_" == "__" goto mods_lpe
+
+%b% %verbose% noop: %tests:~1%
+@if errorlevel 1 goto error
+
+:mods_lpe
+
+@rem Clean up stage.
+@rem
+%b% %verbose% %jobs% uninstall: build2\ bpkg\
+@if errorlevel 1 goto error
+
+@echo off
+
+echo.
+echo Toolchain installation: %idir%\bin
+echo Build configuration: %cdir%
+echo.
+
+goto end
+
+:error
+@echo off
+cd %owd%
+endlocal
+exit /b 1
+
+:end
+endlocal
diff --git a/build.sh b/build.sh
deleted file mode 100755
index eab4cbd..0000000
--- a/build.sh
+++ /dev/null
@@ -1,414 +0,0 @@
-#!/bin/sh
-
-# file : build.sh
-# license : MIT; see accompanying LICENSE file
-
-usage="Usage: $0 [-h|--help] [<options>] <c++-compiler> [<compile-options>]"
-
-# Package repository URL (or path).
-#
-if test -z "$BUILD2_REPO"; then
- BUILD2_REPO="https://stage.build2.org/1"
-# BUILD2_REPO="https://pkg.cppget.org/1/queue/alpha"
-# BUILD2_REPO="https://pkg.cppget.org/1/alpha"
-fi
-
-# The bpkg configuration directory.
-#
-cver="0.13-a.0"
-cdir="build2-toolchain-$cver"
-
-diag ()
-{
- echo "$*" 1>&2
-}
-
-# Note that this function will execute a command with arguments that contain
-# spaces but it will not print them as quoted (and neither does set -x).
-#
-run ()
-{
- diag "+ $@"
- "$@"
- if test "$?" -ne "0"; then
- exit 1
- fi
-}
-
-owd="$(pwd)"
-
-local=
-private=
-idir=
-jobs=
-sudo=
-trust=
-timeout=
-make=
-make_options=
-verbose=
-
-cxx=
-
-while test $# -ne 0; do
- case "$1" in
- -h|--help)
- diag
- diag "$usage"
- diag "Options:"
- diag " --local Don't build from packages, only from local source."
- diag " --install-dir <dir> Alternative installation directory."
- diag " --sudo <prog> Optional sudo program to use (pass false to disable)."
- diag " --private Install shared libraries into private subdirectory."
- diag " --jobs|-j <num> Number of jobs to perform in parallel."
- diag " --repo <loc> Alternative package repository location."
- diag " --trust <fp> Repository certificate fingerprint to trust."
- diag " --timeout <sec> Network operations timeout in seconds."
- diag " --make <arg> Bootstrap using GNU make instead of script."
- diag " --verbose <level> Diagnostics verbosity level between 0 and 6."
- diag
- diag "By default the script will install into /usr/local with private"
- diag "library subdirectories and using sudo(1). To enable private"
- diag "subdirectories and/or use sudo for a custom installation location,"
- diag "you need to specify --private and/or --sudo explicitly, for example:"
- diag
- diag "$0 --install-dir /opt/build2 --sudo sudo g++"
- diag
- diag "If --jobs|-j is unspecified, then the bootstrap step is performed"
- diag "serially with the rest of the process using the number of available"
- diag "hardware threads."
- diag
- diag "The --trust option recognizes two special values: 'yes' (trust"
- diag "everything) and 'no' (trust nothing)."
- diag
- diag "The --make option can be used to bootstrap using GNU make. The"
- diag "first --make value should specify the make executable optionally"
- diag "followed by additional make options, for example:"
- diag
- diag "$0 --make make --make -j8 g++"
- diag
- diag "If --jobs|-j is specified, then its value is passed to make before"
- diag "any additional options."
- diag
- diag "If specified, <compile-options> override the default (-O3) compile"
- diag "options (config.cc.coptions) in the bpkg configuration used to build"
- diag "and install the final toolchain. For example, to build with the debug"
- diag "information (and without optimization):"
- diag
- diag "$0 g++ -g"
- diag
- diag "See the BOOTSTRAP-UNIX file for details."
- diag
- exit 0
- ;;
- --local)
- local=true
- shift
- ;;
- --private)
- private=config.install.private=build2
- shift
- ;;
- --install-dir)
- shift
- if test $# -eq 0; then
- diag "error: installation directory expected after --install-dir"
- diag "$usage"
- exit 1
- fi
- idir="$1"
- shift
- ;;
- -j|--jobs)
- shift
- if test $# -eq 0; then
- diag "error: number of jobs expected after --jobs|-j"
- diag "$usage"
- exit 1
- fi
- jobs="-j $1"
- shift
- ;;
- --sudo)
- shift
- if test $# -eq 0; then
- diag "error: sudo program expected after --sudo"
- diag "$usage"
- exit 1
- fi
- sudo="$1"
- shift
- ;;
- --repo)
- shift
- if test $# -eq 0; then
- diag "error: repository location expected after --repo"
- diag "$usage"
- exit 1
- fi
- BUILD2_REPO="$1"
- shift
- ;;
- --trust)
- shift
- if test $# -eq 0; then
- diag "error: certificate fingerprint expected after --trust"
- diag "$usage"
- exit 1
- fi
- trust="$1"
- shift
- ;;
- --timeout)
- shift
- if test $# -eq 0; then
- diag "error: value in seconds expected after --timeout"
- diag "$usage"
- exit 1
- fi
- timeout="$1"
- shift
- ;;
- --make)
- shift
- if test $# -eq 0; then
- diag "error: argument expected after --make"
- diag "$usage"
- exit 1
- fi
- if test -z "$make"; then
- make="$1"
- else
- make_options="$make_options $1"
- fi
- shift
- ;;
- --verbose)
- shift
- if test $# -eq 0; then
- diag "error: diagnostics level between 0 and 6 expected after --verbose"
- diag "$usage"
- exit 1
- fi
- verbose="$1"
- shift
- ;;
- *)
- cxx="$1"
- shift
- break
- ;;
- esac
-done
-
-if test -z "$cxx"; then
- diag "error: compiler executable expected"
- diag "$usage"
- exit 1
-fi
-
-# Place default <compile-options> into the $@ array.
-#
-if test $# -eq 0; then
- set -- -O3
-fi
-
-# Merge jobs and make_options into make.
-#
-if test -n "$make"; then
- if test -n "$jobs"; then
- make="$make $jobs"
- fi
-
- if test -n "$make_options"; then
- make="$make$make_options" # Already has leading space.
- fi
-fi
-
-if test -z "$idir"; then
- idir=/usr/local
- private=config.install.private=build2
-
- # Only use default sudo for the default installation directory and only if
- # it wasn't specified by the user.
- #
- if test -z "$sudo"; then
- sudo="sudo"
- fi
-fi
-
-if test "$sudo" = false; then
- sudo=
-fi
-
-if test -f build/config.build; then
- diag "error: current directory already configured, start with clean source"
- exit 1
-fi
-
-if test -z "$local" -a -d "../$cdir"; then
- diag "error: ../$cdir/ bpkg configuration directory already exists, remove it"
- exit 1
-fi
-
-# Add $idir/bin to PATH in case it is not already there.
-#
-PATH="$idir/bin:$PATH"
-export PATH
-
-sys="$(build2/config.guess | sed -n 's/^[^-]*-[^-]*-\(.*\)$/\1/p')"
-
-case "$sys" in
- mingw32 | mingw64 | msys | msys2 | cygwin)
- conf_rpath="[null]"
- conf_rpath_stage="[null]"
- conf_sudo="[null]"
- ;;
- *)
- if test -n "$private"; then
- conf_rpath="$idir/lib/build2"
- else
- conf_rpath="$idir/lib"
- fi
-
- conf_rpath_stage="$idir/lib"
-
- if test -n "$sudo"; then
- conf_sudo="$sudo"
- else
- conf_sudo="[null]"
- fi
- ;;
-esac
-
-# We don't have arrays in POSIX shell but we should be ok as long as none of
-# the option values contain spaces. Note also that the expansion must be
-# unquoted.
-#
-bpkg_fetch_ops=
-bpkg_build_ops=
-
-if test -n "$timeout"; then
- bpkg_fetch_ops="--fetch-timeout $timeout"
- bpkg_build_ops="--fetch-timeout $timeout"
-fi
-
-if test "$trust" = "yes"; then
- bpkg_fetch_ops="$bpkg_fetch_ops --trust-yes"
-elif test "$trust" = "no"; then
- bpkg_fetch_ops="$bpkg_fetch_ops --trust-no"
-elif test -n "$trust"; then
- bpkg_fetch_ops="$bpkg_fetch_ops --trust $trust"
-fi
-
-if test -n "$verbose"; then
- verbose="--verbose $verbose"
-fi
-
-# Bootstrap, stage 1.
-#
-run cd build2
-if test -z "$make"; then
- run ./bootstrap.sh "$cxx"
-else
- run $make -f ./bootstrap.gmake "CXX=$cxx"
-fi
-run build2/b-boot --version
-
-# Bootstrap, stage 2.
-#
-run build2/b-boot $verbose $jobs config.cxx="$cxx" config.bin.lib=static build2/exe{b}
-mv build2/b build2/b-boot
-run build2/b-boot --version
-
-run cd ..
-
-# Local installation early return.
-#
-if test "$local" = true; then
-
- run build2/build2/b-boot $verbose configure \
-config.cxx="$cxx" \
-config.cc.coptions="$*" \
-config.bin.lib=shared \
-config.bin.rpath="$conf_rpath" \
-config.install.root="$idir" \
-config.install.sudo="$conf_sudo" \
-$private
-
- run build2/build2/b-boot $verbose $jobs install: build2/ bpkg/ bdep/
-
- run command -v b
- run command -v bpkg
- run command -v bdep
-
- run b --version
- run bpkg --version
- run bdep --version
-
- diag
- diag "Toolchain installation: $idir/bin"
- diag "Build configuration: $owd"
- diag
-
- exit 0
-fi
-
-# Build and stage the build system and the package manager.
-#
-run build2/build2/b-boot $verbose configure \
-config.cxx="$cxx" \
-config.bin.lib=shared \
-config.bin.suffix=-stage \
-config.bin.rpath="$conf_rpath_stage" \
-config.install.root="$idir" \
-config.install.data_root=root/stage \
-config.install.sudo="$conf_sudo"
-
-run build2/build2/b-boot $verbose $jobs install: build2/ bpkg/
-
-run command -v b-stage
-run command -v bpkg-stage
-
-run b-stage --version
-run bpkg-stage --version
-
-# Build the entire toolchain from packages.
-#
-run cd ..
-run mkdir "$cdir"
-run cd "$cdir"
-cdir="$(pwd)" # Save full path for later.
-
-run bpkg-stage $verbose create \
-cc \
-config.cxx="$cxx" \
-config.cc.coptions="$*" \
-config.bin.lib=shared \
-config.bin.rpath="$conf_rpath" \
-config.install.root="$idir" \
-config.install.sudo="$conf_sudo" \
-$private
-
-run bpkg-stage $verbose add "$BUILD2_REPO"
-run bpkg-stage $verbose $bpkg_fetch_ops fetch
-run bpkg-stage $verbose $jobs $bpkg_build_ops build --for install --yes --plan= build2 bpkg bdep
-run bpkg-stage $verbose $jobs install build2 bpkg bdep
-
-run command -v b
-run command -v bpkg
-run command -v bdep
-
-run b --version
-run bpkg --version
-run bdep --version
-
-# Clean up stage.
-#
-run cd "$owd"
-run b $verbose $jobs uninstall: build2/ bpkg/
-
-diag
-diag "Toolchain installation: $idir/bin"
-diag "Build configuration: $cdir"
-diag
diff --git a/build.sh.in b/build.sh.in
new file mode 100644
index 0000000..43c648a
--- /dev/null
+++ b/build.sh.in
@@ -0,0 +1,780 @@
+#!/bin/sh
+
+# file : build.sh.in
+# license : MIT; see accompanying LICENSE file
+
+usage="Usage: $0 [-h|--help] [<options>] [--] <c++-compiler> [<compile-options>] [-- <link-options>]"
+
+# Package repository URL (or path).
+#
+if test -z "$BUILD2_REPO"; then
+ BUILD2_REPO="@BUILD2_REPO@"
+fi
+
+# Package versions.
+#
+build2_ver="@BUILD2_VERSION@"
+bpkg_ver="@BPKG_VERSION@"
+bdep_ver="@BDEP_VERSION@"
+
+# Standard modules comma-separated list and versions.
+#
+# NOTE: we currently print the list as a single line and will need to somehow
+# change that when it becomes too long.
+#
+standard_modules="autoconf, kconfig"
+autoconf_ver="@AUTOCONF_VERSION@"
+kconfig_ver="@KCONFIG_VERSION@"
+
+# The bpkg configuration directory.
+#
+cver="@CONFIG_VER@"
+cdir="build2-toolchain-$cver"
+
+diag ()
+{
+ echo "$*" 1>&2
+}
+
+# Note that this function will execute a command with arguments that contain
+# spaces but it will not print them as quoted (and neither does set -x).
+#
+run ()
+{
+ diag "+ $@"
+ "$@"
+ if test "$?" -ne "0"; then
+ exit 1
+ fi
+}
+
+owd="$(pwd)"
+
+local=
+bpkg_install=true
+bdep_install=true
+modules="$standard_modules"
+system=
+private=
+idir=
+exe_prefix=
+exe_suffix=
+stage_suffix="-stage"
+jobs=
+sudo=
+trust=
+timeout=
+make=
+make_options=
+verbose=
+
+while test $# -ne 0; do
+ case "$1" in
+ -h|--help)
+ diag
+ diag "$usage"
+ diag "Options:"
+ diag " --local Don't build from packages, only from local source."
+ diag " --no-bpkg Don't install bpkg nor bdep (requires --local)."
+ diag " --no-bdep Don't install bdep."
+ diag " --no-modules Don't install standard build system modules."
+ diag " --modules <list> Install only specified standard build system modules."
+ diag " --install-dir <dir> Alternative installation directory."
+ diag " --system <list> Use system-installed versions of specified dependencies."
+ diag " --exe-prefix <pfx> Toolchain executables name prefix."
+ diag " --exe-suffix <sfx> Toolchain executables name suffix."
+ diag " --stage-suffix <sfx> Staged executables name suffix ('-stage' by default)."
+ diag " --sudo <prog> Optional sudo program to use (pass false to disable)."
+ diag " --private Install shared libraries into private subdirectory."
+ diag " --jobs|-j <num> Number of jobs to perform in parallel."
+ diag " --repo <loc> Alternative package repository location."
+ diag " --trust <fp> Repository certificate fingerprint to trust."
+ diag " --timeout <sec> Network operations timeout in seconds."
+ diag " --make <arg> Bootstrap using GNU make instead of script."
+ diag " --verbose <level> Diagnostics verbosity level between 0 and 6."
+ diag
+ diag "By default the script will install into /usr/local with private"
+ diag "library subdirectories and using sudo(1). To enable private"
+ diag "subdirectories and/or use sudo for a custom installation location,"
+ diag "you need to specify --private and/or --sudo explicitly, for example:"
+ diag
+ diag "$0 --install-dir /opt/build2 --sudo sudo g++"
+ diag
+ diag "If --jobs|-j is unspecified, then the bootstrap step is performed"
+ diag "serially with the rest of the process using the number of available"
+ diag "hardware threads."
+ diag
+ diag "The --trust option recognizes two special values: 'yes' (trust"
+ diag "everything) and 'no' (trust nothing)."
+ diag
+ diag "The --make option can be used to bootstrap using GNU make. The"
+ diag "first --make value should specify the make executable optionally"
+ diag "followed by additional make options, for example:"
+ diag
+ diag "$0 --make make --make -j8 g++"
+ diag
+ diag "If --jobs|-j is specified, then its value is passed to make before"
+ diag "any additional options."
+ diag
+ diag "If specified, <compile-options> override the default (-O3) compile"
+ diag "options (config.cc.coptions) in the bpkg configuration used to build"
+ diag "and install the final toolchain. For example, to build with the debug"
+ diag "information (and without optimization):"
+ diag
+ diag "$0 g++ -g"
+ diag
+ diag "Use --system <list> to specify a comma-separated list of dependencies"
+ diag "to use from the system rather than building them from source, for"
+ diag "example:"
+ diag
+ diag "$0 --system libsqlite3,libpkg-config g++"
+ diag
+ diag "The script by default installs the following standard build system"
+ diag "modules:"
+ diag
+ diag "$standard_modules"
+ diag
+ diag "Use --no-modules to suppress installing build system modules or"
+ diag "--modules <list> to specify a comma-separated subset to install."
+ diag
+ diag "See the BOOTSTRAP-UNIX file for details."
+ diag
+ exit 0
+ ;;
+ --local)
+ local=true
+ shift
+ ;;
+ --no-bpkg)
+ bpkg_install=
+ shift
+ ;;
+ --no-bdep)
+ bdep_install=
+ shift
+ ;;
+ --no-modules)
+ modules=
+ shift
+ ;;
+ --modules)
+ shift
+ modules="$1"
+ shift
+ ;;
+ --system)
+ shift
+ system="$1"
+ shift
+ ;;
+ --private)
+ private=config.install.private=build2
+ shift
+ ;;
+ --install-dir)
+ shift
+ if test $# -eq 0; then
+ diag "error: installation directory expected after --install-dir"
+ diag "$usage"
+ exit 1
+ fi
+ idir="$1"
+ shift
+ ;;
+ --exe-prefix)
+ shift
+ if test $# -eq 0; then
+ diag "error: executables name prefix expected after --exe-prefix"
+ diag "$usage"
+ exit 1
+ fi
+ exe_prefix="$1"
+ shift
+ ;;
+ --exe-suffix)
+ shift
+ if test $# -eq 0; then
+ diag "error: executables name suffix expected after --exe-suffix"
+ diag "$usage"
+ exit 1
+ fi
+ exe_suffix="$1"
+ shift
+ ;;
+ --stage-suffix)
+ shift
+ if test $# -eq 0; then
+ diag "error: staged executables name suffix expected after --stage-suffix"
+ diag "$usage"
+ exit 1
+ fi
+ stage_suffix="$1"
+ shift
+ ;;
+ -j|--jobs)
+ shift
+ if test $# -eq 0; then
+ diag "error: number of jobs expected after --jobs|-j"
+ diag "$usage"
+ exit 1
+ fi
+ jobs="-j $1"
+ shift
+ ;;
+ --sudo)
+ shift
+ if test $# -eq 0; then
+ diag "error: sudo program expected after --sudo"
+ diag "$usage"
+ exit 1
+ fi
+ sudo="$1"
+ shift
+ ;;
+ --repo)
+ shift
+ if test $# -eq 0; then
+ diag "error: repository location expected after --repo"
+ diag "$usage"
+ exit 1
+ fi
+ BUILD2_REPO="$1"
+ shift
+ ;;
+ --trust)
+ shift
+ if test $# -eq 0; then
+ diag "error: certificate fingerprint expected after --trust"
+ diag "$usage"
+ exit 1
+ fi
+ trust="$1"
+ shift
+ ;;
+ --timeout)
+ shift
+ if test $# -eq 0; then
+ diag "error: value in seconds expected after --timeout"
+ diag "$usage"
+ exit 1
+ fi
+ timeout="$1"
+ shift
+ ;;
+ --make)
+ shift
+ if test $# -eq 0; then
+ diag "error: argument expected after --make"
+ diag "$usage"
+ exit 1
+ fi
+ if test -z "$make"; then
+ make="$1"
+ else
+ make_options="$make_options $1"
+ fi
+ shift
+ ;;
+ --verbose)
+ shift
+ if test $# -eq 0; then
+ diag "error: diagnostics level between 0 and 6 expected after --verbose"
+ diag "$usage"
+ exit 1
+ fi
+ verbose="$1"
+ shift
+ ;;
+ --)
+ shift
+ break
+ ;;
+ *)
+ break
+ ;;
+ esac
+done
+
+# Compiler.
+#
+if test $# -eq 0; then
+ diag "error: compiler executable expected"
+ diag "$usage"
+ exit 1
+else
+ cxx="$1"
+ shift
+fi
+
+# Compile and link options.
+#
+compile_ops=
+link_ops=
+
+while test $# -ne 0; do
+ if test "$1" != "--"; then
+ compile_ops="$compile_ops $1"
+ shift
+ else
+ shift
+ break
+ fi
+done
+
+while test $# -ne 0; do
+ link_ops="$link_ops $1"
+ shift
+done
+
+if test -z "$compile_ops"; then
+ compile_ops=-O3
+fi
+
+if test -z "$link_ops"; then
+ link_ops="[null]"
+fi
+
+# Merge jobs and make_options into make.
+#
+if test -n "$make"; then
+ if test -n "$jobs"; then
+ make="$make $jobs"
+ fi
+
+ if test -n "$make_options"; then
+ make="$make$make_options" # Already has leading space.
+ fi
+fi
+
+# If --no-bpkg is specified, then we require --local to also be specified
+# since it won't be possible to build things from packages without bpkg. Also
+# imply --no-bdep in this case, since bdep is pretty much useless without
+# bpkg.
+#
+if test -z "$bpkg_install"; then
+ if test -z "$local"; then
+ diag "error: --no-bpkg can only be used for local installation"
+ diag " info: additionally specify --local"
+ exit 1
+ fi
+
+ bdep_install=
+fi
+
+module_version () # <name>
+{
+ eval "echo \$$1_ver"
+}
+
+# Convert the comma-separated modules list into a space-separated list.
+#
+module_list="$(echo "$modules" | sed 's/,/ /g')"
+
+for m in $module_list; do
+ if test -z "$(module_version "$m")"; then
+ diag "error: unknown standard build system module '$m'"
+ diag " info: available standard modules: $standard_modules"
+ exit 1
+ fi
+done
+
+# Convert the comma-separated list of system dependencies into a
+# space-separated list.
+#
+system_list="$(echo "$system" | sed 's/,/ /g')"
+
+# If any dependencies are specified to be used from the system, then specify
+# the respective config.import.*= variables for the bootstrap stage 2 command
+# and for the local or staged build configurations. If the installation is not
+# local, then also specify these dependencies as system for the bpkg-build
+# commands.
+#
+# As a special case, recognize the libpkgconf dependency as a request to force
+# build2 to use that instead of libpkg-config.
+#
+# Note that the build2 driver bootstrapped at stage 1 doesn't read .pc
+# files. Thus, for the bootstrap stage 2 command it is assumed that the
+# headers and libraries of the system dependencies can be found by the
+# compiler and linker at the standard locations. That, however, is not the
+# case for libpkgconf. Thus, if specifying libpkgconf as a system dependency
+# also specify its headers location via, for example, the CPATH environment
+# variable:
+#
+# $ CPATH=/usr/local/include/pkgconf ./build.sh --local --system libpkgconf g++
+#
+bootstrap_system_imports=
+system_imports=
+system_packages=
+
+for d in $system_list; do
+ v="$(echo "$d" | sed 's/[.+-]/_/g')" # Convert to variable name.
+
+ if test "$d" != "libpkgconf"; then
+ si="config.import.$v="
+ else
+ if test -z "$local"; then
+ diag "error: '--system libpkgconf' can only be used for local installation"
+ diag " info: additionally specify --local"
+ exit 1
+ fi
+
+ si="config.build2.libpkgconf=true"
+ fi
+
+ # For now these are the only third-party libraries that are used by the
+ # build system.
+ #
+ if test "$d" = "libpkg-config" -o "$d" = "libpkgconf"; then
+ bootstrap_system_imports="$si"
+ fi
+
+ # Suppress the 'dropping no longer used variable' warnings.
+ #
+ if test -z "$system_imports"; then
+ system_imports="config.config.persist='config.*'@unused=drop"
+ fi
+
+ system_imports="$system_imports $si"
+
+ if test -z "$local"; then
+ if test -n "$system_packages"; then
+ system_packages="$system_packages ?sys:$d"
+ else
+ system_packages="?sys:$d"
+ fi
+ fi
+done
+
+# If the installation directory is unspecified, then assume it is /usr/local.
+# Otherwise, if it is a relative path, then convert it to an absolute path,
+# unless the realpath program is not present on the system or doesn't
+# recognize any of the options we pass, in which case fail, advising to
+# specify an absolute installation directory.
+#
+if test -z "$idir"; then
+ idir=/usr/local
+ private=config.install.private=build2
+
+ # Only use default sudo for the default installation directory and only if
+ # it wasn't specified by the user.
+ #
+ if test -z "$sudo"; then
+ sudo="sudo"
+ fi
+elif test -n "$(echo "$idir" | sed -n 's#^[^/].*$#true#p')"; then
+
+ if ! command -v realpath >/dev/null 2>&1; then
+ diag "error: unable to execute realpath: command not found"
+ diag " info: specify absolute installation directory path"
+ exit 1
+ fi
+
+ # Don't resolve symlinks and allow non-existent path components.
+ #
+ if ! idir="$(realpath -s -m "$idir" 2>/dev/null)"; then
+ diag "error: realpath does not recognize -s -m"
+ diag " info: specify absolute installation directory path"
+ exit 1
+ fi
+fi
+
+if test "$sudo" = false; then
+ sudo=
+fi
+
+# Derive the to be installed executables names based on --exe-{prefix,suffix}.
+# Unless the installation is local, also derive the staged executables names
+# based on --stage-suffix and verify that they don't clash with existing
+# filesystem entries as well as the executables being installed.
+#
+b="${exe_prefix}b$exe_suffix"
+bpkg="${exe_prefix}bpkg$exe_suffix"
+bdep="${exe_prefix}bdep$exe_suffix"
+
+if test -z "$local"; then
+ b_stage="b$stage_suffix"
+ bpkg_stage="bpkg$stage_suffix"
+
+ if test -e "$idir/bin/$b_stage"; then
+ diag "error: staged executable name '$b_stage' clashes with existing $idir/bin/$b_stage"
+ diag " info: specify alternative staged executables name suffix with --stage-suffix"
+ exit 1
+ fi
+
+ if test -e "$idir/bin/$bpkg_stage"; then
+ diag "error: staged executable name '$bpkg_stage' clashes with existing $idir/bin/$bpkg_stage"
+ diag " info: specify alternative staged executables name suffix with --stage-suffix"
+ exit 1
+ fi
+
+ if test "$stage_suffix" = "$exe_suffix" -a -z "$exe_prefix"; then
+ diag "error: suffix '$exe_suffix' is used for both final and staged executables"
+ diag " info: specify alternative staged executables name suffix with --stage-suffix"
+ exit 1
+ fi
+fi
+
+if test -f build/config.build; then
+ diag "error: current directory already configured, start with clean source"
+ exit 1
+fi
+
+if test -z "$local" -a -d "../$cdir"; then
+ diag "error: ../$cdir/ bpkg configuration directory already exists, remove it"
+ exit 1
+fi
+
+# Add $idir/bin to PATH in case it is not already there.
+#
+PATH="$idir/bin:$PATH"
+export PATH
+
+sys="$(build2/config.guess | sed -n 's/^[^-]*-[^-]*-\(.*\)$/\1/p')"
+
+case "$sys" in
+ mingw32 | mingw64 | msys | msys2 | cygwin)
+ conf_rpath="[null]"
+ conf_rpath_stage="[null]"
+ conf_sudo="[null]"
+ ;;
+ *)
+ if test -n "$private"; then
+ conf_rpath="$idir/lib/build2"
+ else
+ conf_rpath="$idir/lib"
+ fi
+
+ conf_rpath_stage="$idir/lib"
+
+ if test -n "$sudo"; then
+ conf_sudo="$sudo"
+ else
+ conf_sudo="[null]"
+ fi
+ ;;
+esac
+
+# We don't have arrays in POSIX shell but we should be ok as long as none of
+# the configuration and option values contain spaces. Note also that the
+# expansion must be unquoted.
+#
+conf_exe_affixes=
+
+if test -n "$exe_prefix"; then
+ conf_exe_affixes="config.bin.exe.prefix=$exe_prefix"
+fi
+
+if test -n "$exe_suffix"; then
+ conf_exe_affixes="$conf_exe_affixes config.bin.exe.suffix=$exe_suffix"
+fi
+
+bpkg_fetch_ops=
+bpkg_build_ops=
+
+if test -n "$timeout"; then
+ bpkg_fetch_ops="--fetch-timeout $timeout"
+ bpkg_build_ops="--fetch-timeout $timeout"
+fi
+
+if test "$trust" = "yes"; then
+ bpkg_fetch_ops="$bpkg_fetch_ops --trust-yes"
+elif test "$trust" = "no"; then
+ bpkg_fetch_ops="$bpkg_fetch_ops --trust-no"
+elif test -n "$trust"; then
+ bpkg_fetch_ops="$bpkg_fetch_ops --trust $trust"
+fi
+
+if test -n "$verbose"; then
+ verbose="--verbose $verbose"
+fi
+
+# Suppress loading of default options files.
+#
+BUILD2_DEF_OPT="0"
+export BUILD2_DEF_OPT
+
+BPKG_DEF_OPT="0"
+export BPKG_DEF_OPT
+
+BDEP_DEF_OPT="0"
+export BDEP_DEF_OPT
+
+# Bootstrap, stage 1.
+#
+# Note: disable all warnings since we cannot do anything more granular during
+# bootstrap stage 1.
+#
+run cd build2
+if test -z "$make"; then
+ run ./bootstrap.sh "$cxx" -w
+else
+ run $make -f ./bootstrap.gmake "CXX=$cxx" CXXFLAGS=-w
+fi
+run build2/b-boot --version
+
+# Bootstrap, stage 2.
+#
+run build2/b-boot $verbose $jobs config.cxx="$cxx" config.bin.lib=static $bootstrap_system_imports build2/exe{b}
+mv build2/b build2/b-boot
+run build2/b-boot --version
+
+run cd ..
+
+# Local installation early return.
+#
+if test "$local" = true; then
+
+ run build2/build2/b-boot $verbose configure \
+config.config.hermetic=true \
+config.cxx="$cxx" \
+config.cc.coptions="${compile_ops# }" \
+config.cc.loptions="${link_ops# }" \
+config.bin.lib=shared \
+config.bin.rpath="$conf_rpath" \
+config.install.root="$idir" \
+config.install.sudo="$conf_sudo" \
+$conf_exe_affixes \
+$private \
+$system_imports
+
+ # Install toolchain.
+ #
+ projects="build2/"
+
+ if test "$bpkg_install" = true; then
+ projects="$projects bpkg/"
+ fi
+
+ if test "$bdep_install" = true; then
+ projects="$projects bdep/"
+ fi
+
+ run build2/build2/b-boot $verbose $jobs install: $projects
+
+ run command -v "$b"
+ run "$b" --version
+
+ if test "$bpkg_install" = true; then
+ run command -v "$bpkg"
+ run "$bpkg" --version
+ fi
+
+ if test "$bdep_install" = true; then
+ run command -v "$bdep"
+ run "$bdep" --version
+ fi
+
+ # Install modules.
+ #
+ projects=
+ tests=
+
+ for m in $module_list; do
+ projects="$projects libbuild2-$m/"
+ tests="$tests tests/libbuild2-$m-tests/"
+ done
+
+ if test -n "$projects"; then
+ run "$b" $verbose $jobs install: '!config.install.scope=project' $projects
+ run "$b" $verbose noop: $tests
+ fi
+
+ diag
+ diag "Toolchain installation: $idir/bin"
+ diag "Build configuration: $owd"
+ diag
+
+ exit 0
+fi
+
+# Build and stage the build system and the package manager.
+#
+run build2/build2/b-boot $verbose configure \
+config.cxx="$cxx" \
+config.bin.lib=shared \
+config.bin.suffix="$stage_suffix" \
+config.bin.rpath="$conf_rpath_stage" \
+config.install.root="$idir" \
+config.install.data_root=root/stage \
+config.install.sudo="$conf_sudo" \
+$system_imports
+
+run build2/build2/b-boot $verbose $jobs install: build2/ bpkg/
+
+run command -v "$b_stage"
+run "$b_stage" --version
+
+run command -v "$bpkg_stage"
+run "$bpkg_stage" --version
+
+# Build the entire toolchain from packages.
+#
+run cd ..
+run mkdir "$cdir"
+run cd "$cdir"
+cdir="$(pwd)" # Save full path for later.
+
+run "$bpkg_stage" $verbose create \
+cc \
+config.config.hermetic=true \
+config.cxx="$cxx" \
+config.cc.coptions="${compile_ops# }" \
+config.cc.loptions="${link_ops# }" \
+config.bin.lib=shared \
+config.bin.rpath="$conf_rpath" \
+config.install.root="$idir" \
+config.install.sudo="$conf_sudo" \
+$conf_exe_affixes \
+$private
+
+packages="build2/$build2_ver bpkg/$bpkg_ver"
+
+if test "$bdep_install" = true; then
+ packages="$packages bdep/$bdep_ver"
+fi
+
+run "$bpkg_stage" $verbose add "$BUILD2_REPO"
+run "$bpkg_stage" $verbose $bpkg_fetch_ops fetch
+run "$bpkg_stage" $verbose $jobs $bpkg_build_ops build --for install --yes --plan= $packages $system_packages
+run "$bpkg_stage" $verbose $jobs install --all
+
+run command -v "$b"
+run "$b" --version
+
+run command -v "$bpkg"
+run "$bpkg" --version
+
+if test "$bdep_install" = true; then
+ run command -v "$bdep"
+ run "$bdep" --version
+fi
+
+# Build, install, and verify the build system modules.
+#
+packages=
+tests=
+
+for m in $module_list; do
+ packages="$packages libbuild2-$m/$(module_version "$m")"
+ tests="$tests tests/libbuild2-$m-tests/"
+done
+
+if test -n "$packages"; then
+ run "$bpkg" $verbose $jobs $bpkg_build_ops build --for install $packages $system_packages
+ run "$bpkg" $verbose $jobs install '!config.install.scope=project' --all-pattern=libbuild2-*
+fi
+
+run cd "$owd"
+
+if test -n "$tests"; then
+ run "$b" $verbose noop: $tests
+fi
+
+# Clean up stage.
+#
+run "$b" $verbose $jobs uninstall: build2/ bpkg/
+
+diag
+diag "Toolchain installation: $idir/bin"
+diag "Build configuration: $cdir"
+diag
diff --git a/build/bootstrap.build b/build/bootstrap.build
index a03f31d..183578f 100644
--- a/build/bootstrap.build
+++ b/build/bootstrap.build
@@ -2,9 +2,16 @@
# license : MIT; see accompanying LICENSE file
project = build2-toolchain
+
amalgamation = # Disable amalgamation.
-subprojects = libpkgconf libbutl build2 \
-libsqlite3 libodb libodb-sqlite libbpkg bpkg bdep
+
+# Note: list them (mostly) explicitly without using wildcards to handle stray
+# subdirectories in the root (debian/, installation location, etc).
+#
+subprojects += libpkg-config/ libbutl/ build2/ libsqlite3/ libodb/ \
+ libodb-sqlite/ libbpkg/ bpkg/ bdep/
+subprojects += libbuild2-*/
+subprojects += tests/*/
using version
using config
diff --git a/build2 b/build2
-Subproject 9ce886d010dee58e5d3e547df84da487fd1c422
+Subproject d7cd4c1d5822ca55c1e097a945a89052e868734
diff --git a/buildfile b/buildfile
index 602069a..aac3b8f 100644
--- a/buildfile
+++ b/buildfile
@@ -1,11 +1,31 @@
# file : buildfile
# license : MIT; see accompanying LICENSE file
-# Note that the project directories order is important (prerequisites go
-# first).
+# NOTE: This buildfile is only meant to be used to prepare the distribution.
+# If you need to build the toolchain manually, follow the local
+# installation instructions in the BOOTSTRAP-* file corresponding to
+# your platform/compiler.
#
-d = libpkgconf/ libbutl/ build2/ \
-libsqlite3/ libodb/ libodb-sqlite/ libbpkg/ bpkg/ bdep/ doc/
+assert ($build.meta_operation == 'dist' || \
+ $build.meta_operation == 'configure' || \
+ $build.meta_operation == 'disfigure') 'only dist and configure supported'
+
+# Package repository URL (or path).
+#
+build2_repo="https://stage.build2.org/1"
+#build2_repo="https://pkg.cppget.org/1/queue/alpha"
+#build2_repo="https://pkg.cppget.org/1/alpha"
+
+# @@ Note that the project directories order is important (prerequisites go
+# first).
+#
+# NOTE: see also subprojects in bootstrap.build if changing anything here.
+#
+d = libpkg-config/ libbutl/ build2/ libsqlite3/ libodb/ libodb-sqlite/ \
+libbpkg/ bpkg/ bdep/ doc/ libbuild2-*/
+
+if ($build.meta_operation == 'dist')
+ d += tests/*/
i = \
INSTALL \
@@ -17,13 +37,79 @@ BOOTSTRAP-WINDOWS-MSVC \
BOOTSTRAP-WINDOWS-CLANG \
BOOTSTRAP-WINDOWS-MINGW
-./: $d \
- doc{$i README} \
- legal{LICENSE AUTHORS} \
- cli{$i} \
- file{build.sh build-*} \
+./: $d \
+ doc{$i README tests/README} \
+ legal{LICENSE AUTHORS} \
+ cli{$i} \
manifest
+# Obtain the toolchain and standard build system modules versions.
+#
+bp = $recall($build.path)
+pt = '^version: (.+)$'
+
+# When adding a new standard build system module, these are the places where
+# you will need to make changes (igrep for the name of one of the existing
+# modules to locate all the places):
+#
+# - this buildfile
+# - build/bootstrap.build (submodules; should be handled automatically)
+# - build scripts: build.sh.in and build-*.bat.in
+# - documentation: BOOTSTRAP-*.cli and UPGRADE.cli (multiple places)
+# - install scripts: prepare, build2-install.sh, and build2-install-*.bat
+# - build2.org/www/ (module docs symlinks for both public and stage, etc)
+# - make sure the module has `builds: all` in its manifest
+# - make sure the module is listed in the mod array in etc/bootstrap
+#
+ver = $process.run_regex($bp 'info:' $src_root/, "$pt", '\1')
+build2_ver = $process.run_regex($bp 'info:' $src_root/build2/, "$pt", '\1')
+bpkg_ver = $process.run_regex($bp 'info:' $src_root/bpkg/, "$pt", '\1')
+bdep_ver = $process.run_regex($bp 'info:' $src_root/bdep/, "$pt", '\1')
+autoconf_ver = $process.run_regex($bp 'info:' $src_root/libbuild2-autoconf/, "$pt", '\1')
+kconfig_ver = $process.run_regex($bp 'info:' $src_root/libbuild2-kconfig/, "$pt", '\1')
+
+# Generate install scripts from templates and include them into the
+# distribution.
+#
+# @@ Redo as ad hoc rule.
+#
+for s: exe{build.sh} file{build-msvc.bat build-clang.bat build-mingw.bat}
+{
+ ./: $s: file{$name($s).$extension($s).in}
+ {
+ dist = true
+ }
+ {{
+ diag sed $<
+
+ t = $path($>)
+ p = $path($<)
+
+ # Note: the same code as in the etc/version script.
+ #
+ sed -e 's/([^.]+)\..*/\1/' <<<"$ver" | set mj
+ sed -e 's/[^.]+\.([^.]+)\..*/\1/' <<<"$ver" | set mn
+ sed -n -e 's/[^.]+\.[^.]+\.[^.-]+-([ab]).*/\1/p' <<<"$ver" | set ab
+ sed -n -e 's/[^.]+\.[^.]+\.[^.-]+-[ab]\.([^.+]+).*/\1/p' <<<"$ver" | set pr
+
+ # Version for configuration directory.
+ #
+ cver = "$mj.$mn"
+
+ if ("$ab" != '')
+ cver = "$cver-$ab.$pr"
+ end
+
+ sed -e 's%@BUILD2_REPO@%'$build2_repo'%' $p >$t
+ sed -e 's/@CONFIG_VER@/'$cver'/' -i $t
+ sed -e 's/@BUILD2_VERSION@/'$build2_ver'/' -i $t
+ sed -e 's/@BPKG_VERSION@/'$bpkg_ver'/' -i $t
+ sed -e 's/@BDEP_VERSION@/'$bdep_ver'/' -i $t
+ sed -e 's/@AUTOCONF_VERSION@/'$autoconf_ver'/' -i $t
+ sed -e 's/@KCONFIG_VERSION@/'$kconfig_ver'/' -i $t
+ }}
+}
+
# Don't install the BOOTSTRAP/INSTALL files. But UPGRADE could be useful.
#
doc{INSTALL}@./: install = false
diff --git a/doc/.gitignore b/doc/.gitignore
index 585f985..584c284 100644
--- a/doc/.gitignore
+++ b/doc/.gitignore
@@ -1,3 +1,3 @@
-build2-toolchain-*.ps
-build2-toolchain-*.pdf
-build2-toolchain-*.xhtml
+build2-*.ps
+build2-*.pdf
+build2-*.xhtml
diff --git a/doc/buildfile b/doc/buildfile
index cae209e..5d78ced 100644
--- a/doc/buildfile
+++ b/doc/buildfile
@@ -4,7 +4,7 @@
define css: file
css{*}: extension = css
-./: doc{build2-toolchain-*} \
+./: doc{build2-*} \
css{code-box common doc pre-box toc} \
file{install.cli intro.cli doc-* *.html2ps}
diff --git a/doc/cli.sh b/doc/cli.sh
index d7ed865..cbf66e2 100755
--- a/doc/cli.sh
+++ b/doc/cli.sh
@@ -1,6 +1,6 @@
#! /usr/bin/env bash
-version=0.13.0-a.0.z
+version=0.17.0-a.0.z
trap 'exit 1' ERR
set -o errtrace # Trap in functions.
@@ -15,7 +15,9 @@ while [ $# -gt 0 ]; do
case $1 in
--clean)
rm -f build2-toolchain-intro.xhtml build2-toolchain-intro*.ps \
- build2-toolchain-intro*.pdf
+build2-toolchain-intro*.pdf
+ rm -f build2-packaging-guide.xhtml build2-packaging-guide*.ps \
+build2-packaging-guide*.pdf
rm -f build2-toolchain-install.xhtml build2-toolchain-install*.ps \
build2-toolchain-install*.pdf
exit 0
@@ -48,6 +50,7 @@ function gen () # <name>
--generate-html --html-suffix .xhtml \
--html-prologue-file doc-prologue.xhtml \
--html-epilogue-file doc-epilogue.xhtml \
+--link-regex '%intro(#.+)?%build2-toolchain-intro.xhtml$1%' \
--link-regex '%b([-.].+)%../../build2/doc/b$1%' \
--link-regex '%bpkg([-.].+)%../../bpkg/doc/bpkg$1%' \
--link-regex '%bdep([-.].+)%../../bdep/doc/bdep$1%' \
@@ -64,6 +67,7 @@ function gen () # <name>
ps2pdf14 -sPAPERSIZE=letter -dOptimize=true -dEmbedAllFonts=true build2-toolchain-$n-letter.ps build2-toolchain-$n-letter.pdf
}
+gen packaging
gen intro
#gen intro1
diff --git a/doc/intro.cli b/doc/intro.cli
index 10548a5..6671cbd 100644
--- a/doc/intro.cli
+++ b/doc/intro.cli
@@ -25,17 +25,13 @@
// - Maximum <pre> line is 70 characters.
//
-"
-\h0#preface|Preface|
-
-This document is an overall introduction to the \c{build2} toolchain that
-shows how the main components, namely the build system, the package dependency
-manager, and the project dependency manager are used together to handle the
-entire C/C++ project development lifecycle: creation, development, testing,
-and delivery. For additional information, including documentation for
-individual toolchain components, man pages, etc., refer to the \c{build2}
-project \l{https://build2.org/doc.xhtml Documentation} page.
-
+// Some people say they find the TLDR "abhorrent" (because it doesn't look
+// like something they can understand without reading the rest of the doc
+// first).
+//
+// Note: command output is most likely outdated.
+//
+/*
\h1#tldr|TL;DR|
@@ -66,8 +62,8 @@ Hello, World!
$ edit repositories.manifest # add https://example.org/libhello.git
$ edit manifest # add 'depends: libhello ^1.0.0'
-$ edit hello/buildfile # import libhello
-$ edit hello/hello.cxx # use libhello
+$ edit hello/buildfile # import libhello library
+$ edit hello/hello.cxx # include libhello header
$ b
fetching from https://example.org/libhello.git
@@ -100,6 +96,20 @@ synchronizing:
reconfigure hello/0.1.0
\
+*/
+
+"
+\h0#preface|Preface|
+
+This document is an overall introduction to the \c{build2} toolchain that
+shows how the main components, namely the build system, the package dependency
+manager, and the project dependency manager are used together to handle the
+entire C/C++ project development lifecycle: creation, development, testing,
+and delivery. For additional information, including documentation for
+individual toolchain components, man pages, HOWTOs, etc., refer to the
+\c{build2} project \l{https://build2.org/doc.xhtml Documentation} page.
+
+
\h1#guide|Getting Started Guide|
The aim of this guide is to get you started developing C/C++ projects with the
@@ -140,8 +150,8 @@ $ bdep new -l c++ -t exe hello
created new executable project hello in /tmp/hello/
\
-The \l{bdep-new(1)} command creates a \i{canonical} \c{build2} project. In
-our case it is an executable implemented in C++.
+The \l{bdep-new(1)} command creates a \c{build2} project. In this 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\
@@ -169,10 +179,14 @@ hello/
└── 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. See \l{#proj-struct Canonical Project Structure} for the more
-detailed discussion and rationale behind this layout.|
+\N|See \l{#proj-struct Canonical Project Structure} for a detailed discussion
+and rationale behind this layout. While it is recommended, especially for new
+projects, \c{build2} is flexible enough to support various arrangements used
+in today's C and C++ projects. Furthermore, the \l{bdep-new(1)} command
+provides a number of customization options and chances are good you will be
+able to create your preferred layout automatically. See
+\l{bdep-new.xhtml#src-layout SOURCE LAYOUT} for more information and
+examples.|
Similar to version control tools, we normally run all \c{build2} tools from
the project's source directory or one of its subdirectories, so:
@@ -268,8 +282,9 @@ $ cat manifest
: 1
name: hello
version: 0.1.0-a.0.z
+language: c++
summary: hello C++ executable
-license: proprietary
+license: other: proprietary
description-file: README.md
url: https://example.org/hello
email: you@example.org
@@ -308,8 +323,12 @@ 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 a 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):
+the process, which is just what we need here.
+
+\N|To create build configurations separately from initialization and to manage
+them after that, use the \l{bdep-config(1)} subcommands.|
+
+Let's start with GCC (remember we are in the project's root directory):
\
$ bdep init -C ../hello-gcc @gcc cc config.cxx=g++
@@ -373,7 +392,7 @@ with Visual Studio, start a command prompt and then run:
> bdep init -C ..\hello-debug @debug cc ^
\"config.cxx=cl /MDd\" ^
\"config.cc.coptions=/Od /Zi\" ^
- config.cc.loptions=/DEBUG
+ config.cc.loptions=/DEBUG:FULL
> bdep init -C ..\hello-release @release cc ^
config.cxx=cl ^
@@ -392,7 +411,15 @@ an absolute path to \c{cl.exe} that you wish to use. For example:
...
\
-|
+In case of the command prompt, you may also want to make your configuration
+\i{hermetic} (\l{b#module-config-hermetic Hermetic Build Configurations}):
+
+\
+> bdep init -C ... cc ... config.config.hermetic=true
+\
+
+Hermetically configuring our project in a suitable Visual Studio command
+prompt makes us free to build it from any other prompt or shell, IDE, etc.|
\N|Besides the \c{coptions} (compile options) and \c{loptions} (link options),
other commonly used \c{cc} module configuration variables are \c{poptions}
@@ -409,7 +436,7 @@ complete list with their rough \c{make} equivalents:
We can also use their \c{config.c.*} (C compilation) and \c{config.cxx.*} (C++
compilation) variants if we only want them applied during the respective
-language compilation. For example:
+language compilation/linking. For example:
\
$ bdep init ... cc \
@@ -456,12 +483,12 @@ $ bdep status
hello configured 0.1.0-a.0.19700101000000
$ b
-c++ hello/cxx{hello}@../hello-gcc/hello/hello/
+c++ hello/cxx{hello} -> ../hello-gcc/hello/hello/obje{hello}
ld ../hello-gcc/hello/hello/exe{hello}
ln ../hello-gcc/hello/hello/exe{hello} -> hello/
$ b test
-test hello/testscript{testscript} ../hello-gcc/hello/hello/exe{hello}
+test ../hello-gcc/hello/hello/exe{hello} + hello/testscript{testscript}
$ hello/hello World
Hello, World!
@@ -478,11 +505,12 @@ $ bdep status @clang
hello configured 0.1.0-a.0.19700101000000
$ b ../hello-clang/hello/
-c++ hello/cxx{hello}@../hello-clang/hello/hello/
+c++ hello/cxx{hello} -> ../hello-clang/hello/hello/obje{hello}
ld ../hello-clang/hello/hello/exe{hello}
$ b test: ../hello-clang/hello/
-test hello/testscript{testscript} ../hello-clang/hello/hello/exe{hello}
+test ../hello-clang/hello/hello/exe{hello} +
+ hello/testscript{testscript}
$ ../hello-clang/hello/hello/hello World
Hello, World!
@@ -495,9 +523,10 @@ more convenient if we could refer to them by names. The \l{bdep-update(1)} and
\
$ bdep test @clang
-c++ hello/cxx{hello}@../hello-clang/hello/hello/
+c++ hello/cxx{hello} -> ../hello-clang/hello/hello/obje{hello}
ld ../hello-clang/hello/hello/exe{hello}
-test hello/testscript{testscript} ../hello-clang/hello/hello/exe{hello}
+test ../hello-clang/hello/hello/exe{hello} +
+ hello/testscript{testscript}
\
And we can also perform the desired build system operation on several (or
@@ -506,10 +535,11 @@ And we can also perform the desired build system operation on several (or
\
$ bdep test @gcc @clang
in configuration @gcc:
-test hello/testscript{testscript} ../hello-gcc/hello/hello/exe{hello}
+test ../hello-gcc/hello/hello/exe{hello} + hello/testscript{testscript}
in configuration @clang:
-test hello/testscript{testscript} ../hello-clang/hello/hello/exe{hello}
+test ../hello-clang/hello/hello/exe{hello} +
+ hello/testscript{testscript}
\
\N|As we will see later, the \l{bdep-test(1)} command also allows us to test
@@ -519,14 +549,14 @@ project. We call it \i{deep testing}.|
While we are here, let's also check how hard it would be to cross-compile:
\
-$ bdep init -C ../hello-mingw @mingw cc config.cxx=x86_64-w64-mingw32-g++
+$ bdep init -C @mingw cc config.cxx=x86_64-w64-mingw32-g++
initializing in project /tmp/hello/
created configuration @mingw /tmp/hello-mingw/ auto-synchronized
synchronizing:
new hello/0.1.0-a.0.19700101000000
$ bdep update @mingw
-c++ hello/cxx{hello}@../hello-mingw/hello/hello/
+c++ hello/cxx{hello} -> ../hello-mingw/hello/hello/obje{hello}
ld ../hello-mingw/hello/hello/exe{hello}
\
@@ -537,7 +567,8 @@ on a properly setup GNU/Linux machine (that automatically uses \c{wine} as an
\
$ bdep test @mingw
-test hello/testscript{testscript} ../hello-mingw/hello/hello/exe{hello}
+test ../hello-mingw/hello/hello/exe{hello} +
+ hello/testscript{testscript}
$ ../hello-mingw/hello/hello/hello.exe Windows
Hello, Windows!
@@ -584,6 +615,24 @@ synchronizing:
drop hello
\
+\N|By default \c{bdep} initializes a project for development by automatically
+passing \c{config.<project>.develop=true} unless a custom value is specified.
+For example:
+
+\
+$ bdep init ... @gcc cc config.cxx=g++ config.hello.develop=false
+\
+
+To change the development mode of an already initialized project, use
+\l{bdep-sync(1)}:
+
+\
+$ bdep sync @gcc config.hello.develop=false
+\
+
+See \l{b#proj-config Project Configuration} for background on the development
+mode.|
+
As mentioned earlier, by default \l{bdep-new(1)} initializes a \c{git}
repository for us. Now that we have successfully built and tested our project,
it might be a good idea to make a first commit and publish it to a remote
@@ -642,17 +691,17 @@ CI request is queued:
Let's see what's going on here. By default \c{ci} submits a test request to
\l{https://ci.cppget.org ci.cppget.org}, a public CI service run by the
\c{build2} project (see available \l{https://ci.cppget.org?build-configs Build
-Configurations} and \l{https://ci.cppget.org?ci Use Policies}). It is testing
-the current working tree state (branch and commit) of our package which should
-be available from our remote repository (on GitHub in this example) since
-that's where the CI service expects to find it. In response we get a URL where
-we can see the build and test results, logs, etc.
+Configurations} and \l{https://ci.cppget.org?ci Use Policies}). In our case it
+will be testing the current working tree state (branch and commit) of our
+package which should be available from our remote repository (on GitHub in
+this example) since that's where the CI service expects to get it from. In
+response we get a URL where we can see the build and test results, logs, etc.
\N|This \i{push} CI model works particularly well with the \"feature branch\"
development workflow. Specifically, you would develop a new feature in a
separate branch, publishing and remote-testing it as necessary. When the
feature is ready, you would merge any changes from \c{master}, test the result
-one more time, and then merge the feature into master.|
+one more time, and then merge (fast-forward) the feature into master.|
Now is 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
@@ -668,12 +717,12 @@ management toolset.
\N|While \c{build2} can work without a VCS, this will result in reduced
functionality.|
-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 \i{package
-consumption} and depends on the build system. The top of the hierarchy is the
-project dependency manager, \l{bdep(1)}. It is used for \i{project
-development} and relies on \c{bpkg} for building project packages and their
-dependencies.
+At the bottom of the hierarchy is the \c{build2} build system, which we invoke
+using the \l{b(1)} driver. Next comes the package dependency manager,
+\l{bpkg(1)}. It is primarily used for \i{package consumption} and depends on
+the build system. The top of the hierarchy is the project dependency manager,
+\l{bdep(1)}. It is used for \i{project development} and relies on \c{bpkg} 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
@@ -691,13 +740,19 @@ order to automate project versioning. Note that currently only \c{git(1)} is
supported.|
Now that we understand the tooling, let's also revisit the notion of \i{build
-configuration} (those \c{hello-gcc} and \c{hello-clang} directories). A
-\c{bdep} build configuration is actually a \c{bpkg} build configuration which,
-in the build system terms, is an \i{amalgamation} \- a project that contains
-\i{subprojects}. In our case, the subprojects in these amalgamations will be
-the projects we have initialized with \c{init} and, as we will see later,
-packages that they depend on. For example, here is what our \c{hello-gcc}
-contains:
+configuration} (those \c{hello-gcc} and \c{hello-clang} directories). While we
+often talk of build configurations in the abstract, as a set of common options
+used to build our code, in \c{build2} this term also has a very concrete
+meaning \- a directory where our projects and their dependencies are built
+with such a set of common options.
+
+The concept of a build configuration appears prominently throughout the
+toolchain: a \c{bdep} build configuration is actually a \c{bpkg} build
+configuration which, in the build system terms, is a special kind of an
+\i{amalgamation} \- a project that contains \i{subprojects}. In our case, the
+subprojects in these amalgamations will be the projects we have initialized
+with \c{init} and, as we will see in a moment, packages that they depend
+on. For example, here is what our \c{hello-gcc} contains:
\
$ tree hello-gcc
@@ -719,9 +774,9 @@ meta-operation (see \l{b(1)} for details).
The important point here is that the \c{bdep} build configuration is not a
black box that you should never look inside of. On the contrary, it is a
-normal and predictable concept of the package manager and the build system and
-as long as you understand what you are doing, you should feel free to interact
-with it directly.|
+well-defined concept of the package manager and the build system and as long
+as you understand what you are doing, you should feel free to interact with it
+directly.|
Let's now move on to the reason why there is \i{dep} in the \c{bdep} name:
dependency management.
@@ -735,8 +790,8 @@ 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 (see
+\c{build2} packages usually come from \i{package repositories}. Two commonly
+used repository types are \i{version control} and \i{archive}-based (see
\l{bpkg-repository-types(1)} for details).
As the name suggests, a version control-based repository uses a VCS as its
@@ -745,15 +800,16 @@ repository normally contains multiple versions of a single package or,
perhaps, of a few related packages.
An archive-based repository contains multiple, potentially unrelated
-packages/versions as archives along with some meta information (package list,
+packages/versions as archives along with some metadate (package list,
prerequisite/complement repositories, signatures, etc) that are all accessible
via HTTP(S).
Version control and archive-based repositories have different
trade-offs. 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 repository \- you might need to add a few files, but that's about it.
+developers since 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 repository \- 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
@@ -790,7 +846,7 @@ the repository being hosted/managed potentially independently.|
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
+consumers. A reasonable strategy then is 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
@@ -810,7 +866,7 @@ along with a list of available versions. Pick a version that you like and you
will see the package version description page with quite a bit of information,
including the list of platform/compiler combinations that this version has
been successfully (or unsuccessfully) tested with. If you like what you see,
-copy the \c{location} value \- this is the repository location where this
+copy the \c{repository} value \- this is the repository location where this
package version can be sourced from.
\N|The \l{https://cppget.org cppget.org} repository is split into several
@@ -921,7 +977,7 @@ to further minor versions. They are equivalent to the following ranges:
\
\N|Zero major version component is customarily used during early development
-where the minor version effectively becomes major. As a result, the tilde
+where the minor version effectively becomes major. As a result, the caret
constraint has a special treatment of this case.|
Unless you have good reasons not to (for example, a dependency does not use
@@ -929,6 +985,11 @@ semantic versioning), we suggest that you use the \c{^} constraint which
provides a good balance between compatibility and upgradability with \c{~}
being a more conservative option.
+Besides the version constraint, the dependency declaration supports a number
+of more advanced features, including conditional dependencies, dependency
+alternatives, and dependency configuration. For details, see the
+\l{bpkg#manifest-package-depends \c{depends}} value documentation.
+
Ok, we've specified where our package comes from (\c{repositories.manifest})
and which versions we find acceptable (\c{manifest}). The next step is to edit
\c{hello/buildfile} and import the \c{libhello} library into our build:
@@ -979,10 +1040,20 @@ to our project:
\
repositories.manifest # add https://pkg.cppget.org/1/stable
manifest # add 'depends: libhello ^1.0.0'
-buildfile # import libhello
-hello.cxx # use libhello
+buildfile # import libhello library
+hello.cxx # include libhello header (or import module)
\
+\N|While the repository URL and package name are easy to find on the
+\l{https://cppget.org cppget.org}'s package description page, the C/C++
+library ecosystem unfortunately does not follow any predictable library or
+header naming scheme. If the library documentation does not provide any clues,
+then another place to check are the library tests and examples that can often
+be found in the package source directory (or source repository). In
+particular, every library in the \c{stable} section of the
+\l{https://cppget.org cppget.org} repository should provide at least a basic
+test.|
+
With a new dependency added, let's check the status of our project:
\
@@ -992,7 +1063,7 @@ warning: authenticity of the certificate for pkg:cppget.org/stable
cannot be established
certificate is for cppget.org, \"Code Synthesis\" <admin@cppget.org>
certificate SHA256 fingerprint:
-86:BA:D4:DE:2C:87:1A:EE:38:<...>:5A:EA:F4:F7:8C:1D:63:30:C6
+70:64:FE:E4:E0:F3:60:F1:B4:<...>:E5:C2:68:63:4C:A6:47:39:43
trust this certificate? [y/n] y
hello configured 0.1.0-a.0.19700101000000
@@ -1013,7 +1084,7 @@ the repository's about page):
\
role: prerequisite
location: https://pkg.cppget.org/1/stable
-trust: 86:BA:D4:DE:2C:87:1A:EE:38:<...>:5A:EA:F4:F7:8C:1D:63:30:C6
+trust: 70:64:FE:E4:E0:F3:60:F1:B4:<...>:E5:C2:68:63:4C:A6:47:39:43
\
To synchronize a project with one or more build configurations we use the
@@ -1034,9 +1105,10 @@ $ b
synchronizing:
new 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-gcc/libhello-1.0.0/libhello/cxx{hello} ->
+ ../hello-gcc/libhello-1.0.0/libhello/objs{hello}
ld ../hello-gcc/libhello-1.0.0/libhello/libs{hello}
-c++ hello/cxx{hello}@../hello-gcc/hello/hello/
+c++ hello/cxx{hello} -> ../hello-gcc/hello/hello/obje{hello}
ld ../hello-gcc/hello/hello/exe{hello}
ln ../hello-gcc/hello/hello/exe{hello} -> hello/
\
@@ -1087,12 +1159,13 @@ For example:
\
$ bdep test -ai
in configuration @gcc:
-test hello/testscript{testscript} ../hello-gcc/hello/hello/exe{hello}
test ../hello-gcc/libhello-1.0.0/tests/basics/exe{driver}
+test ../hello-gcc/hello/hello/exe{hello} + hello/testscript{testscript}
in configuration @clang:
-test hello/testscript{testscript} ../hello-clang/hello/hello/exe{hello}
test ../hello-clang/libhello-1.0.0/tests/basics/exe{driver}
+test ../hello-clang/hello/hello/exe{hello} +
+ hello/testscript{testscript}
\
To get rid of a dependency, we simply remove it from the \c{manifest} file
@@ -1233,6 +1306,319 @@ immediate (\c{sync\ -ui}), or even upgrade immediate and patch the rest
(\c{sync\ -ui} followed by \c{sync\ -pr}).
+\h#guide-build-time-linked|Build-Time Dependencies and Linked Configurations|
+
+The \c{libhello} dependency we've been playing with in the previous two
+sections is a \i{runtime dependency}, that is, our \c{hello} executable needs
+it at run-time. This is typical of libraries and most of our dependencies will
+be of this kind. However, sometimes we may only wish to use a dependency
+during the build, typically a tool, such as a source code generator. This kind
+of dependency is called a \i{build-time dependency}.
+
+\N|Build-time dependencies are an advanced topic and if you don't have an
+immediate need for this functionality, you may skip this section without any
+loss of continuity.|
+
+Why do we need to distinguish between the two kinds of dependencies? The
+primary reason is cross-compilation: if we build a tool in the same
+(cross-compiling) build configuration as our project, then we will not be able
+to execute it during the build (since it's built for a different target than
+what we are running). But even if you are not planning to cross-compile, there
+are other good reasons: if you have multiple build configurations for your
+project, you may want to share a single build of your tool between them (why
+waste time building the same thing multiple times). And even if you only have
+a single build of your project, you may want to build the tool with different
+options (for example, optimized instead of debug).
+
+You can probably see where this is going: in order to properly support
+build-time dependencies, we need to distinguish them from runtime and we need
+an ability to build them in a separate build configuration.
+
+Let's see how all this works using the \l{https://cppget.org/xxd \c{xxd}} tool
+as an example. If you are not familiar, \c{xxd} is a hexdump utility which can
+be used to embed external binary data into C/C++ code in a portable manner.
+Specifically, it can read a binary file and produce a C array definition of
+its contents. For example:
+
+\
+$ xxd -i names.txt
+
+unsigned char names_txt[] = {
+ 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x0a, 0x55, 0x6e, 0x69, 0x76, 0x65,
+ 0x72, 0x73, 0x65, 0x0a, 0x50, 0x65, 0x6f, 0x70, 0x6c, 0x65, 0x0a,
+ 0x4d, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6e, 0x73, 0x0a
+};
+unsigned int names_txt_len = 31;
+\
+
+\N|While the above output is a bit old school (using \c{unsigned int} instead
+of \c{size_t}) and the array/length names are derived from the input file name
+(including directories), \c{xxd} can also produce just the array values
+allowing us to wrap it into an array of our choice. See the
+\l{https://cppget.org/xxd \c{xxd}} package description for examples of
+\c{build2} recipes that do that.|
+
+So here is an idea: instead of failing if the user did not specify the name to
+greet, let's improve our \c{hello} program to greet a random generic name from
+a pre-defined list. To make this list easier to maintain, let's keep it in a
+separate file called \c{names.txt} and use \c{xxd} to embed it into our
+\c{hello} executable. We can use the one name per line format, for example:
+
+\
+$ cat names.txt
+World
+Universe
+People
+Martians
+\
+
+The first step in our plan is to add a build-time dependency on \c{xxd} to our
+project's \c{manifest}, similar to how we did for \c{libhello}:
+
+\
+...
+depends: libhello ^1.0.0
+depends: * xxd >= 8.2.0
+\
+
+The \c{*} mark in front of the \c{xxd} name indicates that it's a build-time
+dependency.
+
+Next we import \c{xxd} in our \c{buildfile}:
+
+\
+...
+
+import libs += libhello%lib{hello}
+
+import! [metadata] xxd = xxd%exe{xxd}
+
+...
+\
+
+There are two main differences compared to the way we import the \c{libhello}
+library: we request metadata (\c{[metadata]}) and we do immediate importation
+(\c{import!}). Let's briefly discuss what this means (for details, refer to
+\l{b#intro-import Target Importation} in the build system manual). Metadata
+for an executable contains information that helps the build system do a better
+job when an executable is used as part of the build. For example, it includes
+the uniform program name to be used for low-verbosity diagnostics as well as
+the version, checksum, and environment that are used to detect changes. And
+immediate importation instructs the build system to skip rule-specific
+importation (for example, search for libraries in compiler-specific search
+paths) and import the target here and now, failing if that's not possible. It
+is usually appropriate for importing executables. Note also that the metadata
+can only be requested in immediate importation.
+
+\N|While requesting the metadata means that you will have a simpler
+\c{buildfile} and a more reliable build, it also likely means that you won't
+be able to use the system-installed version of the executable since it needs
+to be patched to provide the metadata.|
+
+Now that we have the \c{xxd} tool, let's use it from an ad hoc recipe to
+convert \c{names.txt} to \c{names.cxx}. Here is the complete \c{buildfile} for
+our \c{hello} executable:
+
+\
+libs =
+import libs += libhello%lib{hello}
+
+import! [metadata] xxd = xxd%exe{xxd}
+
+exe{hello}: {hxx ixx txx cxx}{** -names} cxx{names} $libs testscript
+
+cxx{names}: file{names.txt} $xxd
+{{
+ i = $path($<[0])
+ env --cwd $directory($i) -- $xxd -i $leaf($i) >$path($>)
+}}
+\
+
+The last bit that we need to do is to modify \c{hello.cxx} to use the list of
+fallback names (the actual implementation is left as an exercise for the
+reader):
+
+\
+#include <iostream>
+
+extern unsigned char names_txt[];
+extern unsigned int names_txt_len;
+
+int main (int argc, char* argv[])
+{
+ using namespace std;
+
+ if (argc < 2)
+ {
+ // TODO: pick a random name from names_txt using newline as
+ // a name separator.
+ }
+
+ ...
+}
+\
+
+Let's recap what we've achieved so far: we've added a build-time dependency on
+\c{xxd}, we've imported it in our \c{buildfile} and used it in an ad hoc
+recipe to generate \c{names.cxx}, and we've modified \c{hello.cxx} to use the
+generated list of names. The only step left is to actually try to build it.
+But before doing that, let's also print the list of build configurations we
+currently have associated with our project (see the \c{list} subcommand
+in \l{bdep-config(1)}):
+
+\
+$ bdep config list
+@gcc /tmp/hello-gcc/ 1 target default,forwarded,auto-synchronized
+@clang /tmp/hello-clang/ 2 target auto-synchronized
+\
+
+\
+$ b
+creating configuration of host type in /tmp/hello-host/ and
+associating it with project(s):
+ /tmp/hello/
+as if by executing command(s):
+ bdep config create @host --type host --no-default /tmp/hello-host \
+ cc config.config.load=~host
+while searching for configuration for build-time dependency xxd of
+package hello/0.1.0-a.0.19700101000000#4
+while synchronizing configuration /tmp/hello-gcc/
+continue? [Y/n] y
+
+synchronizing /tmp/hello-gcc/:
+ new xxd/8.2.3075 [/tmp/hello-host/] (required by hello)
+ upgrade hello/0.1.0-a.0.19700101000000#4
+
+c ../hello-host/xxd-8.2.3075+1/c{xxd} ->
+ ../hello-host/xxd-8.2.3075+1/obje{xxd}
+ld ../hello-host/xxd-8.2.3075/exe{xxd}
+xxd hello/file{names.txt} -> ../hello-gcc/hello/hello/cxx{names}
+c++ ../hello-gcc/hello/hello/cxx{names} ->
+ ../hello-gcc/hello/hello/obje{names}
+c++ hello/cxx{hello} -> ../hello-gcc/hello/hello/obje{hello}
+ld ../hello-gcc/hello/hello/exe{hello}
+\
+
+While the diagnostics is hopefully fairly self-explanatory, let's go over the
+key points. The first part goes exactly as in the previous section: because
+we've added a new dependency, the build configuration needs to be synchronized
+with the project state. However, this is a build-time dependency and
+build-time dependencies are built in configurations of type \c{host}. So
+\c{bdep} first looks for such a configuration among the configurations already
+associated with the project. In our case there isn't one (from the listing
+above we can see that all our configurations are of type \c{target}). In this
+case, \c{bdep} offers to create one automatically. We accept this offer by
+answering \c{y} at the prompt and the rest should again look familiar: the new
+dependency is configured and built (but now in the host configuration) and our
+project is updated (which involves running the new dependency). If we now
+again print the list of build configurations associated with our project, we
+will see the new configuration among them:
+
+\
+$ bdep config list
+@gcc /tmp/hello-gcc/ 1 target default,forwarded,auto-synchronized
+@clang /tmp/hello-clang/ 2 target auto-synchronized
+@host /tmp/hello-host/ 3 host forwarded,auto-synchronized
+\
+
+Let's also try to update our project in the \c{clang} configuration:
+
+\
+$ bdep update @clang
+synchronizing:
+ upgrade hello/0.1.0-a.0.19700101000000#4
+
+xxd hello/file{names.txt} -> ../hello-clang/hello/hello/cxx{names}
+c++ ../hello-clang/hello/hello/cxx{names} ->
+ ../hello-clang/hello/hello/obje{names}
+c++ hello/cxx{hello} -> ../hello-clang/hello/hello/obje{hello}
+ld ../hello-clang/hello/hello/exe{hello}
+\
+
+This time we are neither prompted to create another configuration nor is a new
+instance of \c{xxd} built \- as we would have expected, the existing host
+configuration with the already built \c{xxd} is reused.
+
+From the above output we can see that \c{bdep} creates the host configuration
+using the default host compiler and build options (\c{~host}) which means the
+result will most likely be optimized. But if we don't like something about the
+host configuration that \c{bdep} offers us to create, we can answer \c{n} at
+the prompt, create one ourselves (by perhaps copying and tweaking the command
+line \c{bdep} was going to use), and then restart the build.
+
+Besides the \c{target} and \c{host} types, the third pre-defined configuration
+type is \c{build2}, which is used for build system modules. If you would like
+to try a build-time dependency on a build system module, there is a dummy
+\c{libbuild2-hello} module that you can use. Simply add the following line
+to your \c{manifest}:
+
+\
+depends: * libbuild2-hello
+\
+
+And the following line somewhere in your \c{buildfile}:
+
+\
+using hello
+\
+
+Then build the project and see what happens.
+
+\N|The \c{target} type signifies a configuration for the end-result of our
+build. If no type is specified during the configuration creation with the
+\c{--type} option (or \c{--config-type} if using \c{bdep-new}), then
+\c{target} is assumed.
+
+The \c{host} type signifies a configuration corresponding to the host machine,
+that is, the machine on which the build is performed. It is expected that an
+executable built in the host configuration can be executed. Oftentimes, target
+and host are the same. In this case, if you would prefer not to have separate
+configurations, then you can make your target configuration \i{self-hosted} by
+using the \c{host} type rather than \c{target}. For example:
+
+\
+$ bdep init -C ../hello-gcc @gcc --type host cc config.cxx=g++
+\
+
+The \c{build2} type is a special kind of host configuration that is used to
+build build system modules. It cannot be self-hosted.|
+
+Building build-time dependencies in separate configurations is just one
+application of the more general configuration linking mechanism which allows
+us to build a package in one configuration while its dependencies \- in one or
+more linked configurations. This, for example, can be used to create a
+\"base\" configuration with common dependencies that are shared between
+multiple configurations (sometimes also referred to as build configuration
+overlaying).
+
+Let's see how this works on our \c{hello} project. Imagine \c{libhello} that
+we depend on is very big and takes a while to compile. We also aren't really
+interested in building it in both \c{gcc} and \c{clang} configurations (it's
+our project that we are interested in building with different compilers).
+Since these two compilers are ABI-compatible (at least on Linux), we could
+build \c{libhello} with just one of them and reuse the result with the
+other. Let's see how we can achieve this with linked configurations (refer to
+\l{bdep-config(1)} for details on subcommands involved):
+
+\
+$ bdep config create ../hello-base @base --no-default cc config.cxx=g++
+$ bdep config create ../hello-gcc @gcc --default cc config.cxx=g++
+$ bdep config create ../hello-clang @clang cc config.cxx=clang++
+
+$ bdep config link @gcc @base
+$ bdep config link @clang @base
+
+$ bdep init @gcc { @base }+ ?libhello
+$ bdep init @clang
+\
+
+Most of the commands are hopefully self-explanatory except for the \c{{ @base
+\}+ ?libhello} part. Here \c{?} is a package flag that instructs \c{bdep}
+to treat \c{libhello} as a dependency. And \c{{ @base \}+} tells it to build
+this dependency in the \c{base} configuration (we don't have to do the same
+for \c{clang} since the dependency is already built). See \l{bdep-sync(1)} for
+details on this syntax.
+
\h#guide-versioning-releasing|Versioning and Release Management|
@@ -1629,9 +2015,32 @@ hello/
libhello/
hello-gcc/
hello-clang/
+
+$ tree libhello
+libhello/
+├── build/
+│ └── ...
+├── libhello/
+│ ├── hello.hxx
+│ ├── hello.cxx
+│ └── buildfile
+├── buildfile
+├── manifest
+├── README.md
+└── repositories.manifest
+\
+
+\N|Similar to the executable project, this layout is not mandatory and
+\l{bdep-new(1)} can create a number of alternative library structures. For
+example, if you prefer the \c{include/src} split, try:
+
+\
+$ bdep new -l c++ -t lib,split libhello
\
-Let's also edit the generated \c{manifest} file and add the \c{project} value
+See \l{bdep-new.xhtml#src-layout SOURCE LAYOUT} for more examples.|
+
+Let's edit the generated \c{manifest} file and add the \c{project} value
(customarily after \c{version}) to indicate that our library belongs to the
same overall project as our executable:
@@ -1696,23 +2105,43 @@ And that's it, now we can build and test our new arrangement:
\
$ cd ../hello # back to hello project root
$ bdep test -i
-c++ ../libhello/libhello/cxx{hello}
-c++ ../libhello/tests/basics/cxx{driver}
-c++ hello/cxx{hello}
+c++ ../libhello/libhello/cxx{hello} ->
+ ../hello-gcc/libhello/libhello/objs{hello}
+c++ ../libhello/tests/basics/cxx{driver} ->
+ ../hello-gcc/libhello/tests/basics/obje{driver}
+c++ hello/cxx{hello} -> ../hello-gcc/hello/hello/obje{hello}
ld ../hello-gcc/libhello/libhello/libs{hello}
ld ../hello-gcc/libhello/tests/basics/exe{driver}
ld ../hello-gcc/hello/hello/exe{hello}
test ../hello-gcc/libhello/tests/basics/exe{driver}
-test hello/testscript{testscript} ../hello-gcc/hello/hello/exe{hello}
+test ../hello-gcc/hello/hello/exe{hello} + hello/testscript{testscript}
\
This is also the approach we would use if we wanted to fix a bug in someone
-else's library. That is, we would clone their project repository and
+else's library. That is, we would clone their library repository and
initialize it in the build configurations of our project which will
\"upgrade\" the dependency to use the local version. Then we make the fix,
submit it upstream, and continue using the local version until our fix is
-merged/published, at which point we deinitialize the project and switch
-back to using the upstream version.
+merged/published, at which point we deinitialize their library repository and
+our project will be automatically switched back to using the new upstream
+version of the library. Here is the summary of the steps in this workflow:
+
+\
+$ cd hello/ # Our project.
+$ bdep init -C @gcc ... # Configures libhello as a dependency.
+
+$ git clone .../libhello.git # Need to fix a bug in libhello.
+$ cd libhello
+$ bdep init -A ../hello-gcc @gcc # Upgrades libhello to local version.
+
+# Fix the bug in libhello, test, and submit upstream.
+# Continue using local libhello until the bugfix is published.
+
+$ cd libhello # Bugfix has been published.
+$ bdep deinit @gcc # Switches libhello back to dependency.
+
+$ rm -r libhello # If no longer needed.
+\
Let's now examine the second option: making \c{libhello} a package inside
\c{hello}. Here is the original structure of our \c{hello} project:
@@ -1766,6 +2195,7 @@ hello/
├── libhello/
│ ├── ...
│ └── manifest
+├── buildfile
├── packages.manifest
└── repositories.manifest
\
@@ -1774,8 +2204,21 @@ hello/
the project (repository) while \c{manifest} \- to the package.|
Besides the \c{libhello} directory the \c{new} command also created the
-\c{packages.manifest} file in the root directory of our project. Let's take a
-look inside:
+\c{buildfile} and \c{packages.manifest} files in the root directory of our
+project. First let's take a look inside \c{buildfile}:
+
+\
+import pkgs = */
+
+./: $pkgs
+\
+
+This is what we call a \i{glue \c{buildfile}}. Its purpose is to \"pull\"
+together several packages so that we are able to invoke the build system
+driver from the project root. See \l{b#intro-import Target Importation} for
+details.
+
+Now let's examine \c{packages.manifest}:
\
$ cat packages.manifest
@@ -1831,14 +2274,17 @@ however, that in this case we don't need to add anything to
\
$ cd .. # back to hello project root
$ bdep test
-c++ libhello/libhello/cxx{hello}
-c++ libhello/tests/basics/cxx{driver}
-c++ hello/hello/cxx{hello}
+c++ libhello/libhello/cxx{hello} ->
+ ../hello-gcc/libhello/libhello/objs{hello}
+c++ libhello/tests/basics/cxx{driver} ->
+ ../hello-gcc/libhello/tests/basics/obje{driver}
+c++ hello/hello/cxx{hello} -> ../hello-gcc/hello/hello/obje{hello}
ld ../hello-gcc/libhello/libhello/libs{hello}
ld ../hello-gcc/libhello/tests/basics/exe{driver}
ld ../hello-gcc/hello/hello/exe{hello}
test ../hello-gcc/libhello/tests/basics/exe{driver}
-test hello/hello/testscript{testscript} ../hello-gcc/hello/hello/exe{hello}
+test ../hello-gcc/hello/hello/exe{hello} +
+ hello/hello/testscript{testscript}
\
\N|A multi-package project could have several files, such as \c{README.md} and
@@ -1858,6 +2304,7 @@ hello/
│ ├── LICENSE -> ../LICENSE
│ └── manifest
├── LICENSE
+├── buildfile
├── packages.manifest
└── repositories.manifest
\
@@ -1870,8 +2317,8 @@ Projects} for details.|
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
+\c{bdep} just like we did, this is more of a development than
+a consumption workflow. For consumption it is much easier to use the package
dependency manager, \l{bpkg(1)}, directly.
\N|Note that this approach also works for libraries in case you wish to use
@@ -1892,8 +2339,6 @@ $ bpkg create -d tools cc \
config.install.root=/usr/local \
config.install.sudo=sudo
created new configuration in /tmp/tools/
-
-$ cd tools
\
The same step on Windows using Visual Studio would look like this:
@@ -1910,6 +2355,8 @@ To fetch and build packages (as well as all their dependencies) we use the
like \l{https://cppget.org cppget.org} or build directly from \c{git}:
\
+$ cd tools
+
$ bpkg build hello@https://git.build2.org/hello/hello.git
fetching from https://git.build2.org/hello/hello.git
new libformat/1.0.0 (required by libhello)
@@ -1921,10 +2368,13 @@ configured libformat/1.0.0
configured libprint/1.0.0
configured libhello/1.1.0
configured hello/1.0.0
-c++ libprint-1.0.0/libprint/cxx{print}
-c++ hello-1.0.0/hello/cxx{hello}
-c++ libhello-1.1.0/libhello/cxx{hello}
-c++ libformat-1.0.0/libformat/cxx{format}
+c++ libprint-1.0.0/libprint/cxx{print} ->
+ libprint-1.0.0/libprint/objs{print}
+c++ hello-1.0.0/hello/cxx{hello} -> hello-1.0.0/hello/obje{hello}
+c++ libhello-1.1.0/libhello/cxx{hello} ->
+ libhello-1.1.0/libhello/objs{hello}
+c++ libformat-1.0.0/libformat/cxx{format} ->
+ libformat-1.0.0/libformat/objs{format}
ld libprint-1.0.0/libprint/libs{print}
ld libformat-1.0.0/libformat/libs{format}
ld libhello-1.1.0/libhello/libs{hello}
@@ -1943,16 +2393,24 @@ $ bpkg build hello # build package by name
|
+\N|If building a package involves building a build-time dependency and no
+configuration of type \c{host} (or \c{build2}, if the dependency is a build
+system module) is linked with the target configuration, then a private
+configuration of a suitable type is automatically created and linked. See
+\l{#guide-build-time-linked Build-Time Dependencies and Linked Configurations}
+for background on build-time dependencies and \l{bpkg-cfg-create(1)} for more
+information on \c{bpkg} configuration linking.|
+
Once built, we can install the package to the location that we have specified
with \c{config.install.root} using the \l{bpkg-pkg-install(1)} command:
\
$ bpkg install hello
...
-install libformat-1.0.0/libformat/libs{format}
-install libprint-1.0.0/libprint/libs{print}
-install libhello-1.1.0/libhello/libs{hello}
-install hello-1.0.0/hello/exe{hello}
+install libformat-1.0.0/libformat/libs{format} -> /usr/local/lib/
+install libprint-1.0.0/libprint/libs{print} -> /usr/local/lib/
+install libhello-1.1.0/libhello/libs{hello} -> /usr/local/lib/
+install hello-1.0.0/hello/exe{hello} -> /usr/local/bin/
$ hello World
Hello, World!
@@ -2000,9 +2458,9 @@ along these lines:
│ ├── libprint-1.0.so
│ ├── libprint.so -> libprint-1.0.so
│ └── pkgconfig/
-│ ├── libformat.shared.pc
-│ ├── libhello.shared.pc
-│ └── libprint.shared.pc
+│ ├── libformat.pc
+│ ├── libhello.pc
+│ └── libprint.pc
└── share/
└── doc/
├── libformat/
@@ -2038,11 +2496,58 @@ If we need to uninstall a previously installed package, there is the
\
$ bpkg uninstall hello
-uninstall hello-1.0.0/hello/exe{hello}
-uninstall libhello-1.1.0/libhello/libs{hello}
-uninstall libprint-1.0.0/libprint/libs{print}
-uninstall libformat-1.0.0/libformat/libs{format}
+uninstall hello-1.0.0/hello/exe{hello} <- /usr/local/bin/
+uninstall libhello-1.1.0/libhello/libs{hello} <- /usr/local/lib/
+uninstall libprint-1.0.0/libprint/libs{print} <- /usr/local/lib/
+uninstall libformat-1.0.0/libformat/libs{format} <- /usr/local/lib/
+...
+\
+
+Rather than installing the package locally we could instead generate a
+\i{binary distribution package} for it using the \l{bpkg-pkg-bindist(1)}
+command. Such a binary package can then be installed on a different
+machine. Currently, the \c{bindist} command supports producing Debian (and
+alike, such as Ubuntu) and Fedora (and alike, such as RHEL) packages as well
+as installation archives for all operating systems. For example, to generate a
+Debian package for our \c{hello} (running on Debian or alike):
+
+\
+$ bpkg bindist --recursive=auto --private -o /tmp/hello-deb/ hello
+...
+generated debian package for hello/1.0.0:
+ /tmp/hello-deb/hello_1.0.0-0~debian12_amd64.deb
+ /tmp/hello-deb/hello-dbgsym_1.0.0-0~debian12_amd64.deb
+ /tmp/hello-deb/hello_1.0.0-0~debian12_amd64.buildinfo
+ /tmp/hello-deb/hello_1.0.0-0~debian12_amd64.changes
+
+$ sudo apt-get install /tmp/hello-deb/hello_1.0.0-0~debian12_amd64.deb
+\
+
+And to generate a Fedora package (running on Fedora or alike):
+
+\
+$ bpkg bindist --recursive=auto --private hello
...
+generated fedora package for hello/1.0.0:
+ ~/rpmbuild/RPMS/x86_64/hello-1.0.0-1.fc38.x86_64.rpm
+ ~/rpmbuild/RPMS/x86_64/hello-debuginfo-1.0.0-1.fc38.x86_64.rpm
+
+$ sudo dnf install ~/rpmbuild/RPMS/x86_64/hello-1.0.0-1.fc38.x86_64.rpm
+\
+
+And to generate an installation archive (running on Windows in this
+example):
+
+\
+$ bpkg bindist --recursive=auto ^
+ --private ^
+ --distribution=archive ^
+ -o C:\tmp\hello-zip\ ^
+ config.install.relocatable=true ^
+ hello
+...
+generated archive package for hello/1.0.0:
+ C:\tmp\hello-zip\hello-1.0.0-x86_64-windows10.zip
\
To upgrade or downgrade packages we again use the \c{build} command. Here
@@ -2091,6 +2596,7 @@ purged libformat
purged libprint
\
+
\h#guide-system-deps|Using System-Installed Dependencies|
Our operating system might already have a package manager (which we will refer
@@ -2105,16 +2611,25 @@ and/or test with multiple versions (which is not something that many system
package managers support).
We can also have some build configurations using a system-installed version of
-a dependency while others building it from source, for example, for testing.|
+a dependency while in others building it from source, for example, for
+testing.|
We can instruct \c{build2} to configure a dependency package as available from
-the system rather than building it from source. Let's see how this works in an
-example. Say, we want to use \l{https://cppget.org/libsqlite3 \c{libsqlite3}}
-in our \c{hello} project.
-
-The first step is to add it as a dependency, just like we did for \c{libhello}.
-That is, add another \c{depends} entry to \c{manifest}, then import it in
-\c{buildfile}, and so on.
+the system rather than building it from source. Specifically, we can install a
+suitable version manually (for example, using the system package manager) and
+then communicate this fact as well as the version installed to \c{build2} so
+that it can use this information when resolving version constraints.
+Furthermore, for Debian (and alike, such as Ubuntu) and Fedora (and alike,
+such as RHEL) \c{build2} can automatically query the system package manager
+for the installed version and, if requested, automatically install a suitable
+version from the system repository if none is already installed.
+
+Let's see how all this works in an example. Say, we want to use
+\l{https://cppget.org/libsqlite3 \c{libsqlite3}} in our \c{hello} project.
+
+The first step is to add it as a dependency, just like we did for
+\c{libhello}. That is, add another \c{depends} entry to \c{manifest}, then
+import it in \c{buildfile}, and so on.
Now, if we just run \c{sync} or try to build our project, \c{build2} will
download and build the new dependency from source, just like it did for
@@ -2123,39 +2638,126 @@ configures the \c{libsqlite3} package as coming from the system:
\
$ bdep sync ?sys:libsqlite3
+\
+
+Here \c{?} is a package flag that instructs \c{build2} to treat it as a
+dependency and \c{sys} is a package scheme that tells \c{build2} it comes from
+the system. See \l{bpkg-pkg-build(1)} for details.
+
+Now what exactly happens in this case depends on which operating system we are
+running as well as whether \c{libsqlite3} is already installed. Let's examine
+each combination in turn.
+
+If we are running on an operating system for which there is \c{build2} support
+for the system package manager interactions (currently Debian, Fedora, or
+alike) and \c{libsqlite3} is already installed, then \c{build2} will get its
+version from the system package manager and use that when resolving version
+constraints. For example, running the above command on Debian with
+\c{libsqlite3-dev} version \c{3.42.0} already installed:
+
+\
+$ bdep sync ?sys:libsqlite3
+synchronizing:
+ configure sys:libsqlite3/3.42.0 (required by hello)
+ upgrade hello/0.1.0-a.0.19700101000000#3
+\
+
+If, on the other hand, we are running on an operating system for which there
+is \c{build2} support for the system package manager interactions but
+\c{libsqlite3} is not installed, then \c{build2} will fail:
+
+\
+$ bdep sync ?sys:libsqlite3
+error: no installed system package for libsqlite3
+ info: specify --sys-install to try to install it
+ info: specify libsqlite3/* if package is not installed with system
+ package manager
+ info: specify --sys-no-query to disable system package manager
+ interactions
+\
+
+As you can see, \c{build2} will not attempt to automatically install system
+packages unless explicitly requested with the \c{--sys-install} option. Let's
+try to add that (again, running on Debian):
+
+\
+$ bdep sync --sys-install ?sys:libsqlite3
+updating debian package index...
+synchronizing:
+ sys-install libsqlite3-0/3.42.0-1 (required by sys:libsqlite3)
+ configure sys:libsqlite3/3.42.0 (required by hello)
+ upgrade hello/0.1.0-a.0.19700101000000#3
+installing debian packages...
+The following NEW packages will be installed:
+ libsqlite3-dev
+The following packages will be upgraded:
+ libsqlite3-0 sqlite3
+Do you want to continue? [Y/n] y
+...
+Setting up libsqlite3-0:amd64 (3.42.0-1) ...
+Setting up libsqlite3-dev:amd64 (3.42.0-1) ...
+Setting up sqlite3 (3.42.0-1) ...
+\
+
+\N|You can suppress the system package manager confirmation prompt with the
+\c{--sys-yes} option. By default \c{build2} uses \c{sudo} for system package
+manager interactions that normally require administrative privileges (fetch
+package metadata, install packages, etc). This can be customized with the
+\c{--sys-sudo} option.|
+
+Finally, if we are running on an operating system for which there is no
+\c{build2} support for the system package manager interactions, then, as
+mentioned earlier, it is the user's responsibility to make sure a suitable
+package is installed and, optionally, communicate its version. In this case,
+unless we specify the installed version explicitly, a system-installed package
+is assumed to satisfy any dependency constraint (indicated with the \c{*}
+wildcard instead of the version):
+
+\
+$ bdep sync ?sys:libsqlite3
synchronizing:
- configure sys:libsqlite3/*
+ configure sys:libsqlite3/* (required by hello)
upgrade hello/0.1.0-a.0.19700101000000#3
\
-Here \cb{?} is a package \i{flag} that instructs \c{build2} to treat it as a
-dependency and \cb{sys} is a package \i{scheme} that tells \c{build2} it comes
-from the system. See \l{bpkg-pkg-build(1)} for details.
+\N|You can reduce the supported system package manager case to this case by
+disabling the system package manager interactions with the \c{--sys-no-query}
+option.|
\N|The system-installed dependency doesn't really have to come from the system
package manager. It can also be manually installed and, as discussed in
\l{#guide-unpackaged-deps Using Unpackaged Dependencies}, not necessarily into
the system-default location like \c{/usr/local}.|
-In the above example our dependency still has to be packaged and available
-from one of the project's prerequisite repositories. But it can be a \i{stub}
-\- a package that does not contain any source code and that can only be
-\"obtained\" from the system (see \l{bpkg#package-version Package Version} for
-details). However, if we would like to use a completely unpackaged dependency,
-then we will have to specify its version explicitly either as the actual
-version or as the \c{*} wildcard, for example:
+In the above examples our dependency (\c{libsqlite3}) still has to be packaged
+and available from one of the project's prerequisite repositories. But it can
+be a \i{stub} \- a package that does not contain any source code and that can
+only be \"obtained\" from the system.
+
+\N|The purpose of a stub is to provide the \c{build2} package to system
+package name and version mapping, in case it cannot be deduced automatically.
+See \l{bpkg#package-version Package Version} and
+\l{bpkg#manifest-package-distribution \c{*-{name, version,
+to-downstream-version\}}} package manifest values for details.|
+
+If we would like to use a completely unpackaged dependency, then, for the
+supported system package manager case, we will need to pass the
+\c{--sys-no-stub} option:
+
+\
+$ bdep sync --sys-install --sys-no-stub ?sys:libsqlite3
+\
+
+And for the unsupported system package manager case we will have to specify
+the system version explicitly either as the actual version or as the \c{*}
+wildcard, for example:
\
$ bdep sync ?sys:libsqlite3/* ?sys:libcurl/7.47.0
\
-\N|Currently, unless we specify the installed version explicitly, a
-system-installed package is assumed to satisfy any dependency constraint. In
-the future, \c{build2} will automatically query commonly used system package
-managers for the installed version and maybe even request installation of the
-absent packages. To support this functionality, the package manifest may need
-to specify package name mappings for various system package managers (which is
-the rationale behind stub packages).|
+\N|The reason at least a stub is required by default is due to the automatic
+mapping between \c{build2} and system packages often being unreliable.|
\h#guide-unpackaged-deps|Using Unpackaged Dependencies|
@@ -2280,30 +2882,39 @@ entry as a documentation to users of our project.|
\h1#proj-struct|Canonical Project Structure|
-The goal of establishing a canonical project structure is to create an
-ecosystem of packages that can coexist, are easy to comprehend by both humans
-and tools, scale to complex, real-world requirements, and, last but not least,
-are pleasant to work with.
-
-The canonical structure is primarily meant for a package \- a single library
-or program (or, sometimes, a collection of related programs) with a specific
-and well-defined function. While it may be less suitable for more elaborate,
-multi-library/program \i{end-products} that are not meant to be packaged, most
-of the recommendations discussed below would still apply. Oftentimes, you
-would start with a canonical project and expand from there. Note also that
-while the discussion below focuses on C++, most of it applies equally to C
-projects.
+The goal of establishing a canonical \c{build2} project structure is to create
+an ecosystem of packages that can coexist, are easy to comprehend by both
+humans and tools, scale to complex, real-world requirements, and, last but not
+least, are pleasant to work with.
+
+\N|Here by \i{canonical} we mean a structure that on balance achieves these
+objectives in the simplest possible way. However, not everyone agrees with
+where that balance should be struck. As a result, this structure is only
+recommended and \c{build2} is flexible enough to support various arrangements
+used in modern C and C++ projects. Furthermore, the \l{bdep-new(1)} command
+provides a number of customization options and chances are you will be able to
+create your preferred layout automatically. See \l{bdep-new.xhtml#src-layout
+SOURCE LAYOUT} for more information and examples.|
+
+This canonical structure is primarily meant for a package \- a single library
+or program (or, sometimes, a collection of related libraries or programs)
+with a specific and well-defined function. While it may be less suitable for
+more elaborate, multi-library/program \i{end-products} that are not meant to
+be packaged, most of the recommendations discussed below would still
+apply. Oftentimes, you would start with a canonical project and expand from
+there. Note also that while the discussion below focuses on C++, most of it
+applies equally to C projects.
\N|We often find ourselves factoring common functionality out of such
end-products and into separate packages, for example, in order to be reused in
-another end-product). In this light, it can be helpful to organize a new
+another end-product. In this light, it can be helpful to organize a new
end-product project as a composition of individual packages or source
subdirectories that follow the canonical structure. The \l{bdep-new(1)}
-\c{--package} and \c{--subdirectory} modes can used to automate this process.|
+\c{--package} and \c{--source} modes can be used to automate this process.|
-Projects created by the \l{bdep-new(1)} command have the canonical structure.
-The overall layouts for executable (\c{-t\ exe}) and library (\c{-t\ lib})
-projects are presented below.
+By default, projects created by the \l{bdep-new(1)} command have the canonical
+structure. The overall layouts for executable (\c{-t\ exe}) and library
+(\c{-t\ lib}) projects are presented below.
\
<name>/
@@ -2343,8 +2954,8 @@ below.
\li|\n\n\i{Header and source files (or module interface and implementation
files) are next to each other (no \c{include/} and \c{src/} split).}|
-\li|\n\i{Headers are included with \c{<>} and contain the project directory
-prefix, for example, \c{<libhello/hello.hxx>}.}|
+\li|\n\i{Headers are included with \c{<>} and contain the project name as
+a subdirectory prefix, for example, \c{<libhello/hello.hxx>}.}|
\li|\n\i{Header and source file extensions are either \c{.hpp/.cpp} or
\c{.hxx/.cxx} (\c{.mpp} or \c{.mxx} for module interfaces).}|
@@ -2362,7 +2973,7 @@ If a project consists of a library and an executable, then they should be
split into separate packages (see \l{#guide-dev-multi Developing Multiple
Packages and Projects} for some common arrangements). In this case, by
convention, the library name should start with the \c{lib} prefix, for
-example, \c{libhello} and \c{hello}. It is also strongly recommended (but not
+example, \c{libhello} and \c{hello}. It is also recommended (but not
required) to follow this convention in new projects, even if there are no
plans to have a related executable.
@@ -2394,7 +3005,7 @@ subdirectories (\c{build/}) as well as the available alternative naming
scheme.
-\h#proj-struct-src-dir|Source Directory|
+\h#proj-struct-src-dir|Source Subdirectory|
The project's source code is placed into a subdirectory of the root directory
named the same as the project, for example, \c{hello/hello/} or
@@ -2402,11 +3013,11 @@ named the same as the project, for example, \c{hello/hello/} or
There are several reasons for this layout: It implements the canonical
inclusion scheme (discussed below) where each header is prefixed with its
-project name. It also has a predictable name where users (and tools) can
-expect to find our project's source code. Finally, this layout prevents
-clutter in the project's root directory which usually contains various other
-files (like \c{README}, \c{LICENSE}) and directories (like \c{doc/},
-\c{tests/}, \c{examples/}).
+project name as a subdirectory. It also has a predictable name where users
+(and tools) can expect to find our project's source code. Finally, this layout
+prevents clutter in the project's root directory which usually contains
+various other files (like \c{README}, \c{LICENSE}) and directories (like
+\c{doc/}, \c{tests/}, \c{examples/}).
\N|Another popular approach is to place public headers into the \c{include/}
subdirectory and source files as well as private headers into \c{src/}. The
@@ -2437,11 +3048,11 @@ private \- is not as clear cut as it may seem at first. The common assumption
of the split layout is that only headers from \c{include/} are installed and,
conversely, to use the headers in-place, all one has to do is add \c{-I}
pointing to \c{include/}. On the other hand, it is common for public headers
-to include private, for example, to call an implementation detail function in
-inline or template code (note that the same applies to private modules
-imported in public module interfaces). Which means such private, (or, probably
-now more accurately called \i{implementation detail}) headers have to be
-placed in the \c{include/} directory as well, perhaps into a subdirectory
+to include private headers to, for example, call an implementation detail
+function in inline or template code (note that the same applies to private
+modules imported in public module interfaces). Which means such private (or
+probably now more accurately called \i{implementation detail}) headers have to
+be placed in the \c{include/} directory as well, perhaps into a subdirectory
(such as \c{details/}) or with a file name suffix (such as \c{-impl}) to
signal to the user that they are still \"private\". Needless to say, in an
actively developed project, keeping track of which private headers can still
@@ -2458,18 +3069,19 @@ project consists of only such single-file modules, then \c{include/} and
\c{src/} have effectively become the same thing (note that there couldn't be
any \"private\" modules in \c{src/} since there would be nobody to import
them). In a sense, we already have this situation with header-only libraries
-except that in the case of modules calling the directory \c{include/} would be
-an anachronism.
+except that, in the case of modules, calling the directory \c{include/} would
+be an anachronism.
To summarize, the split directory arrangement offers little benefit over the
-single directory layout, has a number of real drawbacks, and does not fit
+combined directory layout, has a number of real drawbacks, and does not fit
modularized projects well. In practice, private headers are placed into
\c{include/}, often either in a subdirectory or with a special file name
-suffix, a mechanism that is readily available in the single directory layout.|
+suffix, a mechanism that is readily available in the combined directory
+layout.|
All headers within a project should be included using the \c{<>} style
-inclusion and contain the project name as a directory prefix. And all headers
-means \i{all headers} \- public, private, or implementation detail, in
+inclusion and contain the project name as a subdirectory prefix. And all
+headers means \i{all headers} \- public, private, or implementation detail, in
executables or in libraries.
As an example, let's say we've added \c{utility.hxx} to our \c{hello} project.
@@ -2498,10 +3110,11 @@ listed as to be installed), chances are that a completely unrelated header
with the same name will be found and included. Needless to say, debugging
situations like these is unpleasant.
-Prefixing all inclusions with the project name also makes sure that headers
-with common names (for example, \c{utility.hxx}) can coexist (for example,
-when installed into a system-wide directory, such as \c{/usr/include}). The
-prefix also plays an important role in supporting auto-generated headers.
+Prefixing all inclusions with the project name as subdirectory also makes sure
+that headers with common names (for example, \c{utility.hxx}) can coexist (for
+example, when installed into a system-wide directory, such as
+\c{/usr/include}). The subdirectory prefix also plays an important role in
+supporting auto-generated headers.
Note also that this header inclusion scheme is consistent with the module
importation, for example:
@@ -2510,16 +3123,16 @@ importation, for example:
import hello.utility;
\
-Finally, note that while adding the project prefix to the \c{\"\"} style
+Finally, note that while adding the subdirectory prefix to the \c{\"\"} style
inclusion (for example, \c{\"libhello/hello.hxx\"}) will make finding an
unrelated header unlikely, there is still a possibility. And it is not clear
why take the chance when there are no benefits. So let's imagine the \c{\"\"}
style inclusion does not exist and we will all have a much better time.|
If you have to disregard every rule and recommendation in this section but
-one, for example, because you are working on an existing library, then insist
-on this: \b{public header inclusions must use the library name as a directory
-prefix}.
+one, for example, because you are working on an existing library, then at
+minimum insist on this: \b{public header inclusions must use the library name
+as a subdirectory prefix}.
The project's source subdirectory can have subdirectories of its own, for
example, to organize the code into components. Naturally, header inclusions
@@ -2556,10 +3169,10 @@ details/hxx{*}: install = false
\
\N|If you are creating a \i{family of libraries} with a common name prefix,
-then it may make sense to use a nested source directory layout with a common
-top-level directory. As an example, let's say we have the \c{libstud-path} and
-\c{libstud-url} libraries that belong to the same \c{libstud} family. Their
-source subdirectory layouts could look like this:
+then it may make sense to use a nested source subdirectory layout with a
+common top-level directory. As an example, let's say we have the
+\c{libstud-path} and \c{libstud-url} libraries that belong to the same
+\c{libstud} family. Their source subdirectory layouts could look like this:
\
libstud-path/
@@ -2586,12 +3199,12 @@ With the header inclusion paths adjusted accordingly:
#include <libstud/url/url.hxx>
\
-The \l{bdep-new(1)} command provides the \c{source} project type sub-option
+The \l{bdep-new(1)} command provides the \c{subdir} project type sub-option
that allows us to customize the source subdirectory within a project. For
example:
\
-$ bdep new -l c++ -t lib,source=libstud/path libstud-path
+$ bdep new -l c++ -t lib,subdir=libstud/path libstud-path
\
|
@@ -2722,7 +3335,7 @@ namespace hello
}
\
-An executable project may use a namespace (in which case it is natural to call
+An executable project may use a namespace (in which case it is natural to name
it after the project) and its (private) modules shouldn't be qualified with
the project name (in order not to clash with similarly named modules from the
corresponding library, if any). \N{A library may also have private modules in
@@ -2791,8 +3404,8 @@ automatically excluded from the library/executable sources.|
A library's functional/integration tests should go into the \c{tests/}
subdirectory. Each such test should reside in a separate subdirectory,
potentially organized into nested subdirectories (for instance, to correspond
-to the source directory components). For example, if we were creating an XML
-parsing and serialization library, then our \c{tests/} could have the
+to the source subdirectory components). For example, if we were creating an
+XML parsing and serialization library, then our \c{tests/} could have the
following layout:
\
@@ -2855,9 +3468,9 @@ of an out of source build) or next to the sources (in case of an in source
build). See \l{b#intro-dirs-scopes Output Directories and Scopes} for details
on in and out of source builds.
-Projects managed with \l{bdep(1)} are always built out-of-source. However, by
+Projects managed with \l{bdep(1)} are always built out of source. However, by
default, the source directory is configured as \i{forwarded} to one of the
-out-of-source builds. This has two effects: we can run the build system driver
+out of source builds. This has two effects: we can run the build system driver
\l{b(1)} directly in the source directory and certain \"interesting\" targets
(such as executables, documentation, test results, etc) will be automatically
\i{backlinked} to the source directory (see \l{b#intro-operations-config
@@ -2874,9 +3487,9 @@ hello/ ~~> └── hello/
└── hello --> └── *hello
\
-The result is an \i{as-if} in-source build with all the benefits (such as
+The result is an \i{as-if} in source build with all the benefits (such as
having both source and relevant output in the same directory) but without any
-of the drawback (such as the inability to have multiple builds or source
+of the drawbacks (such as the inability to have multiple builds or source
directory cluttered with object files).
\N|The often cited motivation for placing executables into \c{bin/} is that in
diff --git a/doc/packaging.cli b/doc/packaging.cli
new file mode 100644
index 0000000..07486a5
--- /dev/null
+++ b/doc/packaging.cli
@@ -0,0 +1,5392 @@
+// file : doc/packaging.cli
+// license : MIT; see accompanying LICENSE file
+
+"\name=build2-packaging-guide"
+"\subject=toolchain"
+"\title=Packaging Guide"
+
+// NOTES
+//
+// - Maximum <pre> line is 70 characters.
+//
+// - In guideline titles (do/don't) omit a/the.
+
+// TODO:
+//
+// @@ Update pinned repositories (libevent, libasio, xxd, libzstd).
+//
+// @@ Update build2-packaging front page with link to this guide (add
+// organization README?)
+//
+// @@ Enforce continous versioning with pre-commit hook -- maybe add a note?
+//
+// @@ Add example of propagating config.libfoo.debug to macro on build options?
+//
+// @@ Add link from metadata HOWTO to "Modifying upstream source code with
+// preprocessor".
+//
+// @@ Mapping to system package manager names/versions.
+//
+// @@ Are upstream tests well behaved? -- add never exit/take unreasonable time
+//
+
+"
+\h0#preface|Preface|
+
+This document provides guidelines for converting third-party C/C++ projects to
+the \c{build2} build system and making them available as packages from
+\l{https://cppget.org cppget.org}, the \c{build2} community's central package
+repository. For additional information, including documentation for individual
+\c{build2} toolchain components, man pages, HOWTOs, etc., refer to the project
+\l{https://build2.org/doc.xhtml Documentation} page.
+
+
+\h1#intro|Introduction|
+
+The aim of this guide is to ease the conversion of third-party C/C++ projects
+to the \c{build2} build system and publishing them to the
+\l{https://cppget.org cppget.org} package repository by codifying the best
+practices and techniques. By following the presented guidelines you will also
+make it easier for others to review your work and help with ongoing
+maintenance.
+
+\N|A \c{build2}-based project can only consume packages that use the
+\c{build2} build system (with the exception of
+\l{https://build2.org/faq.xhtml#why-syspkg system-installed packages}). In
+other words, there is no support for \"wrapping\" or otherwise adapting
+third-party projects' existing build systems. While replacing the build system
+unquestionably requires more work upfront, the \c{build2} project's experience
+is that the long-term benefits of this effort are well justified (see
+\l{https://build2.org/faq.xhtml#why-package-managers How does \c{build2}
+compare to other package managers?} for details).|
+
+The primary focus of this guide is existing C/C++ projects that use a
+different build system and that are maintained by a third-party, which we will
+refer to as \i{upstream}. Unless upstream is willing to incorporate support
+for \c{build2} directly into their repository, such projects are normally
+packaged for \c{build2} in a separate \c{git} repository under the
+\l{https://github.com/build2-packaging github.com/build2-packaging}
+organization. Note, however, that many of the presented guidelines are also
+applicable when converting your own projects (that is, where you are the
+upstream) as well as projects that use languages other than C or C++.
+
+Most C/C++ packages that are published to \l{https://cppget.org cppget.org}
+are either libraries or executables (projects that provide both are normally
+split into several packages) with libraries being in the strong majority.
+Libraries are also generally more difficult to build correctly. As a result,
+this guide uses libraries as a baseline. In most cases, a library-specific
+step is easily distinguished as such and can be skipped when dealing with
+executables. And in cases where a more nuanced change is required, a note will
+be provided.
+
+At the high-level, packaging a third-party project involves the following
+steps:
+
+\ol|
+
+\li|Create the \c{git} repository and import upstream source code.|
+
+\li|Generate \c{buildfile} templates that match upstream layout.|
+
+\li|Tweak the generated \c{buildfiles} to match upstream build.|
+
+\li|Test locally and using the \l{https://ci.cppget.org \c{build2} CI service}.|
+
+\li|Release and publish the package to \l{https://cppget.org cppget.org}.|
+
+|
+
+Once this process is completed and the package is published, new releases
+normally require a small amount of work provided there are no drastic changes
+in the upstream layout or build. The sequence of steps for a new release would
+typical look like this:
+
+\ol|
+
+\li|Add new and/or remove old upstream source code, if any.|
+
+\li|Tweak \c{buildfiles} to match changes to upstream build, if any.|
+
+\li|Test locally and using the \l{https://ci.cppget.org \c{build2} CI service}.|
+
+\li|Release and publish the package to \l{https://cppget.org cppget.org}.|
+
+|
+
+While packaging a simple library or executable is relatively straightforward,
+the C and C++ languages and their ecosystems are infamous for a large amount
+of variability in the platforms, compilers, source code layouts, and build
+systems used. This leads to what looks like an endless list of special
+considerations that are only applicable in certain, more complex cases.
+
+As result, the presented guidelines are divided into four chapters: \l{#core
+Common Guidelines} cover steps that are applicable to most packaging
+efforts. As mentioned earlier, these steps will assume packaging a library but
+they should be easy to adapt to executables. This chapter is followed by
+\l{#dont-do What Not to Do} which covers the common packaging mistakes and
+omissions. These are unfortunately relatively common because experience with
+other build systems often does not translate directly to \c{build2} and some
+techniques (such as header-only libraries) are discouraged. The last two
+chapters are \l{#howto HOWTO} and \l{#faq FAQ}. The former covers the
+above-mentioned long list of special considerations that are only applicable
+in certain cases while the latter answer frequent packaging-related questions.
+
+Besides the presented guidelines, you may also find the existing packages
+found in \l{https://github.com/build2-packaging github.com/build2-packaging} a
+good source of example material. The repositories pinned to the front page are
+the recommended starting point.
+
+This guide assumes familiarity with the \c{build2} toolchain. At the minimum
+you should have read through \l{intro The \c{build2} Toolchain Introduction}
+and the \l{b#intro Introduction} chapter in the build system manual. Ideally,
+you should also have some experience using \c{build2} in your own projects.
+
+In this guide we will only show the UNIX version of the commands. In most
+cases making a Windows version is a simple matter of adjusting paths and, if
+used, line continuations. And where this is not the case a note will be
+provided showing the equivalent Windows command.
+
+
+\h#intro-term|Terminology|
+
+We use the term \i{upstream} to refer collectively to the third-party project
+as well as to its authors. For example, we may say, \"upstream does not use
+semver\" meaning that the upstream project does not use semver for
+versioning. Or we may say, \"upstream released a new version\" meaning that
+the upstream project's authors released a new version.
+
+We will often use \i{upstream} as a qualifier to refer to a specific part of
+the upstream project. Commonly used qualified terms like this include:
+
+\dl|
+
+\li|\i{upstream repository}
+
+The version control (normally \c{git}) repository of the third-party project.|
+
+\li|\i{upstream source code}
+
+The C/C++ source code that constitutes the third-party project.
+
+|
+
+\li|\i{upstream layout}
+
+The directory structure and location of source code in the third-party
+project.
+
+|
+
+\li|\i{upstream build system}
+
+The equivalents of \c{buildfiles} that are used by the third-party project to
+build its source code, run tests, etc. For example, if upstream uses CMake,
+then all the \c{CMakeLists.txt}, \c{*.cmake}, etc., files will constitute its
+build system.||
+
+To avoid confusion, in this guide we will always use the term \i{project} to
+refer to upstream and \i{package} to refer to its \c{build2} conversion, even
+though we would normally call our own \c{build2}-based work a project, not a
+package (see \l{b#intro-proj-struct Project Structure} for details on the
+\c{build2} terminology in this area). Some commonly used \c{build2}-side terms
+in this guide include:
+
+
+\dl|
+
+\li|\i{package \c{git} repository}
+
+The \c{git} repository that hosts the package of the upstream project.|
+
+
+\li|\i{multi-package repository}
+
+Sometimes it makes sense to split the upstream project into multiple
+\c{build2} packages (for example, a library and an executable). In this case
+the package repository structure must become multi-package.||
+
+
+\h1#core|Common Guidelines|
+
+This chapter describes the recommended sequence of steps for packaging a
+third-party project for \c{build2} with the end-goal of publishing it to the
+\l{https://cppget.org cppget.org} package repository.
+
+
+\h#core-repo|Setup the package repository|
+
+This section covers the creation of the package \c{git} repository and
+the importation of the upstream source code.
+
+\h2#core-repo-exists|Check if package repository already exists|
+
+Before deciding to package a third-party project you have presumably checked
+on \l{https://cppget.org cppget.org} if someone has already packaged it. There
+are several other places that make sense to check as well:
+
+\ul|
+
+\li|\l{https://queue.cppget.org queue.cppget.org} contains packages that
+have been submitted but not yet published.|
+
+\li|\l{https://queue.stage.build2.org queue.stage.build2.org} contains
+packages that have been submitted but can only be published after the next
+release of the \c{build2} toolchain (see \l{#faq-publish-stage Where to
+publish if package requires staged toolchain?} for background).|
+
+\li|\l{https://github.com/build2-packaging github.com/build2-packaging}
+contains all the third-party package repositories. Someone could already be
+working on the package but haven't yet published it.|
+
+\li|\l{https://github.com/build2-packaging/WISHLIST/issues
+github.com/build2-packaging/WISHLIST} contains as issues projects that people
+wish were packaged. These may contain offers to collaborate or announcements
+of ongoing work.||
+
+
+In all these cases you should be able to locate the package \c{git} repository
+and/or connect with others in order to collaborate on the packaging work. If
+the existing effort looks abandoned (for example, there hasn't been any
+progress for a while and the existing maintainer doesn't respond) and you
+would like to take over the package,
+\l{https://build2.org/community.xhtml#help get in touch}.
+
+
+\h2#core-repo-name|Use upstream repository name as package repository name|
+
+It is almost always best to use the upstream repository name as the package
+repository name. If there is no upstream repository (for example, because the
+project doesn't use a version control system), the name used in the source
+archive distribution would be the natural fallback choice.
+
+\N|See \l{#core-package-name Decide on the package name} for the complete
+picture on choosing names.|
+
+\h2#core-repo-create|Create package repository in personal workspace|
+
+For a third-party project, the end result that we are aiming for is a package
+repository under the \l{https://github.com/build2-packaging
+github.com/build2-packaging} organization.
+
+\N|We require all the third-party projects that are published to
+\l{https://cppget.org cppget.org} to be under the
+\l{https://github.com/build2-packaging github.com/build2-packaging}
+organization in order to ensure some continuity in case the original
+maintainer loses interest, etc. You will still be the owner of the repository
+and by hosting your packaging efforts under this organization (as opposed to,
+say, your personal workspace) you make it easier for others to discover your
+work and to contribute to the package maintenance.
+
+Note that this requirement does not apply to your own projects (that is, where
+you are the upstream) and where the \c{build2} support is normally part of the
+upstream repository.
+
+Finally, a note on the use of \c{git} and GitHub: if for some reason you are
+unable to use either, \l{https://build2.org/community.xhtml#help get in touch}
+to discuss alternatives.|
+
+However, the recommended approach is to start with a repository in your
+personal workspace and then, when it is ready or in a reasonably complete
+state, transfer it to \l{https://github.com/build2-packaging
+github.com/build2-packaging}. This gives you the freedom to make destructive
+changes to the repository (including deleting it and starting over) during the
+initial packaging work. It also removes the pressure to perform: you can give
+it a try and if things turn out more difficult than you expected, you can just
+drop the repository.
+
+\N|For repositories under \l{https://github.com/build2-packaging
+github.com/build2-packaging} the \c{master}/\c{main} branch is protected: it
+cannot be deleted and its commit history cannot be overwritten with a forced
+push.|
+
+\N|While you can use any name for a repository under the personal workspace,
+under \l{https://github.com/build2-packaging github.com/build2-packaging} it
+should follow the \l{#core-repo-name Use upstream repository name as package
+repository name} guideline. In particular, there should be no prefixes like
+\c{build2-} or suffixes like \c{-package}. If the repository under your
+personal workspace does not follow this guideline, you will need to rename it
+before transferring it to the \l{https://github.com/build2-packaging
+github.com/build2-packaging} organization.|
+
+There is one potential problem with this approach: it is possible that
+several people will start working on the same third-party project without
+being aware of each other's efforts. If the project you are packaging is
+relatively small and you don't expect it to take more than a day or two, then
+this is probably not worth worrying about. For bigger projects, however, it
+makes sense to announce your work by creating (or updating) the corresponding
+issue in \l{https://github.com/build2-packaging/WISHLIST
+github.com/build2-packaging/WISHLIST}.
+
+To put it all together, the recommended sequence of actions for this step:
+
+\ol|
+
+\li|Create a new empty repository under your personal workspace from the
+ GitHub UI.|
+
+\li|Set the repository description to \c{build2 package for <name>}, where
+\c{<name>} is the third-party project name.|
+
+\li|Make the repository public (otherwise you won't be able to CI it).|
+
+\li|Don't automatically add any files (\c{README}, \c{LICENSE}, etc).|
+
+\li|Clone the empty repository to your machine (using the SSH protocol).||
+
+\N|Since this is your personal repository, you can do the initial work
+directly in \c{master}/\c{main} or in a separate branch, it's up to you.|
+
+As a running example, let's assume we want to package a library called \c{foo}
+whose upstream repository is at \c{https://github.com/<upstream>/foo.git}. We
+have created its package repository at
+\c{https://github.com/<personal>/foo.git} (with the \c{build2 package for foo}
+description) and can now clone it:
+
+\
+$ git clone git@github.com:<personal>/foo.git
+\
+
+
+\h2#core-repo-init|Initialize package repository with \c{bdep new}|
+
+Change to the root directory of the package repository that you have cloned
+in the previous step and run (continuing with our \c{foo} example):
+
+\
+$ cd foo/ # Change to the package repository root.
+$ bdep new --type empty,third-party
+$ tree -a .
+./
+├── .bdep/
+│   └── ...
+├── .git/
+│   └── ...
+├── .gitattributes
+├── .gitignore
+├── README.md
+└── repositories.manifest
+\
+
+\N|We use the special \c{third-party} sub-option which is meant for converting
+third-party projects to \c{build2}. See \l{bdep-new(1)} for details.|
+
+This command creates a number of files in the root of the repository:
+
+\dl|
+
+\li|\n\c{README.md}\n
+
+This is the repository \c{README.md}. We will discuss the recommended content
+for this file later.|
+
+\li|\n\c{repositories.manifest}\n
+
+This file specifies the repositories from which this project will obtain its
+dependencies (see \l{intro#guide-add-remove-deps Adding and Removing
+Dependencies}). If the project you are packaging has no dependencies, then you
+can safely remove this file (it's easy to add later if this changes). And for
+projects that do have dependencies we will discuss the appropriate changes to
+this file later.|
+
+
+\li|\n\c{.gitattributes} and \c{.gitignore}\n
+
+These are the \c{git} infrastructure files for the repository. You shouldn't
+normally need to change anything in them at this stage (see the comments
+inside for details).||
+
+Next add and commit these files:
+
+\
+$ cd foo/ # Change to the package repository root.
+$ git add .
+$ git status
+$ git commit -m \"Initialize package repository\"
+\
+
+\N|In these guidelines we will be using the package repository setup that is
+capable of having multiple packages (referred to as \i{multi-package
+repository}). This is recommended even for upstream projects that only
+provides a single package because it gives us the flexibility of adding new
+packages at a later stage without having to perform a major restructuring of
+our repository.
+
+Note also that upstream providing multiple packages is not the only reason we
+may end up having multiple \c{build2} packages. Another common reason is
+factoring tests into a separate package due to a dependency on a testing
+framework
+(see \l{https://github.com/build2/HOWTO/blob/master/entries/handle-tests-with-extra-dependencies.md
+How do I handle tests that have extra dependencies?} for background and
+details). While upstream adding new packages may not be very common, upstream
+deciding to use a testing framework is a lot more plausible.
+
+The only notable drawback of using a multi-package setup with a single package
+is the extra subdirectory for the package and a few extra files (such as
+\c{packages.manifest} that lists the packages) in the root of the repository.
+If you are certain that the project that you are converting is unlikely to
+have multiple packages (for example, because you are the upstream) and won't
+need extra dependencies for its tests (a reasonable assumption for a C
+project), then you could instead go with the single-package repository where
+the repository root is the package root. See \l{bdep-new(1)} for details on
+how to initialize such a repository. In this guide, however, we will continue
+to assume a multi-package repository setup.|
+
+
+\h2#core-repo-submodule|Add upstream repository as \c{git} submodule|
+
+If the third-party project is available from a \c{git} repository, then the
+recommended approach is to use the \c{git} submodule mechanism to make the
+upstream source code available inside the package repository, customarily in a
+subdirectory called \c{upstream/}.
+
+\N|While \c{git} submodules receive much criticism, in our case we use them
+exactly as intended: to select and track specific (release) commits of an
+external project. As a result, there is nothing tricky about their use for our
+purpose and all the relevant commands will be provided and explained, in case
+you are not familiar with this \c{git} mechanism.|
+
+Given the upstream repository URL, to add it as a submodule, run the following
+command from the package repository root (continuing with our \c{foo} example):
+
+\
+$ cd foo/ # Change to the package repository root.
+$ git submodule add https://github.com/<upstream>/foo.git upstream
+\
+
+\N|You should prefer \c{https://} over \c{git://} for the upstream repository
+URL since the \c{git://} protocol may not be accessible from all networks.
+Naturally, never use a URL that requires authentication, for example, SSH
+(SSH URLs start with \c{git@github.com} for GitHub).|
+
+Besides the repository URL, you also need the commit of the upstream release
+which you will be packaging. It is common practice to tag releases so the
+upstream tags would be the first place to check. Failing that, you can always
+use the commit id.
+
+Assuming the upstream release tag you are interested in is called \c{vX.Y.Z},
+to update the \c{upstream} submodule to point to this release commit, run the
+following commands:
+
+\
+$ cd upstream/
+$ git checkout vX.Y.Z
+$ cd ../
+\
+
+Then add and commit these changes:
+
+\
+$ git add .
+$ git status
+$ git commit -m \"Add upstream submodule, vX.Y.Z\"
+\
+
+Now we have all the upstream source code for the version that we are
+packaging available in the \c{upstream/} subdirectory of our repository.
+
+The plan is to then use symbolic links (symlinks) to non-invasively overlay
+the \c{build2}-related files (\c{buildfile}, \c{manifest}, etc) with the
+upstream source code, if necessary adjusting upstream structure to split it
+into multiple packages and/or to better align with the source/output layouts
+recommended by \c{build2} (see \l{https://build2.org/article/symlinks.xhtml
+Using Symlinks in \c{build2} Projects} for background and rationale). But
+before we can start adding symlinks to the upstream source (and other files
+like \c{README}, \c{LICENSE}, etc), we need to generate the \c{buildfile}
+templates that match the upstream source code layout. This is the subject of
+the next section.
+
+\N|While on UNIX-like operating systems symlinks are in widespread use, on
+Windows it's a niche feature that unfortunately could be cumbersome to use
+(see \l{https://build2.org/article/symlinks.xhtml#windows Symlinks and
+Windows} for details). However, the flexibility afforded by symlinks when
+packaging third-party projects is unmatched by any other mechanism and we
+therefore use them despite potentially sub-optimal packaging experience
+on Windows.|
+
+
+\h#core-package|Create package and generate \c{buildfile} templates|
+
+This section covers the addition of the package to the repository we have
+prepared in the previous steps and the generation of the \c{buildfile}
+templates that match the upstream source code layout.
+
+
+\h2#core-package-name|Decide on the package name|
+
+While choosing the package repository name was pretty straightforward, things
+get less clear cut when it comes to the package name.
+
+\N|If you need a refresher on the distinction between projects and packages,
+see \l{#intro-term Terminology}.|
+
+Picking a name for a package that provides an executable is still relatively
+straightforward: you should use the upstream name (which is usually the same
+as the upstream project name) unless there is a good reason to deviate. One
+recommended place to check before deciding on a name is the
+\l{https://packages.debian.org Debian package repository}. If their package
+name differs from upstream, then there is likely a good reason for that and
+it is worth trying to understand what it is.
+
+\N|Tip: when trying to find the corresponding Debian package, search for the
+executable file name in the package contents if you cannot fine the package by
+its upstream name. Also consider searching in the \c{unstable} distribution in
+addition to \c{stable} for newer packages.|
+
+Picking a name for a package that provides a library is where things can get
+more complicated. While all the recommendations that have been listed for
+executables apply equally to libraries, there are additional considerations.
+
+In \c{build2} we recommend (but not require) that new library projects use a
+name that starts with \c{lib} in order to easily distinguish them from
+executables and avoid any clashes, potential in the future (see
+\l{intro#proj-struct Canonical Project Structure} for details). To illustrate
+the problem, consider the \c{zstd} project which provides a library and an
+executable. In upstream repository both are part of the same codebase that
+doesn't try to separate them into packages so that, for example, library could
+be used without downloading and building the executable. In \c{build2},
+however, we do need to split them into two separate packages and both packages
+cannot be called \c{zstd}. So we call them \c{zstd} and \c{libzstd}.
+
+\N|If you are familiar with the Debian package naming policy, you will
+undoubtedly recognize this approach. In Debian all the library packages (with
+very few exceptions) start with the \c{lib} prefix. So when searching for an
+upstream name in the \l{https://packages.debian.org Debian package repository}
+make sure to prefix it with \c{lib} (unless it already starts with this
+prefix, of course).|
+
+This brings the question of what to do about third-party libraries: should we
+add the \c{lib} prefix to the package name if it's not already there?
+Unfortunately, there is no clear cut answer and whichever decision you make,
+there will be drawbacks. Specifically, if you add the \c{lib} prefix, the main
+drawback is that the package name now deviates from the upstream name and if
+the project maintainer ever decides to add \c{build2} support to the upstream
+repository, there could be substantial friction. On the other hand, if you
+don't add the \c{lib} prefix, then you will always run the risk of a future
+clash with an executable name. And, as was illustrated with the \c{zstd}
+example, a late addition of an executable won't necessarily cause any issues
+to upstream. As a result, we don't have a hard requirement for the \c{lib}
+prefix unless there is already an executable that would cause the clash (this
+applies even if it's not being packaged yet or is provided by an unrelated
+project). If you don't have a strong preference, we recommend that you add the
+\c{lib} prefix (unless it is already there). In particular, this will free you
+from having to check for any potential clashes. See
+\l{https://github.com/build2/HOWTO/blob/master/entries/name-packages-in-project.md
+How should I name packages when packaging third-party projects?} for
+additional background and details.
+
+To build some intuition for choosing package names, let's consider several
+real examples. We start with executables:
+
+\
+ upstream | upstream | Debian | build2 package| build2
+project name|executable name|package name|repository name|package name
+------------+---------------+------------+---------------+------------
+byacc byacc byacc byacc byacc
+sqlite sqlite3 sqlite3 sqlite sqlite3
+vim xxd xxd xxd xxd
+OpenBSD m4 - openbsd-m4 openbsd-m4
+qtbase 5 moc qtbase5-\ Qt5 Qt5Moc
+ dev-tools
+qtbase 6 moc qt6-base-\ Qt6 Qt6Moc
+ dev-tools
+\
+
+The examples are arranged from the most straightforward naming to the
+least. The last two examples show that sometimes, after carefully considering
+upstream naming, you nevertheless have no choice but to ignore it and forge
+your own path.
+
+Next let's look at library examples. Notice that some use the same \c{build2}
+package repository name as the executables above. This means they are part of
+the same multi-package repository.
+
+\
+ upstream | upstream | Debian | build2 package| build2
+project name|library name |package name|repository name|package name
+------------+---------------+------------+---------------+------------
+libevent libevent libevent libevent libevent
+brotli brotli libbrotli brotli libbrotli
+zlib zlib zlib zlib libz
+sqlite libsqlite3 libsqlite3 sqlite libsqlite3
+libsig\ libsigc++ libsigc++ libsig\ libsigc++
+cplusplus cplusplus
+qtbase 5 QtCore qtbase5-dev Qt5 libQt5Core
+qtbase 6 QtCore qt6-base-dev Qt6 libQt6Core
+\
+
+If an upstream project is just a single library, then the project name is
+normally the same as the library name (but there are exceptions, like
+\c{libsigcplusplus} in the above table). However, when looking at the upstream
+repository that contains multiple components (libraries and/or executables,
+like \c{qtcore} in the above example), it may not be immediately obvious what
+the upstream's library names are. In such cases, the corresponding Debian
+packages can really help clarify the situation. Failing that, look into the
+existing build system. In particular, if it generates the \c{pkg-config} file,
+then the name of this file is usually the upstream library name.
+
+\N|Looking at the names of the library binaries is less helpful because on
+UNIX-like systems they must start with the \c{lib} prefix. And on Windows the
+names of library binaries often embed extra information (static/import,
+debug/release, etc) and may not correspond directly to the library name.|
+
+And, speaking of multiple components, if you realize the upstream project
+provides multiple libraries and/or executables, then you need to decide
+whether to split them into separate \c{build2} packages and if so, how. Here,
+again, the corresponding Debian packages can be a good reference point. Note,
+however, that we often deviate from Debian's splits, especially when it comes
+to libraries. Such differences are usually due to Debian focusing on binary
+packages while in \c{build2} we are focusing on source packages.
+
+To give a few example, \c{libevent} shown in the above table provides several
+libraries (\c{libevent-core}, \c{libevent-extra}, etc) and in Debian it is
+actually split into several binary packages along these lines. In \c{build2},
+however, there is a single source package that provides all these libraries
+with everything except \c{libevent-core} being optional. An example which
+shows the decision made in a different direction would be the Boost libraries:
+in Debian all the header-only Boost libraries are bundled into a single
+package while in \c{build2} they are all separate packages.
+
+The overall criteria here can be stated as follows: if a small family of
+libraries provide complimentary functionality (like \c{libevent}), then we put
+them all into a single package, usually making the additional functionality
+optional. However, if the libraries are independent (like Boost) or provide
+alternative rather than complimentary functionality (for example, like
+different backends in \c{imgui}), then we make them separate packages. Note
+that we never bundle an executable and a (public) library in a single package
+(because, when consumed, they usually require different
+\l{bpkg#manifest-package-depends dependency types}: build-time vs run-time).
+
+Note also that while it's a good idea to decide on the package split and all
+the package names upfront to avoid surprises later, you don't have to actually
+provide all the packages right away. For example, if upstream provides a
+library and an executable (like \c{zstd}), you can start with the library and
+the executable package can be added later (potentially by someone else).
+
+\N|In the \"library and executable\" case, if you plan to package both, the
+sensible strategy is to first completely package the library stopping short of
+releasing and publishing, then repeat the same process to package the
+executable, and finally release and publish both.|
+
+Admittedly, the recommendations in this section are all a bit fuzzy and one
+can choose different names or different package splits that could all seem
+reasonable. If you are unsure how to split the upstream project or what names
+to use, \l{https://build2.org/community.xhtml#help get in touch} to discuss
+the alternatives. It can be quite painful to change these things after you
+have completed the remaining packaging steps.
+
+Continuing with our \c{foo} example, we will follow the above recommendation
+and call the library package \c{libfoo}.
+
+
+\h2#core-package-struct|Decide on the package source code layout|
+
+Another aspect we need to decide on is the source code layout inside the
+package. Here we want to stay as close to the upstream layout as possible
+unless there are valid reasons to deviate. Staying close has the best chance
+of giving us a build without any compile errors since the header inclusion in
+the project can be sensitive to this layout. This also makes it easier for
+upstream to adopt the \c{build2} build.
+
+Sometimes, however, there are good reasons for deviating from upstream,
+especially in cases where upstream is clearly following bad practices, for
+example including generically-named public headers without the library name as
+a subdirectory prefix. If you do decide to change the layout, it's usually
+less disruptive (to the build) to rearrange things at the outer levels than at
+the inner. For example, it should normally be possible to move/rename the
+top-level \c{tests/} directory or to place the library source files into a
+subdirectory.
+
+Our overall plan is to create the initial layout and \c{buildfile} templates
+automatically using \l{bdep-new(1)} in the \c{--package} mode, then \"fill\"
+the package with upstream source code using symlinks, and finish off with
+tweaking the generated \c{buildfiles} to match the upstream build.
+
+The main rationale for using \l{bdep-new(1)} instead of doing everything by
+hand is that there are many nuances in getting the build right and
+auto-generated \c{buildfiles} had years of refinement and fine-tuning. The
+familiar structure also makes it easier for others to understand your build,
+for example while reviewing your package submission or helping out with
+maintenance.
+
+The \l{bdep-new(1)} command supports a wide variety of
+\l{bdep-new.xhtml#src-layout source layouts}. While it may take a bit of time
+to understand the customization points necessary to achieve the desired layout
+for your first package, this experience will pay off in spades when you work
+on converting subsequent packages.
+
+And so the focus of the following several steps is to iteratively discover the
+\l{bdep-new(1)} command line that best approximates the upstream layout. The
+recommended procedure is as follows:
+
+\ol|
+
+\li|\nStudy the upstream source layout and existing build system.|
+
+\li|\nCraft and execute the \l{bdep-new(1)} command line necessary to achieve
+the upstream layout.|
+
+\li|\nStudy the auto-generated \c{buildfiles} for things that don't fit and
+need to change. But don't rush to start manually editing the result. First get
+an overview of the required changes and then check if it's possible to achieve
+these changes automatically using one of \l{bdep-new(1)} sub-options. If
+that's the case, delete the package, and restart from step 2.||
+
+This and the following two sections discuss each of these steps in more detail
+and also look at some examples.
+
+The first step above is to study the upstream project in order to understand
+where the various parts are (headers, sources, etc) and how they are built.
+Things that can help here include:
+
+\ul|
+
+\li|Read through the existing build system definitions.|
+
+\li|Try to build the project using the existing build system.|
+
+\li|Try to install the project using the existing build system.|
+
+\li|Look into the Debian package contents to see if there are any differences
+ with regards to the installation locations.||
+
+\N|If while studying the upstream build system you notice other requirements,
+for example, the need to compile source files other than C/C++ (such as
+Objective-C/C++, assembler, etc) or the need to generate files from \c{.in}
+templates (or their \c{.cmake}/\c{.meson} equivalents), and are wondering how
+they would be handled in the \c{build2} build, see the
+\l{#core-adjust-build-src-source-ext Adjust source \c{buildfile}: extra
+requirements} step for a collection of pointers.|
+
+For libraries, the first key pieces of information we need to find is how the
+public headers are included and where they are installed. The two common
+\i{good} practices is to either include the public headers with a library name
+as a subdirectory, for example, \c{#include\ <foo/util.h>}, or to include the
+library name into each public header name, for example, \c{#include\
+<foo-util.h>} or \c{#include\ <foo.h>} (in the last example the header name is
+the library name itself, which is also fairly common). Unfortunately, there is
+also a fairly common \i{bad} practice: having generically named headers (such
+as \c{util.h}) included without the library name as a subdirectory.
+
+\N|The reason this is a bad practice is that libraries that have such headers
+cannot coexist, neither in the same build nor when installed. See
+\l{#howto-bad-inclusion-practice How do I deal with bad header inclusion
+practice?} if you encounter such a case. See \l{intro#proj-struct Canonical
+Project Structure} for additional background and details.|
+
+Where should we look to get this information? While the library source files
+sound like a natural place, oftentimes they include own headers with the
+\c{\"\"} style inclusion, either because the headers are in the same directory
+or because the library build arranges for them to be found this way with
+additional header search paths. As a result, a better place to look could be
+the library's examples and/or tests. Some libraries also describe which
+headers they provide and how to include them in their documentation.
+
+The way public headers are included normally determines where they are
+installed. If they are included with a subdirectory, then they are normally
+installed into the same subdirectory in, say, \c{/usr/include/}. Continuing
+with the above example, a header that is included as \c{<foo/util.h>} would
+normally be installed as \c{/usr/include/foo/util.h}. On the other hand, if
+the library name is part of the header name, then the headers are usually (but
+not always) installed directly into, say, \c{/usr/include/}, for example as
+\c{/usr/include/foo-util.h}.
+
+\N|While these are the commonly used installation schemes, there are
+deviations. In particular, in both cases upstream may choose to add an
+additional subdirectory when installing (so the above examples will instead
+end up with, say, \c{/usr/include/foo-v1/foo/util.h} and
+\c{/usr/include/foo-v1/sub/foo-util.h}). See
+\l{#howto-extra-header-install-subdir How do I handle extra header
+installation subdirectory?} if you encounter such a case.|
+
+The inclusion scheme would normally also be recreated in the upstream source
+code layout. In particular, if upstream includes public headers with a
+subdirectory prefix, then this subdirectory would normally also be present in
+the upstream layout so that such a header can be included from the upstream
+codebase directly. As an example, let's say we determined that public headers
+of \c{libfoo} are included with the \c{foo/} subdirectory, such as
+\c{<foo/util.hpp>}. One of the typical upstream layouts for such a library
+would look like this:
+
+\
+$ tree upstream/
+upstream/
+├── include/
+│   └── foo/
+│   └── util.hpp
+└── src/
+ ├── priv.hpp
+ └── util.cpp
+\
+
+Notice how the \c{util.hpp} header is in the \c{foo/} subdirectory rather
+than in \c{include/} directly.
+
+The second key piece of information we need to find is whether and, if so,
+how the public headers and sources are split. For instance, in the above
+example, we can see that public headers go into \c{include/} while sources and
+private headers go into \c{src/}. But they could also be combined in the same
+directory, for example, as in the following layout:
+
+\
+upstream/
+└── foo/
+ ├── priv.hpp
+ ├── util.cpp
+ └── util.hpp
+\
+
+\N|In multi-package projects, for example, those that provide both a library
+and an executable, you would also want to understand how the sources are split
+between the packages.|
+
+If the headers and sources are split into different directories, then the
+source directory may or may not have the inclusion subdirectory, similar to
+the header directory. In the above split layout the \c{src/} directory doesn't
+contain the inclusion subdirectory (\c{foo/}) while the following layout does:
+
+\
+upstream/
+├── include/
+│   └── foo/
+│   └── util.hpp
+└── src/
+ └── foo/
+ ├── priv.hpp
+ └── util.cpp
+\
+
+With the understanding of these key properties of upstream layout you should
+be in a good position to start crafting the \l{bdep-new(1)} command line that
+recreates it.
+
+\N|The \c{bdep-new} documentation uses slightly more general terminology
+compared to what we used in the previous section in order to also be
+applicable to projects that use modules instead of headers.
+
+Specifically, the inclusion subdirectory (\c{foo/}) is called \i{source
+subdirectory} while the header directory (\c{include/}) and source directory
+(\c{src/}) are called \i{header prefix} and \i{source prefix}, respectively.|
+
+
+\h2#core-package-craft-cmd|Craft \c{bdep new} command line to create package|
+
+The recommended procedure for this step is to read through the \c{bdep-new}'s
+\l{bdep-new.xhtml#src-layout SOURCE LAYOUT} section (which contains a large
+number of examples) while experimenting with various options in an attempt to
+create the desired layout. If the layout you've got isn't quite right yet,
+simply remove the package directory along with the \c{packages.manifest} file
+and try again.
+
+\N|Next to \c{packages.manifest}, \c{bdep-new} will also create the \"glue\"
+\c{buildfile} that allows building all the packages from the repository
+root. You don't need to remove it when re-creating the package.|
+
+Let's illustrate this approach on the first split layout from the previous
+section:
+
+\
+upstream/
+├── include/
+│   └── foo/
+│   └── util.hpp
+└── src/
+ ├── priv.hpp
+ └── util.cpp
+\
+
+We know it's split, so let's start with that and see what we get. Remember,
+our \c{foo} package repository that we have cloned and initialized earlier
+looks like this:
+
+\
+$ tree foo/
+foo/
+├── upstream/
+├── .gitattributes
+├── .gitignore
+├── README.md
+└── repositories.manifest
+\
+
+Now we create the \c{libfoo} package inside:
+
+\
+$ cd foo/
+$ bdep new --package --lang c++ --type lib,split libfoo
+$ tree libfoo/
+libfoo/
+├── include/
+│   └── libfoo/
+│   └── foo.hxx
+└── src/
+ └── libfoo/
+ └── foo.cxx
+\
+
+The outer structure looks right, but inside \c{include/} and \c{src/} things
+are a bit off. Specifically, the source subdirectory should be \c{foo/}, not
+\c{libfoo/}, there shouldn't be one inside \c{src/}, and the file extensions
+don't match upstream. All this can be easily tweaked, however:
+
+\
+$ rm -r libfoo/ packages.manifest
+$ bdep new --package \
+ --lang c++,cpp \
+ --type lib,split,subdir=foo,no-subdir-source \
+ libfoo
+$ tree libfoo/
+libfoo/
+├── include/
+│   └── foo/
+│   └── foo.hpp
+└── src/
+ └── foo.cpp
+\
+
+The other \c{bdep-new} sub-options (see the \l{bdep-new(1)} man page for the
+complete list) that you will likely want to use when packaging a third-party
+project include:
+
+\dl|
+
+\li|\n\cb{no-version}
+
+Omit the auto-generated version header. Usually upstream will provide its own
+equivalent of this functionality.
+
+\N|Note that even if upstream doesn't provide any version information, it's
+not a good idea to try to rectify this by providing your own version header
+since upstream may add it in a future version and you may end up with a
+conflict. Instead, work with the project authors to rectify this upstream.||
+
+\li|\n\cb{no-symexport}\n\cb{auto-symexport}
+
+The \c{no-symexport} sub-option suppresses the generation of the DLL symbol
+exporting header. This is an appropriate option if upstream provides its
+own symbol exporting arrangements.
+
+The \c{auto-symexport} sub-option enables automatic DLL symbol exporting
+support (see \l{b#cc-auto-symexport Automatic DLL Symbol Exporting} for
+background). This is an appropriate option if upstream relies on similar
+support in the existing build system. It is also recommended that you give
+this functionality a try even if upstream does not support building
+shared libraries on Windows.|
+
+\li|\n\cb{binless}
+
+Create a header-only library. See \l{#dont-header-only Don't make
+library header-only if it can be compiled} and
+\l{https://github.com/build2/HOWTO/blob/master/entries/make-header-only-library.md
+How do I make a header-only C/C++ library?}|
+
+\li|\n\cb{buildfile-in-prefix}
+
+Place header/source \c{buildfiles} into the header/source prefix directory
+instead of source subdirectory. To illustrate the difference, compare these
+two auto-generated layouts paying attention to the location of \c{buildfiles}:
+
+\
+$ bdep new ... --type lib,split,subdir=foo libfoo
+$ tree libfoo/
+libfoo/
+├── include/
+│   └── foo/
+│   ├── buildfile
+│   └── foo.hpp
+└── src/
+ └── foo/
+ ├── buildfile
+ └── foo.cpp
+\
+
+\
+$ bdep new ... --type lib,split,subdir=foo,buildfile-in-prefix libfoo
+$ tree libfoo/
+libfoo/
+├── include/
+│   ├── foo/
+│   │   └── foo.hpp
+│   └── buildfile
+└── src/
+ ├── foo/
+ │   └── foo.cpp
+ └── buildfile
+\
+
+Note that this sub-option only makes sense if we have the header and/or source
+prefixes (\c{include/} and \c{src/} in our case) as well as the source
+subdirectory (\c{foo/} in our case).
+
+Why would we want to do this? The main reason is to be able to symlink the
+entire upstream directories rather than individual files. In the first
+listing, the generated \c{buildfiles} are inside the \c{foo/} subdirectories
+which mean we cannot just symlink \c{foo/} from upstream.
+
+With a large number of files to symlink, this can be such a strong motivation
+that it may make sense to invent a source subdirectory in the source prefix
+even if upstream doesn't have one. See \l{#dont-main-target-root-buildfile
+Don't build your main targets in the root \c{buildfile}} for details on this
+technique.
+
+Another reason we may want to move \c{buildfiles} to prefix is to be able to
+handle upstream projects that have multiple source subdirectories. While this
+situation is not very common in the header prefix, it can be encountered in the
+source prefix of more complex projects, where upstream wishes to organize the
+source files into components.||
+
+\N|If upstream uses a mixture of C and C++, then it's recommended to set this
+up using the \c{--lang} sub-option of \c{bdep-new}. For example:
+
+\
+$ bdep new --lang c++,c ...
+\
+
+|
+
+Continuing with our \c{libfoo} example, assuming upstream provides its own
+symbol exporting, the final \c{bdep-new} command line would be:
+
+\
+$ bdep new --package \
+ --lang c++,cpp \
+ --type lib,split,subdir=foo,no-subdir-source,no-version,no-symexport \
+ libfoo
+\
+
+When packaging an executable, things are usually quite a bit simpler: there is
+no version header, symbol exporting, and the layout is normally combined
+(since there are no public headers). Typically the only potentially tricky
+decision you will need to make is whether to use \i{prefix} or \i{source
+subdirectory}. Most likely it will be \i{prefix} since most executable
+projects will use the \c{\"\"} style inclusion for own headers. For example:
+
+\
+$ bdep new --package \
+ --lang c++ \
+ --type exe,no-subdir,prefix=foo,export-stub \
+ foo
+\
+
+\N|The \c{export-stub} sub-option causes the generation of
+\c{build/export.build}, an export stub that facilitates the importation of
+targets from our package (see \l{b#intro-import Target Importation} for
+details). The generation of this file for a library is the default since it
+will normally be used by other projects and thus imported. An executable,
+however, will only need an export stub if it can plausibly be used during the
+build (see \l{intro#guide-build-time-linked Build-Time Dependencies and Linked
+Configurations} for background). Source code generators are an obvious example
+of such executables. A less obvious example would be compression utilities
+such as \c{gzip} or \c{zstd}. If you are unsure, it's best to provide an
+export stub.|
+
+
+\h2#core-package-review|Review and test auto-generated \c{buildfile} templates|
+
+Let's get a more complete view of what got generated by the final \c{bdep-new}
+command line from the previous section:
+
+\
+$ tree libfoo/
+libfoo/
+├── build/
+│   └── ...
+├── include/
+│   └── foo/
+│   ├── buildfile
+│   └── foo.hpp
+├── src/
+│   ├── buildfile
+│   └── foo.cpp
+├── tests/
+│   ├── build/
+│   │   └── ...
+│   ├── basics/
+│   │   ├── buildfile
+│   │   └── driver.cpp
+│   └── buildfile
+├── buildfile
+├── manifest
+└── README.md
+\
+
+Once the overall layout looks right, the next step is to take a closer look at
+the generated \c{buildfiles} to make sure that overall they match the upstream
+build. Of particular interest are the header and source directory
+\c{buildfiles} (\c{libfoo/include/foo/buildifle} and \c{libfoo/src/buildifle}
+in the above listing) which define how the library is built and installed.
+
+Here we are focusing on the macro-level differences that are easier to change
+by tweaking the \c{bdep-new} command line rather than manually. For example,
+if we look at the generated source directory \c{buildfile} and realize it
+builds a \i{binful} library (that is, a library that includes source files and
+therefore produces library binaries) while the upstream library is header-only,
+it is much easier to fix this by re-running \c{bdep-new} with the \c{binless}
+sub-option than by changing the \c{buildfiles} manually.
+
+\N|Don't be tempted to start making manual changes at this stage even if you
+cannot see anything else that can be fixed with a \c{bdep-new} re-run. This
+is still a dry-run and we will recreate the package one more time in the
+following section before starting manual adjustments.|
+
+Besides examining the generated \c{buildfiles}, it's also a good idea to
+build, test, and install the generated package to make sure everything ends up
+where you expected and matches upstream where necessary. In particular, make
+sure public headers are installed into the same location as upstream (unless
+you have decided to deviate, of course) or at least it's clear how to tweak
+the generated \c{buildfiles} to achieve this.
+
+\N|The \c{bdep-new}-generated library is a simple \"Hello, World!\" example
+that can nevertheless be built, tested, and installed. The idea here is to
+verify it matches upstream using the generated source files before replacing
+them with the upstream source file symlinks.
+
+If you are using Windows, then you will need to temporarily replace the
+\c{no-symexport} sub-option with \c{auto-symexport} in order to make the
+generated library buildable. But do not forget to drop this sub-option in
+the next step.|
+
+Note that at this stage it's easiest to build, test, and install in the source
+directory, skipping the \c{bdep} initialization of the package (which we would
+have to de-initialize before we can re-run \c{bdep-new}). Continue with the
+above example, the recommended sequence of commands would be:
+
+\
+$ cd libfoo/
+$ b update
+$ b test
+$ rm -rf /tmp/install
+$ b install config.install.root=/tmp/install
+$ b clean
+\
+
+\N|One relatively common case where the installation location may not match
+upstream are libraries that include their headers without the subdirectory
+prefix (for example, \c{<foo_util.h>} instead of \c{<foo/util.h>}). In such
+cases, in the \c{bdep-new} command, you want to use \i{prefix} rather that
+\i{source subdirectory} (with the latter being the default). For example:
+
+\
+$ bdep new --lib,no-subdir,prefix=foo ...
+\
+
+See \l{bdep-new.xhtml#src-layout SOURCE LAYOUT} for details.|
+
+Let's also briefly discuss other subdirectories and files found in the
+\c{bdep-new}-generated \c{libfoo} package.
+
+The \c{build/} subdirectory is the standard \c{build2} place for project-wide
+build system information (see \l{b#intro-proj-struct Project Structure} for
+details). We will look closer at its contents in the following sections.
+
+In the root directory of our package we find the root \c{buildfile} and
+package \c{manifest}. We will be tweaking both in the following steps. There
+is also \c{README.md} which we will replace with the upstream symlink.
+
+The \c{tests/} subdirectory is the standard \c{build2} tests subproject (see
+\l{b#intro-operations-test Testing} for background and details). While you can
+suppress its generation with the \c{no-tests} \c{bdep-new} sub-option, we
+recommend that you keep it and use it as a starting point for porting upstream
+tests or, if upstream doesn't provide any, for a basic \"smoke test\".
+
+\N|You can easily add/remove/rename this \c{tests/} subproject. The only place
+where it is mentioned explicitly and where you will need to make changes is
+the root \c{buildfile}. In particular, if upstream provides examples that you
+wish to port, it is recommended that you use a copy of the generated
+\c{tests/} subproject as a starting point (not forgetting to add the
+corresponding entry in the root \c{buildfile}).|
+
+
+\h2#core-package-create|Create final package|
+
+If you are satisfied with the \c{bdep-new} command line and there are no more
+automatic adjustments you can squeeze out of it, then it's time to re-run
+\c{bdep-new} one last time to create the final package.
+
+\N|While redoing this step later will require more effort, especially if
+you've made manual modifications to \c{buildfile} and \c{manifest}, nothing is
+set in stone and it can be done again by simply removing the package
+directory, removing (or editing, if you have multiple packages and only want
+to redo some of them) \c{packages.manifest}, and starting over.|
+
+This time, however, we will do things a bit differently in order to take
+advantage of some additional automation offered by \c{bdep-new}.
+
+Firstly, we will use the special \c{third-party} sub-option which is meant for
+converting third-party projects to \c{build2}. Specifically, this sub-option
+automatically enables \c{no-version} and \c{no-symexport} (unless
+\c{auto-symexport} is specified). It also adds a number of values to
+\c{manifest} that makes sense to specify in a package of a third-party
+project. Finally, it generates the \c{PACKAGE-README.md} template which
+describes how to use the package from a \c{build2}-based project (see the
+\l{bpkg#manifest-package-description \c{package-description}} \c{manifest}
+value for background).
+
+Secondly, if the package directory already exists and contains certain files,
+\c{bdep-new} can take this into account when generating the root \c{buildfile}
+and package \c{manifest}. In particular, it will try to guess the license from
+the \c{LICENSE} file and extract the summary from \c{README.md} and use this
+information in \c{manifest} as well as generated \c{PACKAGE-README.md}.
+
+\N|If the file names or formats used by upstream don't match those recognized
+by \c{bdep-new}, then for now simply omit the corresponding files from the
+package directory and add them later manually. Similarly, if an attempt to
+extract the information is unsuccessful, we will have a chance to adjust it in
+\c{manifest} later.
+
+Specifically, for \c{README}, \c{bdep-new} recognizes \c{README.md},
+\c{README.txt} and \c{README} but will only attempt to extract the summary
+from \c{README.md}.
+
+For license files, \c{bdep-new} recognizes \c{LICENSE}, \c{LICENSE.txt}
+\c{LICENSE.md}, \c{COPYING}, and \c{UNLICENSE}.
+
+For changes-related files, \c{bdep-new} recognizes \c{NEWS}, \c{CHANGES}, and
+\c{CHANGELOG} in various cases as well as with the \c{.md}, \c{.txt}
+extensions.|
+
+Continuing with our \c{libfoo} example and assuming upstream provides the
+\c{README.md}, \c{LICENSE}, and \c{NEWS} files, we first manually create the
+package directory, then add the symlinks, and finally run \c{bdep-new} (notice
+that we have replaced \c{no-version} and \c{no-symexport} with \c{third-party}
+and omitted the package name from the \c{bdep-new} command line since we are
+running from inside the package directory):
+
+\
+$ cd foo/ # Change to the package repository root.
+
+$ rm -r libfoo/ packages.manifest
+$ mkdir libfoo/
+
+$ cd libfoo/ # Change to the package root.
+$ ln -s ../upstream/README.md ./
+$ ln -s ../upstream/LICENSE ./
+$ ln -s ../upstream/NEWS ./
+
+$ bdep new --package \
+ --lang c++,cpp \
+ --type lib,split,subdir=foo,no-subdir-source,third-party
+\
+
+The final contents of our package will look like this (\c{->} denotes a
+symlink):
+
+\
+$ cd ../
+$ tree libfoo/
+libfoo/
+├── build/
+│   └── ...
+├── include/
+│   └── foo/
+│   ├── buildfile
+│   └── foo.hpp
+├── src/
+│   ├── buildfile
+│   └── foo.cpp
+├── tests/
+│   ├── build/
+│   │   └── ...
+│   ├── basics/
+│   │   ├── buildfile
+│   │   └── driver.cpp
+│   └── buildfile
+├── buildfile
+├── manifest
+├── NEWS -> ../upstream/NEWS
+├── LICENSE -> ../upstream/LICENSE
+├── README.md -> ../upstream/README.md
+└── PACKAGE-README.md
+\
+
+If auto-detection of \c{README}, \c{LICENSE}, and \c{NEWS} succeeds, then you
+should see the \c{summary} and \c{license} values automatically populated in
+\c{manifest} and the symlinked files listed in the root \c{buildfile}.
+
+
+\h2#core-package-adjust-version|Adjust package version|
+
+While adjusting the \c{bdep-new}-generated code is the subject of the
+following sections, one tweak that we want to make right away is to change the
+package version in the \c{manifest} file.
+
+In this guide we will assume the upstream package uses semver (semantic
+version) or semver-like (that is, has three version components) and will rely
+on the \i{continuous versioning} feature of \c{build2} to make sure that each
+commit in our package repository has a distinct version (see
+\l{intro#guide-versioning-releasing Versioning and Release Management} for
+background).
+
+\N|If upstream does not use semver, then see
+\l{https://github.com/build2/HOWTO/blob/master/entries/handle-projects-which-dont-use-semver.md
+How do I handle projects that don't use semantic versioning?} and
+\l{https://github.com/build2/HOWTO/blob/master/entries/handle-projects-which-dont-use-version.md
+How do I handle projects that don't use versions at all?} for available
+options. If you decide to use the non-semver upstream version as is, then you
+will have to forgo \i{continuous versioning} as well as the use of
+\l{bdep-release(1)} for release management. The rest of the guide, however,
+will still apply. In particular, you will still be able to use \l{bdep-ci(1)}
+and \l{bdep-publish(1)} with a bit of extra effort.|
+
+The overall plan to implement continuous versioning is to start with a
+pre-release snapshot of the upstream version, keep it like that while we are
+adjusting the \c{bdep-new}-generated package and committing our changes (at
+which point we get distinct snapshot versions), and finally, when the package
+is ready to publish, change to the final upstream version with the help of
+\l{bdep-release(1)}. Specifically, if the upstream version is
+\c{\i{X}.\i{Y}.\i{Z}}, then we start with the \c{\i{X}.\i{Y}.\i{Z}-a.0.z}
+pre-release snapshot.
+
+\N|In continuous versioning \c{\i{X}.\i{Y}.\i{Z}-a.0.z} means a snapshot after
+the (non-existent) \c{0}th alpha pre-release of the \c{\i{X}.\i{Y}.\i{Z}}
+version. See \l{intro#guide-versioning-releasing Versioning and Release
+Management} for a more detailed explanation and examples.|
+
+Let's see how this works for our \c{libfoo} example. Say, the upstream version
+that we are packaging is \c{2.1.0}. This means we start with \c{2.1.0-a.0.z}.
+
+\N|Naturally, the upstream version that we are using should correspond to the
+commit of the \c{upstream} submodule we have added in the
+\l{#core-repo-submodule Add upstream repository as \c{git} submodule} step.|
+
+Next we edit the \c{manifest} file in the \c{libfoo} package and change the
+\c{version} value to read:
+
+\
+version: 2.1.0-a.0.z
+\
+
+Let's also commit this initial state of the package for easier rollbacks:
+
+\
+$ cd foo/ # Change to the package repository root.
+$ git add .
+$ git status
+$ git commit -m \"Initialize package\"
+\
+
+
+\h#core-fill|Fill package with source code and add dependencies|
+
+With the package skeleton ready, the next steps are to fill it with upstream
+source code, add dependencies, and make any necessary manual adjustments to
+the generated \c{buildfiles}, \c{manifest}, etc. If we do this all at once,
+however, it can be hard to pin-point the cause of build failures. For example,
+if we convert both the library and its tests right away and something doesn't
+work, it can be hard to determine whether the mistake is in the library or in
+the tests. As a result, we are going to split this work into a sequence or
+smaller steps that incrementally replace the \c{bdep-new}-generated code with
+upstream while allowing us to test each change individually. We will also
+commit the changes on each step for easy rollbacks. Specifically, the overall
+plan is as follows:
+
+\ol|
+
+\li|Initialize (\c{bdep-init}) the package in one or more build configurations.|
+
+\li|Add dependencies, if any.|
+
+\li|Fill the library with upstream source code.|
+
+\li|Adjust project-wide and source subdirectory \c{buildfiles}.|
+
+\li|Make a smoke test for the library.|
+
+\li|Replace the smoke test with upstream tests.|
+
+\li|Tweak root \c{buildfile} and \c{manifest}.||
+
+The first three steps are the subject of this section with the following
+sections covering the rest of the plan.
+
+\N|As you become more experienced with packaging third-party projects for
+\c{build2}, it may make sense to start combining or omitting some steps,
+especially for simpler libraries. For example, if you see that a library
+comes with a simple test that shouldn't cause any complications, then you
+could omit the smoke test.|
+
+
+\h2#core-fill-init|Initialize package in build configurations|
+
+Before we start making any changes to the \c{bdep-new}-generated files, let's
+initialize the package in at least one build configuration so that we are able
+to build and test our changes (see \l{intro#guide Getting Started Guide} for
+background on \c{bdep}-based development workflow). Continuing with our
+\c{libfoo} example from the earlier steps:
+
+\
+$ cd foo/ # Change to the package repository root.
+$ bdep init -C ../foo-gcc @gcc cc config.cxx=g++
+\
+
+\N|If you are initializing subsequent packages in the already created
+configuration, then the command line will be just:
+
+\
+$ bdep init @gcc
+\
+
+|
+
+Let's build and test the \c{bdep-new}-generated package to make sure
+everything is in order:
+
+\
+$ bdep update
+$ bdep test
+$ bdep clean
+\
+
+You can create additional configurations, for example, if you have access to
+several compilers. For instance, to create a build configuration for Clang:
+
+\
+$ bdep init -C ../foo-clang @clang cc config.cxx=clang++
+\
+
+If you would like to perform a certain operation on all the build
+configurations, pass the \c{-a|--all} flag to \c{bdep}:
+
+\
+$ bdep update -a
+$ bdep test -a
+$ bdep clean -a
+\
+
+Let's also verify that the resulting package repository is clean (doesn't have
+any uncommitted or untracked files):
+
+\
+$ git status
+\
+
+\h2#core-fill-depend|Add dependencies|
+
+If the upstream project has any dependencies, now is a good time to specify
+them so that when we attempt to build the upstream source code, they are
+already present.
+
+Identifying whether the upstream project has dependencies is not always easy.
+The natural first places to check are the documentation and the existing build
+system. Sometimes projects also bundle their dependencies with the project
+source code (also called vendoring). So it makes sense to look around the
+upstream repository for anything that looks like bundled dependencies.
+Normally we would need to \"unbundle\" such dependencies when converting to
+\c{build2} by instead specifying a dependency on an external package (see
+\l{#dont-bundle Don't bundle dependencies} for background).
+
+\N|While there are several reasons we insist on unbundling of dependencies,
+the main one is that bundling can cause multiple, potentially conflicting
+copies of the same dependency to exist in the build. This can cause subtle
+build failures that are hard to understand and track down.|
+
+One particularly common case to check for is bundling of the testing
+framework, such as \l{https://cppget.org/catch2 \c{catch2}}, by C++
+projects. If you have identified that the upstream tests depend on a testing
+framework (whether bundled or not), see
+\l{https://github.com/build2/HOWTO/blob/master/entries/handle-tests-with-extra-dependencies.md
+How do I handle tests that have extra dependencies?} for the recommended
+way to deal with that.
+
+\N|One special type of dependency which is easy to overlook is between
+packages in the same package repository. For example, if we were packaging
+both \c{libfoo} as well as the \c{foo} executable that depends on it, then the
+\c{foo} package has a dependency on \c{libfoo} and it must be specified. In
+this case we don't need to add anything to \c{repositories.manifest} and in
+the \c{depends} entry (see below) in \c{foo}'s \c{manifest} we will normally
+use the special \c{==\ $} version constraint, meaning \c{libfoo} should have
+the same version as \c{foo} (see the \l{bpkg#manifest-package-depends
+\c{depends} package \c{manifest} value} for details). For example:
+
+\
+depends: libfoo == $
+\
+
+|
+
+If you have concluded that the upstream project doesn't have any dependencies,
+then you can remove \c{repositories.manifest} from the package repository root
+(unless you have already done so), commit this change, and skip the rest of
+this section.
+
+And if you are still reading, then we assume you have a list of dependencies
+you need to add, preferably with their minimum required versions. If you could
+not identify the minimum required version for a dependency, then you can
+fallback to the latest available version, as will be described in a moment.
+
+With the list of dependencies in hand, the next step is to determine whether
+they are already available as \c{build2} packages. For that, head over to
+\l{https://cppget.org cppget.org} and search for each dependency.
+
+If you are unable to find a package for a dependency, then it means it hasn't
+been packaged for \c{build2} yet. Check the places mentioned in the
+\l{#core-repo-exists Check if package repository already exists} step to see
+if perhaps someone is already working on the package. If not and the
+dependency is not optional, then the only way forward is to first package
+the dependency.
+
+If you do find a package for a dependency, then note the section of the
+repository (\c{stable}, \c{testing}, etc; see \l{intro#guide-repositories
+Package Repositories} for background) from which the minimum required version
+of the package is available. If you were unable to identify the minimum
+required version, then note the latest version available from the \c{stable}
+section.
+
+Given the list of repository sections, edit the \c{repositories.manifest} file
+in the package repository root and uncomment the entry for \c{cppget.org}:
+
+\
+:
+role: prerequisite
+location: https://pkg.cppget.org/1/stable
+#trust: ...
+\
+
+Next, replace \c{stable} at the end of the \c{location} value with the least
+stable section from your list. For example, if your list contains \c{stable},
+\c{testing}, and \c{beta}, then you need \c{beta} (the sections form a
+hierarchy and so \c{beta} includes \c{testing} which in turn includes
+\c{stable}).
+
+\N|If you wish, you can also uncomment the \c{trust} value and replace \c{...}
+with the \l{https://cppget.org/?about repository fingerprint}. This way you
+won't be prompted to confirm the repository authenticity on the first
+fetch. See \l{intro#guide-add-remove-deps Adding and Removing Dependencies}
+for details.|
+
+Once this is done, edit \c{manifest} in package root and add the \c{depends}
+value for each dependency. See \l{intro#guide-add-remove-deps Adding and
+Removing Dependencies} for background. In particular, here you will use the
+minimum required version (or the latest available) to form a version
+constraint. Which constraint operator to use will depend on the dependency's
+versioning policies. If the dependency uses semver, then a \c{^}-based
+constraint is a sensible default.
+
+As an example, let's say our \c{libfoo} depends on \c{libz}, \c{libasio}, and
+\c{libsqlite3}. To specify these dependencies we would add the following
+entries to its \c{manifest}:
+
+\
+depends: libz ^1.2.0
+depends: libasio ^1.28.0
+depends: libsqlite3 ^3.39.4
+\
+
+With all the dependencies specified, let's now synchronize the state of the
+build configurations with our changes by running \l{bdep-sync(1)} from the
+package repository root:
+
+\
+$ bdep sync -a
+\
+
+This command should first fetch the metadata for the repository we specified
+in \c{repositories.manifest} and then fetch, unpack and configure each
+dependency that we specified in \c{manifest}.
+
+\N|If you have any build-time dependencies (see
+\l{intro#guide-build-time-linked Build-Time Dependencies and Linked
+Configurations} for background), then you will get a warning about the
+corresponding \c{config.import.*} variable being unused and therefore
+dropped. This is because we haven't yet added the corresponding \c{import}
+directives to our \c{buildfiles}. For now you can ignore this warning, which
+we will fix later, when we adjust the generated \c{buildfiles}.|
+
+We can examine the resulting state, including the version of each dependency,
+with \l{bdep-status(1)}:
+
+\
+$ bdep status -ai
+\
+
+The last step for this section is to commit our changes:
+
+\
+$ cd foo/ # Change to the package repository root.
+$ git add .
+$ git status
+$ git commit -m \"Add dependencies\"
+\
+
+
+\h2#core-fill-source|Fill with upstream source code|
+
+Now we are ready to begin replacing the \c{bdep-new}-generated files with
+upstream source code symlinks. We start with the library's header and source
+files. Continuing with our \c{libfoo} example, this is what we currently have
+(notice that \c{LICENSE}, \c{README.md}, and \c{NEWS} are already symlinks to
+upstream):
+
+\
+$ cd foo/ # Change to the package repository root.
+
+$ tree libfoo/
+libfoo/
+├── build/
+│   └── ...
+├── include/
+│   └── foo/
+│   ├── buildfile
+│   └── foo.hpp
+├── src/
+│   ├── buildfile
+│   └── foo.cpp
+├── tests/
+│   └── ...
+├── buildfile
+├── manifest
+├── NEWS -> ../upstream/NEWS
+├── LICENSE -> ../upstream/LICENSE
+├── README.md -> ../upstream/README.md
+└── PACKAGE-README.md
+\
+
+Now we replace generated \c{include/foo/foo.hpp} with the library's real
+headers and \c{src/foo.cpp} with its real source files:
+
+\
+$ cd libfoo/ # Change to the package root.
+
+$ cd include/foo/
+$ rm foo.hpp
+$ ln -s ../../../upstream/include/foo/*.hpp ./
+$ cd -
+
+$ cd src/
+$ rm foo.cpp
+$ ln -s ../../upstream/src/*.hpp ./
+$ ln -s ../../upstream/src/*.cpp ./
+$ cd -
+
+$ tree libfoo/
+libfoo/
+├── build/
+│   └── ...
+├── include/
+│   └── foo/
+│   ├── buildfile
+│   ├── core.hpp -> ../../../upstream/include/foo/core.hpp
+│   └── util.hpp -> ../../../upstream/include/foo/util.hpp
+├── src/
+│   ├── buildfile
+│   ├── impl.hpp -> ../../upstream/src/impl.hpp
+│   ├── core.cpp -> ../../upstream/src/core.cpp
+│   └── util.cpp -> ../../upstream/src/util.cpp
+├── tests/
+│   └── ...
+└── ...
+\
+
+Note that the wildcards used above may not be enough in all situations and
+it's a good idea to manually examine the relevant upstream directories and
+make sure nothing is missing. Specifically, look out for:
+
+\ul|
+
+\li|Header/sources with other extensions, for example, C, Objective-C, etc.|
+
+\li|Other files that may be needed, for example, \c{.def}, \c{config.h.in}, etc.|
+
+\li|Subdirectories that contain more header/source files.||
+
+If upstream contains subdirectories with additional header/source files, then
+you can symlink entire subdirectories instead of doing it file by file. For
+example, let's say \c{libfoo}'s upstream source directory contains the
+\c{impl/} subdirectory with additional source files:
+
+\
+$ cd src/
+$ ln -s ../../upstream/impl ./
+$ cd -
+
+$ tree libfoo/
+libfoo/
+├── build/
+│   └── ...
+├── include/
+│   └── ...
+├── src/
+│   ├── impl/ -> ../../upstream/src/impl/
+│   │   ├── bar.cpp
+│   │   └── baz.cpp
+│   ├── buildfile
+│   ├── impl.hpp -> ../../upstream/src/impl.hpp
+│   ├── core.cpp -> ../../upstream/src/core.cpp
+│   └── util.cpp -> ../../upstream/src/util.cpp
+├── tests/
+│   └── ...
+└── ...
+\
+
+Wouldn't it be nice if we could symlink the entire top-level subdirectories
+(\c{include/foo/} and \c{src/} in our case) instead of symlinking individual
+files? As discussed in \l{#core-package-craft-cmd Craft \c{bdep new} command
+line to create package}, we can, but we will need to change the package
+layout. Specifically, we will need to move the \c{buildfiles} out of the
+source subdirectories with the help of the \c{buildfile-in-prefix} sub-option
+of \c{bdep-new}. In the above case, we will also need to invent a source
+subdirectory in \c{src/}. Whether this is a worthwhile change largely depends
+on how many files you have to symlink individually. If it's just a handful,
+then it's probably not worth the complication, especially if you have to
+invent source subdirectories. On the other hand, if you are looking at
+symlinking hundreds of files, changing the layout makes perfect sense.
+
+\N|One minor drawback of symlinking entire directories is that you cannot
+easily patch individual upstream files (see \l{#howto-patch-upstream-source
+How do I patch upstream source code?}).
+
+You will also need to explicitly list such directories as symlinks in
+\c{.gitattributes} if you want your package to be usable from the \c{git}
+repository directly on Windows. See
+\l{https://build2.org/article/symlinks.xhtml#windows Symlinks and Windows} for
+details.|
+
+We won't be able to test this change yet because to make things build we will
+most likely also need to tweak the generated \c{buildfiles}, which is the
+subject of the next section. However, it still makes sense to commit our
+changes to make rollbacks easier:
+
+\
+$ cd foo/ # Change to the package repository root.
+$ git add .
+$ git status
+$ git commit -m \"Add upstream source symlinks\"
+\
+
+
+\h#core-adjust-build|Adjust project-wide and source \c{buildfiles}|
+
+With source code and dependencies added, the next step is to adjust the
+regenerated \c{buildfiles} that build the library. This involves two places:
+the project-wide build system files in \c{build/} and the source subdirectory
+\c{buildfiles} (in \c{include/} and \c{src/} for our \c{libfoo} example).
+
+
+\h2#core-adjust-build-wide|Adjust project-wide build system files in \c{build/}|
+
+We start with reviewing and adjusting the files in the \c{build/} subdirectory
+of our package, where you will find three files:
+
+\
+$ cd foo/ # Change to the package repository root.
+$ tree libfoo/
+libfoo/
+├── build/
+│   ├── bootstrap.build
+│   ├── root.build
+│   └── export.build
+└── ...
+\
+
+
+To recap, the first two contain the project-wide build system setup (see
+\l{b#intro-proj-struct Project Structure} for details) while the last is an
+export stub that facilitates the importation of targets from our package (see
+\l{b#intro-import Target Importation} for details).
+
+Normally you don't need to change anything in \c{bootstrap.build} \- all it
+does is specify the build system project name and load a standard set of core
+build system modules. Likewise, \c{export.build} is ok as generated unless you
+need to do something special, like exporting targets from different
+subdirectories of your package.
+
+While \c{root.build} is also often good as is, situations where you may
+need to tweak it are not uncommon and include:
+
+\ul|
+
+\li|Loading an additional build system module.
+
+ For example, if your package makes use of Objective-C/C++ (see \l{b#c-objc
+ Objective-C Compilation} and \l{b#cxx-objcxx Objective-C++ Compilation})
+ or Assembler (see \l{b#c-as-cpp Assembler with C Preprocessor
+ Compilation}), then \c{root.build} would be the natural place to load the
+ corresponding modules.
+
+ \N|If your package uses a mixture of C and C++, then it's recommended to
+ set this up using the \c{--lang} sub-option of \c{bdep-new} rather
+ than manually. For example:
+
+ \
+ $ bdep new --lang c++,c ...
+ \
+
+ ||
+
+\li|Specifying package configuration variables.
+
+ If upstream provides the ability to configure their code, for example to
+ enable optional features, then you may want to translate this to
+ \c{build2} configuration variables, which are specified in \c{root.build}
+ (see \l{b#proj-config Project Configuration} for background and details).
+
+ Note that you don't need to add all the configuration variables right
+ away. Instead, you could first handle the \"core\" functionality which
+ doesn't require any configuration and then add the configuration variables
+ one by one while also making the corresponding changes in \c{buildfiles}.
+
+ \N|One type of configuration that you should normally not expose when
+ packaging for \c{build2} is support for both header-only and compiled
+ modes. See \l{b#dont-header-only Don't make library header-only if it
+ can be compiled} for details.|||
+
+Also, in C++ projects, if you don't have any inline or template files, then
+you can drop the assignment of the file extension for the \c{ixx{\}} and
+\c{txx{\}} target types, respectively.
+
+If you have added any configuration variables and would like to use
+non-default values for some of them in your build, then you will need to
+reconfigure the package. For example, let's say we have added the
+\c{config.libfoo.debug} variable to our \c{libfoo} package which enables
+additional debugging facilities in the library. This is how we can reconfigure
+all our builds to enable this functionality:
+
+\
+$ bdep sync -a config.libfoo.debug=true
+\
+
+If you have made any changes, commit them (similar to the previous step, we
+cannot test things just yet):
+
+\
+$ cd foo/ # Change to the package repository root.
+$ git add .
+$ git status
+$ git commit -m \"Adjust project-wide build system files\"
+\
+
+
+\h2#core-adjust-build-src|Adjust source subdirectory \c{buildfiles}|
+
+The last step we need to perform before we can try to build our library is to
+adjust its \c{buildfiles}. These \c{buildfiles} are found in the source
+subdirectory or, if we used the \c{buildfile-in-prefix} \c{bdep-new}
+sub-option, in the prefix directory. There will be two \c{buildfiles} if we
+use the split layout (\c{split} sub-option) or a single \c{buildfile} in the
+combined layout. The single \c{buildfile} in the combined layout contains
+essentially the same definitions as the split \c{buildfiles} but combined into
+one and with some minor simplifications that this allows. Here we will assume
+the split layout and continue with our \c{libfoo} from the previous
+sections. To recap, here is the layout we've got with the \c{buildfiles} of
+interest found in \c{include/foo/} and in \c{src/}:
+
+\
+libfoo/
+├── build/
+│   └── ...
+├── include/
+│   └── foo/
+│   ├── buildfile
+│   ├── core.hpp -> ../../../upstream/include/foo/core.hpp
+│   └── util.hpp -> ../../../upstream/include/foo/util.hpp
+├── src/
+│   ├── buildfile
+│   ├── impl.hpp -> ../../upstream/src/impl.hpp
+│   ├── core.cpp -> ../../upstream/src/core.cpp
+│   └── util.cpp -> ../../upstream/src/util.cpp
+├── tests/
+│   └── ...
+└── ...
+\
+
+\N|If instead of a library you are packaging an executable, you can skip
+directly to \l{#core-adjust-build-src-source-exe Adjust source \c{buildfile}:
+executables}.|
+
+
+\h2#core-adjust-build-src-header|Adjust header \c{buildfile}|
+
+The \c{buildfile} in \c{include/foo/} is pretty simple:
+
+\N|The \c{buildfile} in your package may look slightly different, depending on
+the exact \c{bdep-new} sub-options used. However, all the relevant definitions
+discussed below should still be easily recognizable.|
+
+\
+pub_hdrs = {hxx ixx txx}{**}
+
+./: $pub_hdrs
+
+# Install into the foo/ subdirectory of, say, /usr/include/
+# recreating subdirectories.
+#
+{hxx ixx txx}{*}:
+{
+ install = include/foo/
+ install.subdirs = true
+}
+\
+
+Normally, the only change that you would make to this \c{buildfile} is to
+adjust the installation location of headers (see \l{b#intro-operations-install
+Installing} for background). In particular, if our headers were included
+without the \c{<foo/...>} prefix but instead contained the library name in
+their names (for example, \c{foo-util.hpp}), then the installation setup would
+instead look like this:
+
+\
+# Install directly into say, /usr/include/ recreating subdirectories.
+#
+{hxx ixx txx}{*}:
+{
+ install = include/
+ install.subdirs = true
+}
+\
+
+If the library doesn't have any headers in nested subdirectories (for example,
+\c{<foo/util/string.hpp>}), you can drop the \c{install.subdirs} variable:
+
+\
+# Install into the foo/ subdirectory of, say, /usr/include/.
+#
+{hxx ixx txx}{*}: install = include/foo/
+\
+
+\N|In the combined layout, the installation-related definitions are at the end
+of the combined \c{buildfile}.
+
+Compared to the split layout where the public and private headers are
+separated physically, in the combined layout you may need to achieve the same
+result (that is, avoid installing private headers) at the build system
+level. If the library provides only a handful of public headers and this set
+is unlikely to change often, then listing them explicitly is the most
+straightforward approach. For example (the \c{@./} qualifier tells \c{build2}
+they are in the source directory):
+
+\
+# Only install public headers into, say, /usr/include/.
+#
+h{foo}@./ h{foo_version}@./: install = include/
+h{*}: install = false
+\
+
+|
+
+See also \l{#howto-extra-header-install-subdir How do I handle extra header
+installation subdirectory?}
+
+
+\h2#core-adjust-build-src-source|Adjust source \c{buildfile}: overview|
+
+Next is the \c{buildfile} in \c{src/}:
+
+\N|Again, the \c{buildfile} in your package may look slightly different,
+depending on the exact \c{bdep-new} sub-options used. However, all the
+relevant definitions discussed below should still be easily recognizable.
+
+For a binless (header-only) library, this \c{buildfile} will contain only a
+small subset of the definitions shown below. See
+\l{https://github.com/build2/HOWTO/blob/master/entries/make-header-only-library.md
+How do I make a header-only C/C++ library?} for additional considerations when
+packaging header-only libraries.|
+
+\
+intf_libs = # Interface dependencies.
+impl_libs = # Implementation dependencies.
+#import xxxx_libs += libhello%lib{hello}
+
+# Public headers.
+#
+pub = [dir_path] ../include/foo/
+
+include $pub
+
+pub_hdrs = $($pub/ pub_hdrs)
+
+lib{foo}: $pub/{$pub_hdrs}
+
+# Private headers and sources as well as dependencies.
+#
+lib{foo}: {hxx ixx txx cxx}{**} $impl_libs $intf_libs
+
+# Build options.
+#
+out_pfx_inc = [dir_path] $out_root/include/
+src_pfx_inc = [dir_path] $src_root/include/
+out_pfx_src = [dir_path] $out_root/src/
+src_pfx_src = [dir_path] $src_root/src/
+
+cxx.poptions =+ \"-I$out_pfx_src\" \"-I$src_pfx_src\" \
+ \"-I$out_pfx_inc\" \"-I$src_pfx_inc\"
+
+#obja{*}: cxx.poptions += -DFOO_STATIC_BUILD
+#objs{*}: cxx.poptions += -DFOO_SHARED_BUILD
+
+# Export options.
+#
+lib{foo}:
+{
+ cxx.export.poptions = \"-I$out_pfx_inc\" \"-I$src_pfx_inc\"
+ cxx.export.libs = $intf_libs
+}
+
+#liba{foo}: cxx.export.poptions += -DFOO_STATIC
+#libs{foo}: cxx.export.poptions += -DFOO_SHARED
+
+# For pre-releases use the complete version to make sure they cannot
+# be used in place of another pre-release or the final version. See
+# the version module for details on the version.* variable values.
+#
+if $version.pre_release
+ lib{foo}: bin.lib.version = \"-$version.project_id\"
+else
+ lib{foo}: bin.lib.version = \"-$version.major.$version.minor\"
+
+# Don't install private headers.
+#
+{hxx ixx txx}{*}: install = false
+\
+
+
+\h2#core-adjust-build-src-source-clean|Adjust source \c{buildfile}: cleanup|
+
+As a first step, let's remove all the definitions that we don't need in our
+library. The two common pieces of functionality that are often not needed
+are support for auto-generated headers (such as \c{config.h} generated from
+\c{config.h.in}) and dependencies on other libraries.
+
+If you don't have any auto-generated headers, then remove all the assignments
+and expansions of the \c{out_pfx_inc} and \c{out_pfx_src} variables. Here
+is what the relevant lines in the above \c{buildfile} should look like after
+this change:
+
+\
+# Build options.
+#
+src_pfx_inc = [dir_path] $src_root/include/
+src_pfx_src = [dir_path] $src_root/src/
+
+cxx.poptions =+ \"-I$src_pfx_src\" \"-I$src_pfx_inc\"
+
+# Export options.
+#
+lib{foo}:
+{
+ cxx.export.poptions = \"-I$src_pfx_inc\"
+}
+\
+
+\N|If you do have auto-generated headers, then in the split layout you can
+remove \c{out_pfx_inc} if you only have private auto-generated headers and
+\c{out_pfx_src} if you only have public ones.|
+
+\N|In the combined layout the single \c{buildfile} does not set the
+\c{*_pfx_*} variables. Instead it uses the \c{src_root} and \c{out_root}
+variables directly. For example:
+
+\
+# Build options.
+#
+cxx.poptions =+ \"-I$out_root\" \"-I$src_root\"
+
+# Export options.
+#
+lib{foo}:
+{
+ cxx.export.poptions = \"-I$out_root\" \"-I$src_root\"
+}
+\
+
+To remove support for auto-generated headers in the combined \c{buildfile},
+simply remove the corresponding \c{out_root} expansions:
+
+\
+# Build options.
+#
+cxx.poptions =+ \"-I$src_root\"
+
+# Export options.
+#
+lib{foo}:
+{
+ cxx.export.poptions = \"-I$src_root\"
+}
+\
+
+If you only have private auto-generated headers, then only remove the
+expansion from \c{cxx.export.poptions}.|
+
+If you don't have any dependencies, then remove all the assignments and
+expansions of the \c{intf_libs} and \c{intf_libs} variables. That is,
+the following lines in the original \c{buildfile}:
+
+\
+intf_libs = # Interface dependencies.
+impl_libs = # Implementation dependencies.
+#import xxxx_libs += libhello%lib{hello}
+
+# Private headers and sources as well as dependencies.
+#
+lib{foo}: {hxx ixx txx cxx}{**} $impl_libs $intf_libs
+
+# Export options.
+#
+lib{foo}:
+{
+ cxx.export.poptions = \"-I$out_pfx_inc\" \"-I$src_pfx_inc\"
+ cxx.export.libs = $intf_libs
+}
+\
+
+Become just these:
+
+\
+# Private headers and sources as well as dependencies.
+#
+lib{foo}: {hxx ixx txx cxx}{**}
+
+# Export options.
+#
+lib{foo}:
+{
+ cxx.export.poptions = \"-I$out_pfx_inc\" \"-I$src_pfx_inc\"
+}
+\
+
+
+\h2#core-adjust-build-src-source-dep|Adjust source \c{buildfile}: dependencies|
+
+If you do have dependencies, then let's handle them now.
+
+\N|Here we will assume dependencies on other libraries, which is the common
+case. If you have dependencies on executables, for example, source code
+generators, see \l{intro#guide-build-time-linked Build-Time Dependencies and
+Linked Configurations} on how to handle that. In this case you will also need
+to reconfigure your package after adding the corresponding \c{import}
+directives in order to re-acquire the previously dropped \c{config.import.*}
+values. Make sure to also pass any configuration variables you specified in
+\l{#core-adjust-build-wide Adjust project-wide build system files in
+\c{build/}}. For example:
+
+\
+$ bdep sync -a --disfigure config.libfoo.debug=true
+\
+
+|
+
+For each library that your package depends on (and which you have added
+to \c{manifest} in the \l{#core-fill-depend Add dependencies} step),
+you need to first determine whether it's an interface of implementation
+dependency and then import it either into the \c{intf_libs} or \c{impl_libs}
+variable, respectively.
+
+See \l{b#intro-lib Library Exportation and Versioning} for background on the
+interface vs implementation distinction. But as a quick rule of thumb, if the
+library you are packaging includes a header from the dependency library in one
+of its public headers, then it's an interface dependency. Otherwise, it's an
+implementation dependency.
+
+Continuing with our \c{libfoo} example, as we have established in
+\l{#core-fill-depend Add dependencies}, it depends on \c{libasio}, \c{libz},
+and \c{libsqlite3} and let's say we've determined that \c{libasio} is an
+interface dependency because it's included from \c{include/foo/core.hpp} while
+the other two are implementation dependencies because they are only included
+from \c{src/}. Here is how we would change our \c{buildfile} to import them:
+
+\
+intf_libs = # Interface dependencies.
+impl_libs = # Implementation dependencies.
+import intf_libs += libasio%lib{asio}
+import impl_libs += libz%lib{z}
+import impl_libs += libsqlite3%lib{sqlite3}
+\
+
+You can tidy this a bit further if you would like:
+
+\
+import intf_libs = libasio%lib{asio}
+import impl_libs = libz%lib{z}
+import impl_libs += libsqlite3%lib{sqlite3}
+\
+
+\N|If you don't have any implementation or interface dependencies, you can
+remove the assignment and all the expansion of the corresponding \c{*_libs}
+variable.|
+
+Note also that system libraries like \c{-lm}, \c{-ldl} on UNIX or
+\c{advapi32.lib}, \c{ws2_32.lib} on Windows should not be imported. Instead,
+they should be listed in the \c{c.libs} or \c{cxx.libs} variables. See
+\l{https://github.com/build2/HOWTO/blob/master/entries/link-system-library.md
+How do I link a system library} for details.
+
+
+\h2#core-adjust-build-src-source-pub|Adjust source \c{buildfile}: public headers|
+
+With the unnecessary parts of the \c{buildfile} cleaned up and dependencies
+handled, let's discuss the common changes to the remaining definitions, going
+from top to bottom. We start with the public headers block:
+
+\
+# Public headers.
+#
+pub = [dir_path] ../include/foo/
+
+include $pub
+
+pub_hdrs = $($pub/ pub_hdrs)
+
+lib{foo}: $pub/{$pub_hdrs}
+\
+
+This block gets hold of the list of public headers and makes them
+prerequisites of the library. Normally you shouldn't need to make any changes
+here. If you need to exclude some headers, it should be done in the
+header \c{buildfile} in the \c{include/} directory.
+
+\N|In the combined layout the single \c{buildfile} does not have such code.
+Instead, all the headers are covered by the wildcard pattern in the following
+block.|
+
+
+\h2#core-adjust-build-src-source-src|Adjust source \c{buildfile}: sources, private headers|
+
+The next block deals with sources, private headers, and dependencies, if any:
+
+\
+# Private headers and sources as well as dependencies.
+#
+lib{foo}: {hxx ixx txx cxx}{**} $impl_libs $intf_libs
+\
+
+By default it will list all the relevant files as prerequisites of the
+library, starting from the directory of the \c{buildfile} and including all
+the subdirectories, recursively (see \l{b#name-patterns Name Patterns} for
+background on wildcard patterns).
+
+If your C++ package doesn't have any inline or template files, then you can
+remove the \c{ixx} and \c{txx} target types, respectively (which would be
+parallel to the change made in \c{root.build}; see \l{#core-adjust-build-wide
+Adjust project-wide build system files in \c{build/}}). For example:
+
+\
+# Private headers and sources as well as dependencies.
+#
+lib{foo}: {hxx cxx}{**} $impl_libs $intf_libs
+\
+
+\N|Source files other than C/C++ (for example, Assembler, Objective-C/C++) are
+dealt with in \l{#core-adjust-build-src-source-ext Adjust source
+\c{buildfile}: extra requirements} below.|
+
+The other common change to this block is the exclusion of certain files or
+making them conditionally included. As an example, let's say in our \c{libfoo}
+the source subdirectory contains a bunch of \c{*-test.cpp} files which are
+unit tests and should not be listed as prerequisites of a library. Here is how
+we can exclude them:
+
+\
+# Private headers and sources as well as dependencies.
+#
+lib{foo}: {hxx cxx}{** -**-test} $impl_libs $intf_libs
+\
+
+Let's also assume our \c{libfoo} contains \c{impl-win32.cpp} and
+\c{impl-posix.cpp} which provide alternative implementations of the same
+functionality for Windows and POSIX and therefore should only be included as
+prerequisites on the respective platforms. Here is how we can handle that:
+
+\
+# Private headers and sources as well as dependencies.
+#
+lib{foo}: {hxx cxx}{** -impl-win32 -impl-posix -**-test}
+lib{foo}: cxx{impl-win32}: include = ($cxx.target.class == 'windows')
+lib{foo}: cxx{impl-posix}: include = ($cxx.target.class != 'windows')
+lib{foo}: $impl_libs $intf_libs
+\
+
+There are two nuances in the above example worth highlighting. Firstly, we
+have to exclude the files from the wildcard pattern before we can
+conditionally include them. Secondly, we have to always link libraries
+last. In particular, the following is a shorter but an incorrect version of the
+above:
+
+\
+lib{foo}: {hxx cxx}{** -impl-win32 -impl-posix -**-test} \
+ $impl_libs $intf_libs
+lib{foo}: cxx{impl-win32}: include = ($cxx.target.class == 'windows')
+lib{foo}: cxx{impl-posix}: include = ($cxx.target.class != 'windows')
+\
+
+\N|You may also be tempted to use the \c{if} directive instead of the
+\c{include} variable for conditional prerequisites. For example:
+
+\
+if ($cxx.target.class == 'windows')
+ lib{foo}: cxx{impl-win32}
+else
+ lib{foo}: cxx{impl-posix}
+\
+
+This would also be incorrect. For background and details, see
+\l{https://github.com/build2/HOWTO/blob/master/entries/keep-build-graph-config-independent.md
+How do I keep the build graph configuration-independent?}|
+
+
+\h2#core-adjust-build-src-source-opt|Adjust source \c{buildfile}: build and export options|
+
+The next two blocks are the build and export options, which we will discuss
+together:
+
+\
+# Build options.
+#
+out_pfx_inc = [dir_path] $out_root/include/
+src_pfx_inc = [dir_path] $src_root/include/
+out_pfx_src = [dir_path] $out_root/src/
+src_pfx_src = [dir_path] $src_root/src/
+
+cxx.poptions =+ \"-I$out_pfx_src\" \"-I$src_pfx_src\" \
+ \"-I$out_pfx_inc\" \"-I$src_pfx_inc\"
+
+#obja{*}: cxx.poptions += -DFOO_STATIC_BUILD
+#objs{*}: cxx.poptions += -DFOO_SHARED_BUILD
+
+# Export options.
+#
+lib{foo}:
+{
+ cxx.export.poptions = \"-I$out_pfx_inc\" \"-I$src_pfx_inc\"
+ cxx.export.libs = $intf_libs
+}
+
+#liba{foo}: cxx.export.poptions += -DFOO_STATIC
+#libs{foo}: cxx.export.poptions += -DFOO_SHARED
+\
+
+The build options are in effect when the library itself is being built and the
+exported options are propagated to the library consumers (see \l{b#intro-lib
+Library Exportation and Versioning} for background on exported options). For
+now we will ignore the commented out lines that add \c{-DFOO_STATIC*} and
+\c{-DFOO_SHARED*} macros \- they are for symbol exporting and we will discuss
+this topic separately.
+
+If the library you are packaging only relied on platform-independent APIs,
+then chances are you won't need to change anything here. On the other hand, if
+it does anything platform-specific, then you will most likely need to add some
+options.
+
+As discussed in the \l{b#intro-dirs-scopes Output Directories and Scopes}
+section of the build system introduction, there is a number of variables that
+are used to specify compilation and linking options, such as \c{*.poptions}
+(\c{cxx.poptions} in the above example), \c{*.coptions}, etc. The below table
+shows all of them with their rough \c{make} equivalents in the third column:
+
+\
+*.poptions preprocess CPPFLAGS
+*.coptions compile CFLAGS/CXXFLAGS
+*.loptions link LDFLAGS
+*.aoptions archive ARFLAGS
+*.libs system libraries LIBS/LDLIBS
+\
+
+The recommended approach here is to study the upstream build system and copy
+custom compile/link options to the appropriate \c{build2} variables. Note,
+however, that doing it thoughtlessly/faithfully by copying all the options may
+not always be a good idea. See
+\l{https://github.com/build2/HOWTO/blob/master/entries/compile-options-in-buildfile.md
+Which C/C++ compile/link options are OK to specify in a project's buildfile?}
+for the guidelines.
+
+\N|If you are packaging a library that includes a large number of optional
+features, it may be unclear which of them would make sense to enable by
+default. The notorious example of this situation is
+\l{https://github.com/build2-packaging/sqlite \c{libsqlite3}} which provides
+hundreds of preprocessor macros to enable or tune various aspects of its
+functionality.
+
+The recommended approach in cases like this is to study the configuration of
+such a library in distributions like Debian and Fedora and use the same
+defaults. In particular, this will allow us to substitute the \c{build2}
+package with the system-installed version.|
+
+Oftentimes, custom options must only be specified for certain target platforms
+or when using a certain compiler. While \c{build2} provides a large amount of
+information to identify the build configuration as well as more advanced
+\c{buildfile} language mechanisms (such as \l{b#intro-switch Pattern
+Matching}) to make sense of it, this is a large topic for which we refer you
+to \l{b The \c{build2} Build System} manual. Additionally,
+\l{https://github.com/build2-packaging github.com/build2-packaging} now
+contains a large number of packages that you can study and search for
+examples.
+
+\N|While exporting preprocessor macros to communicate configuration is a
+fairly common technique, it has a number of drawbacks and limitations.
+Specifically, a large number of such macros will add a lot of noise to the
+consumer's compilation command lines (especially if multiple libraries indulge
+in this). Plus, the information conveyed by such macros is limited to simple
+values and is not easily accessible in consumer \c{buildfiles}.
+
+To overcome these drawbacks and limitations, \c{build2} provides a mechanism
+for conveying metadata with C/C++ libraries (and executables). See,
+\l{https://github.com/build2/HOWTO/blob/master/entries/convey-additional-information-with-exe-lib.md
+How do I convey additional information (metadata) with executables and C/C++
+libraries?} for details.
+
+Note that outright replacing the preprocessor macros with metadata can be done
+if this information is only used by the library consumers. In other words, if
+the library's public headers rely on the presence of such macros, then we have
+no choice but to export them, potentially also providing the metadata so that
+this information is easily accessible from \c{buildfiles}.|
+
+Let's consider a representative example based on our \c{libfoo} to get a sense
+of what this normally looks like as well as to highlight a few nuances. We
+will assume our \c{libfoo} requires either the \c{FOO_POSIX} or \c{FOO_WIN32}
+macro to be defined during the build in order to identify the target
+platform. Additionally, extra features can be enabled by defining
+\c{FOO_EXTRAS}, which should be done both during the build and for consumption
+(so this macro must also be exported). Next, this library requires the
+\c{-fno-strict-aliasing} compile option for the GCC-class compilers (GCC,
+Clang, etc). Finally, we need to link \c{pthread} on POSIX and \c{ws2_32.lib}
+on Windows. This is how we would work all this into the above fragment:
+
+\
+# Build options.
+#
+out_pfx_inc = [dir_path] $out_root/include/
+src_pfx_inc = [dir_path] $src_root/include/
+out_pfx_src = [dir_path] $out_root/src/
+src_pfx_src = [dir_path] $src_root/src/
+
+cxx.poptions =+ \"-I$out_pfx_src\" \"-I$src_pfx_src\" \
+ \"-I$out_pfx_inc\" \"-I$src_pfx_inc\"
+
+cxx.poptions += -DFOO_EXTRAS
+
+if ($cxx.target.class == 'windows')
+ cxx.poptions += -DFOO_WIN32
+else
+ cxx.poptions += -DFOO_POSIX
+
+#obja{*}: cxx.poptions += -DFOO_STATIC_BUILD
+#objs{*}: cxx.poptions += -DFOO_SHARED_BUILD
+
+if ($cxx.class == 'gcc')
+ cxx.coptions += -fno-strict-aliasing
+
+switch $cxx.target.class, $cxx.target.system
+{
+ case 'windows', 'mingw32'
+ cxx.libs += -lws2_32
+ case 'windows'
+ cxx.libs += ws2_32.lib
+ default
+ cxx.libs += -pthread
+}
+
+# Export options.
+#
+lib{foo}:
+{
+ cxx.export.poptions = \"-I$out_pfx_inc\" \"-I$src_pfx_inc\" -DFOO_EXTRAS
+ cxx.export.libs = $intf_libs
+}
+
+#liba{foo}: cxx.export.poptions += -DFOO_STATIC
+#libs{foo}: cxx.export.poptions += -DFOO_SHARED
+\
+
+There are a few nuances in the above code worth keeping in mind. Firstly,
+notice that we append (rather than assign) to all the non-export variables
+(\c{*.poptions}, \c{*.coptions}, \c{*.libs}). This is because they may already
+contain some values specified by the user with their \c{config.*.*}
+counterparts. On the other hand, the \c{*.export.*} variables are assigned.
+
+Secondly, the order in which we append to the variables is important for the
+value to accumulate correctly. You want to first append all the scope-level
+values, then target type/pattern-specific, and finally any target-specific;
+that is, from more general to more specific (see \l{b#intro-lang Buildfile
+Language} for background). To illustrate this point, let's say in our
+\c{libfoo}, the \c{FOO_POSIX} or \c{FOO_WIN32} macro are only necessary when
+compiling \c{util.cpp}. Below would be the correct order of assigning to
+\c{cxx.poptions}:
+
+\
+cxx.poptions =+ \"-I$out_pfx_src\" \"-I$src_pfx_src\" \
+ \"-I$out_pfx_inc\" \"-I$src_pfx_inc\"
+
+cxx.poptions += -DFOO_EXTRAS
+
+#obja{*}: cxx.poptions += -DFOO_STATIC_BUILD
+#objs{*}: cxx.poptions += -DFOO_SHARED_BUILD
+
+if ($cxx.target.class == 'windows')
+ {obja objs}{util}: cxx.poptions += -DFOO_WIN32
+else
+ {obja objs}{util}: cxx.poptions += -DFOO_POSIX
+\
+
+\N|Not that target-specific \c{*.poptions} and \c{*.coptions} must be
+specified on the object file targets while \c{*.loptions} and \c{*.libs} \- on
+the library or executable targets.|
+
+
+\h2#core-adjust-build-src-source-sym|Adjust source \c{buildfile}: symbol exporting|
+
+Let's now turn to a special sub-topic of the build and export options that
+relates to the shared library symbol exporting. To recap, a shared library on
+Windows must explicitly specify the symbols (functions and global data) that
+it wishes to make accessible by its consumers (executables and other shared
+libraries). This can be achieved in three different ways: The library can
+explicitly mark in its source code the names whose symbols should be
+exported. Alternatively, the library can provide a \c{.def} file to the linker
+that lists the symbols to be exported. Finally, the library can request
+the automatic exporting of all symbols, which is the default semantics on
+non-Windows platforms. Note that the last two approaches only work for
+exporting functions, not data, unless special extra steps are taken by the
+library consumers. Let's discuss each of these approaches in the reverse
+order, that is, starting with the automatic symbol exporting.
+
+The automatic symbol exporting is implemented in \c{build2} by generating a
+\c{.def} file that exports all the relevant symbols. It requires a few
+additional definitions in our \c{buildfile} as described in
+\l{b#cc-auto-symexport Automatic DLL Symbol Exporting}. You can automatically
+generate the necessary setup with the \c{auto-symexport} \c{bdep-new}
+sub-option.
+
+Using a custom \c{.def} file to export symbols is fairly straightforward:
+simply list it as a prerequisite of the library and it will be automatically
+passed to the linker when necessary. For example:
+
+\
+# Private headers and sources as well as dependencies.
+#
+lib{foo}: {hxx cxx}{**} $impl_libs $intf_libs def{foo}
+\
+
+\N|Some third-party projects automatically generate their \c{.def} file. In
+this case you can try to re-create the same generation in the \c{buildfile}
+using an ad hoc recipe (or the \l{b#module-in \c{in}} or
+\l{https://github.com/build2/libbuild2-autoconf \c{autoconf}} build system
+modules). If that doesn't look possible (for example, if the generation logic
+is complex and is implemented in something like Perl or Python), then you can
+try your luck with automatic symbol exporting. Failing that, the only
+remaining option is to use a pre-generated \c{.def} file in the \c{build2}
+build.|
+
+The last approach is to explicitly specify in the source code which symbols
+must be exported by marking the corresponding declarations with
+\c{__declspec(dllexport)} during the library build and
+\c{__declspec(dllimport)} during the library use. This is commonly achieved
+with a macro, customarily called \c{*_EXPORT} or \c{*_API}, which is defined
+to one of the above specifiers based on whether static or shared library is
+being built or is being consumed, which, in turn, is also normally signaled
+with a few more macros, such as \c{*_BUILD_DLL} and \c{*_USE_STATIC}.
+
+\N|Because this approach requires extensive changes to the source code, you
+will normally only use it in your \c{build2} build if it is already used in
+the upstream build.|
+
+In \c{build2} you can explicitly signal any of the four situations
+(shared/static, built/consumed) by uncommenting and adjusting the following
+four lines in the build and export options blocks:
+
+\
+# Build options.
+#
+
+...
+
+#obja{*}: cxx.poptions += -DFOO_STATIC_BUILD
+#objs{*}: cxx.poptions += -DFOO_SHARED_BUILD
+
+# Export options.
+#
+
+...
+
+#liba{foo}: cxx.export.poptions += -DFOO_STATIC
+#libs{foo}: cxx.export.poptions += -DFOO_SHARED
+\
+
+As an example, let's assume our \c{libfoo} defines in one of its headers the
+\c{FOO_EXPORT} macro based on the \c{FOO_BUILD_DLL} (shared library is being
+build) and \c{FOO_USE_STATIC} (static library is being used) macros that it
+expects to be appropriately defined by the build system. This is how we would
+modify the above fragment to handle this setup:
+
+\
+# Build options.
+#
+
+...
+
+objs{*}: cxx.poptions += -DFOO_BUILD_DLL
+
+# Export options.
+#
+
+...
+
+liba{foo}: cxx.export.poptions += -DFOO_USE_STATIC
+\
+
+
+\h2#core-adjust-build-src-source-ver|Adjust source \c{buildfile}: shared library version|
+
+The final few lines in the above \c{buildfile} deal with shared library binary
+(ABI) versioning:
+
+\
+# For pre-releases use the complete version to make sure they cannot
+# be used in place of another pre-release or the final version. See
+# the version module for details on the version.* variable values.
+#
+if $version.pre_release
+ lib{foo}: bin.lib.version = \"-$version.project_id\"
+else
+ lib{foo}: bin.lib.version = \"-$version.major.$version.minor\"
+\
+
+The \c{bdep-new}-generated setup arranges for the platform-independent
+versioning where the package's major and minor version components are embedded
+into the shared library binary name (and \c{soname}) under the assumption
+that only patch versions are ABI-compatible.
+
+The two situations where you would want to change this are when the above
+assumption does not hold and/or when upstream provides platform-specific
+shared library versions which you would like to re-create in your \c{build2}
+build. See \l{b#intro-lib Library Exportation and Versioning} for background
+and details.
+
+
+\h2#core-adjust-build-src-source-exe|Adjust source \c{buildfile}: executables|
+
+If instead of a library you are packaging an executable, then, as mentioned
+earlier, it will most likely be a combined layout with a single \c{buildfile}.
+This \c{buildfile} will also be much simpler compared to the library's. For
+example, give the following \c{bdep-new} command:
+
+\
+$ bdep new --package \
+ --lang c++ \
+ --type exe,no-subdir,prefix=foo,export-stub \
+ foo
+\
+
+The resulting source \c{buildfile} will look like this:
+
+\
+libs =
+#import libs += libhello%lib{hello}
+
+exe{foo}: {hxx ixx txx cxx}{**} $libs testscript
+
+out_pfx = [dir_path] $out_root/foo/
+src_pfx = [dir_path] $src_root/foo/
+
+cxx.poptions =+ \"-I$out_pfx\" \"-I$src_pfx\"
+\
+
+If the executable doesn't have any inline/template/header files, then you can
+remove the \c{ixx}/\c{txx}/\c{hxx} target types, respectively (which would be
+parallel to the change made in \c{root.build}; see \l{#core-adjust-build-wide
+Adjust project-wide build system files in \c{build/}}). For example:
+
+\
+exe{foo}: {hxx cxx}{**} $libs testscript
+\
+
+If the source code includes its own headers with the \c{\"\"} style inclusion
+(or doesn't have any headers), then we can also get rid of \c{out_pfx} and
+\c{src_pfx}. For example:
+
+\
+libs =
+#import libs += libhello%lib{hello}
+
+exe{foo}: {hxx ixx txx cxx}{**} $libs testscript
+\
+
+\N|Unfortunately, it's not uncommon for projects that provide both a library
+and an executable, for the executable source code to include public and/or
+private library headers with the relative \c{\"\"} style inclusion. For
+example:
+
+\
+#include \"../../libfoo/include/foo/util.hpp\"
+#include \"../../libfoo/src/impl.hpp\"
+\
+
+This approach won't work in \c{build2} since the two packages may end up in
+different directories or the library could even be installed. There are two
+techniques that can be used to work around this issue (other than patching the
+upstream source code).
+
+For public headers we can provide, in the appropriate places within the
+executable package, \"thunk headers\" with the same names as public headers
+that simply include the corresponding public header from the library using the
+\c{<>} style inclusion.
+
+For private headers we can provide, again in the appropriate places within the
+executable package, our own symlinks for a subset of private headers. Note
+that this will only work if the use of private headers within the executable
+does not depend on any symbols that are not exported by the library (failing
+that, the executable will have to always link to the static variant of the
+library).
+
+For a real example of both of these techniques, see the
+\l{https://github.com/build2-packaging/zstd \c{zstd}} package repository.|
+
+Dealing with dependencies in executables is similar to libraries except that
+here we don't have the interface/implementation distinction; see the
+\l{#core-adjust-build-src-source-dep Adjust source \c{buildfile}:
+dependencies} step. For example:
+
+\
+import libs = libfoo%lib{foo}
+
+exe{foo}: {hxx ixx txx cxx}{**} $libs testscript
+\
+
+Likewise, dealing with build options in executables is similar to libraries
+except that here we have no export options; see the
+\l{#core-adjust-build-src-source-opt Adjust source \c{buildfile}: build and
+export options} step.
+
+If the executable can plausibly be used in a build, then it's recommended to
+add \c{build2} metadata as describe in
+\l{https://github.com/build2/HOWTO/blob/master/entries/convey-additional-information-with-exe-lib.md
+How do I convey additional information (metadata) with executables and C/C++
+libraries?} See also \l{#howto-patch-upstream-source-preproc Modifying
+upstream source code with C/C++ preprocessor} on how to do it without
+physically modifying upstream source code. \N{See the
+\l{https://github.com/build2-packaging/zstd \c{zstd}} package repository for a
+real example of doing this.}
+
+\N|We will discuss the \c{testscript} prerequisite in the
+\l{#core-test-smoke-exe Make smoke test: executables} step below.|
+
+
+\h2#core-adjust-build-src-source-ext|Adjust source \c{buildfile}: extra requirements|
+
+The changes discussed so far should be sufficient to handle a typical library
+or executable that is written in C and/or C++ and is able to handle platform
+differences with the preprocessor and compile/link options. However, sooner or
+later you will run into a more complex library that may use additional
+languages, require more elaborate platform detection, or use additional
+functionality, such as support for source code generators. The below list
+provides pointers to resources that cover the more commonly encountered
+additional requirements.
+
+\ul|
+
+\li|\l{b#module-in The \c{in} build system module}
+
+Use to process \c{config.h.in} (or other \c{.in} files) that don't require
+Autoconf-style platform probing (\c{HAVE_*} options).|
+
+\li|\l{https://github.com/build2/libbuild2-autoconf The \c{autoconf} build
+ system module}
+
+Use to process \c{config.h.in} (or their CMake/Meson variants) that require
+Autoconf-style platform probing (\c{HAVE_*} options) or CMake/Meson-specific
+substitution syntax (\c{#cmakedefine}, etc).|
+
+\li|\l{b#c-objc Objective-C Compilation} and
+ \l{b#cxx-objcxx Objective-C++ Compilation}
+
+Use to compile Objective-C (\c{.m}) or Objective-C++ (\c{.mm}) source files.|
+
+\li|\l{b#c-as-cpp Assembler with C Preprocessor Compilation}
+
+Use to compile Assembler with C Preprocessor (\c{.S}) source files.|
+
+\li|\l{b#intro-unit-test Implementing Unit Testing}
+
+Use if upstream has tests (normally unit tests) in the source subdirectory.|
+
+\li|\l{intro#guide-build-time-linked Build-Time Dependencies and Linked
+ Configurations}
+
+Use if upstream relies on source code generators, such as
+\l{https://cppget.org/reflex \c{lex}} and \l{https://cppget.org/byacc
+\c{yacc}}.|
+
+\li|\l{https://github.com/build2/HOWTO/ The \c{build2} HOWTO}
+
+See the \c{build2} HOWTO article collection for more unusual requirements.||
+
+
+\h2#core-adjust-build-test|Test library build|
+
+At this point our library should be ready to build, at least in theory. While
+we cannot build and test the entire package before adjusting the generated
+\c{tests/} subproject (the subject of the next step), we can try to build just
+the library and, if it has any unit tests in the source subdirectory, even run
+some tests.
+
+\N|If the library is header only, there won't be anything to build unless
+there are unit tests. Still, you may want to continue with this exercise to
+detect any syntactic mistakes in the \c{buildfiles}, etc.|
+
+To build only a specific subdirectory of our package, we use the build system
+directly (continuing with our \c{libfoo} example):
+
+\
+$ cd libfoo/src/ # Change to the source subdirectory.
+$ b update
+\
+
+If there are any issues, try to fix them and then build again. Once the
+library builds and if it has unit tests, you can try to run them:
+
+\
+$ b test
+\
+
+It also makes sense to test the installation and see if anything is off (such
+as private headers being installed):
+
+\
+$ rm -rf /tmp/install
+$ b install config.install.root=/tmp/install
+\
+
+Once the library builds, it makes sense to commit our changes for easier
+rollbacks:
+
+\
+$ cd foo/ # Change to the package repository root.
+$ git add .
+$ git status
+$ git commit -m \"Adjust source subdirectory buildfiles\"
+\
+
+
+\h#core-test-smoke|Make smoke test|
+
+With the library build sorted, we need tests to make sure the result is
+actually functional. As \l{#core-fill discussed earlier}, it is recommended to
+start with a simple \"smoke test\", make sure that works, and then replace it
+with upstream tests. However, if upstream tests look simple enough, you can
+skip the smoke test. For example, if upstream has all its tests in a single
+source file and the way it is built doesn't look too complicated, then you can
+just use that source file in place of the smoke test.
+
+\N|If upstream has no tests, then the smoke test will have to stay. A library
+can only be published if it has at least one test.
+
+It is also recommended to have the smoke test if upstream tests are in a
+separate package. See
+\l{https://github.com/build2/HOWTO/blob/master/entries/handle-tests-with-extra-dependencies.md
+How do I handle tests that have extra dependencies?} for background and
+details.|
+
+\N|If instead of a library you are packaging an executable, you can skip
+directly to \l{#core-test-smoke-exe Make smoke test: executables}.|
+
+To recap, the \c{bdep-new}-generated \c{tests/} subdirectory looks like this
+(continuing with our \c{libfoo} example):
+
+\
+libfoo/
+├── ...
+└── tests/
+ ├── build/
+ │   ├── bootstrap.build
+ │   └── root.build
+ ├── basics/
+ │   ├── driver.cpp
+ │   └── buildfile
+ └── buildfile
+\
+
+The \c{tests/} subdirectory is a build system subproject, meaning that it can
+be built independently, for example, to test the installed version of the
+library (see \l{b#intro-operations-test Testing} for background). In
+particular, this means it has the \c{build/} subdirectory with project-wide
+build system files, the same as the library. The \c{basics/} subdirectory
+contains the generated test, which is what we will be turning into a smoke
+test. The subproject root \c{buildfile} rarely needs changing.
+
+
+\h2#core-test-smoke-build-wide|Adjust project-wide build system files in \c{tests/build/}|
+
+Review and adjust the generated \c{bootstrap.build} and \c{root.build} (there
+will be no \c{export.build}) similar to the \l{#core-adjust-build-wide Adjust
+project-wide build system files in \c{build/}} step.
+
+Here the only change you would normally make is in \c{root.build} and which is
+to drop the assignment of extensions for target types that are not used in
+tests.
+
+
+\h2#core-test-smoke-adjust|Convert generated test to library smoke test|
+
+The \c{basics/} subdirectory contains the \c{driver.cpp} source file that
+implements the test and \c{buildfile} that builds it. You can rename both the
+test subdirectory (\c{basics/}) and the source file \c{driver.cpp}, for
+example, if you are going with the upstream tests directly. You can also add
+more tests by simply copying \c{basics/}.
+
+The purpose of a smoke test is to make sure the library's public headers can
+be included (including in the installed case, no pun intended), it can be
+linked, and its basic functionality works.
+
+To achieve this, we modify \c{driver.cpp} to include the library's main
+headers and call a few functions. For example, if the library has the
+initialize/deinitialize type of functions, those are good candidates to
+call. If the library is not header-only, make sure that the smoke test calls
+at least one non-inline/template function to test symbol exporting.
+
+\N|Make sure that your test includes the library's public headers the same way
+as would be done by the library consumers.|
+
+Continuing with our \c{libfoo} example, this is what its smoke test might look
+like:
+
+\
+#include <foo/core.hpp>
+#include <foo/util.hpp>
+
+#undef NDEBUG
+#include <cassert>
+
+int main ()
+{
+ foo::context* c (foo::init (0 /* flags */));
+ assert (c != nullptr);
+ foo::deinit (c);
+}
+\
+
+\N|The C/C++ \c{assert()} macro is often adequate for simple tests and does
+not require extra dependencies. But see
+\l{https://github.com/build2/HOWTO/blob/master/entries/use-assert-in-tests.md
+How do I correctly use C/C++ assert() in tests?}|
+
+The test \c{buildfile} is pretty simple:
+
+\
+import libs = libfoo%lib{foo}
+
+exe{driver}: {hxx ixx txx cxx}{**} $libs testscript{**}
+\
+
+If you have adjusted the library target name (\c{lib{foo\}}) in the source
+subdirectory \c{buildfile}, then you will need to make the corresponding
+change in the \c{import} directive here. You may also want to tidy it up by
+removing unused prerequisite types. For example:
+
+\
+import libs = libfoo%lib{foo}
+
+exe{driver}: {hxx cxx}{**} $libs
+\
+
+
+\h2#core-test-smoke-exe|Make smoke test: executables|
+
+If instead of a library we are packaging an executable, then instead of the
+\c{tests/} subproject we get the \c{testscript} file in the source
+subdirectory (see \l{#core-adjust-build-src-source-exe Adjust source
+\c{buildfile}: executables} for a refresher). This file can be used to write
+one or more tests that exercise our executable (see \l{b#intro-operations-test
+Testing} for background).
+
+How exactly to test any given executable depends on its functionality. For
+instance, for a compression utility we could write a roundtrip test that first
+compresses some input, then decompresses it, and finally compares the result
+to the original. For example (taken from the
+\l{https://github.com/build2-packaging/zstd \c{zstd}} package repository):
+
+\
+: roundtrip
+:
+echo 'test content' | $* -zc | $* -dc >'test content'
+\
+
+On the other hand, for an executable that is a source code generator, proper
+testing would involve a separate tests package that has a build-time
+dependency on the executable and that exercises the generated code (see
+\l{https://github.com/build2/HOWTO/blob/master/entries/handle-tests-with-extra-dependencies.md
+How do I handle tests that have extra dependencies?} for background and
+details). \N{See the \l{https://github.com/build2-packaging/thrift/tree/0.17
+\c{thrift}} package repository for an example of this setup.}
+
+If the executable provides a way to query its version, one test that you
+should always be able to write, and which can serve as a last resort smoke
+test, is the version check. For example:
+
+\
+: version
+:
+$* --version >>~\"/EOO/\"
+/.*$(version.major)\.$(version.minor)\.$(version.patch).*/
+EOO
+\
+
+See also
+\l{https://github.com/build2/HOWTO/blob/master/entries/sanitize-test-execution.md
+How do I sanitize the execution of my tests?}
+
+
+\h2#core-test-smoke-locally|Test locally|
+
+With the smoke test ready, we can finally do some end-to-end testing of our
+library build. We will start with doing some local testing to catch basic
+mistakes and then do the full CI to detect any platform/compiler-specific
+issues.
+
+First let's run the test in the default build configuration by invoking the
+build system directly (see \l{intro#guide Getting Started Guide} for
+background on default configurations):
+
+\
+$ cd libfoo/tests/ # Change to the tests/ subproject.
+$ b test
+\
+
+If there are any issues (compile/link errors, test failures), try to address
+them and re-run the test.
+
+Once the library builds in the default configuration and the result passes the
+tests, you can do the same for all the build configurations, in case you have
+\l{#core-fill-init initialized} your library in several:
+
+\
+$ bdep test -a
+\
+
+\h2#core-test-smoke-locally-install|Test locally: installation|
+
+Once the development build works, let's also test the installed version of the
+library. In particular, this makes sure that the public headers are installed
+in a way that is compatible with how they are included by our test (and would
+be included by the library consumers). To test this we first install the
+library into a temporary directory:
+
+\
+$ cd libfoo/ # Change to the package root.
+$ rm -rf /tmp/install
+$ b install config.install.root=/tmp/install
+\
+
+Next we build just the \c{tests/} subproject out of source and arranging for
+it to find the installed library (see \l{b#intro-dirs-scopes Output
+Directories and Scopes} for background on the out of source build syntax):
+
+\
+$ cd libfoo/ # Change to the package root.
+$ b test: tests/@/tmp/libfoo-tests-out/ \
+ config.cc.loptions=-L/tmp/install/lib \
+ config.bin.rpath=/tmp/install/lib
+\
+
+\N|The equivalent MSVC command line would be:
+
+\
+> b install config.install.root=c:\tmp\install
+
+> b test: tests\@c:\tmp\libfoo-tests-out\^
+ config.cc.loptions=/LIBPATH:c:\tmp\install\lib
+\
+
+|
+
+It is a good idea to look over the installed files manually and make sure
+there is nothing unexpected, for example, missing or extraneous files.
+
+Once done testing the installed case, let's clean things up:
+
+\
+$ rm -r /tmp/install /tmp/libfoo-tests-out
+\
+
+\h2#core-test-smoke-locally-dist|Test locally: distribution|
+
+Another special case worth testing is the preparation of the source
+distribution (see \l{b#intro-operations-dist Distributing} for
+background). This, in particular, is how your package will be turned into the
+source archive for publishing to \l{https://cppget.org cppget.org}. Here we
+are primarily looking for missing files. As a bonus, this will also allow us
+to test the in source build. First we distribute our package to a temporary
+directory (again using the default configuration and the build system
+directly):
+
+\
+$ cd libfoo/ # Change to the package root.
+$ b dist config.dist.root=/tmp/dist config.dist.uncommitted=true
+\
+
+The result will be in the \c{/tmp/dist/libfoo-<version>/} directory which
+should resemble our \c{libfoo/} package but without files like \c{.gitignore}.
+Next we build and test the distribution in source:
+
+\
+$ cd /tmp/dist/libfoo-<version>/
+$ b configure config.cxx=g++
+$ b update
+$ b test
+\
+
+\N|If your package has dependencies that you import in your \c{buildfile},
+then the above \c{configure} operation will most likely fail because such
+dependencies cannot be found (it may succeed if they are available as
+system-installed). The error message will suggest specifying the location of
+each dependency with the \c{config.import.*} variable. You can fix this by
+setting each such \c{config.import.*} to the location of the default build
+configuration (created in the \l{#core-fill-init Initialize package in build
+configurations} step) which should contain all the necessary
+dependencies. Simply re-run the \c{configure} operation until you have
+discovered and specified all the necessary \c{config.import.*} variables, for
+example:
+
+\
+$ b configure config.cxx=g++ \
+ config.import.libz=.../foo-gcc \
+ config.import.libasio=.../foo-gcc \
+ config.import.libsqlite3=.../foo-gcc
+\
+
+|
+
+It is a good idea to look over the distributed files manually and make sure
+there is nothing missing or extraneous.
+
+Once done testing the distribution, let's clean things up:
+
+\
+$ rm -r /tmp/dist
+\
+
+
+\h2#core-test-smoke-ci|Commit and test with CI|
+
+With local testing complete, let's commit our changes and submit a remote CI
+job to test our library on all the major platforms and with all the major
+compilers:
+
+\
+$ cd foo/ # Change to the package repository root.
+$ git add .
+$ git status
+$ git commit -m \"Add smoke test\"
+$ git push -u
+
+$ bdep ci
+\
+
+The result of the \l{bdep-ci(1)} command is a link where you can see the
+status of the builds.
+
+\N|Make sure to wait until there are no more unbuilt configurations (that is,
+the number of entries with the \c{<unbuilt>} or \c{building} result is
+\c{0}).|
+
+If any builds fail, view the logs to determine the cause, try to fix it,
+commit your fix, and CI again.
+
+\N|It is possible that upstream does not support some platforms or compilers.
+For example, it's common for smaller projects not to bother with supporting
+\"secondary\" compilers, such as MinGW GCC on Windows or Homebrew GCC on Mac
+OS.
+
+If upstream expressly does not support some platform or compiler, it's probably
+not worth spending time and energy trying to support it in the package. Most
+likely it will require changes to upstream source code and that is best done
+upstream rather than in the package (see \l{#dont-fix-upstream Don't try to
+fix upstream issues in the package} for background). In this case you would
+want to exclude these platforms/compilers from the CI builds using the
+\l{bpkg#manifest-package-builds \c{builds} package \c{manifest} value}.
+
+The other common cause of a failed build is a newer version of a compiler or
+platform that breaks upstream. In this case there are three options: Ideally
+you would want to fix this in upstream and have a new version released.
+Failing that, you may want to patch the upstream code to fix the issues,
+especially if this is one of the major platforms and/or primary compilers (see
+\l{#howto-patch-upstream-source How do I patch upstream source code?} for
+details). Finally, you can just leave the build failing with the expectation
+that it will be fixed in the next upstream version. Note that in this case you
+should not exclude the failing build from CI.|
+
+
+\h#core-test-upstream|Replace smoke test with upstream tests|
+
+With the smoke test working we can now proceed with replacing it with the
+upstream tests.
+
+
+\h2#core-test-upstream-understand|Understand how upstream tests work|
+
+While there are some commonalities in how C/C++ libraries are typically built,
+when it comes to tests there is unfortunately little common ground in how they
+are arranged, built, and executed. As a result, the first step in dealing with
+upstream tests is to study the existing build system and try to understand how
+they work.
+
+\N|If upstream tests prove incomprehensible (which is unfortunately not
+uncommon) and the only options you see are to go with just the smoke test or
+to give up, then go with just the smoke test. In this case it's a good idea to
+create an issue in the package repository mentioning that upstream tests are
+still a TODO.|
+
+\N|If instead of a library you are packaging an executable, then whether the
+below steps will apply depends on the functionality of the executable.
+
+In particular, testing source code generators would normally involve
+exercising the generated code, in which case the following will largely apply,
+though in this case the tests would need to be placed into a separate tests
+package that has a build-time dependency on the executable (see
+\l{https://github.com/build2/HOWTO/blob/master/entries/handle-tests-with-extra-dependencies.md
+How do I handle tests that have extra dependencies?} for background and
+details). In fact, if a source code generator is accompanied by a runtime
+library, then the tests will normally exercise them together (though a runtime
+library might also have its own tests). See the
+\l{https://github.com/build2-packaging/thrift/tree/0.17 \c{thrift}} package
+repository for an example of this setup.|
+
+To get you started with analyzing the upstream tests, below are some of the
+questions you would likely need answered before you can proceed with the
+conversion:
+
+\ul|
+
+\li|\b{Are upstream tests unit tests or integration tests?}
+
+While the distinction is often fuzzy, for our purposes the key differentiator
+between unit and integration tests is which API they use: integration tests
+only use the library's public API while unit tests need access to the
+implementation details.
+
+Normally (but not always), unit tests will reside next to the library source
+code since they need access to more than just the public headers and the
+library binary (private headers, individual object files, utility libraries,
+etc). While integration tests are normally (but again not always) placed into
+a separate subdirectory, usually called \c{tests} or \c{test}.
+
+If the library has unit tests, then refer to \l{b#intro-unit-test Implementing
+Unit Testing} for background on how to handle them in \c{build2}.
+
+If the library has integration tests, then use them to replace (or complement)
+the smoke test.
+
+If the library has unit tests but no integration tests, then it is recommended
+to keep the smoke test since that's the only way the library will be tested
+via its public API.|
+
+
+\li|\b{Do upstream tests use an external testing framework?}
+
+Oftentimes a C++ library will use an external testing framework to implement
+tests. Popular choices include \l{https://cppget.org/catch2 \c{catch2}},
+\l{https://cppget.org/gtest \c{gtest}}, \l{https://cppget.org/doctest
+\c{doctest}}, and \l{https://cppget.org/libboost-test \c{libboost-test}}.
+
+If a library uses such an external testing framework, then it is recommended
+to factor tests into a separate package in order to avoid making the library
+package depend on the testing framework (which is only required during
+testing). See
+\l{https://github.com/build2/HOWTO/blob/master/entries/handle-tests-with-extra-dependencies.md
+How do I handle tests that have extra dependencies?} for details.
+
+\N|Sometimes you will find that upstream bundles the source code of the
+testing framework with their tests. This is especially common with
+\c{catch2}. If that's the case, it is strongly recommended that you
+\"unbundle\" it by making it a proper external dependency. See \l{#dont-bundle
+Don't bundle dependencies} for background.||
+
+
+\li|\b{Are upstream tests in a single or multiple executables?}
+
+It's not unusual for libraries to have a single test executable that runs all
+the test cases. This is especially common if a C++ testing framework is used.
+In this case it is natural to replace the contents of the smoke test with the
+upstream source code, potentially renaming the test subdirectory (\c{basics/})
+to better match upstream naming.
+
+If upstream has multiple test executables, then they could all be in a single
+test subdirectory (potentially reusing some common bits) or spread over
+multiple subdirectories. In both cases it's a good idea to follow the upstream
+structure unless you have good reasons to deviate. In the former case (all
+executables in the same subdirectory), you can re-purpose the smoke test
+subdirectory. In the latter case (each executable in a separate subdirectory)
+you can make copies of the smoke test subdirectory.|
+
+
+\li|\b{Do upstream tests use an internal utility library?}
+
+If there are multiple test executables and they need to share some common
+functionality, then it's not unusual for upstream to place such functionality
+into a static library and then link it to each test executable. In \c{build2}
+such an internal library is best represented with a utility library (see
+\l{b#intro-unit-test Implementing Unit Testing} for details). See the
+following section for an example.|
+
+
+\li|\b{Are upstream tests well behaved?}
+
+Unfortunately, it's not uncommon for upstream tests not to behave well, such
+as to write diagnostics to \c{stdout} instead of \c{stderr}, create temporary
+files without cleaning them up, or assume presence of input files in the
+current working directory. For details on how to deal with such situations see
+\l{https://github.com/build2/HOWTO/blob/master/entries/sanitize-test-execution.md
+How do I sanitize the execution of my tests?}||
+
+
+\h2#core-test-upstream-convert|Convert smoke test to upstream tests|
+
+Once you have a good grasp of how upstream tests work, convert or replace the
+smoke test with the upstream tests. If upstream has multiple test executables,
+you may want to deal with one test at a time, making sure that it passes
+before moving to the next one.
+
+It's normally a good idea to use the smoke test \c{buildfile} as a starting
+point for upstream tests. To recap, the smoke test \c{buildfile} for our
+\c{libfoo} example ended up looking like this:
+
+\
+import libs = libfoo%lib{foo}
+
+exe{driver}: {hxx cxx}{**} $libs
+\
+
+At a minimum you will most likely need to change the name of the executable to
+match upstream. If you need to build multiple executables in the same
+directory, then it's probably best to get rid of the name pattern for the
+source files and specify the prerequisite names explicitly, for example:
+
+\
+import libs = libfoo%lib{foo}
+
+./: exe{test1}: cxx{test1} $libs
+./: exe{test2}: cxx{test2} $libs
+\
+
+If you have a large number of such test executables, then a \l{b#intro-for
+\c{for}-loop} might be a more scalable option:
+
+\
+import libs = libfoo%lib{foo}
+
+for src: cxx{test*}
+ ./: exe{$name($src)}: $src $libs
+\
+
+If the upstream tests have some common functionality that is used by all the
+test executables, then it is best placed into a utility library. For example:
+
+\
+import libs = libfoo%lib{foo}
+
+./: exe{test1}: cxx{test1} libue{common}
+./: exe{test2}: cxx{test2} libue{common}
+
+libue{common}: {hxx cxx}{common} $libs
+\
+
+
+\h2#core-test-upstream-locally|Test locally|
+
+With the upstream tests ready, we re-do the same end-to-end testing as we did
+with the smoke test:
+
+\l{#core-test-smoke-locally Test locally}\n
+\l{#core-test-smoke-locally-install Test locally: installation}\n
+\l{#core-test-smoke-locally-dist Test locally: distribution}\n
+
+
+\h2#core-test-upstream-ci|Commit and test with CI|
+
+With local testing complete, we commit our changes and submit a remote CI
+job. This step is similar to what \l{#core-test-smoke-ci we did for the smoke
+test} but this time we are using the upstream tests:
+
+\
+$ cd foo/ # Change to the package repository root.
+$ git add .
+$ git status
+$ git commit -m \"Add upstream tests\"
+$ git push
+
+$ bdep ci
+\
+
+
+\h#core-examples-benchmarks|Add upstream examples, benchmarks, if any|
+
+If the upstream project provides examples and/or benchmarks and you wish to
+add them to the \c{build2} build (which is not strictly necessary for the
+\c{build2} package to be usable), then now is a good time to do that.
+
+As was mentioned in \l{#core-package-review Review and test auto-generated
+\c{buildfile} templates}, the recommended approach is to copy the \c{tests/}
+subproject (potentially from the commit history before the smoke test was
+replaced with the upstream tests) and use that as a starting point for
+examples and/or benchmarks. Do not forget to add the corresponding entry in
+the root \c{buildfile}.
+
+Once that is done, follow the same steps as in \l{#core-test-upstream Replace
+smoke test with upstream tests} to add upstream examples/benchmarks and test
+the result.
+
+
+\h#core-root|Adjust root files (\c{buildfile}, \c{manifest}, etc)|
+
+The last few files that we need to review and potentially adjust are
+the root \c{buildfile}, package \c{manifest}, and \c{PACKAGE-README.md}.
+
+
+\h2#core-root-buildfile|Adjust root \c{buildfile}|
+
+The main function of the root \c{buildfile} is to pull in all the
+subdirectories that need building plus list targets that are usually found in
+the root directory of a project, typically \c{README.md}, \c{LICENSE},
+etc. This is what the generated root \c{buildfile} looks like for our
+\c{libfoo} project assuming we have symlinked \c{README.md}, \c{LICENSE}, and
+\c{NEWS} from upstream in the \l{#core-package-create Create final package}
+step:
+
+\
+./: {*/ -build/} \
+ doc{README.md PACKAGE-README.md NEWS} \
+ legal{LICENSE} manifest
+
+# Don't install tests.
+#
+tests/: install = false
+\
+
+If the upstream project provides any other documentation (detailed change
+logs, contributing guidelines, etc) or legal files (alternative licenses, list
+of authors, code of conduct, etc), then you may want to symlink and list them
+as the \c{doc{\}} and \c{legal{\}} prerequisites, respectively.
+
+\N|If you are packaging an executable and it provides a man page, then it can
+also be listed in the root \c{buildfile}. For example, if the man page file is
+called \c{foo.1}:
+
+\
+./: ... man1{foo}
+\
+
+|
+
+\N|One file you don't need to list is \c{INSTALL} (or equivalent) which
+normally contains the installation instructions for the upstream build
+system. In the \c{build2} package of a third-party project the
+\c{PACKAGE-README.md} file serves this purpose (see
+\l{#core-root-package-readme Adjust \c{PACKAGE-README.md}} for details).|
+
+
+\h2#core-root-buildfile-doc|Adjust root \c{buildfile}: other subdirectories|
+
+If the upstream project has other subdirectories that makes sense to include
+into the \c{build2} package, then now is a good time to take care of that.
+The most common such case will be extra documentation (besides the root
+\c{README}), typically in a subdirectory called \c{doc/}, \c{docs/}, or
+\c{documentation/}.
+
+The standard procedure for handling such subdirectories will be to symlink the
+relevant files (or the entire subdirectory) and then list the files as
+prerequisites. For this last step, there are two options: we can list the
+files directly in the root \c{buildfile} or we can create a separate
+\c{buildfile} in the subdirectory.
+
+\N|If symlinking entire subdirectories, don't forget to also list them in
+\c{.gitattributes} if you want your package to be usable from the \c{git}
+repository directly on Windows. See
+\l{https://build2.org/article/symlinks.xhtml#windows Symlinks and Windows} for
+details.|
+
+Let's examine each approach using our \c{libfoo} as an example. We will
+assume that the upstream project contains the \c{docs/} subdirectory with
+additional \c{*.md} files that document the library's API. It would make sense
+to include them into the \c{build2} package.
+
+Listing the subdirectory files directly in the root \c{buildfile} works best
+for simple cases, where you have a bunch of static files that don't require
+any special provisions, such as customizations to their installation
+locations. In this case we can symlink the entire \c{docs/} subdirectory:
+
+\
+$ cd libfoo/ # Change to the package root.
+$ ln -s ../upstream/docs ./
+\
+
+The adjustments to the root \c{buildfile} are pretty straightforward: we
+exclude the \c{docs/} subdirectory (since it has no \c{buildfile}) and list
+the \c{*.md} files as prerequisites using the \c{doc{\}} target type (which,
+in particular, makes sure they are installed into the appropriate location):
+
+\
+./: {*/ -build/ -docs/} \
+ doc{README.md PACKAGE-README.md NEWS} \
+ docs/doc{*.md} \
+ legal{LICENSE} manifest
+\
+
+The alternative approach (create a separate \c{buildfile}) is a good choice if
+things are more complicated than that. Let's say we need to adjust the
+installation location of the files in \c{docs/} because there is another
+\c{README.md} inside and that would conflict with the root one when installed
+into the same location. This time we cannot symlink the top-level \c{docs/}
+subdirectory (because we need to place a \c{buildfile} there). The two options
+here are to either symlink the individual files or introduce another
+subdirectory level inside \c{docs/} (which is the same approach as discussed
+in \l{#dont-main-target-root-buildfile Don't build your main targets in the
+root \c{buildfile}}). Let's illustrate both sub-cases.
+
+Symlinking individual files works best when you don't expect the set of files
+to change often. For example, if \c{docs/} contains a man page and its HTML
+rendering, then it's unlikely this set will change. On the other hand, if
+\c{docs/} contains a manual split into an \c{.md} file per chapter, then there
+is a good chance this set of files will fluctuate between releases.
+
+Continuing with our \c{libfoo} example, this is how we symlink the individual
+\c{*.md} files in \c{docs/}:
+
+\
+$ cd libfoo/ # Change to the package root.
+$ mkdir docs
+$ cd docs/
+$ ln -s ../../upstream/docs/*.md ./
+\
+
+Then write a new \c{buildfile} in \c{docs/}:
+
+\
+./: doc{*.md}
+
+# Install the documentation in docs/ into the manual/ subdirectory of,
+# say, /usr/share/doc/libfoo/ since we cannot install both its and root
+# README.md into the same location.
+#
+doc{*.md}: install = doc/manual/
+\
+
+Note that we don't need to make any changes to the root \c{buildfile} since
+this subdirectory will automatically get picked up by the \c{{*/\ -build/\}}
+name pattern that we have there.
+
+Let's now look at the alternative arrangement with another subdirectory level
+inside \c{docs/}. Here we achieve the same result but in a slightly different
+way. Specifically, we call the subdirectory \c{manual/} and install recreating
+subdirectories (see \l{b#intro-operations-install Installing} for background):
+
+\
+$ cd libfoo/ # Change to the package root.
+$ mkdir -p docs/manual
+$ cd docs/manual/
+$ ln -s ../../../upstream/docs/*.md ./
+\
+
+And the corresponding \c{buildfile} in \c{docs/}:
+
+\
+./: doc{**.md}
+
+# Install the documentation in docs/ into, say, /usr/share/doc/libfoo/
+# recreating subdirectories.
+#
+doc{*}:
+{
+ install = doc/
+ install.subdirs = true
+}
+\
+
+\N|Yet another option would be to open a scope for the \c{docs/} subdirectory
+directly in the root \c{buildfile} (see \l{b#intro-dirs-scopes Output
+Directories and Scopes} for background). For example:
+
+\
+$ cd libfoo/ # Change to the package root.
+$ ln -s ../upstream/docs ./
+\
+
+And then add the following to the root \c{buildfile}:
+
+\
+docs/
+{
+ ./: doc{*.md}
+
+ # Install the documentation in docs/ into the manual/ subdirectory
+ # of, say, /usr/share/doc/libfoo/ since we cannot install both its
+ # and root README.md into the same location.
+ #
+ doc{*.md}: install = doc/manual/
+}
+\
+
+However, this approach should be used sparingly since it can quickly make the
+root \c{buildfile} hard to comprehend. Note also that it cannot be used for
+main targets since an export stub requires a \c{buildfile} to load (see
+\l{#dont-main-target-root-buildfile Don't build your main targets in the
+root \c{buildfile}} for details).|
+
+
+\h2#core-root-buildfile-commit|Adjust root \c{buildfile}: commit and test|
+
+Once all the adjustments to the root \c{buildfile} are made, it makes sense to
+test it locally (this time from the root of the package), commit our changes,
+and test with CI:
+
+\
+$ cd libfoo/ # Change to the package root.
+$ b test
+$ bdep test -a
+\
+
+If you had to add any extra files to the root \c{buildfile} (or add
+\c{buildfiles} in extra subdirectories), then it also makes sense to test the
+installation (\l{#core-test-smoke-locally-install Test locally: installation})
+and the preparation of the source distribution
+(\l{#core-test-smoke-locally-dist Test locally: distribution}) to make sure
+the extra files end up in the right places.
+
+Then commit our changes and CI:
+
+\
+$ cd foo/ # Change to the package repository root.
+$ git add .
+$ git status
+$ git commit -m \"Adjust root buildfile\"
+$ git push
+
+$ bdep ci
+\
+
+
+\h2#core-root-manifest|Adjust \c{manifest}|
+
+The next file we need to look over is the package's \c{manifest}. Here is what
+it will look like, using our \c{libfoo} as an example:
+
+\
+: 1
+name: libfoo
+version: 2.1.0-a.0.z
+language: c++
+project: foo
+summary: C++ library implementing secure Foo protocol
+license: MIT ; MIT License.
+description-file: README.md
+package-description-file: PACKAGE-README.md
+changes-file: NEWS
+url: https://example.org/upstream
+email: upstream@example.org
+package-url: https://github.com/build2-packaging/foo
+package-email: packaging@build2.org ; Mailing list.
+depends: * build2 >= 0.16.0
+depends: * bpkg >= 0.16.0
+\
+
+You can find the description of these and other package \c{manifest} values in
+\l{bpkg#manifest-package Package Manifest} (the manifest format is described
+in \l{bpkg#manifest-format Manifest Format}).
+
+In the above listing the values that we likely need to adjust are \c{summary}
+and \c{license}, unless correctly auto-detected by \c{bdep-new} in the
+\l{#core-package-create Create final package} step. See
+\l{#core-root-manifest-summary Adjust \c{manifest}: \c{summary}} and
+\l{#core-root-manifest-license Adjust \c{manifest}: \c{license}} below
+for guidelines on changing these values.
+
+\N|It is not uncommon for projects to be licensed under multiple licenses.
+Note, however, that \c{bdep-new} will only detect one license and you will
+need to specify any additional licenses manually.|
+
+We will also need to change \c{url} and \c{email} with the upstream project's
+homepage URL and e-mail, respectively. If upstream doesn't have a dedicated
+website for the project, then use its repository URL on GitHub or equivalent.
+For e-mail you would normally use a mailing list address. If upstream doesn't
+have any e-mail contacts, then you can drop this value from the
+\c{manifest}. The \c{package-url} and \c{package-email} values normally do not
+need to be changed.
+
+\N|\l{https://lists.build2.org packaging@build2.org} is a mailing list for
+discussions related to the packaging efforts of third-party projects.|
+
+Note also that while you may be tempted to adjust the \c{version} value,
+resist this temptation since this will be done automatically by
+\l{bdep-release(1)} later.
+
+You may also want to add the following value in certain cases:
+
+\dl|
+
+\li|\l{bpkg#manifest-package-changes \cb{changes-file}}
+
+If you have added any extra news of changelog files to the root \c{buildfile}
+(see \l{#core-root-buildfile Adjust root buildfile}), then it may also make
+sense to list them in the \c{manifest}. For example:
+
+\
+changes-file: ChangeLog.txt
+\
+
+|
+
+\li|\l{bpkg#manifest-package-topics \cb{topics}}
+
+Package topics. For example:
+
+\
+topics: network protocol, network security
+\
+
+\N|If the upstream project is hosted on GitHub or similar, then you can
+usually copy the topics from the upstream repository description.||
+
+\li|\l{bpkg#manifest-package-doc-url \cb{doc-url}}\n
+ \l{bpkg#manifest-package-src-url \cb{src-url}}
+
+Documentation and source code URLs. For example:
+
+\
+doc-url: https://example.org/foo/doc/
+src-url: https://github.com/.../foo
+\
+
+||
+
+
+\h2#core-root-manifest-summary|Adjust \c{manifest}: \c{summary}|
+
+For \c{summary} use a brief description of the functionality provided by the
+library or executable. Less than 70 characters is a good target to aim
+for. Don't capitalize subsequent words unless proper nouns and omit the
+trailing dot. For example:
+
+\
+summary: Vim xxd hexdump utility
+\
+
+Omit weasel words such as \"modern\", \"simple\", \"fast\", \"small\", etc.,
+since they don't convey anything specific. Omit \"header-only\" or
+\"single-header\" for C/C++ libraries since, at least in the context of
+\c{build2}, it does not imply any benefit.
+
+If upstream does not offer a sensible summary, the following template is
+recommended for libraries:
+
+\
+summary: <functionality> C library
+summary: <functionality> C++ library
+\
+
+For example:
+
+\
+summary: Event notification C library
+summary: Validating XML parsing and serialization C++ library
+\
+
+If the project consists of multiple packages, it may be tempting to name each
+package in terms of the overall project name, for example:
+
+\
+name: libigl-core
+summary: libigl core module
+\
+
+This doesn't give the user any clue about what functionality is provided
+unless they find out what \c{libigl} is about. Better:
+
+\
+summary: Geometry processing C++ library, core module
+\
+
+If you follow the above pattern, then to produce a summary for external tests
+or examples packages simply add \"tests\" or \"examples\" at the end,
+for example:
+
+\
+summary: Event notification C library tests
+summary: Geometry processing C++ library, core module examples
+\
+
+\h2#core-root-manifest-license|Adjust \c{manifest}: \c{license}|
+
+For \c{license}, use the \l{https://spdx.org/licenses/ SPDX license ID} if at
+all possible. If multiple licenses are involved, use the SPDX License
+expression. See the
+\l{https://build2.org/bpkg/doc/build2-package-manager-manual.xhtml#manifest-package-license
+\c{license} manifest value} documentation for details, including the list of
+the SPDX IDs for the commonly used licenses.
+
+\h2#core-root-manifest-commit|Adjust \c{manifest}: commit and test|
+
+Once all the adjustments to the \c{manifest} are made, it makes sense to test
+it locally, commit our changes, and test with CI:
+
+\
+$ cd libfoo/ # Change to the package root.
+$ b test
+$ bdep test -a
+\
+
+Then commit our changes and CI:
+
+\
+$ cd foo/ # Change to the package repository root.
+$ git add .
+$ git status
+$ git commit -m \"Adjust manifest\"
+$ git push
+
+$ bdep ci
+\
+
+\h2#core-root-package-readme|Adjust \c{PACKAGE-README.md}|
+
+The last package file we need to adjust is \c{PACKAGE-README.md} which
+describes how to use the package from a \c{build2}-based project. The template
+generated by \c{bdep-new} establishes the recommended structure and includes a
+number of placeholders enclosed in \c{<\ >}, such as \c{<UPSTREAM-NAME>} and
+\c{<SUMMARY-OF-FUNCTIONALITY>}, that need to be replaced with the
+package-specific content. While all the placeholders should be
+self-explanatory, below are a couple of guidelines.
+
+For \c{<SUMMARY-OF-FUNCTIONALITY>} it's best to copy a paragraph or two from
+the upstream documentation, usually from \c{README.md} or the project's web
+page.
+
+\N|If the \c{bdep new} command was able to extract the summary from upstream
+\c{README}, then the summary in the heading (first line) will contain that
+information. Otherwise, you would need to adjust it manually, similar to
+\c{manifest} above. In this case use the \c{summary} value form the
+\c{manifest}, perhaps slightly shortened.|
+
+If the package contains a single importable target, as is typical with
+libraries, then it makes sense to drop the \"Importable targets\" section
+since it won't add anything that hasn't already been said in the \"Usage\"
+section.
+
+Similarly, if the package has no configuration variables, then it makes sense
+to drop the \"Configuration variables\" section.
+
+For inspiration, see
+
+\l{https://github.com/build2-packaging/zstd/blob/master/libzstd/PACKAGE-README.md
+\c{PACKAGE-README.md}} in \l{https://github.com/build2-packaging/zstd
+\c{zstd}} and
+\l{https://github.com/build2-packaging/libevent/blob/main/PACKAGE-README.md
+\c{PACKAGE-README.md}} in \l{https://github.com/build2-packaging/libevent
+\c{libevent}} (libraries) as well as
+\l{https://github.com/build2-packaging/zstd/blob/master/zstd/PACKAGE-README.md
+\c{PACKAGE-README.md}} in \l{https://github.com/build2-packaging/zstd
+\c{zstd}} and
+\l{https://github.com/build2-packaging/xxd/blob/master/xxd/README.md
+\c{README.md}} in \l{https://github.com/build2-packaging/xxd \c{xxd}}
+(executables).
+
+\N|If upstream does not provide a \c{README} file, then it makes sense to
+rename \c{PACKAGE-README.md} to just \c{README.md} in the \c{build2} package,
+as was done in the \c{xxd} package mentioned above.|
+
+Once \c{PACKAGE-README.md} is ready, commit and push the changes. You may also
+want to view the result on GitHub to make sure everything is rendered
+correctly.
+
+\
+$ cd foo/ # Change to the package repository root.
+$ git add .
+$ git status
+$ git commit -m \"Adjust PACKAGE-README.md\"
+$ git push
+\
+
+
+\h#core-repo-readme|Adjust package repository \c{README.md}|
+
+With all the package files taken care of, the last file we need to adjust is
+\c{README.md} in the root of our package repository (it was created in the
+\l{#core-repo-init Initialize package repository with \c{bdep new}} step).
+
+\N|If you need to add additional packages and are doing this one package at a
+time (for example, first library then executable in the \"library and
+executable\" project), then this is the point where you would want to restart
+from \l{#core-package Create package and generate \c{buildfile} templates} for
+another iteration. Only once all the packages are added does it make sense
+to continue with updating this \c{README.md}.|
+
+The primary purpose of the package repository \c{README.md} is to provide
+setup instructions as well as any other relevant information for the
+development of the packages as opposed to their consumption. However, it's also
+a good idea to give a brief summary of what this repository is about and to
+point users interested in consumption to the \c{PACKAGE-README.md} files.
+
+The template generated by \c{bdep new} establishes the recommended structure
+to achieve these objectives. It includes a number of placeholders enclosed
+in \c{<\ >}, such as \c{<UPSTREAM-URL>} and \c{<SUMMARY-OF-FUNCTIONALITY>},
+that need to be replaced with the repository-specific content. While all the
+placeholders should be self-explanatory, below are a couple of guidelines.
+
+If there is a single package, then \c{<SUMMARY>} in the heading can be the
+same as in \c{PACKAGE-README.md}. If there are multiple packages, then use
+an overall summary of the upstream project.
+
+For \c{<SUMMARY-OF-FUNCTIONALITY>} it's best to copy a paragraph or two from
+the upstream documentation, usually from \c{README.md} or the project's web
+page. Again, for a single package, this can be copied directly from
+\c{PACKAGE-README.md}.
+
+If there are multiple packages in the repository, then it's recommended to
+replace a single link to \c{PACKAGE-README.md} with a list of links (this
+also shows the available packages). For example:
+
+\
+... If you want to use `foo` in your `build2`-based project, then
+instead see the accompanying `PACKAGE-README.md` files:
+
+* [`libfoo/PACKAGE-README.md`](libfoo/PACKAGE-README.md)
+* [`foo/PACKAGE-README.md`](foo/PACKAGE-README.md)
+\
+
+The remainder of the generated \c{README.md} file are the standard \c{bdep}
+initialization instructions. Adjust them if your package repository requires
+anything special (for example, a host configuration). This is also the place
+to mention anything unusual, such as that upstream does not use semver (and
+thus only a subset of \c{bdep} functionality is usable).
+
+For inspiration, see
+\l{https://github.com/build2-packaging/zstd/blob/master/README.md
+\c{README.md}} in the \l{https://github.com/build2-packaging/zstd \c{zstd}}
+package repository.
+
+Once the repository \c{README.md} is ready, commit and push the changes. You
+may also want to view the result on GitHub to make sure everything is rendered
+correctly.
+
+\
+$ cd foo/ # Change to the package repository root.
+$ git add .
+$ git status
+$ git commit -m \"Adjust package repository README.md\"
+$ git push
+\
+
+
+\h#core-release-publish|Release and publish|
+
+Once all the adjustments are in and everything is tested, we can release the
+final version of the package and then publish it to \l{https://cppget.org
+cppget.org}. Both of these steps are automated with the corresponding \c{bdep}
+commands. But before performing these steps we need to transfer the package
+repository to \l{https://github.com/build2-packaging
+github.com/build2-packaging}.
+
+
+\h2#core-release-publish-transfer|Transfer package repository|
+
+If you have been doing your work in a repository in your personal workspace,
+then now is the time to transfer it to the
+\l{https://github.com/build2-packaging github.com/build2-packaging}
+organization.
+
+\N|It is important to transfer the repository before publishing the first
+version of the package since the repository is used as a proxy for package
+name ownership (see \l{bdep-publish(1)} for details). If you publish the
+package from your personal workspace and then transfer the repository, the
+ownership information will have to be adjusted manually, which we would
+prefer to avoid.|
+
+The first step is to become a member of this organization (unless you already
+are). This will give you permissions to create new repositories, which is
+required to perform a transfer (you will also have full read/write access to
+the repository once transferred). To get an invite,
+\l{https://build2.org/community.xhtml#help get in touch} not forgetting to
+mention your GitHub user name.
+
+If your repository has any prefixes, such as \c{build2-}, or suffixes
+such as \c{-package}, then the next step is to rename it to follow the
+\l{#core-repo-name Use upstream repository name as package repository name}
+guideline. Go to the repository's Settings on GitHub where you should see the
+Rename button.
+
+Finally, to perform the transfer, go to the repository's Settings, Danger Zone
+section, where you should see the Transfer button. Select \c{build2-packaging}
+as the organization to transfer to, and complete the transfer.
+
+Once transferred, you will be considered the maintainer of this package going
+forward. If other members of the \c{build2-packaging} organization wish to
+participate in the package maintenance, the correct etiquette is to do this
+via pull requests. However, if you lose interest in maintaining a package or
+otherwise become unresponsive, we may allow a new maintainer to take over
+this role.
+
+\N|In extraordinary circumstances the \c{build2-packaging} administrators may
+make direct changes to the package, for example, to release a new revision in
+order to address a critical issue. They will still try to coordinate the
+changes with the maintainer but may not always be able to wait for a response
+in time-sensitive cases.|
+
+\h2#core-release-publish-release|Release final version|
+
+As you may recall, our package currently has a pre-release snapshot version of
+the upstream version (see \l{#core-package-adjust-version Adjust package
+version}). Once all the changes are in, we can change to the final upstream
+version, in a sense signaling that this package version is ready.
+
+\N|If you are working in a branch, then now is also the time to merge it into
+\c{master} (or equivalent).|
+
+The recommended way to do this is with the \l{bdep-release(1)} command (see
+\l{intro#guide-versioning-releasing Versioning and Release Management} for
+background). Besides replacing the \c{version} value in the package
+\c{manifest} file, it also commits this change, tags it with the
+\c{v\i{X}.\i{Y}.\i{Z}} tag, and can be instructed to push the changes (or show
+the \c{git} command to do so). This command also by default \"opens\" the next
+development version, which is something that we normally want for our own
+projects but not when we package a third-party one (since we cannot predict
+which version upstream will release next). So we disable this functionality.
+For example:
+
+\
+$ cd foo/ # Change to the package repository root.
+$ bdep release --no-open --show-push
+\
+
+Then review the commit made by \c{bdep-release} and, if everything looks good,
+push the changes by copying the command that it printed:
+
+\
+$ git diff HEAD~1
+$ git push ...
+\
+
+\N|If something is wrong and you need to undo this commit, don't forget to
+also remove the tag. Note also that once you have pushed your changes, you
+cannot undo the commit. Instead, you will need to make a revision. See
+\l{#core-version-management Version management} for background and
+details.|
+
+
+\h2#core-release-publish-publish|Publish released version|
+
+Once the version is released we can publish the package to
+\l{https://cppget.org cppget.org} with the \l{bdep-publish(1)} command (see
+\l{intro#guide-versioning-releasing Versioning and Release Management} for
+background):
+
+\
+$ cd foo/ # Change to the package repository root.
+$ bdep publish
+\
+
+The \c{bdep-publish} command prepares the source distribution of your package,
+uploads the resulting archive to the package repository, and prints a link to
+the package submission in the queue. Open this link in the browser and check
+that there are no surprises in the build results (they should match the
+earlier CI results) or in the displayed package information
+(\c{PACKAGE-README.md}, etc).
+
+\N|While there should normally be no discrepancies in the build results
+compared to our earlier CI submissions, the way the packages are built on CI
+and in the package repository are not exactly the same. Specifically, CI
+builds them from \c{git} while the package repository \- from the submitted
+package archives. If there are differences, it's almost always due to issues
+in the source distribution preparation (see \l{#core-test-smoke-locally-dist
+Test locally: distribution}).|
+
+If everything looks good, then you are done: the package submission will be
+reviewed and, if there are no problems, moved to \l{https://cppget.org
+cppget.org}. If there are problems, then an issue will be created in the
+package repository with the review feedback. In this case you will need to
+\l{#core-version-management-new-revision release and publish a version
+revision} to address any problems. However, in both cases, you should first
+read through the following \l{#core-version-management Package version
+management} section to understand the recommended \"version lifecycle\" of a
+third-party package.
+
+Also, if there is an issue for this package in
+\l{https://github.com/build2-packaging/WISHLIST
+github.com/build2-packaging/WISHLIST}, then you would want to add a comment
+and close it once the package has been moved to \l{https://cppget.org
+cppget.org}.
+
+
+\h#core-version-management|Package version management|
+
+Once we have pushed the release commit, in order to preserve continuous
+versioning (see \l{#core-package-adjust-version Adjust package version} for
+background), no further changes should be made to the package without also
+changing its version.
+
+\N|More precisely, you can make and commit changes without changing the
+version provided they don't affect the package. For example, you may keep a
+\c{TODO} file in the root of your repository which is not part of any
+package. Updating such a file without changing the version is ok since the
+package remains unchanged.|
+
+While in our own projects we can change the versions as we see fit, with
+third-party projects the versions are dictated by upstream and as a result
+we are limited to what we can use to fix issues in our packaging work
+itself. It may be tempting (and perhaps even conceptually correct) to release
+a patch version for our own fixes, however, we will be in trouble if later
+upstream releases the same patch version but with a different set of changes
+(plus the users of our package may wonder where did this version come
+from). As a result, we should only change the major, minor, or patch
+components of the package version in response to the corresponding upstream
+releases. For fixes to the packaging work itself we should instead use version
+revisions.
+
+\N|Because a revision replaces the existing version, we should try to limit
+revision changes to bug fixes and preferably only in the package
+\"infrastructure\" (\c{buildfiles}, \c{manifest}, etc). Fixes to upstream
+source code should be limited to critical bugs and be preferably backported
+from upstream. To put it another way, changes in a revision should have an
+even more limited scope than a patch release.|
+
+Based on this, the recommended \"version lifecycle\" for a third-party
+package is as follows:
+
+\ol|
+
+\li|After a release (the \l{#core-release-publish-release Release final
+version} step above), for example, version \c{2.1.0}, the package enters a
+\"revision phase\" where we can release revisions (\c{2.1.0+1}, \c{2.1.0+2},
+etc) to address any issues in the packaging work. See
+\l{#core-version-management-new-revision New revision} for the detailed
+procedure.|
+
+\li|When a new upstream version is released, for example version \c{2.2.0},
+and we wish to upgrade our package to this version, we switch to its
+pre-release snapshot version (\c{2.2.0-a.0.z}) the same way as we did in the
+\l{#core-package-adjust-version Adjust package version} step initially. See
+\l{#core-version-management-new-version New version} for the detailed
+procedure.|
+
+\li|Once we are done upgrading to the new upstream version, we release the
+final version just like in the \l{#core-release-publish-release Release final
+version} step initially. At this point the package enters another revision
+phase.||
+
+Note also that in the above example, once we have switched to \c{2.2.0-a.0.z},
+we cannot go back and release another revision or patch version for \c{2.1.0}
+on the current branch. Instead, we will need to create a separate branch for
+the \c{2.1.Z} release series and make a revision or patch version there. See
+\l{#core-version-management-old-series New version/revision in old release
+series} for the detailed procedure.
+
+
+\h2#core-version-management-new-revision|New revision|
+
+As discussed in \l{#core-version-management Package version management}, we
+release revisions to fix issues in the package \"infrastructure\"
+(\c{buildfiles}, \c{manifest}, etc) as well as critical bugs in upstream
+source code.
+
+\N|Releasing a new revision is also a good opportunity to review and fix any
+accumulated issues that didn't warrant a revision on their own. See
+\l{#core-version-management-new-version-issues New version: review/fix
+accumulated issues} for background.|
+
+In the revision phase of the package version lifecycle (i.e., when the version
+does not end with \c{-a.0.z}), every commit must be accompanied by the
+revision increment to maintain continuous versioning. As a result, each
+revision release commit necessarily also contains the changes in this
+revision. Below is a typical workflow for releasing and publishing the
+revision:
+
+\
+$ # make changes
+$ # test locally
+$ git add .
+$ bdep release --revision --show-push
+$ # review commit
+$ git push ...
+$ # test with CI
+$ bdep publish
+\
+
+Customarily, the revision commit message has the \c{\"Release version
+X.Y.Z+R\"} summary as generated by \c{bdep-release} followed by the
+description of changes, organized in a list if there are several. For example:
+
+\
+Release version 2.1.0+1
+
+- Don't compile port/strlcpy.c on Linux if GNU libc is 2.38 or newer
+ since it now provides the strl*() functions.
+
+- Switch to using -pthread instead of -D_REENTRANT/-lpthread.
+\
+
+\N|The fact that all the changes must be in a single commit is another reason
+to avoid substantial changes in revisions.|
+
+Note also that you can make multiple commits while developing and testing the
+changes for a revision in a separate branch. However, once they are ready for
+a release, they need to be squashed into a single commit. The
+\l{bdep-release(1)} command provides the \c{--amend} and \c{--squash} options
+to automate this. For example, here is what a workflow with a separate branch
+might look like:
+
+\
+$ git checkout -b wip-2.1.0+1
+
+$ # make strl*() changes
+$ # test locally
+$ git commit -a -m \"Omit port/strlcpy.c if glibc 2.38 or newer\"
+$ git push -u
+$ # test with CI
+
+$ # make pthread changes
+$ # test locally
+$ git commit -a -m \"Switch to using -pthread\"
+$ git push
+$ # test with CI
+
+$ git checkout master
+$ git merge --ff-only wip-2.1.0+1
+$ bdep release --revision --show-push --amend --squash 2
+$ # review commit
+$ # test locally
+$ git push ...
+$ # test with CI
+$ bdep publish
+\
+
+
+\h2#core-version-management-new-version|New version|
+
+As discussed in \l{#core-version-management Package version management}, we
+release new versions strictly in response to the corresponding upstream
+releases.
+
+The amount or work required to upgrade a package to a new upstream version
+depends on the extend of changes in the new version.
+
+On one extreme you may have a patch release which fixes a couple of bugs in
+the upstream source code without any changes to the set of source files,
+upstream build system, etc. In such cases, upgrading a package is a simple
+matter of creating a new work branch, pointing the \c{upstream} \c{git}
+submodule to the new release, running tests, and then merging, releasing, and
+publishing a new package version.
+
+On the other extreme you may have a new major upstream release which is
+essentially a from-scratch rewrite with new source code layout, different
+upstream build system, etc. In such cases it may be easier to likewise start
+from scratch. Specifically, create a new work branch, point the \c{upstream}
+\c{git} submodule to the new release, delete the existing package, and
+continue from \l{#core-package Create package and generate \c{buildfile}
+templates}.
+
+Most of the time, however, it will be something in between where you may need
+to tweak a few things here and there, such as adding symlinks to new source
+files (or removing old ones), tweaking the \c{buildfiles} to reflect changes
+in the upstream build system, etc.
+
+The following sections provide a checklist-like sequence of steps that can be
+used to review upstream changes with links to the relevant earlier sections in
+case adjustments are required.
+
+
+\h2#core-version-management-new-version-branch|New version: create new work branch|
+
+When upgrading a package to a new upstream version it's recommended to do this
+in a new work branch which, upon completion, is merged into \c{master} (or
+equivalent). For example, if the new upstream version is \c{2.2.0}:
+
+\
+$ git checkout -b wip-2.2.0
+\
+
+\N|If you are not the maintainer of the package and would like to help with
+preparing the new version, then, when everything is ready, use this branch
+to create a pull request instead of merging it directly.|
+
+
+\h2#core-version-management-new-version-open|New version: open new version|
+
+This step corresponds to \l{#core-package-adjust-version Adjust package
+version} during the initial packaging. Here we can make use of the
+\c{bdep-release} command to automatically open the new version and make
+the corresponding commit. For example, if the new upstream version is
+\c{2.2.0}:
+
+\
+$ bdep release --open --no-push --open-base 2.2.0
+\
+
+
+\h2#core-version-management-new-version-submodule|New version: update \c{upstream} submodule|
+
+This step corresponds to \l{#core-repo-submodule Add upstream repository as
+\c{git} submodule} during the initial packaging. Here we need to update
+the submodule to point to the upstream commit that corresponds to the
+new version.
+
+For example, if the upstream release tag we are interested in is called
+\c{v2.2.0}, to update the \c{upstream} submodule to point to this release
+commit, run the following commands:
+
+\
+$ cd upstream/
+$ git checkout v2.2.0
+$ cd ../
+
+$ git add .
+$ git status
+$ git commit -m \"Update upstream submodule to 2.2.0\"
+\
+
+
+\h2#core-version-management-new-version-review|New version: review upstream changes|
+
+At this point it's a good idea to get an overview of the upstream changes
+between the two releases in order to determine which adjustments are likely to
+be required in the \c{build2} package. We can use the \c{upstream} submodule
+for that, which contains the change history we need.
+
+One way to get an overview of changes between the releases is to use a
+graphical repository browser such as \c{gitk} and view a cumulative \c{diff}
+of changes between the two versions. For example, assuming the latest packaged
+version is tagged \c{v2.1.0} and the new version is tagged \c{v2.2.0}:
+
+\
+$ cd upstream/
+$ gitk v2.1.0..v2.2.0 &
+\
+
+Then click on the commit tagged \c{v2.2.0}, scroll down and right-click on the
+commit tagged \c{v2.1.0}, and select the \"Diff this -> selected\" menu item.
+This will display the cumulative set of changes between these two upstream
+versions. Review them looking for the following types of changes in
+particular (discussed in the following sections):
+
+\ul|
+
+\li|Changes to the source code layout.|
+
+\li|New dependencies being added or old removed.|
+
+\li|New source files being added or old removed (including in tests, etc).|
+
+\li|Changes to the upstream build system.|
+
+\li|Other new files/subdirectories being added or old removed.||
+
+
+\h2#core-version-management-new-version-layout|New version: layout changes|
+
+As mentioned earlier, for drastic layout changes it may make sense to start
+from scratch and re-generate the package with the \c{bdep-new} command (use
+\l{#core-package-struct Decide on the package source code layout} as a
+starting point). On the other hand, if the changes are minor, then you can try
+to adjust things manually. An in-between strategy is to generate the new
+layout using \c{bdep-new} on the side and then retrofit the relevant changes
+in \c{buildfiles} to the existing package. In a sense, this approach uses
+\c{bdep-new} as a guide to figure out how to implement the new layout.
+
+
+\h2#core-version-management-new-version-dependencies|New version: new/old dependencies|
+
+If upstream added new or removed old dependencies, then you will need to
+replicate these changes in your package as in the \l{#core-fill-depend Add
+dependencies} and \l{#core-adjust-build-src-source-dep Adjust source
+\c{buildfile}: dependencies} initial packaging steps.
+
+
+\h2#core-version-management-new-version-sources|New version: new/old source files|
+
+If upstream added new or removed old source files, then you will need to
+replicate these changes in your package as in the \l{#core-fill-source Fill
+with upstream source code} and possibly \l{#core-adjust-build-src-header
+Adjust header \c{buildfile}} and \l{#core-adjust-build-src-source-src Adjust
+source \c{buildfile}: sources, private headers} initial packaging steps.
+
+Also don't forget about tests, examples, etc., which may also add new or
+remove old source files (typically new tests). See
+\l{#core-test-upstream-convert Convert smoke test to upstream tests}.
+
+If there are any manual modifications to the upstream source code, then you
+will also need to re-apply them to the new version as discussed in
+\l{#howto-patch-upstream-source-manual Modifying upstream source code
+manually}.
+
+
+\h2#core-version-management-new-version-build|New version: changes to build system|
+
+If upstream changed anything in the build system, then you may need to
+replicate these changes in your package's \c{buildfiles}. The relevant initial
+packaging steps are: \l{#core-adjust-build-wide Adjust project-wide build system files in
+\c{build/}} and \l{#core-adjust-build-src-source-opt Adjust source
+\c{buildfile}: build and export options}.
+
+The corresponding steps for tests are: \l{#core-test-smoke-build-wide Adjust
+project-wide build system files in \c{tests/build/}} and
+\l{#core-test-upstream-convert Convert smoke test to upstream tests}.
+
+
+\h2#core-version-management-new-version-other|New version: other new/old files/subdirectories|
+
+If upstream added or removed any other files or subdirectories that are
+relevant to our package (such as documentation), then adjust the package
+similar to the \l{#core-root-buildfile Adjust root \c{buildfile}} and
+\l{#core-root-buildfile-doc Adjust root \c{buildfile}: other subdirectories}
+initial packaging steps.
+
+
+\h2#core-version-management-new-version-root|New version: review \c{manifest} and \c{PACKAGE-README.md}|
+
+It makes sense to review the package \c{manifest} (\l{#core-root-manifest
+Adjust \c{manifest}}) and \c{PACKAGE-README.md} (\l{#core-root-package-readme
+Adjust \c{PACKAGE-README.md}}) for any updates.
+
+
+\h2#core-version-management-new-version-repo|New version: review repository \c{README.md}|
+
+If any new packages were added in this version or if there are any changes to
+the development workflow, then it makes sense to review and if necessary
+update package repository \c{README.md} (\l{#core-repo-readme Adjust package
+repository \c{README.md}}).
+
+
+\h2#core-version-management-new-version-issues|New version: review/fix accumulated issues|
+
+When a bug is identified in an already released package version, we may not
+always be able to fix it immediately (for example, by
+\l{#core-version-management-new-revision releasing a revision}). This could be
+because the change is too extensive/risky for a revision or simply not
+critical enough to warrant a release. In such cases it's recommended to file
+an issue in the package repository with the view to fix it when the next
+opportunity arises. Releasing a new upstream version is one such opportunity
+and it makes sense to review any accumulated package issues and see if any
+of them could be addressed.
+
+
+\h2#core-version-management-new-version-test|New version: test locally and with CI|
+
+Once all the adjustments are in, test the package both locally and with CI
+similar to how we did it during the initial packaging after completing the
+smoke test:
+
+\l{#core-test-smoke-locally Test locally}\n
+\l{#core-test-smoke-locally-install Test locally: installation}\n
+\l{#core-test-smoke-locally-dist Test locally: distribution}\n
+\l{#core-test-smoke-ci Commit and test with CI}
+
+
+\h2#core-version-management-new-version-release|New version: merge, release, and publish|
+
+When the new version of the package is ready to be released, merge the
+work branch to \c{master} (or equivalent):
+
+\
+$ git checkout master
+$ git merge --ff-only wip-2.2.0
+\
+
+Then release and publish using the same steps as after the initial packaging:
+\l{#core-release-publish Release and publish}.
+
+
+\h2#core-version-management-old-series|New version/revision in old release series|
+
+As discussed in \l{#core-version-management Package version management}, if we
+have already switched to the next upstream version in the \c{master} (or
+equivalent) branch, we cannot go back and release a new version or revision
+for an older release series on the same branch. Instead, we need to create a
+separate, long-lived branch for this work.
+
+As an example, let's say we need to release another revision or a patch
+version for an already released \c{2.1.0} while our \c{master} branch has
+already moved on to \c{2.2.0}. In this case we create a new branch, called
+\c{2.1}, to continue with the \c{2.1.Z} release series. The starting point of
+this branch should be the latest released version/revision in the \c{2.1}
+series. Let's say in our case it is \c{2.1.0+2}, meaning we have released two
+revisions for \c{2.1.0} on the \c{master} branch before upgrading to
+\c{2.2.0}. Therefore we use the \c{v2.1.0+2} release tag to start the
+\c{2.1} branch:
+
+\
+$ git checkout -b 2.1 v2.1.0+2
+\
+
+Once this is done, we continue with the same steps as in
+\l{#core-version-management-new-revision New revision} or
+\l{#core-version-management-new-version New version} except that we never
+merge this branch to \c{master}. If we ever need to release another revision
+or version in this release series, then we continue using this branch. In a
+sense, this branch becomes the equivalent of the \c{master} branch for this
+release series and you should treat it as such (once published, never delete,
+rewrite its history, etc).
+
+\N|It is less likely but possible that you may need to release a new minor
+version in an old release series. For example, the master branch may have
+moved on to \c{3.0.0} and you want to release \c{2.2.0} after the already
+released \c{2.1.0}. In this case it makes sense to call the branch \c{2} since
+it corresponds to the \c{2.Y.Z} release series. If you already have the
+\c{2.1} branch, then it makes sense to rename it to \c{2}.|
+
+
+\h1#dont-do|What Not to Do|
+
+This chapter describes the common anti-patterns along with the recommended
+alternative approaches.
+
+
+\h#dont-from-scratch|Don't write \c{buildfiles} from scratch, use \c{bdep-new}|
+
+Unless you have good reasons not to, create the initial project layout
+automatically using \l{bdep-new(1)}, then tweak it if necessary and fill with
+upstream source code.
+
+The main rationale here is that there are many nuances in getting the build
+right and auto-generated \c{buildfiles} had years of refinement and
+fine-tuning. The familiar structure also makes it easier for others to
+understand your build, for example while reviewing your package submission
+or helping out with the package maintenance.
+
+The \l{bdep-new(1)} command supports a wide variety of
+\l{bdep-new.xhtml#src-layout source layouts}. While it may take a bit of time
+to understand the customization points necessary to achieve the desired layout
+for your first package, this will pay off in spades when you work on
+converting subsequent packages.
+
+See \l{#core-package-craft-cmd Craft \c{bdep\ new} command line to create
+package} for details.
+
+
+\h#dont-fix-upstream|Avoid fixing upstream issues in the \c{build2} package|
+
+Any deviations from upstream makes the \c{build2} package more difficult to
+maintain. In particular, if you make a large number of changes to the upstream
+source code, releasing a new version will require a lot of work. As a result,
+it is recommended to avoid fixing upstream issues in the \c{build2} package.
+Instead, try to have the issues fixed upstream and wait for them to be
+released as a new version.
+
+Sometimes, however, you may have no choice. For example, upstream is inactive
+or has no plans to release a new version with your fixes any time soon. Or you
+may want to add support for a platform/compiler that upstream is not willing
+or capable of supporting.
+
+Note that even if you do fix some issues in the \c{build2} package directly,
+try hard to also incorporate them upstream so that you don't need to maintain
+the patches forever.
+
+See also \l{#dont-change-upstream Avoid changing upstream source code layout}
+and \l{#howto-patch-upstream-source How do I patch upstream source code?}
+
+
+\h#dont-change-upstream|Avoid changing upstream source code layout|
+
+It's a good idea to stay as close to the upstream's source code layout as
+possible. For background and rationale, see \l{#core-package-struct Decide on
+the package source code layout}.
+
+
+\h#dont-header-only|Don't make library header-only if it can be compiled|
+
+Some libraries offer two alternative modes: header-only and compiled. Unless
+there are good reasons not to, a \c{build2} build of such a library should use
+the compiled mode.
+
+\N|Some libraries use the \i{precompiled} term to describe the non-header-only
+mode. We don't recommend using this term in the \c{build2} package since it
+has a strong association with precompiled headers and can therefore be
+confusing. Instead, use the \i{compiled} term.|
+
+The main rationale here is that a library would not be offering a compiled
+mode if there were no benefits (usually faster compile times of library
+consumers) and there is no reason not to take advantage of it in the
+\c{build2} package.
+
+There are, however, valid reasons why a compiled mode cannot be used, the most
+common of which are:
+
+\ul|
+
+\li|The compiled mode is not well maintained/tested by upstream and therefore
+offers inferior user experience.|
+
+\li|The compiled mode does not work on some platforms, usually Windows due to
+the lack of symbol export support (but see \l{b#cc-auto-symexport Automatic
+DLL Symbol Exporting}).|
+
+\li|Uses of the compiled version of the library requires changes to the
+library consumers, for example, inclusion of different headers.|
+
+|
+
+If a compiled mode cannot always be used, then it may be tempting to support
+both modes by making the mode user-configurable. Unless there are strong
+reasons to, you should resist this temptation and, if the compiled mode is not
+universally usable, then use the header-only mode everywhere.
+
+The main rationale here is that variability adds complexity which makes the
+result more prone to bugs, more difficult to use, and harder to review and
+maintain. If you really want to have the compiled mode, then the right way to
+achieve it is to work with upstream to fix any issues that prevent its use
+in \c{build2}.
+
+There are, however, valid reasons why supporting both modes may be needed, the
+most common of which are:
+
+\ul|
+
+\li|The library is widely used in both modes but switching from one mode to
+the other requires changes to the library consumers (for example, inclusion of
+different headers). In this case only supporting one mode would mean not
+supporting a large number of library consumers.|
+
+\li|The library consists of a large number of independent components while its
+common for applications to only use a small subset of them. And compiling all
+of them in the compiled mode takes a substantial amount of time. Note that
+this can alternatively be addressed by making the presence of optional
+components user-configurable.|
+
+|
+
+
+\h#dont-bundle|Don't bundle dependencies|
+
+Sometimes third-party projects bundle their dependencies with their source
+code (also called vendoring). For example, a C++ library may bundle a testing
+framework. This is especially common with \l{https://cppget.org/catch2
+\c{catch2}} where one often encounters a comical situation with only a few
+kilobytes of library source code and over 600KB of \c{catch2.hpp}.
+
+The extra size, while wasteful, is not the main issue, however. The bigger
+problem is that if a bug is fixed in the bundled dependency, then to propagate
+the fix we will need to release a new version (or revision) of each package
+that bundles it. Needless to say this is not scalable.
+
+While this doesn't apply to testing frameworks, an even bigger issue with
+bundling of dependencies in general is that two libraries that bundle the same
+dependency (potentially of different versions) may not be able to coexist in
+the same build with the symptoms ranging from compile errors to subtle runtime
+issues that are hard to diagnose.
+
+As a result, it is strongly recommended that you unbundle any dependencies
+that upstream may have bundled. In case of testing frameworks, see
+\l{https://github.com/build2/HOWTO/blob/master/entries/handle-tests-with-extra-dependencies.md
+How do I handle tests that have extra dependencies?} for the recommended way
+to deal with such cases.
+
+\N|One special case where a bundled dependency may be warranted is a small
+utility that is completely inline/private to the implementation and where
+making it an external dependency may lead to a less performant result (due to
+the inability to inline without resorting to LTO). The \c{xxhash}
+implementation in \c{libzstd} is a representative example of this situation.|
+
+
+\h#dont-main-target-root-buildfile|Don't build your main targets in the root \c{buildfile}|
+
+It may be tempting to have your main targets (libraries, executables) in the
+root \c{buildfile}, especially if it allows you to symlink entire directories
+from \c{upstream/} (which is not possible if you have to have a \c{buildfile}
+inside). However, this is not recommended except for the simplest of projects.
+
+Firstly, this quickly gets messy since you have to combine managing
+\c{README}, \c{LICENSE}, etc., and subdirectories with your main target
+builds. More importantly, this also means that when your main target is
+imported (and thus the \c{buildfile} that defines this target must be loaded),
+your entire project will be loaded, including any \c{tests/} and \c{examples/}
+subprojects, and that is wasteful.
+
+
+If you want to continue symlinking entire directories from \c{upstream/} but
+without moving everything to the root \c{buildfile}, the recommended approach
+is to simply add another subdirectory level. Let's look at a few concrete
+example to illustrate the technique (see \l{#core-package-struct Decide on the
+package source code layout} for background on the terminology used).
+
+Here is the directory structure of a package which uses a combined layout (no
+header/source split) and where the library target is in the root
+\c{buildfile}:
+
+\
+libigl-core/
+├── igl/ -> ../upstream/igl/
+├── tests/
+└── buildfile # Defines lib{igl-core}.
+\
+
+And here is the alternative structure where we have added the extra
+\c{libigl-core} subdirectory with its own \c{buildfile}:
+
+\
+libigl-core/
+├── libigl-core/
+│   ├── igl/ -> ../../upstream/igl/
+│   └── buildfile # Defines lib{igl-core}.
+├── tests/
+└── buildfile
+\
+
+Below is the \c{bdep-new} invocation that can be used to automatically
+create this alternative structure (see \l{#core-package-craft-cmd Craft
+\c{bdep\ new} command line to create package} for background and
+\l{bdep-new(1)} for details):
+
+\
+$ bdep new \
+ --type lib,prefix=libigl-core,subdir=igl,buildfile-in-prefix \
+ libigl-core
+\
+
+Let's also look at an example of the split layout, which may require a
+slightly different \c{bdep-new} sub-options to achieve the same result. Here
+is the layout which matched upstream exactly:
+
+\
+$ bdep new --type lib,split,subdir=foo,no-subdir-source libfoo
+$ tree libfoo
+libfoo/
+├── include/
+│   └── foo/
+│   ├── buildfile
+│   └── ...
+└── src/
+ ├── buildfile
+ └── ...
+\
+
+However, with this layout we will not be able to symlink the entire
+\c{include/foo/} and \c{src/} subdirectories because there are \c{buildfiles}
+inside (and which may tempt you to just move everything to the root
+\c{buildfile}). To fix this we can move the \c{buildfiles} out of source
+subdirectory \c{foo/} and into prefixes (\c{include/} and \c{src/}) using the
+\c{buildfile-in-prefix} sub-option. And since \c{src/} doesn't have a source
+subdirectory, we have to invent one:
+
+\
+$ bdep new --type lib,split,subdir=foo,buildfile-in-prefix libfoo
+$ tree libfoo
+libfoo/
+├── include/
+│   ├── foo/ -> ../../upstream/include/foo/
+│   └── buildfile
+└── src/
+ ├── foo/ -> ../../upstream/src/
+ └── buildfile
+\
+
+
+\h#dont-big-changes-revision|Don't make extensive changes in a revision|
+
+Unlike a new version, a revision replaces the previous revision of the same
+version and as a result must be strictly backwards-compatible in all aspects
+with what it replaces. If you make extensive changes in a revision, it becomes
+difficult to guarantee that this requirement is satisfied. As a result, you
+should refrain from making major changes, like substantially altering the
+build, in a revision, instead delaying such changes until the next version.
+
+
+\h1#howto|Packaging HOWTO|
+
+This chapter provides advice on how to handle less common packaging
+tasks and requirements.
+
+
+\h#howto-patch-upstream-source|How do I patch upstream source code?|
+
+If you need to change something in the upstream source code, there are several
+options: You can make a copy of the upstream source file and make the
+modifications there. While straightforward, this approach has one major
+drawback: you will have to keep re-applying the changes for every subsequent
+version unless and until upstream incorporates your changes. The other two
+options try to work around this drawback.
+
+The first alternative option is to modify the upstream source code
+automatically during the build, typically using an ad hoc recipe. This
+approach works best when the changes are regular and can be applied
+mechanically with something like the \l{testscript#builtins-sed \c{sed}
+builtin}.
+
+The second alternative option is to use the C/C++ preprocessor to make the
+necessary changes to the upstream source code during compilation. Unlike the
+first alternative, this approach doesn't have a prescribed way to apply it in
+every situation and often requires some imagination. Note that it also has the
+tendency to quickly get out of hand, at which point it's wise to keep it
+simple and use the first option (manual modification).
+
+The following sections examine each approach in detail.
+
+
+\h2#howto-patch-upstream-source-manual|Modifying upstream source code manually|
+
+As an illustration of this approach, let's say we need to patch
+\c{src/foo.cpp} in our \c{libfoo} example from the previous sections (see the
+\l{#core-fill-source Fill with upstream source code} step for a refresher).
+The recommended sequence of steps is as follows:
+
+\ol|
+
+\li|Rename the upstream symlink to \c{.orig}:
+
+\
+$ cd libfoo/src/
+$ mv foo.cpp foo.cpp.orig
+\
+
+|
+
+\li|Make a deep copy of \c{.orig}:
+
+\
+$ cp -H foo.cpp.orig foo.cpp
+\
+
+|
+
+\li|Make any necessary modifications in the deep copy:
+
+\
+$ edit foo.cpp
+\
+
+|
+
+\li|Create a patch for the modifications:
+
+\
+$ diff -u foo.cpp.orig foo.cpp >foo.cpp.patch
+\
+
+||
+
+The presence of the \c{.orig} and \c{.patch} files makes it clear that the
+upstream code was modified. They are also useful when re-applying the changes
+to the new version of the upstream source code. The recommended sequence of
+steps for this task is as follows:
+
+\ol|
+
+\li|After the \c{upstream} submodule update (see the
+\l{#core-version-management-new-version-submodule New version: update
+\c{upstream} submodule} step), the \c{.orig} symlink points to the new version
+of the upstream source file.|
+
+\li|Overwrite old modified version with a deep copy of new \c{.orig}:
+
+\
+$ cp -H foo.cpp.orig foo.cpp
+\
+
+|
+
+\li|Apply old modifications to the new deep copy:
+
+\
+$ patch <foo.cpp.patch
+\
+
+If some hunks of the patch could not be applied, manually resolve any
+conflicts.|
+
+\li|If in the previous step the patch did not apply cleanly, regenerate it:
+
+\
+$ diff -u foo.cpp.orig foo.cpp >foo.cpp.patch
+\
+
+||
+
+
+\h2#howto-patch-upstream-source-build|Modifying upstream source code during build|
+
+As an illustration of this approach, let's say upstream is using the
+\c{${VAR\}} style variable substitutions in their \c{config.h.cmake} instead
+of the more traditional \c{@VAR@} style:
+
+\
+/* config.h.cmake */
+
+#define FOO_VERSION \"${PROJECT_VERSION}\"
+\
+
+The \c{${VAR\}} style is not supported by the \c{build2}
+\l{https://github.com/build2/libbuild2-autoconf \c{autoconf}} module which
+means we cannot use the upstream \c{config.h.cmake} as is. While we could
+patch this file manually to use \c{@VAR@} instead, this is a pretty mechanical
+change that can be easily made with a simple ad hoc recipe during the build,
+freeing us from manually applying the same changes in subsequent versions. For
+example:
+
+\
+using autoconf
+
+h{config}: in{config.h.in}
+{
+ autoconf.flavor = cmake
+ PROJECT_VERSION = $version
+}
+
+in{config.h.in}: file{config.h.cmake}
+{{
+ sed -e 's/\$\{(.+)\}/@\1@/g' $path($<) >$path($>)
+}}
+\
+
+
+\h2#howto-patch-upstream-source-preproc|Modifying upstream source code with C/C++ preprocessor|
+
+A good illustration of this approach is adding the \c{build2} metadata to an
+executable (see
+\l{https://github.com/build2/HOWTO/blob/master/entries/convey-additional-information-with-exe-lib.md
+How do I convey additional information (metadata) with executables and C/C++
+libraries?} for background). Let's say we have a symlink to upstream's
+\c{main.c} that implements the executable's \c{main()} function and we need to
+add a snipped of code at the beginning of this function that handles the
+\c{--build2-metadata} option. While manually modifying \c{main.c} is not a
+wrong approach, we can try to be clever and do it automatically with the
+preprocessor.
+
+Specifically, we can create another file next to the \c{main.c} symlink,
+calling it, for example, \c{main-build2.c}, with the following contents:
+
+\
+/* Handle --build2-metadata in main() (see also buildfile). */
+
+#define main xmain
+#include \"main.c\"
+#undef main
+
+#include <stdio.h>
+#include <string.h>
+
+int main (int argc, const char** argv)
+{
+ if (argc == 2 && strncmp (argv[1], \"--build2-metadata=\", 18) == 0)
+ {
+ printf (\"# build2 buildfile foo\n\");
+ printf (\"export.metadata = 1 foo\n\");
+ printf (\"foo.name = [string] foo\n\");
+ ...
+ return 0;
+ }
+
+ return xmain (argc, argv);
+}
+\
+
+The idea here is to rename the original \c{main()} with the help of the C
+preprocessor and provide our own \c{main()} which, after handling
+\c{--build2-metadata} calls the original. One notable deal-breaker for this
+approach would be a C++ implementation of \c{main()} that doesn't have the
+explicit \c{return}. There is also a better chance in C++ for the \c{main}
+macro to replace something unintended.
+
+To complete this we also need to modify our \c{buildfile} to exclude
+\c{main.c} from compilation (since it is compiled as part of \c{main-build2.c}
+via the preprocessor inclusion). For example:
+
+\
+exe{foo}: {h c}{** -main}
+exe{foo}: c{main}: include = adhoc # Included in main-build2.c.
+\
+
+
+\h#howto-bad-inclusion-practice|How do I deal with bad header inclusion practice?|
+
+This section explains how to deal with libraries that include their public,
+generically-named headers without the library name as a subdirectory
+prefix. Such libraries cannot coexist, neither in the same build nor when
+installed.
+
+Specifically, as an illustration of the problem, consider the \c{libfoo}
+library with a public header named \c{util.h} that is included as \c{<util.h>}
+(instead of, say, \c{<libfoo/util.h>} or \c{<foo/util.h>}). If this library's
+headers are installed directly into, say, \c{/usr/include}, then if two such
+libraries happened to be installed at the same time, then one will overwrite
+the other's header. There are also problems in the non-installed case: if two
+such libraries are used by the same project, then which \c{<util.h>} header
+gets included depends on which library's header search path ends up being
+specified first on the command line (with the \c{-I} option).
+
+These issues are severe enough that libraries with such inclusion issues
+cannot be published to \l{https://cppget.org cppget.org} without them being
+addressed in the \c{build2} package. Thankfully, most library authors these
+days use the library name as an inclusion prefix (or sometimes they have
+headers that are decorated with the library name). However, libraries that do
+not follow these guidelines do exist and this section describes how to change
+their inclusion scheme if you are attempting to package one of them.
+
+\N|One notable consequence of changing the inclusion scheme is that it will no
+longer be possible to use a system-installed version of the package (because
+it presumably still uses the unqualified inclusion scheme). Note, however,
+that distributions like Debian and Fedora have the same co-existence issue as
+we do and are generally strict about potential header clashes. In
+particular, it is not uncommon to find Debian packages installing library
+headers into subdirectories of \c{/usr/include} to avoid such clashes. And if
+you find this to be the case for the library you are packaging, then it may
+make sense to use the same prefix as used by the main distributions for
+compatibility.
+
+It is also possible that distributions disregard these considerations for some
+libraries. This usually happens for older, well-known libraries that happened
+to be installed this way in the early days and changing things now will be too
+disruptive. In a sense, it is understood that such libraries effectively
+\"own\" the unqualified header names that they happen to be using. If you
+think you are packaging such a library,
+\l{https://build2.org/community.xhtml#help get in touch} to discuss this
+further since it may make sense to also disregard this rule in
+\l{https://cppget.org cppget.org}.|
+
+As a concrete example of the approach, let's continue with \c{libfoo} that has
+\c{util.h} and which upstream expects the users to include as \c{<util.h>}.
+The is what the upstream source code layout may look like:
+
+\
+libfoo/
+├── include/
+│   └── util.h
+└── src/
+ └── ...
+\
+
+Our plan is to change the inclusion scheme in the \c{build2} package from
+\c{<util.h>} to \c{<libfoo/util.h>}. To this effect, we use a slightly
+modified layout for our package (see \l{#core-package-craft-cmd Craft \c{bdep
+new} command line to create package} on how to achieve it):
+
+\
+libfoo/
+├── include/
+│   └── libfoo/
+│   └── util.h -> ../../../upstream/include/util.h
+└── src/
+ └── ... -> ../../upstream/src/...
+\
+
+The installation-related section in our \l{#core-adjust-build-src-header
+header \c{buildfile}} will look like this:
+
+\
+# Install into the libfoo/ subdirectory of, say, /usr/include/
+# recreating subdirectories.
+#
+{hxx ixx txx}{*}:
+{
+ install = include/libfoo/
+ install.subdirs = true
+}
+\
+
+In the \l{#core-adjust-build-src-source source \c{buildfile}} we will most
+likely need to add the \c{include/libfoo} header search path since the
+upstream source files continue to include public headers without the library
+prefix (there should be no harm in that and it's not worth modifying them):
+
+\
+# Build options.
+#
+out_pfx_inc = [dir_path] $out_root/include/
+src_pfx_inc = [dir_path] $src_root/include/
+out_pfx_src = [dir_path] $out_root/src/
+src_pfx_src = [dir_path] $src_root/src/
+
+# Unqualified (without <libfoo/...>) header search paths.
+#
+out_pfx_inc_unq = [dir_path] $out_root/include/libfoo
+src_pfx_inc_unq = [dir_path] $src_root/include/libfoo
+
+cxx.poptions =+ \"-I$out_pfx_src\" \"-I$src_pfx_src\" \\
+ \"-I$out_pfx_inc\" \"-I$src_pfx_inc\" \\
+ \"-I$out_pfx_inc_unq\" \"-I$src_pfx_inc_unq\"
+\
+
+It is also possible that public headers include each other as \c{<util.h>}
+rather than the more common \c{\"util.h\"}. If that's the case, then we need
+to fix that and there are two ways to do it. The first approach is to patch
+the public headers to include each other with the library prefix (that is,
+\c{<libfoo/util.h>}, etc). See \l{#howto-patch-upstream-source How do I patch
+upstream source code?} for details.
+
+The second approach is to support including public headers both ways, that is,
+as \c{<libfoo/util.h>} and as \c{<util.h>}. This will not only solve the above
+problem (public headers including each other), but also support any existing
+code that uses this library and most likely includes its headers the old way,
+without the prefix.
+
+There is, however, a major drawback to doing that: while the installation of
+the library can now co-exist with other libraries (because we install its
+public headers into, say, \c{/usr/include/libfoo}), it may still not be usable
+in combination with other libraries from the same build (because we still add
+the unqualified header search path).
+
+If you still want to provide this dual inclusion support, the way to achieve
+it is by exporting the unqualified header search path and also adding it to
+the \c{pkg-config} files (see \l{#howto-extra-header-install-subdir How do I
+handle extra header installation subdirectory?} for background on the
+latter). For example:
+
+\
+# Export options.
+#
+lib{foo}:
+{
+ cxx.export.poptions = \"-I$out_pfx_inc\" \"-I$src_pfx_inc\" \\
+ \"-I$out_pfx_inc_unq\" \"-I$src_pfx_inc_unq\"
+ cxx.export.libs = $intf_libs
+}
+
+# Make sure headers installed into, say, /usr/include/libfoo/
+# can also be included without the directory prefix for backwards
+# compatibility.
+#
+lib{foo}: cxx.pkgconfig.include = include/ include/libfoo/
+\
+
+
+\h#howto-extra-header-install-subdir|How do I handle extra header installation subdirectory?|
+
+This section explains how to handle an additional header installation
+subdirectory. As an illustration of the problem, consider the \c{libfoo}
+example from the previous sections (see the \l{#core-fill-source Fill with
+upstream source code} step for a refresher). In that example the library
+headers are included as \c{<foo/util.hpp>} and installed as, say,
+\c{/usr/include/foo/util.hpp}. In this scheme the installed header inclusion
+works without requiring any extra steps from our side because the compiler
+searches for header in \c{/usr/include} by default.
+
+However, some libraries choose to install their headers into a subdirectory
+of, say, \c{/usr/include} but without having this subdirectory as part of the
+inclusion path (\c{foo/} in \c{<foo/util.hpp>}). The two typical reasons for
+this are support for installing multiple versions of the same library
+side-by-side (for example, \c{/usr/include/foo-v1/foo/util.hpp}) as well as
+not using the library name as the inclusion subdirectory prefix and then
+having to hide the headers in a subdirectory due to potential clashes with
+other headers (if installed directly into, say, \c{/usr/include}; see
+\l{#howto-bad-inclusion-practice How do I deal with bad header inclusion
+practice?} for background).
+
+In such cases the installed header inclusion does not work out of the box and
+we have to arrange for an additional header search path to be added via
+\c{pkg-config}. Let's use the versioned library case to illustrate this
+technique. The relevant part from the \l{#core-adjust-build-src-header header
+\c{buildfile}} will look like this:
+
+\
+# Install into the foo-vN/foo/ subdirectory of, say, /usr/include/
+# recreating subdirectories.
+#
+{hxx ixx txx}{*}:
+{
+ install = include/\"foo-v$version.major\"/foo/
+ install.subdirs = true
+}
+\
+
+The part that we need to add, this time to the
+\l{#core-adjust-build-src-source source \c{buildfile}}, looks like this:
+
+\
+# Make sure headers installed into, say, /usr/include/foo-vN/foo/
+# can be included as <foo/*.hpp> by overriding the header search
+# path in the generated pkg-config files.
+#
+lib{foo}: cxx.pkgconfig.include = include/\"foo-v$version.major\"/
+\
+
+\N|The variable will be \c{c.pkgconfig.include} for a C library.|
+
+
+\h#howto-no-extension-header|How do I handle headers without an extension?|
+
+If all the headers in a project have no extension, then you can simply
+specify the empty \c{extension} value for the \c{hxx{\}} target type
+in \c{build/root.build}:
+
+\
+hxx{*}: extension =
+cxx{*}: extension = cpp
+\
+
+Note, however, that using wildcard patterns for such headers in your
+\c{buildfile} is a bad idea since such a wildcard will most likely pick up
+other files that also have no extension (such as \c{buildfile}, executables on
+UNIX-like systems, etc). Instead, it's best to spell the names of such headers
+explicitly. For example, instead of:
+
+\
+lib{hello}: {hxx cxx}{*}
+\
+
+Write:
+
+\
+lib{hello}: cxx{*} hxx{hello}
+\
+
+If only some headers in a project have no extension, then it's best to specify
+the non-empty extension for the \c{extension} variable in \c{build/root.build}
+(so that you can still use wildcards for headers with extensions) and spell
+out the headers with no extension explicitly. Continuing with the above
+example, if we have both the \c{hello.hpp} and \c{hello} headers, then we can
+handle them like this:
+
+\
+hxx{*}: extension = hpp
+cxx{*}: extension = cpp
+\
+
+\
+lib{hello}: {hxx cxx}{*} hxx{hello.}
+\
+
+Notice the trailing dot in \c{hxx{hello.\}} \- this is the explicit \"no
+extension\" specification. See \l{b#targets Targets and Target Types}
+for details.
+
+
+\h#howto-debug-macro|How do I expose extra debug macros of a library?|
+
+Sometimes libraries provide extra debugging facilities that are usually
+enabled or disabled with a macro. For example, \c{libfoo} may provide the
+\c{LIBFOO_DEBUG} macro that enables additional sanity checks, tracing, etc.
+Normally, such facilities are disabled by default.
+
+While it may seem like a good idea to detect a debug build and enable this
+automatically, it is not: such facilities usually impose substantial overheads
+and the presence of debug information does not mean that performance is not
+important (people routinely make optimized builds with debug information).
+
+As a result, the recommended approach is to expose this as a configuration
+variable that the consumers of the library can use (see \l{b#proj-config
+Project Configuration} for background). Continue with the \c{libfoo} example,
+we can add \c{config.libfoo.debug} to its \c{build/root.build}:
+
+\
+# build/root.build
+
+config [bool] config.libfoo.debug ?= false
+\
+
+And then define the \c{LIBFOO_DEBUG} macro based on that in the \c{buildfile}:
+
+\
+# src/buildfile
+
+if $config.libfoo.debug
+ cxx.poptions += -DLIBFOO_DEBUG
+\
+
+If the macro is also used in the library's interface (for example, in inline
+or template functions), then we will also need to export it (see
+\l{#core-adjust-build-src-source-opt Adjust source \c{buildfile}: build and
+export options} for details):
+
+\
+# src/buildfile
+
+if $config.libfoo.debug
+{
+ cxx.poptions += -DLIBFOO_DEBUG
+ lib{foo}: cxx.export.poptions += -DLIBFOO_DEBUG
+}
+\
+
+\N|If the debug facility in question should be enabled by default even in the
+optimized builds (in which case the macro usually has the \c{NO_DEBUG}
+semantics), the other option is to hook it up to the standard \c{NDEBUG}
+macro, for example, in the library's configuration header file.|
+
+Note that such \c{.debug} configuration variables should primarily be meant
+for the user to selectively enable extra debugging support in certain
+libraries of their build. However, if your project depends on a number of
+libraries with such extra debugging support and it generally makes sense to
+also enable this support in dependencies if it is enabled in your project,
+then you may want to propagate your \c{.debug} configuration value to the
+dependencies (see the \l{bpkg#manifest-package-depends \c{depends} package
+\c{manifest} value} for details on dependency configuration). You, however,
+should still allow the user to override this decision on the per-dependency
+basis.
+
+Continuing with the above example, let's say we have \c{libbar} with
+\c{config.libbar.debug} that depends on \c{libfoo} and wishes by default to
+enable debugging in \c{libfoo} if it is enabled in \c{libbar}. This is how we
+can correctly arrange for this in \c{libbar}'s \c{manifest}:
+
+\
+depends:
+\\
+libfoo ^1.2.3
+{
+ # We prefer to enable debug in libfoo if enabled in libbar
+ # but accept if it's disabled (for example, by the user).
+ #
+ prefer
+ {
+ if $config.libbar.debug
+ config.libfoo.debug = true
+ }
+
+ accept (true)
+}
+\\
+\
+
+
+\h1#faq|Packaging FAQ|
+
+\h#faq-alpha-stable|Why is my package in \c{alpha} rather than \c{stable}?|
+
+If your package uses a semver version (or semver-like, that is, has three
+version components) and the first component is zero (for example, \c{0.1.0}),
+then, according to the semver specification, this is an alpha version and
+\l{bdep-publish(1)} automatically published such a version to the \c{alpha}
+section of the repository.
+
+Sometimes, however, in a third-party package, while the version may look like
+semver, upstream may not assign the zero first component any special
+meaning. In such cases you can override the \c{bdep-publish} behavior with the
+\c{--section} option, for example:
+
+\
+$ bdep publish --section=stable
+\
+
+Note that you should only do this if you are satisfied that by having the zero
+first component upstream does not imply alpha quality. Getting an explicit
+statement to this effect from upstream is recommended.
+
+
+\h#faq-publish-stage|Where to publish if package requires staged toolchain?|
+
+If your package requires the \l{https://build2.org/community.xhtml#stage staged
+toolchain}, for example, because it needs a feature or bugfix that is not yet
+available in the released toolchain, then you won't be able to publish it to
+\c{cppget.org}. Specifically, if your package has the accurate \c{build2}
+version constraint and you attempt to publish it, you will get an error like
+this:
+
+\
+error: package archive is not valid
+ info: unable to satisfy constraint (build2 >= 0.17.0-) for package foo
+ info: available build2 version is 0.16.0
+\
+
+There are three alternative ways to proceed in this situation:
+
+\ol|
+
+\li|Wait until the next release and then publish the package to
+\c{cppget.org}.|
+
+\li|If the requirement for the staged toolchain is \"minor\", that is, it
+doesn't affect the common functionality of the package or only affects a small
+subset of platforms/compilers, then you can lower the toolchain version
+requirement and publish the package to \c{cppget.org}. For example, if you
+require the staged toolchain because of a bugfix that only affects one
+platform, it doesn't make sense to delay publishing the package since it is
+perfectly usable on all the other platforms in the meantime.|
+
+\li|Publish it to \l{https://queue.stage.build2.org queue.stage.build2.org},
+the staging package repository. This repository contain new packages that
+require the staged toolchain to work and which will be automatically
+moved to \c{cppget.org} once the staged version is released. The other
+advantage of publishing to this repository (besides not having to remember
+to manually publish the package once the staged version is released) is
+that your package becomes available from an archive repository, which is
+substantially faster than a \c{git} repository.
+
+To publish to this repository, use the following \c{bdep-publish} command
+line:
+
+\
+$ bdep publish --repository=https://stage.build2.org ...
+\
+
+||
+
+
+"
diff --git a/doc/style b/doc/style
-Subproject 10f31a8bea8e5817fccf01978009c1ecaf3eabf
+Subproject b72eb624d13b1628e27e9f6c0b3c80853e8e015
diff --git a/libbpkg b/libbpkg
-Subproject 594a3bc993cd1d0df054ccc1ff06f5c047827fe
+Subproject 3f971b0055a5ad0e6af7b6923556e4263a119d7
diff --git a/libbuild2-autoconf b/libbuild2-autoconf
new file mode 120000
index 0000000..8f9c866
--- /dev/null
+++ b/libbuild2-autoconf
@@ -0,0 +1 @@
+submodules/libbuild2-autoconf/libbuild2-autoconf \ No newline at end of file
diff --git a/libbuild2-kconfig b/libbuild2-kconfig
new file mode 120000
index 0000000..b65cb37
--- /dev/null
+++ b/libbuild2-kconfig
@@ -0,0 +1 @@
+submodules/libbuild2-kconfig/libbuild2-kconfig \ No newline at end of file
diff --git a/libbutl b/libbutl
-Subproject 205c54bf10f4b0fdce64c5dace5c5a86de27d24
+Subproject 3a55e033e4fc9a18ede99c4f9dd69fd30c383cf
diff --git a/libodb b/libodb
-Subproject 0a9fc7cec04a3702a8ae586836b8b1fa83487bf
+Subproject 0074faad1b27f3cd52a606c438e4f1375956d73
diff --git a/libodb-sqlite b/libodb-sqlite
-Subproject 7085d9781b960a77f71d4f16e246ed44ea30b9f
+Subproject 73598cebc38cb5875cb6245b794cfb1194c61cc
diff --git a/libpkg-config b/libpkg-config
new file mode 120000
index 0000000..9e074db
--- /dev/null
+++ b/libpkg-config
@@ -0,0 +1 @@
+submodules/libpkg-config/libpkg-config \ No newline at end of file
diff --git a/libpkgconf b/libpkgconf
deleted file mode 120000
index 198d89a..0000000
--- a/libpkgconf
+++ /dev/null
@@ -1 +0,0 @@
-pkgconf/libpkgconf \ No newline at end of file
diff --git a/libsqlite3 b/libsqlite3
index 8e6dbf9..3ab815d 120000
--- a/libsqlite3
+++ b/libsqlite3
@@ -1 +1 @@
-sqlite/libsqlite3 \ No newline at end of file
+submodules/sqlite/libsqlite3 \ No newline at end of file
diff --git a/manifest b/manifest
index 70e39cc..a18422f 100644
--- a/manifest
+++ b/manifest
@@ -2,6 +2,6 @@
# Note: not a real package, just for the version module.
#
-version: 0.13.0-a.0.z
-depends: * build2 >= 0.13.0-
-depends: * bpkg >= 0.13.0-
+version: 0.17.0-a.0.z
+depends: * build2 >= 0.16.0-
+depends: * bpkg >= 0.16.0-
diff --git a/pkgconf b/pkgconf
deleted file mode 160000
-Subproject a881eefe7a5fe884e5b958bb2b861e58e90a044
diff --git a/sqlite b/sqlite
deleted file mode 160000
-Subproject 8f36ed542aa426f42d44fde6f6afc2888234c9f
diff --git a/submodules/libbuild2-autoconf b/submodules/libbuild2-autoconf
new file mode 160000
+Subproject 5a21714e143ef4403fbe9d2e92151581de81eab
diff --git a/submodules/libbuild2-kconfig b/submodules/libbuild2-kconfig
new file mode 160000
+Subproject 8d6272e45c99c678db4469f74141850e9eb9b17
diff --git a/submodules/libpkg-config b/submodules/libpkg-config
new file mode 160000
+Subproject 81bc60b381959b99cdef93d9326f3dd9522c307
diff --git a/submodules/sqlite b/submodules/sqlite
new file mode 160000
+Subproject 5b013b5507eb14bf51e565ec844d1fc462302f6
diff --git a/tests/README b/tests/README
new file mode 100644
index 0000000..6084038
--- /dev/null
+++ b/tests/README
@@ -0,0 +1,2 @@
+This subdirectory contains external tests for projects (such as build system
+modules) found in the root directory.
diff --git a/tests/libbuild2-autoconf-tests b/tests/libbuild2-autoconf-tests
new file mode 120000
index 0000000..38b1b4a
--- /dev/null
+++ b/tests/libbuild2-autoconf-tests
@@ -0,0 +1 @@
+../submodules/libbuild2-autoconf/libbuild2-autoconf-tests \ No newline at end of file
diff --git a/tests/libbuild2-kconfig-tests b/tests/libbuild2-kconfig-tests
new file mode 120000
index 0000000..2b2f3a7
--- /dev/null
+++ b/tests/libbuild2-kconfig-tests
@@ -0,0 +1 @@
+../submodules/libbuild2-kconfig/libbuild2-kconfig-tests \ No newline at end of file