Keir Mierle | 2c1e56b | 2019-11-15 16:32:11 -0800 | [diff] [blame] | 1 | .. _chapter-style: |
| 2 | |
| 3 | .. default-domain:: cpp |
| 4 | |
| 5 | .. highlight:: sh |
| 6 | |
| 7 | =========================== |
| 8 | Style Guide and Conventions |
| 9 | =========================== |
| 10 | |
Armando Montanez | f2bbb75 | 2020-03-03 09:50:37 -0800 | [diff] [blame] | 11 | .. tip:: |
| 12 | Pigweed runs ``pw format`` as part of ``pw presubmit`` to perform some code |
| 13 | formatting checks. To speed up the review process, consider adding ``pw |
| 14 | presubmit`` as a git push hook using the following command: |
| 15 | ``pw presubmit --install`` |
| 16 | |
Keir Mierle | 2c1e56b | 2019-11-15 16:32:11 -0800 | [diff] [blame] | 17 | --------- |
| 18 | C++ style |
| 19 | --------- |
| 20 | |
| 21 | The Pigweed C++ style guide is closely based on Google's external C++ Style |
| 22 | Guide, which is found on the web at |
| 23 | https://google.github.io/styleguide/cppguide.html. The Google C++ Style Guide |
| 24 | applies to Pigweed except as described in this document. |
| 25 | |
| 26 | The Pigweed style guide only applies to Pigweed itself. It does not apply to |
Alexei Frolov | 44d5473 | 2020-01-10 14:45:43 -0800 | [diff] [blame] | 27 | projects that use Pigweed or to the third-party code included with Pigweed. |
Keir Mierle | 2c1e56b | 2019-11-15 16:32:11 -0800 | [diff] [blame] | 28 | Non-Pigweed code is free to use features restricted by Pigweed, such as dynamic |
| 29 | memory allocation and the entirety of the C++ Standard Library. |
| 30 | |
| 31 | Recommendations in the :doc:`embedded_cpp_guide` are considered part of the |
| 32 | Pigweed style guide, but are separated out since it covers more general |
| 33 | embedded development beyond just C++ style. |
| 34 | |
| 35 | Automatic formatting |
| 36 | ==================== |
| 37 | Pigweed uses `clang-format <https://clang.llvm.org/docs/ClangFormat.html>`_ to |
| 38 | automatically format Pigweed source code. A ``.clang-format`` configuration is |
| 39 | provided with the Pigweed repository. |
| 40 | |
| 41 | Automatic formatting is essential to facilitate large-scale, automated changes |
| 42 | in Pigweed. Therefore, all code in Pigweed is expected to be formatted with |
| 43 | ``clang-format`` prior to submission. Existing code may be reformatted at any |
| 44 | time. |
| 45 | |
| 46 | If ``clang-format`` formats code in an undesirable or incorrect way, it can be |
| 47 | disabled for the affected lines by adding ``// clang-format off``. |
| 48 | ``clang-format`` must then be re-enabled with a ``// clang-format on`` comment. |
| 49 | |
| 50 | .. code-block:: cpp |
| 51 | |
| 52 | // clang-format off |
Alexei Frolov | 44d5473 | 2020-01-10 14:45:43 -0800 | [diff] [blame] | 53 | constexpr int kMyMatrix[] = { |
Keir Mierle | 2c1e56b | 2019-11-15 16:32:11 -0800 | [diff] [blame] | 54 | 100, 23, 0, |
| 55 | 0, 542, 38, |
| 56 | 1, 2, 201, |
| 57 | }; |
| 58 | // clang-format on |
| 59 | |
| 60 | C Standard Library |
| 61 | ================== |
| 62 | In C++ headers, always use the C++ versions of C Standard Library headers (e.g. |
| 63 | ``<cstdlib>`` instead of ``<stdlib.h>``). If the header is used by both C and |
| 64 | C++ code, only the C header should be used. |
| 65 | |
| 66 | In C++ code, it is preferred to use C functions from the ``std`` namespace. For |
| 67 | example, use ``std::memcpy`` instead of ``memcpy``. The C++ standard does not |
| 68 | require the global namespace versions of the functions to be provided. Using |
| 69 | ``std::`` is more consistent with the C++ Standard Library and makes it easier |
| 70 | to distinguish Pigweed functions from library functions. |
| 71 | |
| 72 | Within core Pigweed, do not use C standard library functions that allocate |
| 73 | memory, such as ``std::malloc``. There are exceptions to this for when dynamic |
| 74 | allocation is enabled for a system; Pigweed modules are allowed to add extra |
| 75 | functionality when a heap is present; but this must be optional. |
| 76 | |
| 77 | C++ Standard Library |
| 78 | ==================== |
| 79 | Much of the C++ Standard Library is not a good fit for embedded software. Many |
| 80 | of the classes and functions were not designed with the RAM, flash, and |
| 81 | performance constraints of a microcontroller in mind. For example, simply |
| 82 | adding the line ``#include <iostream>`` can increase the binary size by 150 KB! |
Alexei Frolov | 44d5473 | 2020-01-10 14:45:43 -0800 | [diff] [blame] | 83 | This is larger than many microcontrollers' entire internal storage. |
Keir Mierle | 2c1e56b | 2019-11-15 16:32:11 -0800 | [diff] [blame] | 84 | |
| 85 | However, with appropriate caution, a limited set of standard C++ libraries can |
| 86 | be used to great effect. Developers can leverage familiar, well-tested |
| 87 | abstractions instead of writing their own. C++ library algorithms and classes |
| 88 | can give equivalent or better performance than hand-written C code. |
| 89 | |
| 90 | A limited subset of the C++ Standard Library is permitted in Pigweed. To keep |
| 91 | Pigweed small, flexible, and portable, functions that allocate dynamic memory |
| 92 | must be avoided. Care must be exercised when using multiple instantiations of a |
| 93 | template function, which can lead to code bloat. |
| 94 | |
| 95 | The following C++ Standard Library headers are always permitted: |
| 96 | |
| 97 | * ``<array>`` |
| 98 | * ``<complex>`` |
| 99 | * ``<initializer_list>`` |
| 100 | * ``<iterator>`` |
| 101 | * ``<limits>`` |
| 102 | * ``<optional>`` |
| 103 | * ``<random>`` |
| 104 | * ``<ratio>`` |
| 105 | * ``<span>`` |
| 106 | * ``<string_view>`` |
| 107 | * ``<tuple>`` |
| 108 | * ``<type_traits>`` |
| 109 | * ``<utility>`` |
| 110 | * ``<variant>`` |
| 111 | * C Standard Library headers (``<c*>``) |
| 112 | |
| 113 | With caution, parts of the following headers can be used: |
| 114 | |
| 115 | * ``<algorithm>`` -- be wary of potential memory allocation |
| 116 | * ``<atomic>`` -- not all MCUs natively support atomic operations |
| 117 | * ``<bitset>`` -- conversions to or from strings are disallowed |
| 118 | * ``<functional>`` -- do **not** use ``std::function`` |
| 119 | * ``<new>`` -- for placement new |
| 120 | * ``<numeric>`` -- be wary of code size with multiple template instantiations |
| 121 | |
| 122 | Never use any of these headers: |
| 123 | |
| 124 | * Dynamic containers (``<list>``, ``<map>``, ``<set>``, ``<vector>``, etc.) |
| 125 | * Streams (``<iostream>``, ``<ostream>``, ``<fstream>``, etc.) |
| 126 | * ``<exception>`` |
| 127 | * ``<future>``, ``<mutex>``, ``<thread>`` |
| 128 | * ``<memory>`` |
| 129 | * ``<regex>`` |
| 130 | * ``<scoped_allocator>`` |
| 131 | * ``<sstream>`` |
| 132 | * ``<stdexcept>`` |
| 133 | * ``<string>`` |
| 134 | * ``<valarray>`` |
| 135 | |
| 136 | Headers not listed here should be carefully evaluated before they are used. |
| 137 | |
| 138 | These restrictions do not apply to third party code or to projects that use |
| 139 | Pigweed. |
| 140 | |
| 141 | Combining C and C++ |
| 142 | =================== |
| 143 | Prefer to write C++ code over C code, using ``extern "C"`` for symbols that must |
| 144 | have C linkage. ``extern "C"`` functions should be defined within C++ |
| 145 | namespaces to simplify referring to other code. |
| 146 | |
| 147 | C++ functions with no parameters do not include ``void`` in the parameter list. |
| 148 | C functions with no parameters must include ``void``. |
| 149 | |
| 150 | .. code-block:: cpp |
| 151 | |
| 152 | namespace pw { |
| 153 | |
| 154 | bool ThisIsACppFunction() { return true; } |
| 155 | |
| 156 | extern "C" int pw_ThisIsACFunction(void) { return -1; } |
| 157 | |
| 158 | extern "C" { |
| 159 | |
| 160 | int pw_ThisIsAlsoACFunction(void) { |
| 161 | return ThisIsACppFunction() ? 100 : 0; |
| 162 | } |
| 163 | |
| 164 | } // extern "C" |
| 165 | |
| 166 | } // namespace pw |
| 167 | |
| 168 | Comments |
| 169 | ======== |
| 170 | Prefer C++-style (``//``) comments over C-style commments (``/* */``). C-style |
| 171 | comments should only be used for inline comments. |
| 172 | |
| 173 | .. code-block:: cpp |
| 174 | |
| 175 | // Use C++-style comments, except where C-style comments are necessary. |
| 176 | // This returns a random number using an algorithm I found on the internet. |
| 177 | #define RANDOM_NUMBER() [] { \ |
| 178 | return 4; /* chosen by fair dice roll */ \ |
| 179 | }() |
| 180 | |
| 181 | Indent code in comments with two additional spaces, making a total of three |
| 182 | spaces after the ``//``. All code blocks must begin and end with an empty |
Alexei Frolov | 44d5473 | 2020-01-10 14:45:43 -0800 | [diff] [blame] | 183 | comment line, even if the blank comment line is the last line in the block. |
Keir Mierle | 2c1e56b | 2019-11-15 16:32:11 -0800 | [diff] [blame] | 184 | |
| 185 | .. code-block:: cpp |
| 186 | |
| 187 | // Here is an example of code in comments. |
| 188 | // |
| 189 | // int indentation_spaces = 2; |
| 190 | // int total_spaces = 3; |
| 191 | // |
| 192 | // engine_1.thrust = RANDOM_NUMBER() * indentation_spaces + total_spaces; |
| 193 | // |
| 194 | bool SomeFunction(); |
| 195 | |
| 196 | Control statements |
| 197 | ================== |
| 198 | All loops and conditional statements must use braces. |
| 199 | |
| 200 | The syntax ``while (true)`` if preferred over ``for (;;)`` for infinite loops. |
| 201 | |
| 202 | Include guards |
| 203 | ============== |
| 204 | The first non-comment line of every header file must be ``#pragma once``. Do |
| 205 | not use traditional macro include guards. The ``#pragma once`` should come |
| 206 | directly after the Pigweed copyright block, with no blank line, followed by a |
| 207 | blank, like this: |
| 208 | |
| 209 | .. code-block:: cpp |
| 210 | |
Keir Mierle | 086ef1c | 2020-03-19 02:03:51 -0700 | [diff] [blame] | 211 | // Copyright 2020 The Pigweed Authors |
Keir Mierle | 2c1e56b | 2019-11-15 16:32:11 -0800 | [diff] [blame] | 212 | // |
| 213 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not |
Wyatt Hepler | 1a96094 | 2019-11-26 14:13:38 -0800 | [diff] [blame] | 214 | // use this file except in compliance with the License. You may obtain a copy of |
| 215 | // the License at |
Keir Mierle | 2c1e56b | 2019-11-15 16:32:11 -0800 | [diff] [blame] | 216 | // |
| 217 | // https://www.apache.org/licenses/LICENSE-2.0 |
| 218 | // |
| 219 | // Unless required by applicable law or agreed to in writing, software |
| 220 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| 221 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
Wyatt Hepler | 1a96094 | 2019-11-26 14:13:38 -0800 | [diff] [blame] | 222 | // License for the specific language governing permissions and limitations under |
| 223 | // the License. |
Keir Mierle | 2c1e56b | 2019-11-15 16:32:11 -0800 | [diff] [blame] | 224 | #pragma once |
| 225 | |
| 226 | // Header file-level comment goes here... |
| 227 | |
| 228 | Memory allocation |
| 229 | ================= |
| 230 | Dynamic memory allocation can be problematic. Heap allocations and deallocations |
| 231 | occupy valuable CPU cycles. Memory usage becomes nondeterministic, which can |
| 232 | result in a system crashing without a clear culprit. |
| 233 | |
| 234 | To keep Pigweed portable, core Pigweed code is not permitted to dynamically |
| 235 | (heap) allocate memory, such as with ``malloc`` or ``new``. All memory should be |
| 236 | allocated with automatic (stack) or static (global) storage duration. Pigweed |
| 237 | must not use C++ libraries that use dynamic allocation. |
| 238 | |
| 239 | Projects that use Pigweed are free to use dynamic allocation, provided they |
| 240 | have selected a target that enables the heap. |
| 241 | |
| 242 | Naming |
| 243 | ====== |
| 244 | Entities shall be named according to the `Google style guide |
| 245 | <https://google.github.io/styleguide/cppguide.html>`_, with the following |
| 246 | additional requirements. |
| 247 | |
| 248 | **C++ code** |
| 249 | * All Pigweed C++ code must be in the ``pw`` namespace. Namespaces for |
| 250 | modules should be nested under ``pw``. For example, |
| 251 | ``pw::string::Format()``. |
| 252 | * Whenever possible, private code should be in a source (.cc) file and placed |
| 253 | in anonymous namespace nested under ``pw``. |
| 254 | * If private code must be exposed in a header file, it must be in a namespace |
| 255 | nested under ``pw``. The namespace may be named for its subsystem or use a |
| 256 | name that designates it as private, such as ``internal``. |
Keir Mierle | 003044a | 2020-04-14 10:56:20 -0700 | [diff] [blame] | 257 | * Template arguments for non-type names (e.g. ``template <int foo_bar>``) |
| 258 | should follow the variable naming convention, which means snake case (e.g. |
| 259 | ``foo_bar``). This matches the Google C++ style, however the wording in the |
| 260 | official style guide isn't explicit and could be interpreted to use |
| 261 | ``kFooBar`` style naming. Wide practice establishes that the naming |
| 262 | convention is ``snake_case``, and so that is the style we use in Pigweed. |
| 263 | |
| 264 | **Note:** At time of writing much of Pigweed incorrectly follows the |
| 265 | ``kCamelCase`` naming for non-type template arguments. This is a bug that |
| 266 | will be fixed eventually. |
Keir Mierle | 2c1e56b | 2019-11-15 16:32:11 -0800 | [diff] [blame] | 267 | |
| 268 | **C code** |
| 269 | * Public names used by C code must be prefixed with ``pw_``. |
| 270 | * If private code must be exposed in a header, private names used by C code |
| 271 | must be prefixed with ``_pw_``. |
| 272 | * Avoid writing C source (.c) files in Pigweed. Prefer to write C++ code with |
| 273 | C linkage using ``extern "C"``. Within C source, private C functions and |
| 274 | variables must be named with the ``_pw_`` prefix and should be declared |
| 275 | ``static`` whenever possible; for example, ``_pw__MyPrivateFunction``. |
| 276 | * The C prefix rules apply to |
| 277 | |
| 278 | * C functions (``int pw_FunctionName(void);``), |
| 279 | * variables used by C code (``int pw_variable_name;``), |
| 280 | * constant variables used by C code (``int pw_kConstantName;``), and |
| 281 | * structs used by C code (``typedef struct {} pw_StructName;``). |
| 282 | |
| 283 | The prefix does not apply to struct members, which use normal Google style. |
| 284 | |
| 285 | **Preprocessor macros** |
| 286 | * Public Pigweed macros must be prefixed with ``PW_``. |
| 287 | * Private Pigweed macros must be prefixed with ``_PW_``. |
| 288 | |
| 289 | **Example** |
| 290 | |
| 291 | .. code-block:: cpp |
| 292 | |
| 293 | namespace pw { |
| 294 | namespace nested_namespace { |
| 295 | |
| 296 | // C++ names (types, variables, functions) must be in the pw namespace. |
| 297 | // They are named according to the Google style guide. |
| 298 | constexpr int kGlobalConstant = 123; |
| 299 | |
| 300 | // Prefer using functions over extern global variables. |
| 301 | extern int global_variable; |
| 302 | |
| 303 | class Class {}; |
| 304 | |
| 305 | void Function(); |
| 306 | |
| 307 | extern "C" { |
| 308 | |
| 309 | // Public Pigweed code used from C must be prefixed with pw_. |
| 310 | extern const int pw_kGlobalConstant; |
| 311 | |
| 312 | extern int pw_global_variable; |
| 313 | |
| 314 | void pw_Function(void); |
| 315 | |
| 316 | typedef struct { |
| 317 | int member_variable; |
| 318 | } pw_Struct; |
| 319 | |
| 320 | // Private Pigweed code used from C must be prefixed with _pw_. |
| 321 | extern const int _pw_kPrivateGlobalConstant; |
| 322 | |
| 323 | extern int _pw_private_global_variable; |
| 324 | |
| 325 | void _pw_PrivateFunction(void); |
| 326 | |
| 327 | typedef struct { |
| 328 | int member_variable; |
| 329 | } _pw_PrivateStruct; |
| 330 | |
| 331 | } // extern "C" |
| 332 | |
| 333 | // Public macros must be prefixed with PW_. |
| 334 | #define PW_PUBLIC_MACRO(arg) arg |
| 335 | |
| 336 | // Private macros must be prefixed with _PW_. |
| 337 | #define _PW_PRIVATE_MACRO(arg) arg |
| 338 | |
| 339 | } // namespace nested_namespace |
| 340 | } // namespace pw |
| 341 | |
| 342 | Namespace scope formatting |
| 343 | ========================== |
| 344 | All non-indented blocks (namespaces, ``extern "C"`` blocks, and preprocessor |
| 345 | conditionals) must have a comment on their closing line with the |
| 346 | contents of the starting line. |
| 347 | |
| 348 | All nested namespaces should be declared together with no blank lines between |
| 349 | them. |
| 350 | |
| 351 | .. code-block:: cpp |
| 352 | |
| 353 | #include "some/header.h" |
| 354 | |
| 355 | namespace pw::nested { |
| 356 | namespace { |
| 357 | |
| 358 | constexpr int kAnonConstantGoesHere = 0; |
| 359 | |
| 360 | } // namespace |
| 361 | |
| 362 | namespace other { |
| 363 | |
| 364 | const char* SomeClass::yes = "no"; |
| 365 | |
| 366 | bool ThisIsAFunction() { |
| 367 | #if PW_CONFIG_IS_SET |
| 368 | return true; |
| 369 | #else |
| 370 | return false; |
| 371 | #endif // PW_CONFIG_IS_SET |
| 372 | } |
| 373 | |
| 374 | extern "C" { |
| 375 | |
| 376 | const int pw_kSomeConstant = 10; |
| 377 | int pw_some_global_variable = 600; |
| 378 | |
| 379 | void pw_CFunction() { ... } |
| 380 | |
| 381 | } // extern "C" |
| 382 | |
| 383 | } // namespace |
| 384 | } // namespace pw::nested |
| 385 | |
| 386 | Pointers and references |
| 387 | ======================= |
| 388 | For pointer and reference types, place the asterisk or ampersand next to the |
| 389 | type. |
| 390 | |
| 391 | .. code-block:: cpp |
| 392 | |
| 393 | int* const number = &that_thing; |
| 394 | constexpr const char* kString = "theory!" |
| 395 | |
| 396 | bool FindTheOneRing(const Region& where_to_look) { ... } |
| 397 | |
| 398 | Prefer storing references over storing pointers. Pointers are required when the |
| 399 | pointer can change its target or may be ``nullptr``. Otherwise, a reference or |
| 400 | const reference should be used. In accordance with the Google C++ style guide, |
| 401 | only const references are permitted as function arguments; pointers must be used |
| 402 | in place of mutable references when passed as function arguments. |
| 403 | |
| 404 | Preprocessor macros |
| 405 | =================== |
| 406 | Macros should only be used when they significantly improve upon the C++ code |
| 407 | they replace. Macros should make code more readable, robust, and safe, or |
| 408 | provide features not possible with standard C++, such as stringification, line |
| 409 | number capturing, or conditional compilation. When possible, use C++ constructs |
| 410 | like constexpr variables in place of macros. Never use macros as constants, |
| 411 | except when a string literal is needed or the value must be used by C code. |
| 412 | |
| 413 | When macros are needed, the macros should be accompanied with extensive tests |
| 414 | to ensure the macros are hard to use wrong. |
| 415 | |
| 416 | Stand-alone statement macros |
| 417 | ---------------------------- |
| 418 | Macros that are standalone statements must require the caller to terminate the |
Alexei Frolov | 44d5473 | 2020-01-10 14:45:43 -0800 | [diff] [blame] | 419 | macro invocation with a semicolon. For example, the following does *not* conform |
Keir Mierle | 2c1e56b | 2019-11-15 16:32:11 -0800 | [diff] [blame] | 420 | to Pigweed's macro style: |
| 421 | |
| 422 | .. code-block:: cpp |
| 423 | |
| 424 | // BAD! Definition has built-in semicolon. |
| 425 | #define PW_LOG_IF_BAD(mj) \ |
| 426 | CallSomeFunction(mj); |
| 427 | |
| 428 | // BAD! Compiles without error; semicolon is missing. |
Alexei Frolov | 44d5473 | 2020-01-10 14:45:43 -0800 | [diff] [blame] | 429 | PW_LOG_IF_BAD("foo") |
Keir Mierle | 2c1e56b | 2019-11-15 16:32:11 -0800 | [diff] [blame] | 430 | |
| 431 | Here's how to do this instead: |
| 432 | |
| 433 | .. code-block:: cpp |
| 434 | |
| 435 | // GOOD; requires semicolon to compile. |
| 436 | #define PW_LOG_IF_BAD(mj) \ |
| 437 | CallSomeFunction(mj) |
| 438 | |
| 439 | // GOOD; fails to compile due to lacking semicolon. |
Alexei Frolov | 44d5473 | 2020-01-10 14:45:43 -0800 | [diff] [blame] | 440 | PW_LOG_IF_BAD("foo") |
Keir Mierle | 2c1e56b | 2019-11-15 16:32:11 -0800 | [diff] [blame] | 441 | |
| 442 | For macros in function scope that do not already require a semicolon, the |
| 443 | contents can be placed in a ``do { ... } while (0)`` loop. |
| 444 | |
| 445 | .. code-block:: cpp |
| 446 | |
| 447 | #define PW_LOG_IF_BAD(mj) \ |
| 448 | do { \ |
| 449 | if (mj.Bad()) { \ |
| 450 | Log(#mj " is bad") \ |
| 451 | } \ |
| 452 | } while (0) |
| 453 | |
| 454 | Standalone macros at global scope that do not already require a semicolon can |
| 455 | add a ``static_assert`` or throwaway struct declaration statement as their |
| 456 | last line. |
| 457 | |
| 458 | .. code-block:: cpp |
| 459 | |
| 460 | #define PW_NEAT_THING(thing) \ |
| 461 | bool IsNeat_##thing() { return true; } \ |
| 462 | static_assert(true, "Macros must be terminated with a semicolon") |
| 463 | |
| 464 | Private macros in public headers |
| 465 | -------------------------------- |
| 466 | Private macros in public headers must be prefixed with ``_PW_``, even if they |
| 467 | are undefined after use; this prevents collisions with downstream users. For |
| 468 | example: |
| 469 | |
| 470 | .. code-block:: cpp |
| 471 | |
| 472 | #define _PW_MY_SPECIAL_MACRO(op) ... |
| 473 | ... |
| 474 | // Code that uses _PW_MY_SPECIAL_MACRO() |
| 475 | ... |
| 476 | #undef _PW_MY_SPECIAL_MACRO |
| 477 | |
| 478 | Macros in private implementation files (.cc) |
| 479 | -------------------------------------------- |
| 480 | Macros within .cc files that should only used within one file should be |
| 481 | undefined after their last use; for example: |
| 482 | |
| 483 | .. code-block:: cpp |
| 484 | |
| 485 | #define DEFINE_OPERATOR(op) \ |
| 486 | T operator ## op(T x, T y) { return x op y; } \ |
| 487 | static_assert(true, "Macros must be terminated with a semicolon") \ |
| 488 | |
| 489 | DEFINE_OPERATOR(+); |
| 490 | DEFINE_OPERATOR(-); |
| 491 | DEFINE_OPERATOR(/); |
| 492 | DEFINE_OPERATOR(*); |
| 493 | |
| 494 | #undef DEFINE_OPERATOR |
| 495 | |
| 496 | Preprocessor conditional statements |
| 497 | =================================== |
| 498 | When using macros for conditional compilation, prefer to use ``#if`` over |
| 499 | ``#ifdef``. This checks the value of the macro rather than whether it exists. |
| 500 | |
| 501 | * ``#if`` handles undefined macros equivalently to ``#ifdef``. Undefined |
| 502 | macros expand to 0 in preprocessor conditional statements. |
| 503 | * ``#if`` evaluates false for macros defined as 0, while ``#ifdef`` evaluates |
| 504 | true. |
| 505 | * Macros defined using compiler flags have a default value of 1 in GCC and |
| 506 | Clang, so they work equivalently for ``#if`` and ``#ifdef``. |
| 507 | * Macros defined to an empty statement cause compile-time errors in ``#if`` |
| 508 | statements, which avoids ambiguity about how the macro should be used. |
| 509 | |
| 510 | All ``#endif`` statements should be commented with the expression from their |
| 511 | corresponding ``#if``. Do not indent within preprocessor conditional statements. |
| 512 | |
| 513 | .. code-block:: cpp |
| 514 | |
| 515 | #if USE_64_BIT_WORD |
| 516 | using Word = uint64_t; |
| 517 | #else |
| 518 | using Word = uint32_t; |
| 519 | #endif // USE_64_BIT_WORD |
| 520 | |
| 521 | Unsigned integers |
| 522 | ================= |
| 523 | Unsigned integers are permitted in Pigweed. Aim for consistency with existing |
| 524 | code and the C++ Standard Library. Be very careful mixing signed and unsigned |
| 525 | integers. |
| 526 | |
| 527 | ------------ |
| 528 | Python style |
| 529 | ------------ |
| 530 | Pigweed uses the standard Python style: PEP8, which is available on the web at |
| 531 | https://www.python.org/dev/peps/pep-0008/. All Pigweed Python code should pass |
| 532 | ``yapf`` when configured for PEP8 style. |
| 533 | |
Wyatt Hepler | ab4eb7a | 2020-01-08 18:04:31 -0800 | [diff] [blame] | 534 | Python 3 |
| 535 | ======== |
| 536 | Pigweed uses Python 3. Some modules may offer limited support for Python 2, but |
| 537 | Python 3.6 or newer is required for most Pigweed code. |
Wayne Jackson | d597e46 | 2020-06-03 15:03:12 -0700 | [diff] [blame] | 538 | |
| 539 | --------------- |
| 540 | Build files: GN |
| 541 | --------------- |
| 542 | |
| 543 | Each Pigweed source module will require a build file named BUILD.gn which |
| 544 | encapsulates the build targets and specifies their sources and dependencies. |
| 545 | The format of this file is simlar in structure to the |
| 546 | `Bazel/Blaze format <https://docs.bazel.build/versions/3.2.0/build-ref.html>`_ |
| 547 | (Googlers may also review `go/build-style <go/build-style>`_), but with |
| 548 | nomenclature specific to Pigweed. For each target specified within the build |
| 549 | file there are a list of depdency fields. Those fields, in their expected |
| 550 | order, are: |
| 551 | |
| 552 | * ``<public_config>`` -- external build configuration |
| 553 | * ``<public_deps>`` -- necessary public dependencies (ie: Pigweed headers) |
| 554 | * ``<public>`` -- exposed package public interface header files |
| 555 | * ``<config>`` -- package build configuration |
| 556 | * ``<sources>`` -- package source code |
| 557 | * ``<deps>`` -- package necessary local dependencies |
| 558 | |
| 559 | Assets within each field must be listed in alphabetical order |
| 560 | |
| 561 | .. code-block:: cpp |
| 562 | |
| 563 | # Here is a brief example of a GN build file. |
| 564 | |
| 565 | import("$dir_pw_unit_test/test.gni") |
| 566 | |
| 567 | config("default_config") { |
| 568 | include_dirs = [ "public" ] |
| 569 | } |
| 570 | |
| 571 | source_set("pw_sample_module") { |
| 572 | public_configs = [ ":default_config" ] |
| 573 | public_deps = [ |
Kevin Zeng | 1e10ef2 | 2020-06-09 20:47:14 -0700 | [diff] [blame^] | 574 | dir_pw_span, |
Wayne Jackson | d597e46 | 2020-06-03 15:03:12 -0700 | [diff] [blame] | 575 | dir_pw_status, |
| 576 | ] |
| 577 | public = [ "public/pw_sample_module/sample_module.h" ] |
| 578 | sources = [ |
| 579 | "public/pw_sample_module/internal/sample_module.h", |
| 580 | "sample_module.cc", |
| 581 | "used_by_sample_module.cc", |
| 582 | ] |
| 583 | deps = [ dir_pw_varint ] |
| 584 | } |
| 585 | |
| 586 | pw_test_group("tests") { |
| 587 | tests = [ ":sample_module_test" ] |
| 588 | } |
| 589 | |
| 590 | pw_test("sample_module_test") { |
Wayne Jackson | d597e46 | 2020-06-03 15:03:12 -0700 | [diff] [blame] | 591 | sources = [ "sample_module_test.cc" ] |
Kevin Zeng | 1e10ef2 | 2020-06-09 20:47:14 -0700 | [diff] [blame^] | 592 | deps = [ ":sample_module" ] |
Wayne Jackson | d597e46 | 2020-06-03 15:03:12 -0700 | [diff] [blame] | 593 | } |
| 594 | |
| 595 | pw_doc_group("docs") { |
| 596 | sources = [ "docs.rst" ] |
| 597 | } |