You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
364 lines
14 KiB
364 lines
14 KiB
# Open Screen Library
|
|
|
|
The openscreen library implements the Open Screen Protocol and the Chromecast
|
|
protocols (both control and streaming).
|
|
|
|
Information about the protocol and its specification can be found [on
|
|
GitHub](https://github.com/webscreens/openscreenprotocol).
|
|
|
|
# Getting the code
|
|
|
|
## Installing depot_tools
|
|
|
|
openscreen library dependencies are managed using `gclient`, from the
|
|
[depot_tools](https://www.chromium.org/developers/how-tos/depottools) repo.
|
|
|
|
To get gclient, run the following command in your terminal:
|
|
```bash
|
|
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
|
|
```
|
|
|
|
Then add the `depot_tools` folder to your `PATH` environment variable.
|
|
|
|
Note that openscreen does not use other features of `depot_tools` like `repo` or
|
|
`drover`. However, some `git-cl` functions *do* work, like `git cl try`, `git cl
|
|
lint` and `git cl upload.`
|
|
|
|
## Checking out code
|
|
|
|
From the parent directory of where you want the openscreen checkout (e.g.,
|
|
`~/my_project_dir`), configure `gclient` and check out openscreen with the
|
|
following commands:
|
|
|
|
```bash
|
|
cd ~/my_project_dir
|
|
gclient config https://chromium.googlesource.com/openscreen
|
|
gclient sync
|
|
```
|
|
|
|
The first `gclient` command will create a default .gclient file in
|
|
`~/my_project_dir` that describes how to pull down the `openscreen` repository.
|
|
The second command creates an `openscreen/` subdirectory, downloads the source
|
|
code, all third-party dependencies, and the toolchain needed to build things;
|
|
and at their appropriate revisions.
|
|
|
|
## Syncing your local checkout
|
|
|
|
To update your local checkout from the openscreen master repository, just run
|
|
|
|
```bash
|
|
cd ~/my_project_dir/openscreen
|
|
git pull
|
|
gclient sync
|
|
```
|
|
|
|
This will rebase any local commits on the remote top-of-tree, and update any
|
|
dependencies that have changed.
|
|
|
|
# Build setup
|
|
|
|
The following are the main tools are required for development/builds:
|
|
|
|
- Build file generator: `gn`
|
|
- Code formatter: `clang-format`
|
|
- Builder: `ninja` ([GitHub releases](https://github.com/ninja-build/ninja/releases))
|
|
- Compiler/Linker: `clang` (installed by default) or `gcc` (installed by you)
|
|
|
|
All of these--except `gcc` as noted above--are automatically downloaded/updated
|
|
for the Linux and Mac environments via `gclient sync` as described above. The
|
|
first two are installed into `buildtools/<platform>/`.
|
|
|
|
Mac only: XCode must be installed on the system, to link against its frameworks.
|
|
|
|
`clang-format` is used for maintaining consistent coding style, but it is not a
|
|
complete replacement for adhering to Chromium/Google C++ style (that's on you!).
|
|
The presubmit script will sanity-check that it has been run on all new/changed
|
|
code.
|
|
|
|
## Linux clang
|
|
|
|
On Linux, the build will automatically download the Clang compiler from the
|
|
Google storage cache, the same way that Chromium does it.
|
|
|
|
Ensure that libstdc++ 8 is installed, as clang depends on the system
|
|
instance of it. On Debian flavors, you can run:
|
|
|
|
```bash
|
|
sudo apt-get install libstdc++-8-dev
|
|
```
|
|
|
|
## Linux gcc
|
|
|
|
Setting the `gn` argument "is_gcc=true" on Linux enables building using gcc
|
|
instead.
|
|
|
|
```bash
|
|
gn gen out/Default --args="is_gcc=true"
|
|
```
|
|
|
|
Note that g++ version 7 or newer must be installed. On Debian flavors you can
|
|
run:
|
|
|
|
```bash
|
|
sudo apt-get install gcc-7
|
|
```
|
|
|
|
## Mac clang
|
|
|
|
On Mac OS X, the build will use the clang provided by
|
|
[XCode](https://apps.apple.com/us/app/xcode/id497799835?mt=12), which must be
|
|
installed.
|
|
|
|
## Debug build
|
|
|
|
Setting the `gn` argument "is_debug=true" enables debug build.
|
|
|
|
```bash
|
|
gn gen out/Default --args="is_debug=true"
|
|
```
|
|
|
|
To install debug information for libstdc++ 8 on Debian flavors, you can run:
|
|
|
|
```bash
|
|
sudo apt-get install libstdc++6-8-dbg
|
|
```
|
|
|
|
## gn configuration
|
|
|
|
Running `gn args` opens an editor that allows to create a list of arguments
|
|
passed to every invocation of `gn gen`.
|
|
|
|
```bash
|
|
gn args out/Default
|
|
```
|
|
|
|
# Building targets
|
|
|
|
## Building the OSP demo
|
|
|
|
The following commands will build a sample executable and run it.
|
|
|
|
``` bash
|
|
mkdir out/Default
|
|
gn gen out/Default # Creates the build directory and necessary ninja files
|
|
ninja -C out/Default demo # Builds the executable with ninja
|
|
./out/Default/demo # Runs the executable
|
|
```
|
|
|
|
The `-C` argument to `ninja` works just like it does for GNU Make: it specifies
|
|
the working directory for the build. So the same could be done as follows:
|
|
|
|
``` bash
|
|
./gn gen out/Default
|
|
cd out/Default
|
|
ninja
|
|
./demo
|
|
```
|
|
|
|
After editing a file, only `ninja` needs to be rerun, not `gn`. If you have
|
|
edited a `BUILD.gn` file, `ninja` will re-run `gn` for you.
|
|
|
|
Unless you like to wait longer than necessary for builds to complete, run
|
|
`autoninja` instead of `ninja`, which takes the same command-line arguments.
|
|
This will automatically parallelize the build for your system, depending on
|
|
number of processor cores, RAM, etc.
|
|
|
|
For details on running `demo`, see its [README.md](demo/README.md).
|
|
|
|
## Building other targets
|
|
|
|
Running `ninja -C out/Default gn_all` will build all non-test targets in the
|
|
repository.
|
|
|
|
`gn ls --type=executable out/Default/` will list all of the executable targets
|
|
that can be built.
|
|
|
|
If you want to customize the build further, you can run `gn args out/Default` to
|
|
pull up an editor for build flags. `gn args --list out/Default` prints all of
|
|
the build flags available.
|
|
|
|
## Building and running unit tests
|
|
|
|
```bash
|
|
ninja -C out/Default unittests
|
|
./out/Default/unittests
|
|
```
|
|
|
|
## Building and running fuzzers
|
|
|
|
In order to build fuzzers, you need the GN arg `use_libfuzzer=true`. It's also
|
|
recommended to build with `is_asan=true` to catch additional problems. Building
|
|
and running then might look like:
|
|
```bash
|
|
gn gen out/libfuzzer --args="use_libfuzzer=true is_asan=true is_debug=false"
|
|
ninja -C out/libfuzzer some_fuzz_target
|
|
out/libfuzzer/some_fuzz_target <args> <corpus_dir> [additional corpus dirs]
|
|
```
|
|
|
|
The arguments to the fuzzer binary should be whatever is listed in the GN target
|
|
description (e.g. `-max_len=1500`). These arguments may be automatically
|
|
scraped by Chromium's ClusterFuzz tool when it runs fuzzers, but they are not
|
|
built into the target. You can also look at the file
|
|
`out/libfuzzer/some_fuzz_target.options` for what arguments should be used. The
|
|
`corpus_dir` is listed as `seed_corpus` in the GN definition of the fuzzer
|
|
target.
|
|
|
|
# Continuous build and try jobs
|
|
|
|
openscreen uses [LUCI builders](https://ci.chromium.org/p/openscreen/builders)
|
|
to monitor the build and test health of the library. Current builders include:
|
|
|
|
| Name | Arch | OS | Toolchain | Build | Notes |
|
|
|------------------------|--------|--------------------|-----------|---------|------------------------|
|
|
| linux64_debug | x86-64 | Ubuntu Linux 16.04 | clang | debug | ASAN enabled |
|
|
| linux64_gcc_debug | x86-64 | Ubuntu Linux 18.04 | gcc-7 | debug | |
|
|
| linux64_tsan | x86-64 | Ubuntu Linux 16.04 | clang | release | TSAN enabled |
|
|
| mac_debug | x86-64 | Mac OS X/Xcode | clang | debug | |
|
|
| chromium_linux64_debug | x86-64 | Ubuntu Linux 16.04 | clang | debug | built within chromium |
|
|
| chromium_mac_debug | x86-64 | Mac OS X/Xcode | clang | debug | built within chromium |
|
|
| linux64_coverage_debug | x86-64 | Ubuntu Linux 16.04 | clang | debug | used for code coverage |
|
|
|
|
You can run a patch through the try job queue (which tests it on all
|
|
non-chromium builders) using `git cl try`, or through Gerrit (details below).
|
|
|
|
The chromium builders compile openscreen HEAD vs. chromium HEAD. They run as
|
|
experimental trybots and continuous-integration FYI bots.
|
|
|
|
# Submitting changes
|
|
|
|
openscreen library code should follow the [Open Screen Library Style
|
|
Guide](docs/style_guide.md).
|
|
|
|
openscreen uses [Chromium Gerrit](https://chromium-review.googlesource.com/) for
|
|
patch management and code review (for better or worse).
|
|
|
|
The following sections contain some tips about dealing with Gerrit for code
|
|
reviews, specifically when pushing patches for review, getting patches reviewed,
|
|
and committing patches.
|
|
|
|
## Uploading a patch for review
|
|
|
|
The `git cl` tool handles details of interacting with Gerrit (the Chromium code
|
|
review tool) and is recommended for pushing patches for review. Once you have
|
|
committed changes locally, simply run:
|
|
|
|
```bash
|
|
git cl format
|
|
git cl upload
|
|
```
|
|
|
|
The first command will will auto-format the code changes. Then, the second
|
|
command runs the `PRESUBMIT.sh` script to check style and, if it passes, a
|
|
newcode review will be posted on `chromium-review.googlesource.com`.
|
|
|
|
If you make additional commits to your local branch, then running `git cl
|
|
upload` again in the same branch will merge those commits into the ongoing
|
|
review as a new patchset.
|
|
|
|
It's simplest to create a local git branch for each patch you want reviewed
|
|
separately. `git cl` keeps track of review status separately for each local
|
|
branch.
|
|
|
|
## Addressing merge conflicts
|
|
|
|
If conflicting commits have been landed in the repository for a patch in review,
|
|
Gerrit will flag the patch as having a merge conflict. In that case, use the
|
|
instructions above to rebase your commits on top-of-tree and upload a new
|
|
patchset with the merge conflicts resolved.
|
|
|
|
## Tryjobs
|
|
|
|
Clicking the `CQ DRY RUN` button (also, confusingly, labeled `COMMIT QUEUE +1`)
|
|
will run the current patchset through all LUCI builders and report the results.
|
|
It is always a good idea get a green tryjob on a patch before sending it for
|
|
review to avoid extra back-and-forth.
|
|
|
|
You can also run `git cl try` from the commandline to submit a tryjob.
|
|
|
|
## Code reviews
|
|
|
|
Send your patch to one or more committers in the
|
|
[COMMITTERS](https://chromium.googlesource.com/openscreen/+/refs/heads/master/COMMITTERS)
|
|
file for code review. All patches must receive at least one LGTM by a committer
|
|
before it can be submitted.
|
|
|
|
## Submission
|
|
|
|
After your patch has received one or more LGTM commit it by clicking the
|
|
`SUBMIT` button (or, confusingly, `COMMIT QUEUE +2`) in Gerrit. This will run
|
|
your patch through the builders again before committing to the main openscreen
|
|
repository.
|
|
|
|
<!-- TODO(mfoltz): split up README.md into more manageable files. -->
|
|
## Working with ARM/ARM64/the Raspberry PI
|
|
|
|
openscreen supports cross compilation for both arm32 and arm64 platforms, by
|
|
using the `gn args` parameter `target_cpu="arm"` or `target_cpu="arm64"`
|
|
respectively. Note that quotes are required around the target arch value.
|
|
|
|
Setting an arm(64) target_cpu causes GN to pull down a sysroot from openscreen's
|
|
public cloud storage bucket. Google employees may update the sysroots stored
|
|
by requesting access to the Open Screen pantheon project and uploading a new
|
|
tar.xz to the openscreen-sysroots bucket.
|
|
|
|
NOTE: The "arm" image is taken from Chromium's debian arm image, however it has
|
|
been manually patched to include support for libavcodec and libsdl2. To update
|
|
this image, the new image must be manually patched to include the necessary
|
|
header and library dependencies. Note that if the versions of libavcodec and
|
|
libsdl2 are too out of sync from the copies in the sysroot, compilation will
|
|
succeed, but you may experience issues decoding content.
|
|
|
|
To install the last known good version of the libavcodec and libsdl packages
|
|
on a Raspberry Pi, you can run the following command:
|
|
|
|
```bash
|
|
sudo ./cast/standalone_receiver/install_demo_deps_raspian.sh
|
|
```
|
|
|
|
NOTE: until [Issue 106](http://crbug.com/openscreen/106) is resolved, you may
|
|
experience issues streaming to a Raspberry Pi if multiple network interfaces
|
|
(e.g. WiFi + Ethernet) are enabled. The workaround is to disable either the WiFi
|
|
or ethernet connection.
|
|
|
|
## Code Coverage
|
|
|
|
Code coverage can be checked using clang's source-based coverage tools. You
|
|
must use the GN argument `use_coverage=true`. It's recommended to do this in a
|
|
separate output directory since the added instrumentation will affect
|
|
performance and generate an output file every time a binary is run. You can
|
|
read more about this in [clang's
|
|
documentation](http://clang.llvm.org/docs/SourceBasedCodeCoverage.html) but the
|
|
bare minimum steps are also outlined below. You will also need to download the
|
|
pre-built clang coverage tools, which are not downloaded by default. The
|
|
easiest way to do this is to set a custom variable in your `.gclient` file.
|
|
Under the "openscreen" solution, add:
|
|
```python
|
|
"custom_vars": {
|
|
"checkout_clang_coverage_tools": True,
|
|
},
|
|
```
|
|
then run `gclient runhooks`. You can also run the python command from the
|
|
`clang_coverage_tools` hook in `//DEPS` yourself or even download the tools
|
|
manually
|
|
([link](https://storage.googleapis.com/chromium-browser-clang-staging/)).
|
|
|
|
Once you have your GN directory (we'll call it `out/coverage`) and have
|
|
downloaded the tools, do the following to generate an HTML coverage report:
|
|
```bash
|
|
out/coverage/openscreen_unittests
|
|
third_party/llvm-build/Release+Asserts/bin/llvm-profdata merge -sparse default.profraw -o foo.profdata
|
|
third_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]
|
|
```
|
|
There are a few things to note here:
|
|
- `default.profraw` is generated by running the instrumented code, but
|
|
`foo.profdata` can be any path you want.
|
|
- `<out dir>` should be an empty directory for placing the generated HTML
|
|
files. You can view the report at `<out dir>/index.html`.
|
|
- `[filter paths]` is a list of paths to which you want to limit the coverage
|
|
report. For example, you may want to limit it to cast/ or even
|
|
cast/streaming/. If this list is empty, all data will be in the report.
|
|
|
|
The same process can be used to check the coverage of a fuzzer's corpus. Just
|
|
add `-runs=0` to the fuzzer arguments to make sure it only runs the existing
|
|
corpus then exits.
|