Starboard is Cobalt's porting layer and OS abstraction. It attempts to encompass all the platform-specific functionality that Cobalt actually uses, and nothing that it does not.
Cobalt and Starboard have been migrated from the GYP build system to the GN build system. This readme only contains instructions for GN, as GYP is no longer supported.
See starboard/doc
for more detailed documentation.
All source locations are specified relative to starboard/
(this directory).
.
- This is the root directory for the Starboard project, and contains all the public headers that Starboard defines.examples/
- Example code demonstrating various aspects of Starboard API usage.stub/
- The home of the Stub Starboard implementation. This contains aBUILD.gn
file that defines a library with all the source files needed to provide a complete linkable Starboard implementation.nplb/
- "No Platform Left Behind," Starboard's platform verification test suite.shared/
- The home of all code that can be shared between Starboard implementations. Subdirectories delimit code that can be shared between platforms that share some facet of their OS API.
Before starting a Cobalt/Starboard port, first you will need to define the canonical names for your set of platform configurations. These will be used when organizing the code for your platforms.
What determines what goes into one platform configuration versus another? A platform configuration has a one-to-one mapping to a production binary. So, if you will need to produce a new binary, you are going to need a new platform configuration for that.
The recommended naming convention for a <platform-configuration>
is:
<family-name>-<binary-variant>
Where <family-name>
is a name specific to the family of products you are
porting to Starboard and <binary-variant>
is one or more tokens that uniquely
describe the specifics of the binary you want that configuration to produce.
For example, let's say your company is named BobCo. BobCo employs multiple different device architectures so it will need to define multiple platform configurations.
All the BobCo devices are called BobBox, so it's a reasonable choice as a
product <family-name>
. But they have both big- and little-endian ARM
chips. So they might define two platform configurations:
bobbox-armeb
- For big-endian ARM devices.bobbox-armel
- For little-endian ARM devices.
To be perfectly compatible with the Cobalt source tree layout, any code that is
written by a party that isn't the Cobalt team should be in the
third_party/
directory. The choice is up to you, but we recommend that you
follow this practice, even if, as we expect to be common, you do not plan on
sharing your Starboard implementation with anyone.
Primarily, following this convention ensures that no future changes to Cobalt or Starboard will conflict with your source code additions. Starboard is intended to be a junction where new Cobalt versions or Starboard implementations can be replaced without significant (and hopefully, any) code changes.
We recommend that you place your code here in the source tree:
third_party/starboard/<family-name>/
With subdirectories:
shared/
- For code shared between architectures within a product family.<binary-variant>/
- For any code that is specific to a specific binary variant. Each one of these must at least haveBUILD.gn
,configuration_public.h
,platform_configuration/BUILD.gn
,platform_configuration/configuration.gni
, andtoolchain/BUILD.gn
files.
In the BobCo's BobBox example, we would see something like:
third_party/starboard/bobbox/
shared/
armeb/
platform_configuration/
BUILD.gn
configuration.gni
toolchain/
BUILD.gn
BUILD.gn
configuration_public.h
armel/
platform_configuration/
BUILD.gn
configuration.gni
toolchain/
BUILD.gn
BUILD.gn
configuration_public.h
And so on.
You can start off by copying files from a reference port to your port's location. Currently these reference ports include:
starboard/stub
starboard/linux
starboard/raspi
The platform's BUILD.gn
contains absolute paths, so the paths will still be
valid if you copy it to a new directory. You can then incrementally replace
files with new implementations as necessary.
The cleanest, simplest starting point is from the Stub reference
implementation. Nothing will work, but you should be able to compile and link it
with your toolchain. You can then replace stub implementations with
implementations from starboard/shared
or your own custom implementations
module-by-module, until you have gone through all modules.
You may also choose to copy either the Desktop Linux or Raspberry Pi ports and work backwards fixing things that don't compile or work on your platform.
For example, for bobbox-armel
, you might do:
mkdir -p third_party/starboard/bobbox
cp -R starboard/stub third_party/starboard/bobbox/armel
Modify the files in <binary-variant>/
as appropriate (you will probably be
coming back to these files a lot).
Update <binary-variant>/BUILD.gn
to point at all the source files that you
want to build as your new Starboard implementation. The //
expression in GN
refers to the top-level directory of your source tree. Otherwise, files are
assumed to be relative to the directory the BUILD.gn
or .gni
file is in.
The BUILD.gn
file contains absolute paths, so the paths will still be valid
if you copy it to a new directory. You can then incrementally replace files
with new implementations as necessary.
In order to use a new platform configuration in a build, you need to ensure that
you have a BUILD.gn
, toolchain/BUILD.gn
,
platform_configuration/configuration.gni
, and
platform_configuration/BUILD.gn
in their own directory for each binary
variant, plus the header files configuration_public.h
.
You must add your platform name to starboard/build/platforms.py
along with
the path to the port to be able to build it.
- Recursively copy
starboard/stub
tothird_party/starboard/<family-name>/<binary-variant>
. You may also consider copying from another reference platform, likeraspi-2
orlinux-x64x11
. - Add your platform and path to
starboard/build/platforms.py
. - In
platform_configuration/configuration.gni
- Delete variables in the file that are not needed for your platform.
- Set
gl_type
to the appropriate value if it is not the defaultsystem_gles2
. - Set
enable_in_app_dial
totrue
orfalse
. This enables or disables the DIAL server that runs inside Cobalt, only when Cobalt is running. You do not want in-app DIAL if you already have system-wide DIAL support.
- In
platform_configuration/BUILD.gn
- Update your toolchain command-line flags and libraries. Make sure you don't assume a particular workstation layout, as it is likely to be different for someone else.
- In
toolchain/BUILD.gn
- Either use the
clang_toolchain
template and pass the base path to your toolchain, or use thegcc_toolchain
and pass the full path to each tool you use. - Set
is_clang = true
intoolchain_args
ingcc_toolchain
if the toolchain uses clang.
- Either use the
- Go through
configuration_public.h
and adjust all the configuration values as appropriate for your platform. - Update
BUILD.gn
to point at all the source files you want to build as part of your new Starboard implementation (as mentioned above).
If you want to use cobalt/build/gn.py
, you'll also need a
third_party/starboard/<family-name>/<binary-variant>/args.gn
file. This
should contain the gn arguments necessary to build your platform. Pay
particular attention to target_platform
, target_os
, target_cpu
, and
is_clang
. The defaults for each can be found in
starboard/build/config/BUILDCONFIG.gn
. If you don't care about using gn.py
,
all of these arguments can be passed using gn args
or gn gen
with --args
.
For example, the first command below might instead look like
gn gen out/bobbox-armeb_debug --args='target_platform="bobbox-armeb" build_type="debug"'
.
You should now be able to run GN with your new port. From your the top level directory:
$ python cobalt/build/gn.py -c debug -p bobbox-armeb
$ ninja -C out/bobbox-armeb_debug nplb
This will attempt to build the "No Platform Left Behind" test suite with your new Starboard implementation, and you are ready to start porting!
When bringing up a new Starboard platform, it is suggested that you try to get the NPLB tests passing module-by-module. Because of dependencies between modules, you will find it easier to get some modules passing sooner than other modules.
Here's a recommended module implementation order in which to get things going (still significantly subject to change based on feedback):
- Configuration
- main(), Application, & Event Pump (i.e. the call into SbEventHandle)
- Memory
- Byte Swap
- Time
- String/Character/Double
- Log
- File
- Directory
- System
- Atomic
- Thread & Thread Types
- Mutex
- Condition Variable
- Once
- Socket
- SocketWaiter
- Window
- Input
- Blitter (if applicable)
- Audio Sink
- Media & Player
- DRM
- TimeZone
- User
- Storage