DO use fixed length types defined in stdint.h
instead of language keywords determined by the compiler (e.g., int64_t, uint8_t
, not long, unsigned char
).
DO use const
and static
and visibility modifiers to scope exposure of variables and methods as much as possible.
DO use doxygen comments, with [in,out] direction annotation in all public API headers. This is also encouraged, but not strictly required, for internal API headers as well.
DON'T use global variables where possible.
DON'T use abbreviations unless they are already well-known terms known by users (e.g., “app”, “info”), or are already required for use by developers (e.g., “min”, “max”, “args”). Examples of bad use would be num_widgets
instead of widget_count
, and opt_widgets
instead of option_widgets
or optional_widgets
.
DON'T use hard-coded magic numbers for things that have to be consistent between different files. Instead use a #define
or an enum or const value, as appropriate.
DON'T use the same C function name with two different prototypes across the project where possible.
DON'T use commented-out code, or code in an #if 0
or equivalent. Make sure all code is actually built.
DO make sure any header file can be included directly, without requiring other headers to be included first. That is, any dependencies should be included within the header file itself.
DO include system headers (with <>
) before local headers (with ""
), and list them in alphabetical order where possible. This helps ensure there are not duplicate includes, and also helps ensure that headers are usable directly.
DO use #pragma once
in all header files, rather than using ifdefs to test for duplicate inclusion.
clang-format
For all C/C++ files (*.c
, *.cpp
and *.h
), we use clang-format
(specifically version 3.6) to apply our code formatting rules. After modifying C/C++ files and before merging, be sure to run:
$ ./scripts/format-code
This allows us to apply formatting choices such as the use of Allman style braces and the 80 character column width consistently.
Please stage the formatting changes with your commit, instead of making an extra “Format Code” commit. Your editor can likely be set up to automatically run clang-format
across the file or region you're editing. See:
The .clang-format file describes the style that is enforced by the script, which is based off the LLVM style with modifications closer to the default Visual Studio style. See clang-format style options for details.
If you see unexpected formatting changes in the code, verify that you are running version 11 or higher of the LLVM tool-chain.
The following license header must be included at the top of every new code file:
// Copyright (c) <Contributor> // SPDX-License-Identifier: Apache-2.0
It should be prefixed with the file's comment marker. If there is a compelling reason to not include this header, the file can be added to .check-license.ignore
.
All files are checked for this header with the script:
$ ./scripts/check-license
Naming conventions we use that are not automated include:
lower_snake_case
for variable, member/field, and function names.UPPER_SNAKE_CASE
for macro names and constants.lower_snake_case
file names for headers and sources.memory_context
, not mem_ctx
)._
to indicate internal and private fields or methods (e.g., _internal_field, _internal_method()
)._
) is reserved for local definitions (static, file-scope definitions). e.g., static ubpf_result_t _do_something(..).struct
definitions with _
(this is an exception to point 6), and always create a typedef
with the suffix _t
. For example:typedef struct _ubpf_widget { uint64_t count; } ubpf_widget_t;
ubpf_
(e.g., ubpf_result_t
).Above all, if a file happens to differ in style from these guidelines (e.g., private members are named m_member
rather than _member
), the existing style in that file takes precedence.