Karl Wiberg | bb821e2 | 2017-09-03 03:02:12 | [diff] [blame] | 1 | # WebRTC coding style guide |
| 2 | |
Karl Wiberg | e1d464e | 2017-09-08 13:12:36 | [diff] [blame] | 3 | ## **General advice** |
Karl Wiberg | 241d710 | 2017-09-08 13:07:15 | [diff] [blame] | 4 | |
| 5 | Some older parts of the code violate the style guide in various ways. |
| 6 | |
| 7 | * If making small changes to such code, follow the style guide when |
| 8 | it’s reasonable to do so, but in matters of formatting etc., it is |
| 9 | often better to be consistent with the surrounding code. |
| 10 | * If making large changes to such code, consider first cleaning it up |
| 11 | in a separate CL. |
| 12 | |
Karl Wiberg | e1d464e | 2017-09-08 13:12:36 | [diff] [blame] | 13 | ## **C++** |
Karl Wiberg | bb821e2 | 2017-09-03 03:02:12 | [diff] [blame] | 14 | |
| 15 | WebRTC follows the [Chromium][chr-style] and [Google][goog-style] C++ |
Karl Wiberg | e1ed241 | 2017-09-06 09:10:23 | [diff] [blame] | 16 | style guides. In cases where they conflict, the Chromium style guide |
| 17 | trumps the Google style guide, and the rules in this file trump them |
| 18 | both. |
Karl Wiberg | bb821e2 | 2017-09-03 03:02:12 | [diff] [blame] | 19 | |
Karl Wiberg | 91d0ab7 | 2017-09-07 15:05:31 | [diff] [blame] | 20 | [chr-style]: https://chromium.googlesource.com/chromium/src/+/HEAD/styleguide/c++/c++.md |
Karl Wiberg | bb821e2 | 2017-09-03 03:02:12 | [diff] [blame] | 21 | [goog-style]: https://google.github.io/styleguide/cppguide.html |
| 22 | |
Karl Wiberg | 180d992 | 2018-03-15 10:21:05 | [diff] [blame] | 23 | ### C++ version |
| 24 | |
| 25 | WebRTC is written in C++11, but with some restrictions: |
| 26 | |
| 27 | * We only allow the subset of C++11 (language and library) in the |
| 28 | “allowed” section of [this Chromium page][chromium-cpp11]. |
| 29 | * We only allow the subset of C++11 that is also valid C++14; |
| 30 | otherwise, users would not be able to compile WebRTC in C++14 mode. |
| 31 | |
| 32 | [chromium-cpp11]: https://chromium-cpp.appspot.com/ |
| 33 | |
Karl Wiberg | c3af97d | 2018-08-27 02:26:18 | [diff] [blame] | 34 | ### Abseil |
| 35 | |
| 36 | You may use a subset of the utilities provided by the [Abseil][abseil] |
| 37 | library when writing WebRTC C++ code. [Details](abseil-in-webrtc.md). |
| 38 | |
| 39 | [abseil]: https://abseil.io/about/ |
| 40 | |
Karl Wiberg | 08c5cb0 | 2018-03-14 11:23:12 | [diff] [blame] | 41 | ### <a name="h-cc-pairs"></a>`.h` and `.cc` files come in pairs |
| 42 | |
| 43 | `.h` and `.cc` files should come in pairs, with the same name (except |
| 44 | for the file type suffix), in the same directory, in the same build |
| 45 | target. |
| 46 | |
| 47 | * If a declaration in `path/to/foo.h` has a definition in some `.cc` |
| 48 | file, it should be in `path/to/foo.cc`. |
| 49 | * If a definition in `path/to/foo.cc` file has a declaration in some |
| 50 | `.h` file, it should be in `path/to/foo.h`. |
| 51 | * Omit the `.cc` file if it would have been empty, but still list the |
| 52 | `.h` file in a build target. |
| 53 | * Omit the `.h` file if it would have been empty. (This can happen |
| 54 | with unit test `.cc` files, and with `.cc` files that define |
| 55 | `main`.) |
| 56 | |
| 57 | This makes the source code easier to navigate and organize, and |
| 58 | precludes some questionable build system practices such as having |
| 59 | build targets that don’t pull in definitions for everything they |
| 60 | declare. |
| 61 | |
| 62 | [Examples and exceptions](style-guide/h-cc-pairs.md). |
| 63 | |
Karl Wiberg | e1ed241 | 2017-09-06 09:10:23 | [diff] [blame] | 64 | ### ArrayView |
Karl Wiberg | bb821e2 | 2017-09-03 03:02:12 | [diff] [blame] | 65 | |
Karl Wiberg | e1ed241 | 2017-09-06 09:10:23 | [diff] [blame] | 66 | When passing an array of values to a function, use `rtc::ArrayView` |
| 67 | whenever possible—that is, whenever you’re not passing ownership of |
| 68 | the array, and don’t allow the callee to change the array size. |
| 69 | |
| 70 | For example, |
| 71 | |
| 72 | instead of | use |
| 73 | ------------------------------------|--------------------- |
| 74 | `const std::vector<T>&` | `ArrayView<const T>` |
| 75 | `const T* ptr, size_t num_elements` | `ArrayView<const T>` |
| 76 | `T* ptr, size_t num_elements` | `ArrayView<T>` |
| 77 | |
Karl Wiberg | 3b4c590 | 2018-03-14 11:27:55 | [diff] [blame] | 78 | See [the source](api/array_view.h) for more detailed docs. |
Karl Wiberg | fb4e677 | 2017-09-04 09:27:33 | [diff] [blame] | 79 | |
Taylor Brandstetter | efc5fbd | 2017-12-08 19:42:15 | [diff] [blame] | 80 | ### sigslot |
| 81 | |
| 82 | sigslot is a lightweight library that adds a signal/slot language |
| 83 | construct to C++, making it easy to implement the observer pattern |
| 84 | with minimal boilerplate code. |
| 85 | |
| 86 | When adding a signal to a pure interface, **prefer to add a pure |
| 87 | virtual method that returns a reference to a signal**: |
| 88 | |
| 89 | ``` |
| 90 | sigslot::signal<int>& SignalFoo() = 0; |
| 91 | ``` |
| 92 | |
| 93 | As opposed to making it a public member variable, as a lot of legacy |
| 94 | code does: |
| 95 | |
| 96 | ``` |
| 97 | sigslot::signal<int> SignalFoo; |
| 98 | ``` |
| 99 | |
| 100 | The virtual method approach has the advantage that it keeps the |
| 101 | interface stateless, and gives the subclass more flexibility in how it |
| 102 | implements the signal. It may: |
| 103 | |
| 104 | * Have its own signal as a member variable. |
| 105 | * Use a `sigslot::repeater`, to repeat a signal of another object: |
| 106 | |
| 107 | ``` |
| 108 | sigslot::repeater<int> foo_; |
| 109 | /* ... */ |
| 110 | foo_.repeat(bar_.SignalFoo()); |
| 111 | ``` |
| 112 | * Just return another object's signal directly, if the other object's |
| 113 | lifetime is the same as its own. |
| 114 | |
| 115 | ``` |
| 116 | sigslot::signal<int>& SignalFoo() { return bar_.SignalFoo(); } |
| 117 | ``` |
| 118 | |
Karl Wiberg | 0d44625 | 2018-03-19 22:27:35 | [diff] [blame] | 119 | ### std::bind |
| 120 | |
| 121 | Don’t use `std::bind`—there are pitfalls, and lambdas are almost as |
| 122 | succinct and already familiar to modern C++ programmers. |
| 123 | |
| 124 | ### std::function |
| 125 | |
| 126 | `std::function` is allowed, but remember that it’s not the right tool |
| 127 | for every occasion. Prefer to use interfaces when that makes sense, |
| 128 | and consider `rtc::FunctionView` for cases where the callee will not |
| 129 | save the function object. |
| 130 | |
Taylor Brandstetter | 212a206 | 2017-10-12 18:22:48 | [diff] [blame] | 131 | ### Forward declarations |
| 132 | |
| 133 | WebRTC follows the [Google][goog-forward-declarations] C++ style guide |
| 134 | with respect to forward declarations. In summary: avoid using forward |
| 135 | declarations where possible; just `#include` the headers you need. |
| 136 | |
| 137 | [goog-forward-declarations]: https://google.github.io/styleguide/cppguide.html#Forward_Declarations |
| 138 | |
Karl Wiberg | e1d464e | 2017-09-08 13:12:36 | [diff] [blame] | 139 | ## **C** |
Karl Wiberg | fb4e677 | 2017-09-04 09:27:33 | [diff] [blame] | 140 | |
| 141 | There’s a substantial chunk of legacy C code in WebRTC, and a lot of |
| 142 | it is old enough that it violates the parts of the C++ style guide |
| 143 | that also applies to C (naming etc.) for the simple reason that it |
| 144 | pre-dates the use of the current C++ style guide for this code base. |
| 145 | |
| 146 | * If making small changes to C code, mimic the style of the |
| 147 | surrounding code. |
| 148 | * If making large changes to C code, consider converting the whole |
| 149 | thing to C++ first. |
Karl Wiberg | ee3d760 | 2017-09-04 12:46:47 | [diff] [blame] | 150 | |
Karl Wiberg | e1d464e | 2017-09-08 13:12:36 | [diff] [blame] | 151 | ## **Java** |
Karl Wiberg | 241d710 | 2017-09-08 13:07:15 | [diff] [blame] | 152 | |
| 153 | WebRTC follows the [Google Java style guide][goog-java-style]. |
| 154 | |
| 155 | [goog-java-style]: https://google.github.io/styleguide/javaguide.html |
| 156 | |
Karl Wiberg | e1d464e | 2017-09-08 13:12:36 | [diff] [blame] | 157 | ## **Objective-C and Objective-C++** |
Karl Wiberg | 241d710 | 2017-09-08 13:07:15 | [diff] [blame] | 158 | |
| 159 | WebRTC follows the |
| 160 | [Chromium Objective-C and Objective-C++ style guide][chr-objc-style]. |
| 161 | |
| 162 | [chr-objc-style]: https://chromium.googlesource.com/chromium/src/+/HEAD/styleguide/objective-c/objective-c.md |
| 163 | |
Karl Wiberg | e1d464e | 2017-09-08 13:12:36 | [diff] [blame] | 164 | ## **Python** |
Karl Wiberg | 241d710 | 2017-09-08 13:07:15 | [diff] [blame] | 165 | |
| 166 | WebRTC follows [Chromium’s Python style][chr-py-style]. |
| 167 | |
| 168 | [chr-py-style]: https://chromium.googlesource.com/chromium/src/+/HEAD/styleguide/styleguide.md#python |
| 169 | |
Karl Wiberg | e1d464e | 2017-09-08 13:12:36 | [diff] [blame] | 170 | ## **Build files** |
Karl Wiberg | ee3d760 | 2017-09-04 12:46:47 | [diff] [blame] | 171 | |
Karl Wiberg | 91d0ab7 | 2017-09-07 15:05:31 | [diff] [blame] | 172 | The WebRTC build files are written in [GN][gn], and we follow |
| 173 | the [Chromium GN style guide][chr-gn-style]. Additionally, there are |
| 174 | some WebRTC-specific rules below; in case of conflict, they trump the |
| 175 | Chromium style guide. |
| 176 | |
| 177 | [gn]: https://chromium.googlesource.com/chromium/src/tools/gn/ |
| 178 | [chr-gn-style]: https://chromium.googlesource.com/chromium/src/tools/gn/+/HEAD/docs/style_guide.md |
| 179 | |
Per Kjellander | a7f2d84 | 2018-01-10 15:54:53 | [diff] [blame] | 180 | ### <a name="webrtc-gn-templates"></a>WebRTC-specific GN templates |
Karl Wiberg | 91d0ab7 | 2017-09-07 15:05:31 | [diff] [blame] | 181 | |
| 182 | Use the following [GN templates][gn-templ] to ensure that all |
| 183 | our [targets][gn-target] are built with the same configuration: |
| 184 | |
| 185 | instead of | use |
| 186 | -----------------|--------------------- |
| 187 | `executable` | `rtc_executable` |
| 188 | `shared_library` | `rtc_shared_library` |
| 189 | `source_set` | `rtc_source_set` |
| 190 | `static_library` | `rtc_static_library` |
| 191 | `test` | `rtc_test` |
| 192 | |
| 193 | [gn-templ]: https://chromium.googlesource.com/chromium/src/tools/gn/+/HEAD/docs/language.md#Templates |
| 194 | [gn-target]: https://chromium.googlesource.com/chromium/src/tools/gn/+/HEAD/docs/language.md#Targets |
| 195 | |
Per Kjellander | a7f2d84 | 2018-01-10 15:54:53 | [diff] [blame] | 196 | ### Target visibility and the native API |
| 197 | |
| 198 | The [WebRTC-specific GN templates](#webrtc-gn-templates) declare build |
| 199 | targets whose default `visibility` allows all other targets in the |
| 200 | WebRTC tree (and no targets outside the tree) to depend on them. |
| 201 | |
| 202 | Prefer to restrict the visibility if possible: |
| 203 | |
| 204 | * If a target is used by only one or a tiny number of other targets, |
| 205 | prefer to list them explicitly: `visibility = [ ":foo", ":bar" ]` |
| 206 | * If a target is used only by targets in the same `BUILD.gn` file: |
| 207 | `visibility = [ ":*" ]`. |
| 208 | |
| 209 | Setting `visibility = [ "*" ]` means that targets outside the WebRTC |
| 210 | tree can depend on this target; use this only for build targets whose |
| 211 | headers are part of the [native API](native-api.md). |
| 212 | |
Karl Wiberg | ee3d760 | 2017-09-04 12:46:47 | [diff] [blame] | 213 | ### Conditional compilation with the C preprocessor |
| 214 | |
| 215 | Avoid using the C preprocessor to conditionally enable or disable |
Karl Wiberg | 91d0ab7 | 2017-09-07 15:05:31 | [diff] [blame] | 216 | pieces of code. But if you can’t avoid it, introduce a GN variable, |
Karl Wiberg | ee3d760 | 2017-09-04 12:46:47 | [diff] [blame] | 217 | and then set a preprocessor constant to either 0 or 1 in the build |
| 218 | targets that need it: |
| 219 | |
| 220 | ``` |
| 221 | if (apm_debug_dump) { |
| 222 | defines = [ "WEBRTC_APM_DEBUG_DUMP=1" ] |
| 223 | } else { |
| 224 | defines = [ "WEBRTC_APM_DEBUG_DUMP=0" ] |
| 225 | } |
| 226 | ``` |
| 227 | |
| 228 | In the C, C++, or Objective-C files, use `#if` when testing the flag, |
| 229 | not `#ifdef` or `#if defined()`: |
| 230 | |
| 231 | ``` |
| 232 | #if WEBRTC_APM_DEBUG_DUMP |
| 233 | // One way. |
| 234 | #else |
| 235 | // Or another. |
| 236 | #endif |
| 237 | ``` |
| 238 | |
| 239 | When combined with the `-Wundef` compiler option, this produces |
| 240 | compile time warnings if preprocessor symbols are misspelled, or used |
| 241 | without corresponding build rules to set them. |