David Ghandehari | 9e5b587 | 2016-07-28 09:50:04 -0700 | [diff] [blame] | 1 | # Starboard |
| 2 | |
| 3 | Starboard is Cobalt's porting layer and OS abstraction. It attempts to encompass |
| 4 | all the platform-specific functionality that Cobalt actually uses, and nothing |
| 5 | that it does not. |
| 6 | |
| 7 | |
| 8 | ## Current State |
| 9 | |
David Ghandehari | 8c5039b | 2016-08-17 19:39:30 -0700 | [diff] [blame] | 10 | Desktop Linux Cobalt is fully implemented on top of Starboard, and version 1 of |
| 11 | the Starboard API is mostly locked down. |
David Ghandehari | 9e5b587 | 2016-07-28 09:50:04 -0700 | [diff] [blame] | 12 | |
| 13 | |
| 14 | ## Interesting Source Locations |
| 15 | |
| 16 | All source locations are specified relative to `src/starboard/` (this directory). |
| 17 | |
| 18 | * `.` - This is the root directory for the Starboard project, and contains all |
| 19 | the public headers that Starboard defines. |
| 20 | * `examples/` - Example code demonstrating various aspects of Starboard API |
| 21 | usage. |
| 22 | * `linux/` - The home of the Linux Starboard implementation. This contains a |
| 23 | `starboard_platform.gyp` file that defines a library with all the source |
| 24 | files needed to provide a complete Starboard Linux implementation. Source |
| 25 | files that are specific to Linux are in this directory, whereas shared |
| 26 | implementations are pulled from the shared directory. |
| 27 | * `nplb/` - "No Platform Left Behind," Starboard's platform verification test |
| 28 | suite. |
| 29 | * `shared/` - The home of all code that can be shared between Starboard |
| 30 | implementations. Subdirectories delimit code that can be shared between |
| 31 | platforms that share some facet of their OS API. |
| 32 | |
| 33 | |
| 34 | ## Building with Starboard |
| 35 | |
| 36 | Follow the Cobalt instructions, except when invoking gyp: |
| 37 | |
| 38 | $ cobalt/build/gyp_cobalt -C debug linux-x64x11 |
| 39 | |
| 40 | and when invoking ninja: |
| 41 | |
| 42 | $ ninja -C out/linux-x64x11_debug cobalt |
| 43 | |
| 44 | |
| 45 | ## Quick Guide to Starting a Port |
| 46 | |
| 47 | ### I. Enumerate and Name Your Platform Configurations |
| 48 | |
| 49 | Before starting a Cobalt/Starboard port, first you will need to define the |
| 50 | canonical names for your set of platform configurations. These will be used when |
| 51 | organizing the code for your platforms. |
| 52 | |
| 53 | What determines what goes into one platform configuration versus another? A |
| 54 | platform configuration has a one-to-one mapping to a production binary. So, if |
| 55 | you will need to produce a new binary, you are going to need a new platform |
| 56 | configuration for that. |
| 57 | |
| 58 | The recommended naming convention for a `<platform-configuration>` is: |
| 59 | |
| 60 | <family-name>-<binary-variant> |
| 61 | |
| 62 | Where `<family-name>` is a name specific to the family of products you are |
| 63 | porting to Starboard and `<binary-variant>` is one or more tokens that uniquely |
| 64 | describe the specifics of the binary you want that configuration to produce. |
| 65 | |
| 66 | For example, let's say your company is named BobCo. BobCo employs multiple |
| 67 | different device architectures so it will need to define multiple platform |
| 68 | configurations. |
| 69 | |
| 70 | All the BobCo devices are called BobBox, so it's a reasonable choice as a |
| 71 | product `<family-name>`. But they have both big- and little-endian MIPS |
| 72 | chips. So they might define two platform configurations: |
| 73 | |
| 74 | 1. `bobbox-mipseb` - For big-endian MIPS devices. |
| 75 | 1. `bobbox-mipsel` - For little-endian MIPS devices. |
| 76 | |
| 77 | |
| 78 | ### II. Choose a Location in the Source Tree for Your Starboard Port |
| 79 | |
| 80 | To be perfectly compatible with the Cobalt source tree layout, any code that is |
| 81 | written by a party that isn't the Cobalt team should be in the |
| 82 | `src/third_party/` directory. The choice is up to you, but we recommend that you |
| 83 | follow this practice, even if, as we expect to be common, you do not plan on |
| 84 | sharing your Starboard implementation with anyone. |
| 85 | |
| 86 | Primarily, following this convention ensures that no future changes to Cobalt or |
| 87 | Starboard will conflict with your source code additions. Starboard is intended |
| 88 | to be a junction where new Cobalt versions or Starboard implementations can be |
| 89 | replaced without significant (and hopefully, any) code changes. |
| 90 | |
| 91 | We recommend that you place your code here in the source tree: |
| 92 | |
| 93 | src/third_party/starboard/<family-name>/ |
| 94 | |
| 95 | With subdirectories: |
| 96 | |
| 97 | * `shared/` - For code shared between architectures within a product family. |
| 98 | * `<binary-variant>/` - For any code that is specific to a specific binary |
| 99 | variant. Each one of these must at least have `configuration_public.h`, |
| 100 | `atomic_public.h`, `thread_types_public.h`, `gyp_configuration.py`, |
| 101 | `gyp_configuration.gypi`, and `starboard_platform.gyp` files. |
| 102 | |
| 103 | In the BobCo's BobBox example, we would see something like: |
| 104 | |
| 105 | * `src/third_party/starboard/bobbox/` |
| 106 | * `shared/` |
| 107 | * `mipseb/` |
| 108 | * `atomic_public.h` |
| 109 | * `configuration_public.h` |
| 110 | * `gyp_configuration.gypi` |
| 111 | * `gyp_configuration.py` |
| 112 | * `starboard_platform.gyp` |
| 113 | * `thread_types_public.h` |
| 114 | * `mipsel/` |
| 115 | * `atomic_public.h` |
| 116 | * `configuration_public.h` |
| 117 | * `gyp_configuration.gypi` |
| 118 | * `gyp_configuration.py` |
| 119 | * `starboard_platform.gyp` |
| 120 | * `thread_types_public.h` |
| 121 | |
| 122 | And so on. |
| 123 | |
| 124 | |
| 125 | ### III. Base Your Port on a Reference Port |
| 126 | |
| 127 | You can start off by copying files from a reference port to your port's |
| 128 | location. Currently these reference ports include: |
| 129 | |
| 130 | * `src/starboard/stub` |
| 131 | * `src/starboard/linux` |
| 132 | * `src/starboard/raspi` |
| 133 | |
| 134 | The `starboard_platform.gyp` contains absolute paths, so the paths will still be |
| 135 | valid if you copy it to a new directory. You can then incrementally replace |
| 136 | files with new implementations as necessary. |
| 137 | |
David Ghandehari | 8c5039b | 2016-08-17 19:39:30 -0700 | [diff] [blame] | 138 | The cleanest, simplest starting point is from the Stub reference |
| 139 | implementation. Nothing will work, but you should be able to compile and link it |
| 140 | with your toolchain. You can then replace stub implementations with |
| 141 | implementations from `src/starboard/shared` or your own custom implementations |
| 142 | module-by-module, until you have gone through all modules. |
David Ghandehari | 9e5b587 | 2016-07-28 09:50:04 -0700 | [diff] [blame] | 143 | |
David Ghandehari | 8c5039b | 2016-08-17 19:39:30 -0700 | [diff] [blame] | 144 | You may also choose to copy either the Desktop Linux or Raspberry Pi ports and |
| 145 | work backwards fixing things that don't compile or work on your platform. |
| 146 | |
| 147 | For example, for `bobbox-mipsel`, you might do: |
| 148 | |
| 149 | mkdir -p src/third_party/starboard/bobbox |
| 150 | cp -R src/starboard/stub src/third_party/starboard/bobbox/mipsel |
David Ghandehari | 9e5b587 | 2016-07-28 09:50:04 -0700 | [diff] [blame] | 151 | |
| 152 | Modify the files in `<binary-variant>/` as appropriate (you will probably be |
| 153 | coming back to these files a lot). |
| 154 | |
| 155 | Update `<binary-variant>/starboard_platform.gyp` to point at all the source |
| 156 | files that you want to build as your new Starboard implementation. The |
| 157 | `'<(DEPTH)'` expression in GYP expands to enough `../`s to take you to the |
| 158 | `src/` directory of your source tree. Otherwise, files are assumed to be |
| 159 | relative to the directory the `.gyp` or `.gypi` file is in. |
| 160 | |
David Ghandehari | 9e5b587 | 2016-07-28 09:50:04 -0700 | [diff] [blame] | 161 | In order to use a new platform configuration in a build, you need to ensure that |
| 162 | you have a `gyp_configuration.py`, `gyp_configuration.gypi`, and |
Andrew Top | a953d4e | 2016-11-22 22:38:45 -0800 | [diff] [blame] | 163 | `starboard_platform.gyp` in their own directory for each binary variant, plus |
David Ghandehari | 9e5b587 | 2016-07-28 09:50:04 -0700 | [diff] [blame] | 164 | the header files `configuration_public.h`, `atomic_public.h`, and |
| 165 | `thread_types_public.h`. `gyp_cobalt` will scan your directories for these |
| 166 | files, and then calculate a port name based on the directories between |
| 167 | `src/third_party/starboard` and your `gyp_configuration.*` files. (e.g. for |
| 168 | `src/third_party/starboard/bobbox/mipseb/gyp_configuration.py`, it would choose |
David Ghandehari | 8c5039b | 2016-08-17 19:39:30 -0700 | [diff] [blame] | 169 | the platform configuration name `bobbox-mipseb`.) |
David Ghandehari | 9e5b587 | 2016-07-28 09:50:04 -0700 | [diff] [blame] | 170 | |
David Ghandehari | 8c5039b | 2016-08-17 19:39:30 -0700 | [diff] [blame] | 171 | |
| 172 | ### IV. A New Port, Step-by-Step |
| 173 | |
| 174 | 1. Recursively copy `src/starboard/stub` to |
| 175 | `src/third_party/starboard/<family-name>/<binary-variant>`. You may also |
| 176 | consider copying from another reference platform, like `raspi-1` or |
| 177 | `linux-x64x11`. |
| 178 | 1. In `gyp_configuration.py` |
| 179 | 1. In the `CreatePlatformConfig()` function, pass your |
| 180 | `<platform-configuration>` as the parameter to the PlatformConfig |
| 181 | constructor, like `return PlatformConfig('bobbox-mipseb')`. |
| 182 | 1. In `GetVariables` |
| 183 | 1. Set `'clang': 1` if your toolchain is clang. |
| 184 | 1. Delete other variables in that function that are not needed for |
| 185 | your platform. |
| 186 | 1. In `GetEnvironmentVariables`, set the dictionary values to point to the |
| 187 | toolchain analogs for the toolchain for your platform. |
| 188 | 1. In `gyp_configuration.gypi` |
| 189 | 1. Update the names of the configurations and the default_configuration to |
| 190 | be `<platform-configuation>_<build-type>` for your platform |
| 191 | configuration name, where `<build-type>` is one of `debug`, `devel`, |
| 192 | `qa`, `gold`. |
David Ghandehari | 9e5b587 | 2016-07-28 09:50:04 -0700 | [diff] [blame] | 193 | 1. Update your platform variables. |
| 194 | 1. Set `'target_arch'` to your architecture: `'arm'`, `'ppc'`, |
| 195 | `'x64'`, `'x86'`, `'mips'` |
| 196 | 1. Set `'target_os': 'linux'` if your platform is Linux-based. |
| 197 | 1. Set `'gl_type': 'system_gles2'` if you are using the system EGL + |
| 198 | GLES2 implementation. |
| 199 | 1. Set `'in_app_dial'` to `1` or `0`. This enables or disables the |
| 200 | DIAL server that runs inside Cobalt, only when Coblat is |
| 201 | running. You do not want in-app DIAL if you already have |
| 202 | system-wide DIAL support. |
| 203 | 1. Update your toolchain command-line flags and libraries. Make sure you |
| 204 | don't assume a particular workstation layout, as it is likely to be |
| 205 | different for someone else. |
| 206 | 1. Update the global defines in `'target_defaults'.'defines'`, if |
| 207 | necessary. |
David Ghandehari | 8c5039b | 2016-08-17 19:39:30 -0700 | [diff] [blame] | 208 | 1. Go through `configuration_public.h` and adjust all the configuration values |
| 209 | as appropriate for your platform. |
| 210 | 1. Update `starboard_platform.gyp` to point at all the source files you want |
| 211 | to build as part of your new Starboard implementation (as mentioned above). |
| 212 | 1. Update `atomic_public.h` and `thread_types_public.h` as necessary to point |
| 213 | at the appropriate shared or custom implementations. |
David Ghandehari | 9e5b587 | 2016-07-28 09:50:04 -0700 | [diff] [blame] | 214 | |
| 215 | |
| 216 | You should now be able to run gyp with your new port. From your `src/` directory: |
| 217 | |
| 218 | $ cobalt/build/gyp_cobalt -C debug bobbox-mipseb |
| 219 | $ ninja -C out/bobbox-mipseb_debug nplb |
| 220 | |
| 221 | This will attempt to build the "No Platform Left Behind" test suite with your |
| 222 | new Starboard implementation, and you are ready to start porting! |
| 223 | |
| 224 | |
| 225 | ## Suggested Implementation Order |
| 226 | |
| 227 | When bringing up a new Starboard platform, it is suggested that you try to get |
| 228 | the NPLB tests passing module-by-module. Because of dependencies between |
| 229 | modules, you will find it easier to get some modules passing sooner than other |
| 230 | modules. |
| 231 | |
| 232 | Here's a recommended module implementation order in which to get things going |
| 233 | (still significantly subject to change based on feedback): |
| 234 | |
| 235 | 1. Configuration |
| 236 | 1. main(), Application, & Event Pump (i.e. the call into SbEventHandle) |
| 237 | 1. Memory |
| 238 | 1. Byte Swap |
| 239 | 1. Time |
| 240 | 1. String/Character/Double |
| 241 | 1. Log |
| 242 | 1. File |
| 243 | 1. Directory |
| 244 | 1. System |
| 245 | 1. Atomic |
| 246 | 1. Thread & Thread Types |
| 247 | 1. Mutex |
| 248 | 1. Condition Variable |
| 249 | 1. Once |
| 250 | 1. Socket |
| 251 | 1. SocketWaiter |
| 252 | 1. Window |
| 253 | 1. Input |
| 254 | 1. Blitter (if applicable) |
| 255 | 1. Audio Sink |
| 256 | 1. Media & Player |
| 257 | 1. DRM |
| 258 | 1. TimeZone |
| 259 | 1. User |
| 260 | 1. Storage |