pw_toolchain#
Embedded toolchains for GN-based Pigweed projects
Stable GN
GN toolchains function both as a set of tools for compilation and as a workspace for evaluating build files. The same compilations and actions can be executed by different toolchains. Each toolchain maintains its own set of build args, and build steps from all toolchains can be executed in parallel.
C/C++ toolchain support libraries#
pw_toolchain
provides some toolchain-related C/C++ libraries.
std:abort
wrapper#
The std::abort function is used to terminate a program abnormally. This function may be called by standard library functions, so is often linked into binaries, even if users never intentionally call it.
For embedded builds, the abort
implementation likely does not work as
intended. For example, it may pull in undesired dependencies (e.g.
std::raise
) and end in an infinite loop.
pw_toolchain
provides the pw_toolchain:wrap_abort
library that replaces
abort
in builds where the default behavior is undesirable. It uses the
-Wl,--wrap=abort
linker option to redirect to abort
calls to
PW_CRASH
instead.
arm-none-eabi-gcc support#
Targets building with the GNU Arm Embedded Toolchain (arm-none-eabi-gcc
)
should depend on the pw_toolchain/arm_gcc:arm_none_eabi_gcc_support
library. In GN, that target should be included in pw_build_LINK_DEPS
. In
Bazel, it should be added to link_extra_lib or
directly to the deps of any binary being build with that toolchain:
cc_binary(
deps = [
# Other deps, omitted
] + select({
"@platforms//cpu:armv7e-m": [
"@pigweed//pw_toolchain/arm_gcc:arm_none_eabi_gcc_support",
],
"//conditions:default": [],
}),
)
Newlib OS interface#
Newlib, the C Standard Library
implementation provided with arm-none-eabi-gcc
, defines a set of OS
interface functions that
should be implemented. Newlib provides default implementations, but using these
results in linker warnings like the following:
readr.c:(.text._read_r+0x10): warning: _read is not implemented and will always fail
Most of the OS interface functions should never be called in embedded builds.
The pw_toolchain/arg_gcc:newlib_os_interface_stubs
library, which is
provided through pw_toolchain/arm_gcc:arm_none_eabi_gcc_support
, implements
these functions and forces a linker error if they are used. It also
automatically includes a wrapper for abort
for use of stdout
and
stderr
which abort if they are called.
If you need to use your own wrapper for abort
, include the library directly
using pw_toolchain/arm_gcc:newlib_os_interface_stubs
.
pw_toolchain/no_destructor.h#
-
template<typename T>
class NoDestructor# Helper type to create a function-local static variable of type
T
whenT
has a non-trivial destructor. Storing aT
in apw::NoDestructor<T>
will prevent~T()
from running, even when the variable goes out of scope.This class is useful when a variable has static storage duration but its type has a non-trivial destructor. Destructor ordering is not defined and can cause issues in multithreaded environments. Additionally, removing destructor calls can save code size.
Except in generic code, do not use
pw::NoDestructor<T>
with trivially destructible types. Use the type directly instead. If the variable can beconstexpr
, make itconstexpr
.pw::NoDestructor<T>
provides a similar API tostd::optional
. Use*
or->
to access the wrapped type.Example usage:
pw::sync::Mutex& GetMutex() { // Use NoDestructor to avoid running the mutex destructor when exit-time // destructors run. static const pw::NoDestructor<pw::sync::Mutex> global_mutex; return *global_mutex; }
In Clang,
pw::NoDestructor
can be replaced with the [[clang::no_destroy]] attribute.pw::NoDestructor<T>
is similar to Chromium’sbase::NoDestructor<T>
in src/base/no_destructor.h.Warning
Misuse of NoDestructor can cause memory leaks and other problems. Only skip destructors when you know it is safe to do so.
builtins#
builtins are LLVM’s equivalent of libgcc, the compiler will insert calls to
these routines. Setting the dir_pw_third_party_builtins
gn var to your
compiler-rt/builtins checkout will enable building builtins from source instead
of relying on the shipped libgcc.