blob: 83e55d2f909676d2814b12c10032d1d625186cb3 [file] [log] [blame]
# Copyright 2016 The Cobalt Authors. All Rights Reserved.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# See the License for the specific language governing permissions and
# limitations under the License.
"""Starboard Android shared platform configuration for gyp_cobalt."""
from __future__ import print_function
import imp # pylint: disable=deprecated-module
import os
import subprocess
from import sdk_utils
from import clang as clang_build
from import PlatformConfiguration
from import build
from import test_filter
from import ar
from import bash
from import clang
from import clangxx
from import cp
from import touch
_APK_DIR = os.path.join(os.path.dirname(__file__), os.path.pardir, 'apk')
_APK_BUILD_ID_FILE = os.path.join(_APK_DIR, '')
_COBALT_GRADLE = os.path.join(_APK_DIR, '')
# The API level of NDK tools to use. This should be the minimum API level on
# which the app is expected to run. If some feature from a newer NDK level is
# needed, this may be increased with caution.
# Using 24 will lead to missing symbols on API 23 devices.
# Maps the Android ABI to the clang & ar executable names.
'x86': ('i686-linux-android{}-clang'.format(_ANDROID_NDK_API_LEVEL),
'x86_64': ('x86_64-linux-android{}-clang'.format(_ANDROID_NDK_API_LEVEL),
class AndroidConfiguration(PlatformConfiguration):
"""Starboard Android platform configuration."""
# TODO: make ASAN work with NDK tools and enable it by default
def __init__(self,
super(AndroidConfiguration, self).__init__(platform,
self._target_toolchain = None
self._host_toolchain = None
self.android_abi = android_abi
self.sabi_json_path = sabi_json_path
self.android_home = sdk_utils.GetSdkPath()
self.android_ndk_home = sdk_utils.GetNdkPath()
print('Using Android SDK at {}'.format(self.android_home))
print('Using Android NDK at {}'.format(self.android_ndk_home))
def GetBuildFormat(self):
"""Returns the desired build format."""
# The comma means that ninja and qtcreator_ninja will be chained and use the
# same input information so that .gyp files will only have to be parsed
# once.
return 'ninja,qtcreator_ninja'
def GetVariables(self, configuration):
variables = super(AndroidConfiguration, self).GetVariables(
configuration, use_clang=1)
return variables
def GetDeployPathPatterns(self):
# example src/out/android-arm64/devel/cobalt.apk
return ['*.apk']
def GetGeneratorVariables(self, config_name):
_ = config_name
generator_variables = {
'qtcreator_session_name_prefix': 'cobalt',
return generator_variables
def SetupPlatformTools(self, build_number):
sdk_utils.InstallSdkIfNeeded()[_COBALT_GRADLE, '--reset'])
with open(_APK_BUILD_ID_FILE, 'w') as build_id_file:
def GetEnvironmentVariables(self):
env_variables = {}
# Android builds tend to consume significantly more memory than the
# default settings permit, so cap this at 1 in order to avoid build
# issues. Without this, 32GB machines end up getting automatically
# configured to run 5 at a time, which can be too much for at least
# android-arm64_debug.
# TODO: Eventually replace this with something more robust, like an
# implementation of the abstract toolchain for Android.
env_variables.update({'GYP_LINK_CONCURRENCY': '1'})
return env_variables
def GetTargetToolchain(self, **kwargs):
if not self._target_toolchain:
tool_prefix = os.path.join(sdk_utils.GetNdkPath(), 'toolchains', 'llvm',
'prebuilt', 'linux-x86_64', 'bin', '')
cc_path = self.build_accelerator + ' ' + tool_prefix + _ABI_TOOL_NAMES[
cxx_path = cc_path + '++'
ar_path = tool_prefix + _ABI_TOOL_NAMES[self.android_abi][1]
clang_flags = [
# libwebp uses the cpufeatures library to detect ARM NEON support
# Mimic build/cmake/android.toolchain.cmake in the Android NDK.
# Other flags
'-fno-strict-aliasing', # See
# Default visibility is hidden to enable dead stripping.
# Any warning will stop the build.
# Disable errors for the warning till the Android NDK r19 is fixed.
# The warning is trigger when compiling .c files and complains for
# '-stdlib=libc++' which is added by the NDK.
# Don't warn about register variables (in base and net)
# Don't warn about deprecated ICU methods (in googleurl and net)
# Skia doesn't use overrides.
# shifting a negative signed value is undefined
# Don't warn for implicit sign conversions. (in v8 and protobuf)
clang_defines = [
# Enable compile-time decisions based on the ABI
# -DANDROID is an argument to some ifdefs in the NDK's eglplatform.h
# Cobalt on Linux flag
# So that we get the PRI* macros from inttypes.h
# Enable GNU extensions to get prototypes like ffsl.
# Undefining __linux__ causes the system headers to make wrong
# assumptions about which C-library is used on the platform.
# Undefining __linux__ leaves libc++ without a threads implementation.
# TODO: See if there's a way to make libcpp threading use Starboard.
linker_flags = [
# Use the static LLVM libc++.
# Mimic build/cmake/android.toolchain.cmake in the Android NDK, but
# force build-id to sha1, so that older lldb versions can still find
# debugsymbols, see
# Wrapper synchronizes punch-out video bounds with the UI frame.
self._target_toolchain = [
path=cc_path, defines=clang_defines, extra_flags=clang_flags),
extra_flags=clang_flags + [
path=cc_path, defines=clang_defines, extra_flags=clang_flags),
clangxx.SharedLibraryLinker(path=cxx_path, extra_flags=linker_flags),
clangxx.ExecutableLinker(path=cxx_path, extra_flags=linker_flags),
return self._target_toolchain
def GetHostToolchain(self, **kwargs):
if not self._host_toolchain:
if not hasattr(self, 'host_compiler_environment'):
self.host_compiler_environment = build.GetHostCompilerEnvironment(
clang_build.GetClangSpecification(), self.build_accelerator)
cc_path = self.host_compiler_environment['CC_host']
cxx_path = self.host_compiler_environment['CXX_host']
self._host_toolchain = [
return self._host_toolchain
def GetLauncher(self):
"""Gets the module used to launch applications on this platform."""
module_path = os.path.abspath(
os.path.join(os.path.dirname(__file__), ''))
launcher_module = imp.load_source('launcher', module_path)
return launcher_module
def GetTestFilters(self):
filters = super(AndroidConfiguration, self).GetTestFilters()
for target, tests in self.__FILTERED_TESTS.iteritems():
filters.extend(test_filter.TestFilter(target, test) for test in tests)
return filters
# A map of failing or crashing tests per target.
__FILTERED_TESTS = { # pylint: disable=invalid-name
'player_filter_tests': [
# GetMaxNumberOfCachedFrames() on Android is device dependent,
# and Android doesn't provide an API to get it. So, this function
# doesn't make sense on Android. But HoldFramesUntilFull tests depend
# on this number strictly.
# Currently, invalid input tests are not supported.
# Android currently does not support multi-video playback, which
# the following tests depend upon.
# The video pipeline will hang if it doesn't receive any input.
# The e/eac3 audio time reporting during pause will be revisitied.
'nplb': [
# This test is failing because localhost is not defined for IPv6 in
# /etc/hosts.
# These tests are taking longer due to interop on android. Work is
# underway to investigate whether this is acceptable.
# SbDirectory has problems with empty Asset dirs.
# These tests are disabled due to not receiving the kEndOfStream
# player state update within the specified timeout.
# Android does not use SbDrmSessionClosedFunc, which these tests
# depend on.
# This test is failing because Android calls the
# SbDrmSessionUpdateRequestFunc with SbDrmStatus::kSbDrmStatusSuccess
# when invalid initialization data is passed to
# SbDrmGenerateSessionUpdateRequest().
def GetPathToSabiJsonFile(self):
return self.sabi_json_path