|
Packit |
95bb47 |
# C Style and Coding Standards for Persistent Memory Development Kit
|
|
Packit |
95bb47 |
|
|
Packit |
95bb47 |
This document defines the coding standards and conventions for writing
|
|
Packit |
95bb47 |
PMDK code. To ensure readability and consistency within the code,
|
|
Packit |
95bb47 |
the contributed code must adhere to the rules below.
|
|
Packit |
95bb47 |
|
|
Packit |
95bb47 |
### Introduction
|
|
Packit |
95bb47 |
The Persistent Memory Development Kit coding style is quite similar to the style
|
|
Packit |
95bb47 |
used for the SunOS product.
|
|
Packit |
95bb47 |
A full description of that standard can be found
|
|
Packit |
95bb47 |
[here.](https://www.cis.upenn.edu/~lee/06cse480/data/cstyle.ms.pdf)
|
|
Packit |
95bb47 |
|
|
Packit |
95bb47 |
This document does not cover the entire set of recommendations and formatting rules
|
|
Packit |
95bb47 |
used in writing PMDK code, but rather focuses on some PMDK-specific conventions,
|
|
Packit |
95bb47 |
not described in the document mentioned above, as well as the ones the violation
|
|
Packit |
95bb47 |
of which is most frequently observed during the code review.
|
|
Packit |
95bb47 |
Also, keep in mind that more important than the particular style is **consistency**
|
|
Packit |
95bb47 |
of coding style. So, when modifying the existing code, the changes should be
|
|
Packit |
95bb47 |
coded in the same style as the file being modified.
|
|
Packit |
95bb47 |
|
|
Packit |
95bb47 |
### Code formatting
|
|
Packit |
95bb47 |
Most of the common stylistic errors can be detected by the
|
|
Packit |
95bb47 |
[style checker program](https://github.com/pmem/pmdk/blob/master/utils/cstyle)
|
|
Packit |
95bb47 |
included in the repo.
|
|
Packit |
95bb47 |
Simply run `make cstyle` or `CSTYLE.ps1` to verify if your code is well-formatted.
|
|
Packit |
95bb47 |
|
|
Packit |
95bb47 |
Here is the list of the most important rules:
|
|
Packit |
95bb47 |
- The limit of line length is 80 characters.
|
|
Packit |
95bb47 |
- Indent the code with TABs, not spaces. Tab width is 8 characters.
|
|
Packit |
95bb47 |
- Do not break user-visible strings (even when they are longer than 80 characters)
|
|
Packit |
95bb47 |
- Put each variable declaration in a separate line.
|
|
Packit |
95bb47 |
- Do not use C++ comments (`//`).
|
|
Packit |
95bb47 |
- Spaces around operators are mandatory.
|
|
Packit |
95bb47 |
- No whitespace is allowed at the end of line.
|
|
Packit |
95bb47 |
- For multi-line macros, do not put whitespace before `\` character.
|
|
Packit |
95bb47 |
- Precede definition of each function with a brief, non-trivial description.
|
|
Packit |
95bb47 |
(Usually a single line is enough.)
|
|
Packit |
95bb47 |
- Use `XXX` tag to indicate a hack, problematic code, or something to be done.
|
|
Packit |
95bb47 |
- For pointer variables, place the `*` close to the variable name not pointer type.
|
|
Packit |
95bb47 |
- Avoid unnecessary variable initialization.
|
|
Packit |
95bb47 |
- Never type `unsigned int` - just use `unsigned` in such case.
|
|
Packit |
95bb47 |
Same with `long int` and `long`, etc.
|
|
Packit |
95bb47 |
- Sized types like `uint32_t`, `int64_t` should be used when there is an on-media format.
|
|
Packit |
95bb47 |
Otherwise, just use `unsigned`, `long`, etc.
|
|
Packit |
95bb47 |
- Functions with local scope must be declared as `static`.
|
|
Packit |
95bb47 |
|
|
Packit |
95bb47 |
### License & copyright
|
|
Packit |
95bb47 |
- Make sure you have the right to submit your contribution under the BSD license,
|
|
Packit |
95bb47 |
especially if it is based upon previous work.
|
|
Packit |
95bb47 |
See [CONTRIBUTING.md](https://github.com/pmem/pmdk/blob/master/CONTRIBUTING.md) for details.
|
|
Packit |
95bb47 |
- A copy of the [BSD-style License](https://github.com/pmem/pmdk/blob/master/LICENSE)
|
|
Packit |
95bb47 |
must be placed at the beginning of each source file, script or man page
|
|
Packit |
95bb47 |
(Obviously, it does not apply to README's, Visual Studio projects and \*.match files.)
|
|
Packit |
95bb47 |
- When adding a new file to the repo, or when making a contribution to an existing
|
|
Packit |
95bb47 |
file, feel free to put your copyright string on top of it.
|
|
Packit |
95bb47 |
|
|
Packit |
95bb47 |
### Naming convention
|
|
Packit |
95bb47 |
- Keep identifier names short, but meaningful. One-letter variables are discouraged.
|
|
Packit |
95bb47 |
- Use proper prefix for function name, depending on the module it belongs to.
|
|
Packit |
95bb47 |
- Use *under_score* pattern for function/variable names. Please, do not use
|
|
Packit |
95bb47 |
CamelCase or Hungarian notation.
|
|
Packit |
95bb47 |
- UPPERCASE constant/macro/enum names.
|
|
Packit |
95bb47 |
- Capitalize first letter for variables with global or module-level scope.
|
|
Packit |
95bb47 |
- Avoid using `l` as a variable name, because it is hard to distinguish `l` from `1`
|
|
Packit |
95bb47 |
on some displays.
|
|
Packit |
95bb47 |
|
|
Packit |
95bb47 |
### Multi-OS support (Linux/FreeBSD/Windows)
|
|
Packit |
95bb47 |
- Do not add `#ifdef <OS>` sections lightly. They should be treated as technical
|
|
Packit |
95bb47 |
debt and avoided when possible.
|
|
Packit |
95bb47 |
- Use `_WIN32` macro for conditional directives when including code using
|
|
Packit |
95bb47 |
Windows-specific API.
|
|
Packit |
95bb47 |
- Use `__FreeBSD__` macro for conditional directives for FreeBSD-specific code.
|
|
Packit |
95bb47 |
- Use `_MSC_VER` macro for conditional directives when including code using VC++
|
|
Packit |
95bb47 |
or gcc specific extensions.
|
|
Packit |
95bb47 |
- In case of large portions of code (i.e. a whole function) that have different
|
|
Packit |
95bb47 |
implementation for each OS, consider moving them to separate files.
|
|
Packit |
95bb47 |
(i.e. *xxx_linux.c*, *xxx_freebsd.c* and *xxx_windows.c*)
|
|
Packit |
95bb47 |
- Keep in mind that `long int` is always 32-bit in VC++, even when building for
|
|
Packit |
95bb47 |
64-bit platforms. Remember to use `long long` types whenever it applies, as well
|
|
Packit |
95bb47 |
as proper formatting strings and type suffixes (i.. `%llu`, `ULL`).
|
|
Packit |
95bb47 |
- Standard compliant solutions should be used in preference of compiler-specific ones.
|
|
Packit |
95bb47 |
(i.e. static inline functions versus statement expressions)
|
|
Packit |
95bb47 |
- Do not use formatting strings that are not supported by Windows implementations
|
|
Packit |
95bb47 |
of printf()/scanf() family. (like `%m`)
|
|
Packit |
95bb47 |
- It is recommended to use `PRI*` and `SCN*` macros in printf()/scanf() functions
|
|
Packit |
95bb47 |
for width-based integral types (`uint32_t`, `int64_t`, etc.).
|
|
Packit |
95bb47 |
|
|
Packit |
95bb47 |
### Debug traces and assertions
|
|
Packit |
95bb47 |
- Put `LOG(3, ...)` at the beginning of each function. Consider using higher
|
|
Packit |
95bb47 |
log level for most frequently called routines.
|
|
Packit |
95bb47 |
- Make use of `COMPILE_ERROR_ON` and `ASSERT*` macros.
|
|
Packit |
95bb47 |
- Use `ERR()` macro to log error messages.
|
|
Packit |
95bb47 |
|
|
Packit |
95bb47 |
### Unit tests
|
|
Packit |
95bb47 |
- There **must** be unit tests provided for each new function/module added.
|
|
Packit |
95bb47 |
- Test scripts **must** start with `#!/usr/bin/env <shell>` for portability between Linux and FreeBSD.
|
|
Packit |
95bb47 |
- Please, see [this](https://github.com/pmem/pmdk/blob/master/src/test/README)
|
|
Packit |
95bb47 |
and [that](https://github.com/pmem/pmdk/blob/master/src/test/unittest/README)
|
|
Packit |
95bb47 |
document to get familiar with
|
|
Packit |
95bb47 |
our test framework and the guidelines on how to write and run unit tests.
|
|
Packit |
95bb47 |
|
|
Packit |
95bb47 |
### Commit messages
|
|
Packit |
95bb47 |
All commit lines (entered when you run `git commit`) must follow the common
|
|
Packit |
95bb47 |
conventions for git commit messages:
|
|
Packit |
95bb47 |
- The first line is a short summary, no longer than **50 characters,** starting
|
|
Packit |
95bb47 |
with an area name and then a colon. There should be no period after
|
|
Packit |
95bb47 |
the short summary.
|
|
Packit |
95bb47 |
- Valid area names are: **pmem, obj, blk, log, vmem, vmmalloc, jemalloc,
|
|
Packit |
95bb47 |
**test, doc, daxio, pmreorder, pool** (for *libpmempool* and *pmempool*), **rpmem**
|
|
Packit |
95bb47 |
(for *librpmem* and *rpmemd*), **benchmark, examples** and **common** (for everything else).
|
|
Packit |
95bb47 |
- It is acceptable for the short summary to be the only thing in the commit
|
|
Packit |
95bb47 |
message if it is a trivial change. Otherwise, the second line must be
|
|
Packit |
95bb47 |
a blank line.
|
|
Packit |
95bb47 |
- Starting at the third line, additional information is given in complete
|
|
Packit |
95bb47 |
English sentences and, optionally, bulleted points. This content must not
|
|
Packit |
95bb47 |
extend beyond **column 72.**
|
|
Packit |
95bb47 |
- The English sentences should be written in the imperative, so you say
|
|
Packit |
95bb47 |
"Fix bug X" instead of "Fixed bug X" or "Fixes bug X".
|
|
Packit |
95bb47 |
- Bullet points should use hanging indents when they take up more than
|
|
Packit |
95bb47 |
one line (see example below).
|
|
Packit |
95bb47 |
- There can be any number of paragraphs, separated by a blank line, as many
|
|
Packit |
95bb47 |
as it takes to describe the change.
|
|
Packit |
95bb47 |
- Any references to GitHub issues are at the end of the commit message.
|
|
Packit |
95bb47 |
|
|
Packit |
95bb47 |
For example, here is a properly-formatted commit message:
|
|
Packit |
95bb47 |
```
|
|
Packit |
95bb47 |
doc: fix code formatting in man pages
|
|
Packit |
95bb47 |
|
|
Packit |
95bb47 |
This section contains paragraph style text with complete English
|
|
Packit |
95bb47 |
sentences. There can be as many paragraphs as necessary.
|
|
Packit |
95bb47 |
|
|
Packit |
95bb47 |
- Bullet points are typically sentence fragments
|
|
Packit |
95bb47 |
|
|
Packit |
95bb47 |
- The first word of the bullet point is usually capitalized and
|
|
Packit |
95bb47 |
if the point is long, it is continued with a hanging indent
|
|
Packit |
95bb47 |
|
|
Packit |
95bb47 |
- The sentence fragments don't typically end with a period
|
|
Packit |
95bb47 |
|
|
Packit |
95bb47 |
Ref: pmem/issues#1
|
|
Packit |
95bb47 |
```
|