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