Preview of main at d0a501a, 2026-11-07

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

WEBCPP_TARGET_WASIP2

__wasip2__

wasm32-wasip2, a component of WASI 0.2, built with wasi-sdk’s clang

WEBCPP_TARGET_WASIP3

__wasip3__

wasm32-wasip3, a component of WASI 0.3, built with wasi-sdk’s clang

WEBCPP_TARGET_EMSCRIPTEN

__EMSCRIPTEN__

Emscripten, for a browser or for node

WEBCPP_TARGET_NATIVE

none of the three, nor __wasm__

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 defined WEBCPP_NO_EXCEPTIONS. A build without exceptions, such as one with -fno-exceptions, which b2’s exception-handling=off gives, 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, as BOOST_VERSION is Boost’s: 0.1.0 is 100 and 1.2.3 is 100203. So WEBCPP_VERSION % 100 is the patch level, WEBCPP_VERSION / 100 % 1000 the minor version and WEBCPP_VERSION / 100000 the 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, as BOOST_LIB_VERSION is 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

alone-config

<webcpp/config.hpp> compiles alone, as the only include of its translation unit.

version

<webcpp/version.hpp> compiles alone, and its two macros name one version, WEBCPP_LIB_VERSION writing the patch level exactly when it is not 0.

target

Exactly one target macro is defined, the one of the toolset the build is for, which test/Jamfile tells the test.

exceptions, exceptions_off, exceptions_developer_off

WEBCPP_HAS_EXCEPTIONS is defined exactly when webcpp has exceptions: as the build asks, with exception-handling=off, and with WEBCPP_NO_EXCEPTIONS defined, which leaves BOOST_NO_EXCEPTIONS as the compiler has it; config never defines WEBCPP_NO_EXCEPTIONS, and it includes <boost/config.hpp>.

predefined_target, predefined_wasip2, predefined_wasip3, predefined_emscripten, predefined_exceptions

A target macro, or WEBCPP_HAS_EXCEPTIONS, defined on the command line stops the build with config’s message alone.

unsupported_wasip1, unsupported_wasm32_unknown, unsupported_wasm

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 <boost/config.hpp> for the second, and __wasm__ defined alone natively.

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

clang-wasip2, the clang of wasi-sdk for wasm32-wasip2, run by wasmtime

13

2

wasip3

clang-wasip3, for wasm32-wasip3, run by wasmtime

11

2

emscripten

emscripten, Emscripten’s em++, whose programs b2’s toolset runs with node itself

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

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.

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.

WEBCPP_NO_EXCEPTIONS

Defined by the developer to disable the exceptions of every webcpp library at once, even in a build that has them.

WEBCPP_TARGET_EMSCRIPTEN

Defined when the program is built with Emscripten, for a browser or for node.

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.

WEBCPP_TARGET_WASIP2

Defined when the program is built for wasm32-wasip2, as a component of WASI 0.2.

WEBCPP_TARGET_WASIP3

Defined when the program is built for wasm32-wasip3, as a component of WASI 0.3.

WEBCPP_VERSION

webcpp’s version as a number, major * 100000 + minor * 100 + patch, as BOOST_VERSION is Boost’s.

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.

Synopsis

Declared in <webcpp/config.hpp>

#define WEBCPP_HAS_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.

Synopsis

Declared in <webcpp/version.hpp>

#define WEBCPP_LIB_VERSION

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.

Synopsis

Declared in <webcpp/config.hpp>

#define WEBCPP_NO_EXCEPTIONS

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.

Synopsis

Declared in <webcpp/config.hpp>

#define WEBCPP_TARGET_EMSCRIPTEN

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.

Synopsis

Declared in <webcpp/config.hpp>

#define WEBCPP_TARGET_NATIVE

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.

Synopsis

Declared in <webcpp/config.hpp>

#define WEBCPP_TARGET_WASIP2

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.

Synopsis

Declared in <webcpp/config.hpp>

#define WEBCPP_TARGET_WASIP3

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.

Synopsis

Declared in <webcpp/version.hpp>

#define WEBCPP_VERSION

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.