Introduction
config is webcpp’s configuration, as
Boost.Config is
Boost’s, one of the libraries of webcpp.
<webcpp/config.hpp> tells a program the target it is built for
(Targets) and whether webcpp has exceptions
(Exceptions), and <webcpp/version.hpp> webcpp’s version
(Version).
Every webcpp library’s own configuration, <webcpp/<library>/config.hpp>,
includes <webcpp/config.hpp> first, and every public header of the library
includes its configuration first: whatever a program includes of webcpp,
config is read before it. <webcpp/config.hpp> includes
<boost/config.hpp> and <webcpp/version.hpp>, so a program that includes
it has Boost.Config’s macros and webcpp’s version too.
config is macros only, as Boost.Config is: it declares no namespace, no type
and no function, and needs Boost’s headers and nothing to build or link. Its
macros are the collection’s, WEBCPP_*, where every other library’s are
WEBCPP_<LIBRARY>_*, and so no library’s name is target, has, no,
lib, version or test, alone or followed by an underscore and more
(has_x): its macros would meet config’s, or the tests’ WEBCPP_TEST_*.
A library builds its own configuration on it. The program below holds the
configuration of a library of its own, my_library, in a few lines: its macro
MY_LIBRARY_NO_EXCEPTIONS is defined when webcpp has no exceptions, or when
the developer defines it alone, as each webcpp library defines its
WEBCPP_<LIBRARY>_NO_EXCEPTIONS:
// my_library's own macro: defined when webcpp has no exceptions (the compiler has none, or the
// developer defined WEBCPP_NO_EXCEPTIONS), or when the developer defines it alone.
#if !defined(WEBCPP_HAS_EXCEPTIONS) && !defined(MY_LIBRARY_NO_EXCEPTIONS)
#define MY_LIBRARY_NO_EXCEPTIONS
#endif
The program then chooses its code by that macro, as the library’s own code does:
#ifdef MY_LIBRARY_NO_EXCEPTIONS
std::puts("my_library: exceptions off");
#else
std::puts("my_library: exceptions on");
#endif
Built with exceptions, as every target of webcpp builds by default, it prints, natively, on wasm32-wasip2, on wasm32-wasip3 and with Emscripten:
my_library: exceptions on
Built with exception-handling=off, the same program prints:
my_library: exceptions off
Targets
webcpp builds a program for one of four targets, and <webcpp/config.hpp>
defines exactly one macro, which names it, from the macro the compiler
itself defines for that target:
| Macro | The compiler defines | The target |
|---|---|---|
|
|
wasm32-wasip2, a component of WASI 0.2, built with wasi-sdk’s clang |
|
|
wasm32-wasip3, a component of WASI 0.3, built with wasi-sdk’s clang |
|
|
Emscripten, for a browser or for node |
|
none of the three, nor |
the host’s system, with any compiler for it: GCC, Clang or MSVC |
The macros come from the compiler, never from the build system: a program
compiled by hand, with a plain clang++ or with wasi-sdk’s, gets the macro
b2 would give it. The program of Introduction chooses by them,
when it is compiled, the name of where its standard output goes:
// Where the program's standard output goes, chosen when it is compiled.
constexpr std::string_view output() {
#ifdef WEBCPP_TARGET_EMSCRIPTEN
return "the JavaScript console";
#elif defined(WEBCPP_TARGET_WASIP2) || defined(WEBCPP_TARGET_WASIP3)
return "the WASI host's standard output";
#else
return "the process's standard output";
#endif
}
A WebAssembly build for none of the three WebAssembly targets, such as
wasm32-wasip1 or wasm32-unknown-unknown, is not read as native: the
compiler defines __wasm__ there, and <webcpp/config.hpp> stops the
build with the error
unsupported target: webcpp builds for wasm32-wasip2, wasm32-wasip3, Emscripten and natively
The header names the target before it includes <boost/config.hpp>, so
that wasm32-unknown-unknown, which has no C++ standard library and on
which Boost.Config stops at a header that is not there, gets this message
first. A new target will get a macro of its own.
The target macros, and WEBCPP_HAS_EXCEPTIONS (Exceptions), are
defined by <webcpp/config.hpp> alone. A build that defines one of them
before the header, on the command line or in a header of its own, stops with the
error
WEBCPP_TARGET_* and WEBCPP_HAS_EXCEPTIONS are defined by <webcpp/config.hpp> alone
and with nothing more: the rest of the header is skipped, so that no macro is defined a second time.
Exceptions
Every target of webcpp builds with exceptions on, and whether a program uses
them is the choice of whoever builds it. <webcpp/config.hpp> tells that
choice to every webcpp library with two macros:
WEBCPP_HAS_EXCEPTIONS-
Defined when webcpp has exceptions: when the compiler has them, so that Boost.Config defines no
BOOST_NO_EXCEPTIONS, and the developer has not definedWEBCPP_NO_EXCEPTIONS. A build without exceptions, such as one with-fno-exceptions, which b2’sexception-handling=offgives, has none. WEBCPP_NO_EXCEPTIONS-
Never defined by config: the developer defines it, on the compiler’s command line (
-DWEBCPP_NO_EXCEPTIONS) or in a b2 project’s requirements (<define>WEBCPP_NO_EXCEPTIONS), to turn off the exceptions of every webcpp library at once, in a build that has them.
Each webcpp library’s own macro, WEBCPP_<LIBRARY>_NO_EXCEPTIONS, follows
them, as MY_LIBRARY_NO_EXCEPTIONS does in the program of
Introduction: it is defined when WEBCPP_HAS_EXCEPTIONS is not,
and a developer may still define it alone, to turn off the exceptions of
one library and keep the others’. A program sets WEBCPP_NO_EXCEPTIONS
once, for every webcpp library alike, without knowing which of them throws.
Boost’s own exceptions are left as the compiler has them:
WEBCPP_NO_EXCEPTIONS does not define BOOST_NO_EXCEPTIONS, and Boost’s
code keeps its exceptions in a build that has them.
Version
<webcpp/version.hpp> gives webcpp’s version, the version of the
collection, as <boost/version.hpp> gives Boost’s, with two macros:
WEBCPP_VERSION-
The version as a number,
major * 100000 + minor * 100 + patch, asBOOST_VERSIONis Boost’s: 0.1.0 is100and 1.2.3 is100203. SoWEBCPP_VERSION % 100is the patch level,WEBCPP_VERSION / 100 % 1000the minor version andWEBCPP_VERSION / 100000the major one, and a program compares it in#if, as in#if WEBCPP_VERSION >= 100. WEBCPP_LIB_VERSION-
The version as text,
"<major>_<minor>", with"_<patch>"after it when the patch level is not 0, asBOOST_LIB_VERSIONis Boost’s:"0_1"is 0.1.0 and"1_2_3"is 1.2.3.
<webcpp/version.hpp> is the one place webcpp’s version is written. It
moves to the next version right after each release, by the release
procedure of webcpp’s
AGENTS.md
(chapter 5), so that between two releases it names the one in preparation.
How config is tested
What config does, it does when a program is compiled, so its tests are
compiled and never run, each declared in test/Jamfile with one of
webcpp’s rules: webcpp.headers-alone, which compiles each public header
as the only include of its translation unit; webcpp.compile, a
translation unit that checks the macros with #error and static_assert
and passes when it compiles; and webcpp.compile-diagnostic, a source that
passes when clang stops it with the error it states. test/Jamfile
declares 14 of them:
| Test | What it checks |
|---|---|
|
|
|
|
|
Exactly one target macro is defined, the one of the toolset the build is
for, which |
|
|
|
A target macro, or |
|
A WebAssembly build for none of webcpp’s targets stops with
"unsupported target": wasm32-wasip1 and wasm32-unknown-unknown with
wasi-sdk’s clang, before |
example/Jamfile builds the program this page shows, runs it, and compares
what it printed with the .expected beside it; a program that returns
anything but 0 fails too.
Targets
test/Jamfile and example/Jamfile declare the four targets,
webcpp.targets native wasip2 wasip3 emscripten, and b2 builds each program
for those alone. A webcpp.compile-diagnostic test is built on b2’s clang
toolset alone, native clang, clang-wasip2 and clang-wasip3, since
-verify, which reads the error a source states, is clang’s: GCC, MSVC and
Emscripten skip the predefined_* and unsupported_* tests.
| Target | Toolset | Tests declared | Examples |
|---|---|---|---|
native |
any toolset that is not one of the three below: GCC, Clang and MSVC among them |
12 |
2 |
wasip2 |
|
13 |
2 |
wasip3 |
|
11 |
2 |
emscripten |
|
11 |
2 |
A count is of the tests a target’s Jamfile declares: with GCC, MSVC and
Emscripten, b2 skips the predefined_* and unsupported_* tests among
them, as above.
From the root of a webcpp checkout, these build every test and build and
run every example, natively, for wasm32-wasip2, for wasm32-wasip3 and with Emscripten,
with the toolsets a user-config.jam registers, as webcpp’s
AGENTS.md shows:
b2 libs/config/test libs/config/example
b2 toolset=clang-wasip2 testing.launcher=wasmtime libs/config/test libs/config/example
b2 toolset=clang-wasip3 testing.launcher=wasmtime libs/config/test libs/config/example
b2 toolset=emscripten libs/config/test libs/config/example
Emscripten is given no testing.launcher: b2’s toolset runs its programs
with node itself. b2 compares timestamps, so a result that counts is built
from scratch, with b2 -a. b2 libs/config/test//target builds one test
alone, while working on it.
The test matrix
The continuous integration runs config’s tests and examples in lanes, one toolset each: the native compilers, wasip2, wasip3 and emscripten. Each lane builds from scratch and records what b2 built and ran:
b2 -a --dump-tests --out-xml=<lane>.xml toolset=<toolset> libs/config/test libs/config/example
webcpp’s tools/report/report.py merges the files of every lane into a
matrix: a page of the libraries by lanes, and a page of each library’s tests
and examples by lanes, where each cell says whether that program passed in
that lane, or how it failed. A test b2 skips in a lane, as a
predefined_* test with GCC, is a grey cell there. The matrix is published
with the documentation, at https://webcpporg.github.io/webcpp/report/.
Reference
The macros of <webcpp/config.hpp> and <webcpp/version.hpp>.
Macros
| Name | Description |
|---|---|
Defined when webcpp has exceptions: when the compiler has them, so that Boost.Config defines no |
|
webcpp’s version as text, |
|
Defined by the developer to disable the exceptions of every webcpp library at once, even in a build that has them. |
|
Defined when the program is built with Emscripten, for a browser or for node. |
|
Defined when the program is built natively, for the host’s system: for none of wasm32-wasip2, wasm32-wasip3 and Emscripten, and not for WebAssembly, which, outside those three targets, stops the build. |
|
Defined when the program is built for wasm32-wasip2, as a component of WASI 0.2. |
|
Defined when the program is built for wasm32-wasip3, as a component of WASI 0.3. |
|
webcpp’s version as a number, |
WEBCPP_HAS_EXCEPTIONS
Defined when webcpp has exceptions: when the compiler has them, so that Boost.Config defines no BOOST_NO_EXCEPTIONS, and the developer has not defined WEBCPP_NO_EXCEPTIONS.
Description
Each library’s WEBCPP_<LIBRARY>_NO_EXCEPTIONS is defined when this is not, or when the developer defines it alone.
See Also
"Exceptions", in the guide.
WEBCPP_LIB_VERSION
webcpp’s version as text, "<major>_<minor>", with "_<patch>" after it when the patch level is not 0, as BOOST_LIB_VERSION is Boost’s.
Description
"0_1" is 0.1.0 and "1_2_3" is 1.2.3.
See Also
"Version", in the guide.
WEBCPP_NO_EXCEPTIONS
Defined by the developer to disable the exceptions of every webcpp library at once, even in a build that has them.
Description
With it, WEBCPP_HAS_EXCEPTIONS is not defined, and so each library’s WEBCPP_<LIBRARY>_NO_EXCEPTIONS is. Boost’s own exceptions are left as the compiler has them: BOOST_NO_EXCEPTIONS is not defined by it.
See Also
"Exceptions", in the guide.
WEBCPP_TARGET_EMSCRIPTEN
Defined when the program is built with Emscripten, for a browser or for node.
Description
The compiler says so with __EMSCRIPTEN__.
See Also
"Targets", in the guide.
WEBCPP_TARGET_NATIVE
Defined when the program is built natively, for the host’s system: for none of wasm32-wasip2, wasm32-wasip3 and Emscripten, and not for WebAssembly, which, outside those three targets, stops the build.
See Also
"Targets", in the guide.
WEBCPP_TARGET_WASIP2
Defined when the program is built for wasm32-wasip2, as a component of WASI 0.2.
Description
The compiler says so with __wasip2__, which wasi-sdk’s clang defines for the target wasm32-wasip2.
See Also
"Targets", in the guide.
WEBCPP_TARGET_WASIP3
Defined when the program is built for wasm32-wasip3, as a component of WASI 0.3.
Description
The compiler says so with __wasip3__, which wasi-sdk’s clang defines for the target wasm32-wasip3.
See Also
"Targets", in the guide.
WEBCPP_VERSION
webcpp’s version as a number, major * 100000 + minor * 100 + patch, as BOOST_VERSION is Boost’s.
Description
0.1.0 is 100 and 1.2.3 is 100203: WEBCPP_VERSION % 100 is the patch level, WEBCPP_VERSION / 100 % 1000 the minor version and WEBCPP_VERSION / 100000 the major one.
See Also
"Version", in the guide.
Appendix A: Changelog
What changed in config in each version of webcpp, newest first, one line per change. "Unreleased" is what the next version brings. The release notes of every version are on webcpp’s index page.
Unreleased
webcpp 0.1.0
-
Added the library, with webcpp’s target, exceptions and version macros.