• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Open Screen Library
2
3The openscreen library implements the Open Screen Protocol and the Chromecast
4protocols (both control and streaming).
5
6Information about the protocol and its specification can be found [on
7GitHub](https://github.com/webscreens/openscreenprotocol).
8
9# Getting the code
10
11## Installing depot_tools
12
13openscreen library dependencies are managed using `gclient`, from the
14[depot_tools](https://www.chromium.org/developers/how-tos/depottools) repo.
15
16To get gclient, run the following command in your terminal:
17```bash
18    git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
19```
20
21Then add the `depot_tools` folder to your `PATH` environment variable.
22
23Note that openscreen does not use other features of `depot_tools` like `repo` or
24`drover`.  However, some `git-cl` functions *do* work, like `git cl try`, `git cl
25lint` and `git cl upload.`
26
27## Checking out code
28
29From the parent directory of where you want the openscreen checkout (e.g.,
30`~/my_project_dir`), configure `gclient` and check out openscreen with the
31following commands:
32
33```bash
34    cd ~/my_project_dir
35    gclient config https://chromium.googlesource.com/openscreen
36    gclient sync
37```
38
39The first `gclient` command will create a default .gclient file in
40`~/my_project_dir` that describes how to pull down the `openscreen` repository.
41The second command creates an `openscreen/` subdirectory, downloads the source
42code, all third-party dependencies, and the toolchain needed to build things;
43and at their appropriate revisions.
44
45## Syncing your local checkout
46
47To update your local checkout from the openscreen master repository, just run
48
49```bash
50   cd ~/my_project_dir/openscreen
51   git pull
52   gclient sync
53```
54
55This will rebase any local commits on the remote top-of-tree, and update any
56dependencies that have changed.
57
58# Build setup
59
60The following are the main tools are required for development/builds:
61
62 - Build file generator: `gn`
63 - Code formatter: `clang-format`
64 - Builder: `ninja` ([GitHub releases](https://github.com/ninja-build/ninja/releases))
65 - Compiler/Linker: `clang` (installed by default) or `gcc` (installed by you)
66
67All of these--except `gcc` as noted above--are automatically downloaded/updated
68for the Linux and Mac environments via `gclient sync` as described above. The
69first two are installed into `buildtools/<platform>/`.
70
71Mac only: XCode must be installed on the system, to link against its frameworks.
72
73`clang-format` is used for maintaining consistent coding style, but it is not a
74complete replacement for adhering to Chromium/Google C++ style (that's on you!).
75The presubmit script will sanity-check that it has been run on all new/changed
76code.
77
78## Linux clang
79
80On Linux, the build will automatically download the Clang compiler from the
81Google storage cache, the same way that Chromium does it.
82
83Ensure that libstdc++ 8 is installed, as clang depends on the system
84instance of it. On Debian flavors, you can run:
85
86```bash
87   sudo apt-get install libstdc++-8-dev
88```
89
90## Linux gcc
91
92Setting the `gn` argument "is_gcc=true" on Linux enables building using gcc
93instead.
94
95```bash
96  gn gen out/Default --args="is_gcc=true"
97```
98
99Note that g++ version 7 or newer must be installed.  On Debian flavors you can
100run:
101
102```bash
103  sudo apt-get install gcc-7
104```
105
106## Mac clang
107
108On Mac OS X, the build will use the clang provided by
109[XCode](https://apps.apple.com/us/app/xcode/id497799835?mt=12), which must be
110installed.
111
112## Debug build
113
114Setting the `gn` argument "is_debug=true" enables debug build.
115
116```bash
117  gn gen out/Default --args="is_debug=true"
118```
119
120To install debug information for libstdc++ 8 on Debian flavors, you can run:
121
122```bash
123   sudo apt-get install libstdc++6-8-dbg
124```
125
126## gn configuration
127
128Running `gn args` opens an editor that allows to create a list of arguments
129passed to every invocation of `gn gen`.
130
131```bash
132  gn args out/Default
133```
134
135# Building targets
136
137## Building the OSP demo
138
139The following commands will build a sample executable and run it.
140
141``` bash
142  mkdir out/Default
143  gn gen out/Default          # Creates the build directory and necessary ninja files
144  ninja -C out/Default demo   # Builds the executable with ninja
145  ./out/Default/demo          # Runs the executable
146```
147
148The `-C` argument to `ninja` works just like it does for GNU Make: it specifies
149the working directory for the build.  So the same could be done as follows:
150
151``` bash
152  ./gn gen out/Default
153  cd out/Default
154  ninja
155  ./demo
156```
157
158After editing a file, only `ninja` needs to be rerun, not `gn`.  If you have
159edited a `BUILD.gn` file, `ninja` will re-run `gn` for you.
160
161Unless you like to wait longer than necessary for builds to complete, run
162`autoninja` instead of `ninja`, which takes the same command-line arguments.
163This will automatically parallelize the build for your system, depending on
164number of processor cores, RAM, etc.
165
166For details on running `demo`, see its [README.md](demo/README.md).
167
168## Building other targets
169
170Running `ninja -C out/Default gn_all` will build all non-test targets in the
171repository.
172
173`gn ls --type=executable out/Default/` will list all of the executable targets
174that can be built.
175
176If you want to customize the build further, you can run `gn args out/Default` to
177pull up an editor for build flags. `gn args --list out/Default` prints all of
178the build flags available.
179
180## Building and running unit tests
181
182```bash
183  ninja -C out/Default unittests
184  ./out/Default/unittests
185```
186
187## Building and running fuzzers
188
189In order to build fuzzers, you need the GN arg `use_libfuzzer=true`.  It's also
190recommended to build with `is_asan=true` to catch additional problems.  Building
191and running then might look like:
192```bash
193  gn gen out/libfuzzer --args="use_libfuzzer=true is_asan=true is_debug=false"
194  ninja -C out/libfuzzer some_fuzz_target
195  out/libfuzzer/some_fuzz_target <args> <corpus_dir> [additional corpus dirs]
196```
197
198The arguments to the fuzzer binary should be whatever is listed in the GN target
199description (e.g. `-max_len=1500`).  These arguments may be automatically
200scraped by Chromium's ClusterFuzz tool when it runs fuzzers, but they are not
201built into the target.  You can also look at the file
202`out/libfuzzer/some_fuzz_target.options` for what arguments should be used.  The
203`corpus_dir` is listed as `seed_corpus` in the GN definition of the fuzzer
204target.
205
206# Continuous build and try jobs
207
208openscreen uses [LUCI builders](https://ci.chromium.org/p/openscreen/builders)
209to monitor the build and test health of the library.  Current builders include:
210
211| Name                   | Arch   | OS                 | Toolchain | Build   | Notes                  |
212|------------------------|--------|--------------------|-----------|---------|------------------------|
213| linux64_debug          | x86-64 | Ubuntu Linux 16.04 | clang     | debug   | ASAN enabled           |
214| linux64_gcc_debug      | x86-64 | Ubuntu Linux 18.04 | gcc-7     | debug   |                        |
215| linux64_tsan           | x86-64 | Ubuntu Linux 16.04 | clang     | release | TSAN enabled           |
216| mac_debug              | x86-64 | Mac OS X/Xcode     | clang     | debug   |                        |
217| chromium_linux64_debug | x86-64 | Ubuntu Linux 16.04 | clang     | debug   | built within chromium  |
218| chromium_mac_debug     | x86-64 | Mac OS X/Xcode     | clang     | debug   | built within chromium  |
219| linux64_coverage_debug | x86-64 | Ubuntu Linux 16.04 | clang     | debug   | used for code coverage |
220
221You can run a patch through the try job queue (which tests it on all
222non-chromium builders) using `git cl try`, or through Gerrit (details below).
223
224The chromium builders compile openscreen HEAD vs. chromium HEAD.  They run as
225experimental trybots and continuous-integration FYI bots.
226
227# Submitting changes
228
229openscreen library code should follow the [Open Screen Library Style
230Guide](docs/style_guide.md).
231
232openscreen uses [Chromium Gerrit](https://chromium-review.googlesource.com/) for
233patch management and code review (for better or worse).
234
235The following sections contain some tips about dealing with Gerrit for code
236reviews, specifically when pushing patches for review, getting patches reviewed,
237and committing patches.
238
239## Uploading a patch for review
240
241The `git cl` tool handles details of interacting with Gerrit (the Chromium code
242review tool) and is recommended for pushing patches for review.  Once you have
243committed changes locally, simply run:
244
245```bash
246  git cl format
247  git cl upload
248```
249
250The first command will will auto-format the code changes. Then, the second
251command runs the `PRESUBMIT.sh` script to check style and, if it passes, a
252newcode review will be posted on `chromium-review.googlesource.com`.
253
254If you make additional commits to your local branch, then running `git cl
255upload` again in the same branch will merge those commits into the ongoing
256review as a new patchset.
257
258It's simplest to create a local git branch for each patch you want reviewed
259separately.  `git cl` keeps track of review status separately for each local
260branch.
261
262## Addressing merge conflicts
263
264If conflicting commits have been landed in the repository for a patch in review,
265Gerrit will flag the patch as having a merge conflict.  In that case, use the
266instructions above to rebase your commits on top-of-tree and upload a new
267patchset with the merge conflicts resolved.
268
269## Tryjobs
270
271Clicking the `CQ DRY RUN` button (also, confusingly, labeled `COMMIT QUEUE +1`)
272will run the current patchset through all LUCI builders and report the results.
273It is always a good idea get a green tryjob on a patch before sending it for
274review to avoid extra back-and-forth.
275
276You can also run `git cl try` from the commandline to submit a tryjob.
277
278## Code reviews
279
280Send your patch to one or more committers in the
281[COMMITTERS](https://chromium.googlesource.com/openscreen/+/refs/heads/master/COMMITTERS)
282file for code review.  All patches must receive at least one LGTM by a committer
283before it can be submitted.
284
285## Submission
286
287After your patch has received one or more LGTM commit it by clicking the
288`SUBMIT` button (or, confusingly, `COMMIT QUEUE +2`) in Gerrit.  This will run
289your patch through the builders again before committing to the main openscreen
290repository.
291
292<!-- TODO(mfoltz): split up README.md into more manageable files. -->
293## Working with ARM/ARM64/the Raspberry PI
294
295openscreen supports cross compilation for both arm32 and arm64 platforms, by
296using the `gn args` parameter `target_cpu="arm"` or `target_cpu="arm64"`
297respectively. Note that quotes are required around the target arch value.
298
299Setting an arm(64) target_cpu causes GN to pull down a sysroot from openscreen's
300public cloud storage bucket. Google employees may update the sysroots stored
301by requesting access to the Open Screen pantheon project and uploading a new
302tar.xz to the openscreen-sysroots bucket.
303
304NOTE: The "arm" image is taken from Chromium's debian arm image, however it has
305been manually patched to include support for libavcodec and libsdl2. To update
306this image, the new image must be manually patched to include the necessary
307header and library dependencies. Note that if the versions of libavcodec and
308libsdl2 are too out of sync from the copies in the sysroot, compilation will
309succeed, but you may experience issues decoding content.
310
311To install the last known good version of the libavcodec and libsdl packages
312on a Raspberry Pi, you can run the following command:
313
314```bash
315sudo ./cast/standalone_receiver/install_demo_deps_raspian.sh
316```
317
318NOTE: until [Issue 106](http://crbug.com/openscreen/106) is resolved, you may
319experience issues streaming to a Raspberry Pi if multiple network interfaces
320(e.g. WiFi + Ethernet) are enabled. The workaround is to disable either the WiFi
321or ethernet connection.
322
323## Code Coverage
324
325Code coverage can be checked using clang's source-based coverage tools.  You
326must use the GN argument `use_coverage=true`.  It's recommended to do this in a
327separate output directory since the added instrumentation will affect
328performance and generate an output file every time a binary is run.  You can
329read more about this in [clang's
330documentation](http://clang.llvm.org/docs/SourceBasedCodeCoverage.html) but the
331bare minimum steps are also outlined below.  You will also need to download the
332pre-built clang coverage tools, which are not downloaded by default.  The
333easiest way to do this is to set a custom variable in your `.gclient` file.
334Under the "openscreen" solution, add:
335```python
336  "custom_vars": {
337    "checkout_clang_coverage_tools": True,
338  },
339```
340then run `gclient runhooks`.  You can also run the python command from the
341`clang_coverage_tools` hook in `//DEPS` yourself or even download the tools
342manually
343([link](https://storage.googleapis.com/chromium-browser-clang-staging/)).
344
345Once you have your GN directory (we'll call it `out/coverage`) and have
346downloaded the tools, do the following to generate an HTML coverage report:
347```bash
348out/coverage/openscreen_unittests
349third_party/llvm-build/Release+Asserts/bin/llvm-profdata merge -sparse default.profraw -o foo.profdata
350third_party/llvm-build/Release+Asserts/bin/llvm-cov show out/coverage/openscreen_unittests -instr-profile=foo.profdata -format=html -output-dir=<out dir> [filter paths]
351```
352There are a few things to note here:
353 - `default.profraw` is generated by running the instrumented code, but
354 `foo.profdata` can be any path you want.
355 - `<out dir>` should be an empty directory for placing the generated HTML
356 files.  You can view the report at `<out dir>/index.html`.
357 - `[filter paths]` is a list of paths to which you want to limit the coverage
358 report.  For example, you may want to limit it to cast/ or even
359 cast/streaming/.  If this list is empty, all data will be in the report.
360
361The same process can be used to check the coverage of a fuzzer's corpus.  Just
362add `-runs=0` to the fuzzer arguments to make sure it only runs the existing
363corpus then exits.
364