aboutsummaryrefslogtreecommitdiff
path: root/doc/intro.cli
diff options
context:
space:
mode:
Diffstat (limited to 'doc/intro.cli')
-rw-r--r--doc/intro.cli375
1 files changed, 279 insertions, 96 deletions
diff --git a/doc/intro.cli b/doc/intro.cli
index 045d949..6671cbd 100644
--- a/doc/intro.cli
+++ b/doc/intro.cli
@@ -25,10 +25,12 @@
// - Maximum <pre> line is 70 characters.
//
-// Some people say the find the TLDR "abhorrent" (because it doesn't look
+// 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|
@@ -104,8 +106,8 @@ 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.
+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|
@@ -280,6 +282,7 @@ $ cat manifest
: 1
name: hello
version: 0.1.0-a.0.z
+language: c++
summary: hello C++ executable
license: other: proprietary
description-file: README.md
@@ -389,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 ^
@@ -480,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!
@@ -502,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!
@@ -519,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
@@ -530,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
@@ -550,7 +556,7 @@ 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}
\
@@ -561,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!
@@ -1098,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/
\
@@ -1151,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
@@ -1480,11 +1489,13 @@ 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/c{xxd}
+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-gcc/hello/hello/cxx{names}
-c++ ../hello-gcc/hello/hello/cxx{names}
-c++ hello/cxx{hello}@../hello-gcc/hello/hello/
+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}
\
@@ -1517,9 +1528,10 @@ $ bdep update @clang
synchronizing:
upgrade hello/0.1.0-a.0.19700101000000#4
-xxd ../hello-clang/hello/hello/cxx{names}
-c++ ../hello-clang/hello/hello/cxx{names}
-c++ hello/cxx{hello}@../hello-clang/hello/hello/
+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}
\
@@ -2093,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:
@@ -2242,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
@@ -2333,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}
@@ -2369,10 +2407,10 @@ 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!
@@ -2458,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
@@ -2511,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
@@ -2525,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
@@ -2543,39 +2638,126 @@ configures the \c{libsqlite3} package as coming from the system:
\
$ bdep sync ?sys:libsqlite3
-synchronizing:
- configure sys:libsqlite3/* (required by hello)
- upgrade hello/0.1.0-a.0.19700101000000#3
\
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/* (required by hello)
+ upgrade hello/0.1.0-a.0.19700101000000#3
+\
+
+\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|
@@ -2725,7 +2907,7 @@ 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{--source} modes can be used to automate this process.|
@@ -2772,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).}|
@@ -2823,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
@@ -2831,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
@@ -2898,8 +3080,8 @@ 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.
@@ -2928,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:
@@ -2940,7 +3123,7 @@ 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{\"\"}
@@ -2949,7 +3132,7 @@ 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 at
minimum insist on this: \b{public header inclusions must use the library name
-as a directory prefix}.
+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
@@ -2986,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/
@@ -3221,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:
\