aboutsummaryrefslogtreecommitdiff
path: root/style-guide.md
blob: dd4fb527d565bad824fd9b7ab26e97a9219974a7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
# WebRTC coding style guide

## **General advice**

Some older parts of the code violate the style guide in various ways.

* If making small changes to such code, follow the style guide when
  it’s reasonable to do so, but in matters of formatting etc., it is
  often better to be consistent with the surrounding code.
* If making large changes to such code, consider first cleaning it up
  in a separate CL.

## **C++**

WebRTC follows the [Chromium][chr-style] and [Google][goog-style] C++
style guides. In cases where they conflict, the Chromium style guide
trumps the Google style guide, and the rules in this file trump them
both.

[chr-style]: https://chromium.googlesource.com/chromium/src/+/HEAD/styleguide/c++/c++.md
[goog-style]: https://google.github.io/styleguide/cppguide.html

### C++ version

WebRTC is written in C++14, but with some restrictions:

* We only allow the subset of C++14 (language and library) that is not
  banned by Chromium; see [this page][chromium-cpp].
* We only allow the subset of C++14 that is also valid C++17;
  otherwise, users would not be able to compile WebRTC in C++17 mode.

[chromium-cpp]: https://chromium-cpp.appspot.com/

Unlike the Chromium and Google C++ style guides, we do not allow C++20-style
designated initializers, because we want to stay compatible with compilers that
do not yet support them.

### Abseil

You may use a subset of the utilities provided by the [Abseil][abseil]
library when writing WebRTC C++ code. [Details](abseil-in-webrtc.md).

[abseil]: https://abseil.io/about/

### <a name="h-cc-pairs"></a>`.h` and `.cc` files come in pairs

`.h` and `.cc` files should come in pairs, with the same name (except
for the file type suffix), in the same directory, in the same build
target.

* If a declaration in `path/to/foo.h` has a definition in some `.cc`
  file, it should be in `path/to/foo.cc`.
* If a definition in `path/to/foo.cc` file has a declaration in some
  `.h` file, it should be in `path/to/foo.h`.
* Omit the `.cc` file if it would have been empty, but still list the
  `.h` file in a build target.
* Omit the `.h` file if it would have been empty. (This can happen
  with unit test `.cc` files, and with `.cc` files that define
  `main`.)

This makes the source code easier to navigate and organize, and
precludes some questionable build system practices such as having
build targets that don’t pull in definitions for everything they
declare.

[Examples and exceptions](style-guide/h-cc-pairs.md).

### TODO comments

Follow the [Google style][goog-style-todo]. When referencing a WebRTC bug,
prefer the url form, e.g.
```
// TODO(bugs.webrtc.org/12345): Delete the hack when blocking bugs are resolved.
```

[goog-style-todo]: https://google.github.io/styleguide/cppguide.html#TODO_Comments

### Deprecation

Annotate the declarations of deprecated functions and classes with
[ABSL_DEPRECATED][ABSL_DEPRECATED] to cause an error when they're used inside
webrtc and a compiler warning when they're used by dependant projects. Like so:

```
ABSL_DEPRECATED("bugs.webrtc.org/12345")
std::pony PonyPlz(const std::pony_spec& ps);
```

NOTE 1: The annotation goes on the declaration in the .h file, not the
definition in the .cc file!

NOTE 2: In order to have unit tests that use the deprecated function without
getting errors, do something like this:

```
std::pony DEPRECATED_PonyPlz(const std::pony_spec& ps);
ABSL_DEPRECATED("bugs.webrtc.org/12345")
inline std::pony PonyPlz(const std::pony_spec& ps) {
  return DEPRECATED_PonyPlz(ps);
}
```

In other words, rename the existing function, and provide an inline wrapper
using the original name that calls it. That way, callers who are willing to
call it using the DEPRECATED_-prefixed name don't get the warning.

[ABSL_DEPRECATED]: https://source.chromium.org/chromium/chromium/src/+/master:third_party/abseil-cpp/absl/base/attributes.h?q=ABSL_DEPRECATED

### ArrayView

When passing an array of values to a function, use `rtc::ArrayView`
whenever possible—that is, whenever you’re not passing ownership of
the array, and don’t allow the callee to change the array size.

For example,

instead of                          | use
------------------------------------|---------------------
`const std::vector<T>&`             | `ArrayView<const T>`
`const T* ptr, size_t num_elements` | `ArrayView<const T>`
`T* ptr, size_t num_elements`       | `ArrayView<T>`

See [the source](api/array_view.h) for more detailed docs.

### sigslot

SIGSLOT IS DEPRECATED.

Prefer webrtc::CallbackList, and manage thread safety yourself.

### Smart pointers

The following smart pointer types are recommended:

   * std::unique_ptr for all singly-owned objects
   * rtc::scoped_refptr for all objects with shared ownership

Use of std::shared_ptr is *not permitted*. It is
[banned](https://chromium-cpp.appspot.com/#library-blocklist) in the Chromium
style guide (overriding the Google style guide), and offers no compelling
advantage over rtc::scoped_refptr (which is cloned from the corresponding
Chromium type).

In most cases, one will want to explicitly control lifetimes, and therefore
use std::unique_ptr, but in some cases, for instance  where references have
to exist both from the API users and internally, with no way to
invalidate pointers held by the API user, rtc::scoped_refptr can be
appropriate.

### std::bind

Don’t use `std::bind`—there are pitfalls, and lambdas are almost as
succinct and already familiar to modern C++ programmers.

### std::function

`std::function` is allowed, but remember that it’s not the right tool
for every occasion. Prefer to use interfaces when that makes sense,
and consider `rtc::FunctionView` for cases where the callee will not
save the function object.

### Forward declarations

WebRTC follows the [Google][goog-forward-declarations] C++ style guide
with respect to forward declarations. In summary: avoid using forward
declarations where possible; just `#include` the headers you need.

[goog-forward-declarations]: https://google.github.io/styleguide/cppguide.html#Forward_Declarations

## **C**

There’s a substantial chunk of legacy C code in WebRTC, and a lot of
it is old enough that it violates the parts of the C++ style guide
that also applies to C (naming etc.) for the simple reason that it
pre-dates the use of the current C++ style guide for this code base.

* If making small changes to C code, mimic the style of the
  surrounding code.
* If making large changes to C code, consider converting the whole
  thing to C++ first.

## **Java**

WebRTC follows the [Google Java style guide][goog-java-style].

[goog-java-style]: https://google.github.io/styleguide/javaguide.html

## **Objective-C and Objective-C++**

WebRTC follows the
[Chromium Objective-C and Objective-C++ style guide][chr-objc-style].

[chr-objc-style]: https://chromium.googlesource.com/chromium/src/+/HEAD/styleguide/objective-c/objective-c.md

## **Python**

WebRTC follows [Chromium’s Python style][chr-py-style].

[chr-py-style]: https://chromium.googlesource.com/chromium/src/+/HEAD/styleguide/styleguide.md#python

## **Build files**

The WebRTC build files are written in [GN][gn], and we follow
the [Chromium GN style guide][chr-gn-style]. Additionally, there are
some WebRTC-specific rules below; in case of conflict, they trump the
Chromium style guide.

[gn]: https://chromium.googlesource.com/chromium/src/tools/gn/
[chr-gn-style]: https://chromium.googlesource.com/chromium/src/tools/gn/+/HEAD/docs/style_guide.md

### <a name="webrtc-gn-templates"></a>WebRTC-specific GN templates

Use the following [GN templates][gn-templ] to ensure that all
our [targets][gn-target] are built with the same configuration:

instead of       | use
-----------------|---------------------
`executable`     | `rtc_executable`
`shared_library` | `rtc_shared_library`
`source_set`     | `rtc_source_set`
`static_library` | `rtc_static_library`
`test`           | `rtc_test`

[gn-templ]: https://chromium.googlesource.com/chromium/src/tools/gn/+/HEAD/docs/language.md#Templates
[gn-target]: https://chromium.googlesource.com/chromium/src/tools/gn/+/HEAD/docs/language.md#Targets

### Target visibility and the native API

The [WebRTC-specific GN templates](#webrtc-gn-templates) declare build
targets whose default `visibility` allows all other targets in the
WebRTC tree (and no targets outside the tree) to depend on them.

Prefer to restrict the visibility if possible:

* If a target is used by only one or a tiny number of other targets,
  prefer to list them explicitly: `visibility = [ ":foo", ":bar" ]`
* If a target is used only by targets in the same `BUILD.gn` file:
  `visibility = [ ":*" ]`.

Setting `visibility = [ "*" ]` means that targets outside the WebRTC
tree can depend on this target; use this only for build targets whose
headers are part of the [native API](native-api.md).

### Conditional compilation with the C preprocessor

Avoid using the C preprocessor to conditionally enable or disable
pieces of code. But if you can’t avoid it, introduce a GN variable,
and then set a preprocessor constant to either 0 or 1 in the build
targets that need it:

```
if (apm_debug_dump) {
  defines = [ "WEBRTC_APM_DEBUG_DUMP=1" ]
} else {
  defines = [ "WEBRTC_APM_DEBUG_DUMP=0" ]
}
```

In the C, C++, or Objective-C files, use `#if` when testing the flag,
not `#ifdef` or `#if defined()`:

```
#if WEBRTC_APM_DEBUG_DUMP
// One way.
#else
// Or another.
#endif
```

When combined with the `-Wundef` compiler option, this produces
compile time warnings if preprocessor symbols are misspelled, or used
without corresponding build rules to set them.