• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1.. _module-pw_toolchain:
2
3============
4pw_toolchain
5============
6GN toolchains function both as a set of tools for compilation and as a workspace
7for evaluating build files. The same compilations and actions can be executed by
8different toolchains. Each toolchain maintains its own set of build args, and
9build steps from all toolchains can be executed in parallel.
10
11-------------
12GN Toolchains
13-------------
14``pw_toolchain`` module provides GN toolchains that may be used to build
15Pigweed. Various GCC and Clang toolchains for multiple platforms are provided.
16Toolchains names typically include the compiler (``clang`` or ``gcc`` and
17optimization level (``debug``, ``size_optimized``, ``speed_optimized``).
18
19Non-C/C++ toolchains
20====================
21``pw_toolchain/non_c_toolchain.gni`` provides the ``pw_non_c_toolchain``
22template. This template creates toolchains that cannot compile C/C++ source
23code. These toolchains may only be used to execute GN actions or declare groups
24of targets in other toolchains. Attempting to compile C/C++ code with either of
25these toolchains results in errors.
26
27Non-C/C++ toolchains can be used to consolidate actions that should only occur
28once in a multi-toolchain build. Build targets from all toolchains can refer to
29these actions in a non-C/C++ toolchain so they only execute once instead of once
30per toolchain.
31
32For example, Pigweed runs protobuf compilation and Python package actions like
33installation and Pylint in toolchains created with ``pw_non_c_toolchain``. This
34allows all toolchains to cleanly share the same protobuf and Python declarations
35without any duplicated work.
36
37Testing other compiler versions
38===============================
39The clang-based toolchain provided by Pigweed can be substituted with another
40version by modifying the ``pw_toolchain_CLANG_PREFIX`` GN build argument to
41point to the directory that contains the desired clang, clang++, and llvm-ar
42binaries. This should only be used for debugging purposes. Pigweed does not
43officially support any compilers other than those provided by Pigweed.
44
45Running static analysis checks
46==============================
47``clang-tidy`` can be run as a compiler replacement, to analyze all sources
48built for a target. ``pw_toolchain/static_analysis_toolchain.gni`` provides
49the ``pw_static_analysis_toolchain`` template. This template creates toolchains
50that execute ``clang-tidy`` for C/C++ sources, and mock implementations of
51the ``link``, ``alink`` and ``solink`` tools.
52
53In addition to the standard toolchain requirements (`cc`, `cxx`, etc..), the
54``pw_static_analysis_toolchain`` template requires a scope ``static_analysis``
55to be defined on the invoker.
56
57.. code-block::
58
59   static_analysis = {
60    # Configure whether static_analysis should be enabled for invoker toolchain.
61    # This is must be set true if using pw_static_analysis_toolchain.
62    enabled = true
63    # Optionally override clang-tidy binary to use by setting to proper path.
64    clang_tidy_path = ""
65    # Optionally specify additional command(s) to run as part of cc tool.
66    cc_post = ""
67    # Optionally specify additional command(s) to run as part of cxx tool.
68    cxx_post = ""
69   }
70
71The ``generate_toolchain`` supports the above mentioned ``static_analysis``
72scope, which if specified must at the very least define the bool ``enabled``
73within the scope. If the ``static_analysis`` scope is provided and
74``static_analysis.enabled = true``, the derived toolchain
75``${target_name}.static_analysis`` will be generated using
76``pw_generate_static_analysis_toolchain`` and the toolchain options.
77
78An example on the utility of the ``static_analysis`` scope args is shown in the
79snippet below where we enable clang-tidy caching and add ``//.clang-tidy`` as a
80dependency to the generated ``.d`` files for the
81``pw_static_analysis_toolchain``.
82
83.. code-block::
84
85   static_analysis = {
86    clang_tidy_path = "//third_party/ctcache/clang-tidy"
87    _clang_tidy_cfg_path = rebase_path("//.clang-tidy", root_build_dir)
88    cc_post = "echo '-: $_clang_tidy_cfg_path' >> {{output}}.d"
89    cxx_post = "echo '-: $_clang_tidy_cfg_path' >> {{output}}.d"
90   }
91
92Excluding files from checks
93–--------------------------
94The build argument ``pw_toolchain_STATIC_ANALYSIS_SKIP_SOURCES_RES`` is used
95to exclude source files from the analysis. The list must contain regular
96expressions matching individual files, rather than directories. For example,
97provide ``"the_path/.*"`` to exclude all files in all directories under
98``the_path``.
99
100The build argument ``pw_toolchain_STATIC_ANALYSIS_SKIP_INCLUDE_PATHS`` is used
101used to exclude header files from the analysis. This argument must be a list of
102POSIX-style path suffixes for include paths, or regular expressions matching
103include paths. For example, passing ``the_path/include`` excludes all header
104files that are accessed from include paths ending in ``the_path/include``,
105while passing ``.*/third_party/.*`` excludes all third-party header files.
106
107Note that ``pw_toolchain_STATIC_ANALYSIS_SKIP_INCLUDE_PATHS`` operates on
108include paths, not header file paths. For example, say your compile commands
109include ``-Idrivers``, and this results in a file at ``drivers/public/i2c.h``
110being included. You can skip this header by adding ``drivers`` or ``drivers.*``
111to ``pw_toolchain_STATIC_ANALYSIS_SKIP_INCLUDE_PATHS``, but *not* by adding
112``drivers/.*``: this last regex matches the header file path, but not the
113include path.
114
115Provided toolchains
116-------------------
117``pw_toolchain`` provides static analysis GN toolchains that may be used to
118test host targets:
119
120- pw_toolchain_host_clang.debug.static_analysis
121- pw_toolchain_host_clang.speed_optimized.static_analysis
122- pw_toolchain_host_clang.size_optimized.static_analysis
123- pw_toolchain_host_clang.fuzz.static_analysis
124  (if pw_toolchain_OSS_FUZZ_ENABLED is false)
125- pw_toolchain_arm_clang.debug.static_analysis
126- pw_toolchain_arm_clang.speed_optimized.static_analysis
127- pw_toolchain_arm_clang.size_optimized.static_analysis
128
129For example, to run ``clang-tidy`` on all source dependencies of the
130``default`` target:
131
132.. code-block::
133
134   generate_toolchain("my_toolchain") {
135     ..
136     static_analysis = {
137      enabled = true
138     }
139   }
140
141   group("static_analysis") {
142     deps = [ ":default(my_toolchain.static_analysis)" ]
143   }
144
145.. warning::
146
147   The status of the static analysis checks might change when
148   any relevant .clang-tidy file is updated. You should
149   clean the output directory before invoking
150   ``clang-tidy``.
151
152Target traits
153=============
154Pigweed targets expose a set of constants that describe properties of the target
155or the toolchain compiling code for it. These are referred to as target traits.
156
157In GN, these traits are exposed as GN args and are prefixed with
158``pw_toolchain_`` (e.g. ``pw_toolchain_CXX_STANDARD``). They are defined in
159``pw_toolchain/traits.gni``.
160
161Traits must never be set by the user (e.g. with ``gn args``). Traits are always
162set by the target.
163
164.. warning::
165
166   This feature is under development and is likely to change significantly.
167   See `b/234883746 <http://issuetracker.google.com/issues/234883746>`_.
168
169List of traits
170--------------
171- ``CXX_STANDARD``. The C++ standard used by the toolchain. The value must be an
172  integer value matching one of the standard values for the ``__cplusplus``
173  macro. For example, ``201703`` corresponds to C++17. See
174  https://en.cppreference.com/w/cpp/preprocessor/replace#Predefined_macros for
175  further details.
176
177----------------
178Bazel toolchains
179----------------
180Pigweed provides a suite of building blocks for designing a custom C/C++
181toolchain in Bazel. See the :ref:`module-pw_toolchain_bazel` module
182documentation for more information.
183
184.. _module-pw_toolchain-bazel-upstream-pigweed-toolchains:
185
186Upstream Pigweed Toolchains
187===========================
188You can use Pigweed's upstream toolchains by calling
189``register_pigweed_cxx_toolchains()`` provided by
190``@pigweed//pw_toolchain:register_toolchains.bzl`` in your ``WORKSPACE`` file.
191
192
193.. admonition:: Note
194   :class: warning
195
196   Pigweed's upstream toolchains are subject to change without notice. If you
197   would prefer more stability in toolchain configurations, consider declaring
198   custom toolchains in your project.
199
200---------------
201C/C++ libraries
202---------------
203``pw_toolchain`` provides some toolchain-related C/C++ libraries.
204
205``std:abort`` wrapper
206=====================
207The `std::abort <https://en.cppreference.com/w/cpp/utility/program/abort>`_
208function is used to terminate a program abnormally. This function may be called
209by standard library functions, so is often linked into binaries, even if users
210never intentionally call it.
211
212For embedded builds, the ``abort`` implementation likely does not work as
213intended. For example, it may pull in undesired dependencies (e.g.
214``std::raise``) and end in an infinite loop.
215
216``pw_toolchain`` provides the ``pw_toolchain:wrap_abort`` library that replaces
217``abort`` in builds where the default behavior is undesirable. It uses the
218``-Wl,--wrap=abort`` linker option to redirect to ``abort`` calls to
219``PW_CRASH`` instead.
220
221arm-none-eabi-gcc support
222=========================
223Targets building with the GNU Arm Embedded Toolchain (``arm-none-eabi-gcc``)
224should depend on the ``pw_toolchain/arm_gcc:arm_none_eabi_gcc_support``
225library. In GN, that target should be included in ``pw_build_LINK_DEPS``. In
226Bazel, it should be added to `link_extra_lib
227<https://bazel.build/reference/be/c-cpp#cc_binary.link_extra_lib>`__ or
228directly to the `deps` of any binary being build with that toolchain:
229
230.. code-block:: python
231
232   cc_binary(
233      deps = [
234        # Other deps, omitted
235      ] + select({
236        "@platforms//cpu:armv7e-m": [
237          "@pigweed//pw_toolchain/arm_gcc:arm_none_eabi_gcc_support",
238        ],
239        "//conditions:default": [],
240      }),
241   )
242
243Newlib OS interface
244-------------------
245`Newlib <https://sourceware.org/newlib/>`_, the C Standard Library
246implementation provided with ``arm-none-eabi-gcc``, defines a set of `OS
247interface functions <https://sourceware.org/newlib/libc.html#Stubs>`_ that
248should be implemented. Newlib provides default implementations, but using these
249results in linker warnings like the following:
250
251.. code-block:: none
252
253   readr.c:(.text._read_r+0x10): warning: _read is not implemented and will always fail
254
255Most of the OS interface functions should never be called in embedded builds.
256The ``pw_toolchain/arg_gcc:newlib_os_interface_stubs`` library, which is
257provided through ``pw_toolchain/arm_gcc:arm_none_eabi_gcc_support``, implements
258these functions and forces a linker error if they are used. It also
259automatically includes a wrapper for ``abort`` for use of ``stdout`` and
260``stderr`` which abort if they are called.
261
262If you need to use your own wrapper for ``abort``, include the library directly
263using ``pw_toolchain/arm_gcc:newlib_os_interface_stubs``.
264
265pw_toolchain/no_destructor.h
266============================
267.. doxygenclass:: pw::NoDestructor
268
269builtins
270========
271builtins are LLVM's equivalent of libgcc, the compiler will insert calls to
272these routines. Setting the ``dir_pw_third_party_builtins`` gn var to your
273compiler-rt/builtins checkout will enable building builtins from source instead
274of relying on the shipped libgcc.
275