blob: e3af0671e18a189701577374d18421dddc1a4721 [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
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# 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
import os
from subprocess import call
import gyp_utils
import starboard.android.shared.sdk_utils as sdk_utils
from starboard.build.platform_configuration import PlatformConfiguration
from starboard.tools.testing import test_filter
from starboard.tools.toolchain import ar
from starboard.tools.toolchain import bash
from starboard.tools.toolchain import clang
from starboard.tools.toolchain import clangxx
from starboard.tools.toolchain import cp
from starboard.tools.toolchain import touch
_APK_DIR = os.path.join(os.path.dirname(__file__), os.path.pardir, 'apk')
_APK_BUILD_ID_FILE = os.path.join(_APK_DIR, 'build.id')
_COBALT_GRADLE = os.path.join(_APK_DIR, 'cobalt-gradle.sh')
# Maps the Android ABI to the name of the toolchain.
_ABI_TOOLCHAIN_NAME = {
'x86': 'i686-linux-android',
'armeabi': 'arm-linux-androideabi',
'armeabi-v7a': 'arm-linux-androideabi',
'arm64-v8a': 'aarch64-linux-android',
}
class AndroidConfiguration(PlatformConfiguration):
"""Starboard Android platform configuration."""
# TODO: make ASAN work with NDK tools and enable it by default
def __init__(self, platform, android_abi, asan_enabled_by_default=False):
super(AndroidConfiguration, self).__init__(platform,
asan_enabled_by_default)
self._target_toolchain = None
self._host_toolchain = None
self.AppendApplicationConfigurationPath(os.path.dirname(__file__))
self.android_abi = android_abi
self.host_compiler_environment = gyp_utils.GetHostCompilerEnvironment()
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)
variables.update({
'ANDROID_HOME':
self.android_home,
'NDK_HOME':
self.android_ndk_home,
'ANDROID_ABI':
self.android_abi,
'include_path_platform_deploy_gypi':
'starboard/android/shared/platform_deploy.gypi',
'javascript_engine':
'v8',
'cobalt_enable_jit':
1,
})
return variables
def GetGeneratorVariables(self, configuration):
_ = configuration
generator_variables = {
'qtcreator_session_name_prefix': 'cobalt',
}
return generator_variables
def GetEnvironmentVariables(self):
sdk_utils.InstallSdkIfNeeded(self.android_abi)
call([_COBALT_GRADLE, '--reset'])
with open(_APK_BUILD_ID_FILE, 'w') as build_id_file:
build_id_file.write('{}'.format(gyp_utils.GetBuildNumber()))
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):
if not self._target_toolchain:
tool_prefix = os.path.join(
sdk_utils.GetToolsPath(self.android_abi), 'bin',
_ABI_TOOLCHAIN_NAME[self.android_abi] + '-')
cc_path = tool_prefix + 'clang'
cxx_path = tool_prefix + 'clang++'
ar_path = tool_prefix + 'ar'
clang_flags = [
# We'll pretend not to be Linux, but Starboard instead.
'-U__linux__',
# libwebp uses the cpufeatures library to detect ARM NEON support
'-I{}/sources/android/cpufeatures'.format(self.android_ndk_home),
# Mimic build/cmake/android.toolchain.cmake in the Android NDK.
'-ffunction-sections',
'-funwind-tables',
'-fstack-protector-strong',
'-no-canonical-prefixes',
# Other flags
'-fsigned-char',
'-fno-limit-debug-info',
'-fno-exceptions',
'-fcolor-diagnostics',
'-fno-strict-aliasing', # See http://crbug.com/32204
# Default visibility is hidden to enable dead stripping.
'-fvisibility=hidden',
# Any warning will stop the build.
'-Werror',
# 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.
'-Wno-error=unused-command-line-argument',
# Don't warn about register variables (in base and net)
'-Wno-deprecated-register',
# Don't warn about deprecated ICU methods (in googleurl and net)
'-Wno-deprecated-declarations',
# Skia doesn't use overrides.
'-Wno-inconsistent-missing-override',
# shifting a negative signed value is undefined
'-Wno-shift-negative-value',
# Don't warn for implicit sign conversions. (in v8 and protobuf)
'-Wno-sign-conversion',
]
clang_defines = [
# Enable compile-time decisions based on the ABI
'ANDROID_ABI={}'.format(self.android_abi),
# -DANDROID is an argument to some ifdefs in the NDK's eglplatform.h
'ANDROID',
# Cobalt on Linux flag
'COBALT_LINUX',
# So that we get the PRI* macros from inttypes.h
'__STDC_FORMAT_MACROS',
# Enable GNU extensions to get prototypes like ffsl.
'_GNU_SOURCE=1',
# Undefining __linux__ causes the system headers to make wrong
# assumptions about which C-library is used on the platform.
'__BIONIC__',
# Undefining __linux__ leaves libc++ without a threads implementation.
# TODO: See if there's a way to make libcpp threading use Starboard.
'_LIBCPP_HAS_THREAD_API_PTHREAD',
]
linker_flags = [
# Use the static LLVM libc++.
'-static-libstdc++',
# Mimic build/cmake/android.toolchain.cmake in the Android NDK.
'-Wl,--build-id',
'-Wl,--warn-shared-textrel',
'-Wl,--fatal-warnings',
'-Wl,--gc-sections',
'-Wl,-z,nocopyreloc',
# Wrapper synchronizes punch-out video bounds with the UI frame.
'-Wl,--wrap=eglSwapBuffers',
]
self._target_toolchain = [
clang.CCompiler(
path=cc_path, defines=clang_defines, extra_flags=clang_flags),
clang.CxxCompiler(
path=cxx_path,
defines=clang_defines,
extra_flags=clang_flags + [
'-std=c++11',
]),
clang.AssemblerWithCPreprocessor(
path=cc_path, defines=clang_defines, extra_flags=clang_flags),
ar.StaticThinLinker(path=ar_path),
ar.StaticLinker(path=ar_path),
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):
if not self._host_toolchain:
cc_path = self.host_compiler_environment['CC_host'],
cxx_path = self.host_compiler_environment['CXX_host']
self._host_toolchain = [
clang.CCompiler(path=cc_path),
clang.CxxCompiler(path=cxx_path),
clang.AssemblerWithCPreprocessor(path=cc_path),
ar.StaticThinLinker(),
ar.StaticLinker(),
clangxx.ExecutableLinker(path=cxx_path),
clangxx.SharedLibraryLinker(path=cxx_path),
cp.Copy(),
touch.Stamp(),
bash.Shell(),
]
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.py'))
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 = {
'player_filter_tests': [
'AudioDecoderTests/AudioDecoderTest.EndOfStreamWithoutAnyInput/0',
'AudioDecoderTests/AudioDecoderTest.MultipleInputs/0',
'AudioDecoderTests/AudioDecoderTest.ResetBeforeInput/0',
'AudioDecoderTests/AudioDecoderTest.SingleInput/0',
'VideoDecoderTests/VideoDecoderTest.DecodeFullGOP/0',
'VideoDecoderTests/VideoDecoderTest.DecodeFullGOP/1',
'VideoDecoderTests/VideoDecoderTest.DecodeFullGOP/2',
'VideoDecoderTests/VideoDecoderTest.DecodeFullGOP/3',
'VideoDecoderTests/VideoDecoderTest.EndOfStreamWithoutAnyInput/0',
'VideoDecoderTests/VideoDecoderTest.EndOfStreamWithoutAnyInput/1',
'VideoDecoderTests/VideoDecoderTest.EndOfStreamWithoutAnyInput/2',
'VideoDecoderTests/VideoDecoderTest.EndOfStreamWithoutAnyInput/3',
'VideoDecoderTests/VideoDecoderTest'
'.GetCurrentDecodeTargetBeforeWriteInputBuffer/0',
'VideoDecoderTests/VideoDecoderTest'
'.GetCurrentDecodeTargetBeforeWriteInputBuffer/2',
'VideoDecoderTests/VideoDecoderTest.HoldFramesUntilFull/0',
'VideoDecoderTests/VideoDecoderTest.HoldFramesUntilFull/1',
'VideoDecoderTests/VideoDecoderTest.ResetBeforeInput/0',
'VideoDecoderTests/VideoDecoderTest.ResetBeforeInput/1',
'VideoDecoderTests/VideoDecoderTest.ResetBeforeInput/2',
'VideoDecoderTests/VideoDecoderTest.ResetBeforeInput/3',
'VideoDecoderTests/VideoDecoderTest.Preroll/0',
'VideoDecoderTests/VideoDecoderTest.Preroll/1',
'VideoDecoderTests/VideoDecoderTest.SingleInput/0',
'VideoDecoderTests/VideoDecoderTest.SingleInput/1',
'VideoDecoderTests/VideoDecoderTest.SingleInput/2',
'VideoDecoderTests/VideoDecoderTest.SingleInput/3',
# On some platforms, and for some decoders (such as AVC), Android
# returns MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER for the test's
# invalid input frame instead of signaling an error, which the test is
# looking for.
'VideoDecoderTests/VideoDecoderTest.SingleInvalidInput/0',
'VideoDecoderTests/VideoDecoderTest.SingleInvalidInput/1',
# Android currently does not support multi-video playback, which
# the following tests depend upon.
'VideoDecoderTests/VideoDecoderTest.ThreeMoreDecoders/0',
'VideoDecoderTests/VideoDecoderTest.ThreeMoreDecoders/1',
'VideoDecoderTests/VideoDecoderTest.ThreeMoreDecoders/2',
'VideoDecoderTests/VideoDecoderTest.ThreeMoreDecoders/3',
],
}