skia2/infra/bots/recipe_modules/build/default.py
Ben Wagner 998066127e Update XCode
Chromium now requires the 10.15 SDK
(https://bugs.chromium.org/p/chromium/issues/detail?id=1023913), which
breaks the CommandBuffer bot because it's trying to compile with XCode
10.3, which provides the 10.14 SDK.

What's worse, due to reasons I don't fully understand, after failing to
compile CommandBuffer due to the dependence on the 10.15 SDK, the ninja
out dir is poisoned for future compiles that don't depend on the 10.15
SDK.

Also includes a code snippet from
https://skia-review.googlesource.com/c/skia/+/264429 to find the xSAN
dylibs.

Change-Id: I3cd7661a5ea984ea6899e7a5e8cf878581538d9e
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/272736
Reviewed-by: Ben Wagner aka dogben <benjaminwagner@google.com>
2020-02-23 23:15:26 +00:00

381 lines
14 KiB
Python

# Copyright 2018 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
from . import util
def build_command_buffer(api, chrome_dir, skia_dir, out):
api.run(api.python, 'build command_buffer',
script=skia_dir.join('tools', 'build_command_buffer.py'),
args=[
'--chrome-dir', chrome_dir,
'--output-dir', out,
'--extra-gn-args', 'mac_sdk_min="10.13"',
'--no-sync', '--no-hooks', '--make-output-dir'])
def compile_swiftshader(api, extra_tokens, swiftshader_root, cc, cxx, out):
"""Build SwiftShader with CMake.
Building SwiftShader works differently from any other Skia third_party lib.
See discussion in skia:7671 for more detail.
Args:
swiftshader_root: root of the SwiftShader checkout.
cc, cxx: compiler binaries to use
out: target directory for libEGL.so and libGLESv2.so
"""
swiftshader_opts = [
'-DSWIFTSHADER_BUILD_TESTS=OFF',
'-DSWIFTSHADER_WARNINGS_AS_ERRORS=0',
]
cmake_bin = str(api.vars.slave_dir.join('cmake_linux', 'bin'))
env = {
'CC': cc,
'CXX': cxx,
'PATH': '%%(PATH)s:%s' % cmake_bin
}
# Extra flags for MSAN/TSAN, if necessary.
san = None
if 'MSAN' in extra_tokens:
san = ('msan','memory')
elif 'TSAN' in extra_tokens:
san = ('tsan','thread')
if san:
short,full = san
clang_linux = str(api.vars.slave_dir.join('clang_linux'))
libcxx = clang_linux + '/' + short
cflags = ' '.join([
'-fsanitize=' + full,
'-stdlib=libc++',
'-L%s/lib' % libcxx,
'-lc++abi',
'-I%s/include' % libcxx,
'-I%s/include/c++/v1' % libcxx,
])
swiftshader_opts.extend([
'-DSWIFTSHADER_{}=ON'.format(short.upper()),
'-DCMAKE_C_FLAGS=%s' % cflags,
'-DCMAKE_CXX_FLAGS=%s' % cflags,
])
# Build SwiftShader.
api.file.ensure_directory('makedirs swiftshader_out', out)
with api.context(cwd=out, env=env):
api.run(api.step, 'swiftshader cmake',
cmd=['cmake'] + swiftshader_opts + [swiftshader_root, '-GNinja'])
api.run(api.step, 'swiftshader ninja',
cmd=['ninja', '-C', out, 'libEGL.so', 'libGLESv2.so'])
def compile_fn(api, checkout_root, out_dir):
skia_dir = checkout_root.join('skia')
compiler = api.vars.builder_cfg.get('compiler', '')
configuration = api.vars.builder_cfg.get('configuration', '')
extra_tokens = api.vars.extra_tokens
os = api.vars.builder_cfg.get('os', '')
target_arch = api.vars.builder_cfg.get('target_arch', '')
clang_linux = str(api.vars.slave_dir.join('clang_linux'))
win_toolchain = str(api.vars.slave_dir.join('win_toolchain'))
moltenvk = str(api.vars.slave_dir.join('moltenvk'))
cc, cxx, ccache = None, None, None
extra_cflags = []
extra_ldflags = []
args = {'werror': 'true'}
env = {}
if os == 'Mac':
# XCode build is listed in parentheses after the version at
# https://developer.apple.com/news/releases/, or on Wikipedia here:
# https://en.wikipedia.org/wiki/Xcode#Version_comparison_table
# Use lowercase letters.
XCODE_BUILD_VERSION = '11c29'
extra_cflags.append(
'-DDUMMY_xcode_build_version=%s' % XCODE_BUILD_VERSION)
mac_toolchain_cmd = api.vars.slave_dir.join(
'mac_toolchain', 'mac_toolchain')
xcode_app_path = api.vars.cache_dir.join('Xcode.app')
# Copied from
# https://chromium.googlesource.com/chromium/tools/build/+/e19b7d9390e2bb438b566515b141ed2b9ed2c7c2/scripts/slave/recipe_modules/ios/api.py#322
with api.step.nest('ensure xcode') as step_result:
step_result.presentation.step_text = (
'Ensuring Xcode version %s in %s' % (
XCODE_BUILD_VERSION, xcode_app_path))
install_xcode_cmd = [
mac_toolchain_cmd, 'install',
# "ios" is needed for simulator builds
# (Build-Mac-Clang-x64-Release-iOS).
'-kind', 'ios',
'-xcode-version', XCODE_BUILD_VERSION,
'-output-dir', xcode_app_path,
]
api.step('install xcode', install_xcode_cmd)
api.step('select xcode', [
'sudo', 'xcode-select', '-switch', xcode_app_path])
if 'iOS' in extra_tokens:
if target_arch == 'arm':
# Can only compile for 32-bit up to iOS 10.
env['IPHONEOS_DEPLOYMENT_TARGET'] = '10.0'
else:
# Our iOS devices are on an older version.
# Can't compile for Metal before 11.0.
env['IPHONEOS_DEPLOYMENT_TARGET'] = '11.0'
else:
# We have some bots on 10.13.
env['MACOSX_DEPLOYMENT_TARGET'] = '10.13'
if 'CheckGeneratedFiles' in extra_tokens:
compiler = 'Clang'
args['skia_compile_processors'] = 'true'
args['skia_generate_workarounds'] = 'true'
# ccache + clang-tidy.sh chokes on the argument list.
if (api.vars.is_linux or os == 'Mac') and 'Tidy' not in extra_tokens:
if api.vars.is_linux:
ccache = api.vars.slave_dir.join('ccache_linux', 'bin', 'ccache')
# As of 2020-02-07, the sum of each Debian9-Clang-x86
# non-flutter/android/chromebook build takes less than 75G cache space.
env['CCACHE_MAXSIZE'] = '75G'
else:
ccache = api.vars.slave_dir.join('ccache_mac', 'bin', 'ccache')
# As of 2020-02-10, the sum of each Build-Mac-Clang- non-android build
# takes ~30G cache space.
env['CCACHE_MAXSIZE'] = '50G'
args['cc_wrapper'] = '"%s"' % ccache
env['CCACHE_DIR'] = api.vars.cache_dir.join('ccache')
env['CCACHE_MAXFILES'] = '0'
# Compilers are unpacked from cipd with bogus timestamps, only contribute
# compiler content to hashes. If Ninja ever uses absolute paths to changing
# directories we'll also need to set a CCACHE_BASEDIR.
env['CCACHE_COMPILERCHECK'] = 'content'
if compiler == 'Clang' and api.vars.is_linux:
cc = clang_linux + '/bin/clang'
cxx = clang_linux + '/bin/clang++'
extra_cflags .append('-B%s/bin' % clang_linux)
extra_ldflags.append('-B%s/bin' % clang_linux)
extra_ldflags.append('-fuse-ld=lld')
extra_cflags.append('-DDUMMY_clang_linux_version=%s' %
api.run.asset_version('clang_linux', skia_dir))
if 'Static' in extra_tokens:
extra_ldflags.extend(['-static-libstdc++', '-static-libgcc'])
elif compiler == 'Clang':
cc, cxx = 'clang', 'clang++'
if 'Tidy' in extra_tokens:
# Swap in clang-tidy.sh for clang++, but update PATH so it can find clang++.
cxx = skia_dir.join("tools/clang-tidy.sh")
env['PATH'] = '%s:%%(PATH)s' % (clang_linux + '/bin')
if 'Coverage' in extra_tokens:
# See https://clang.llvm.org/docs/SourceBasedCodeCoverage.html for
# more info on using llvm to gather coverage information.
extra_cflags.append('-fprofile-instr-generate')
extra_cflags.append('-fcoverage-mapping')
extra_ldflags.append('-fprofile-instr-generate')
extra_ldflags.append('-fcoverage-mapping')
if compiler != 'MSVC' and configuration == 'Debug':
extra_cflags.append('-O1')
if 'Exceptions' in extra_tokens:
extra_cflags.append('/EHsc')
if 'Fast' in extra_tokens:
extra_cflags.extend(['-march=native', '-fomit-frame-pointer', '-O3',
'-ffp-contract=off'])
if len(extra_tokens) == 1 and extra_tokens[0].startswith('SK'):
extra_cflags.append('-D' + extra_tokens[0])
# If we're limiting Skia at all, drop skcms to portable code.
if 'SK_CPU_LIMIT' in extra_tokens[0]:
extra_cflags.append('-DSKCMS_PORTABLE')
if 'SkVM' in extra_tokens:
extra_cflags.append('-DSK_USE_SKVM_BLITTER')
if 'MSAN' in extra_tokens:
extra_ldflags.append('-L' + clang_linux + '/msan')
elif 'TSAN' in extra_tokens:
extra_ldflags.append('-L' + clang_linux + '/tsan')
elif api.vars.is_linux:
extra_ldflags.append('-L' + clang_linux + '/lib')
if configuration != 'Debug':
args['is_debug'] = 'false'
if 'ANGLE' in extra_tokens:
args['skia_use_angle'] = 'true'
if 'SwiftShader' in extra_tokens:
swiftshader_root = skia_dir.join('third_party', 'externals', 'swiftshader')
swiftshader_out = out_dir.join('swiftshader_out')
compile_swiftshader(api, extra_tokens, swiftshader_root, cc, cxx, swiftshader_out)
args['skia_use_egl'] = 'true'
extra_cflags.extend([
'-DGR_EGL_TRY_GLES3_THEN_GLES2',
'-I%s' % skia_dir.join(
'third_party', 'externals', 'egl-registry', 'api'),
'-I%s' % skia_dir.join(
'third_party', 'externals', 'opengl-registry', 'api'),
])
extra_ldflags.extend([
'-L%s' % swiftshader_out,
])
if 'CommandBuffer' in extra_tokens:
# CommandBuffer runs against GLES version of CommandBuffer also, so
# include both.
args.update({
'skia_gl_standard': '""',
})
chrome_dir = checkout_root
api.run.run_once(build_command_buffer, api, chrome_dir, skia_dir, out_dir)
if 'MSAN' in extra_tokens:
args['skia_use_fontconfig'] = 'false'
if 'ASAN' in extra_tokens:
args['skia_enable_spirv_validation'] = 'false'
if 'NoDEPS' in extra_tokens:
args.update({
'is_official_build': 'true',
'skia_enable_fontmgr_empty': 'true',
'skia_enable_gpu': 'true',
'skia_enable_pdf': 'false',
'skia_use_expat': 'false',
'skia_use_freetype': 'false',
'skia_use_harfbuzz': 'false',
'skia_use_libjpeg_turbo': 'false',
'skia_use_libpng': 'false',
'skia_use_libwebp': 'false',
'skia_use_vulkan': 'false',
'skia_use_zlib': 'false',
})
if 'Shared' in extra_tokens:
args['is_component_build'] = 'true'
if 'Vulkan' in extra_tokens and not 'Android' in extra_tokens:
args['skia_use_vulkan'] = 'true'
args['skia_enable_vulkan_debug_layers'] = 'true'
if 'MoltenVK' in extra_tokens:
args['skia_moltenvk_path'] = '"%s"' % moltenvk
if 'Metal' in extra_tokens:
args['skia_use_metal'] = 'true'
if 'OpenCL' in extra_tokens:
args['skia_use_opencl'] = 'true'
if api.vars.is_linux:
extra_cflags.append(
'-isystem%s' % api.vars.slave_dir.join('opencl_headers'))
extra_ldflags.append(
'-L%s' % api.vars.slave_dir.join('opencl_ocl_icd_linux'))
elif 'Win' in os:
extra_cflags.append(
'-imsvc%s' % api.vars.slave_dir.join('opencl_headers'))
extra_ldflags.append(
'/LIBPATH:%s' %
skia_dir.join('third_party', 'externals', 'opencl-lib', '3-0', 'lib',
'x86_64'))
if 'iOS' in extra_tokens:
# Bots use Chromium signing cert.
args['skia_ios_identity'] = '".*GS9WA.*"'
# Get mobileprovision via the CIPD package.
args['skia_ios_profile'] = '"%s"' % api.vars.slave_dir.join(
'provisioning_profile_ios',
'Upstream_Testing_Provisioning_Profile.mobileprovision')
if compiler == 'Clang' and 'Win' in os:
args['clang_win'] = '"%s"' % api.vars.slave_dir.join('clang_win')
extra_cflags.append('-DDUMMY_clang_win_version=%s' %
api.run.asset_version('clang_win', skia_dir))
sanitize = ''
for t in extra_tokens:
if t.endswith('SAN'):
sanitize = t
if api.vars.is_linux and t == 'ASAN':
# skia:8712 and skia:8713
extra_cflags.append('-DSK_ENABLE_SCOPED_LSAN_SUPPRESSIONS')
if 'SafeStack' in extra_tokens:
assert sanitize == ''
sanitize = 'safe-stack'
if 'Wuffs' in extra_tokens:
args['skia_use_wuffs'] = 'true'
for (k,v) in {
'cc': cc,
'cxx': cxx,
'sanitize': sanitize,
'target_cpu': target_arch,
'target_os': 'ios' if 'iOS' in extra_tokens else '',
'win_sdk': win_toolchain + '/win_sdk' if 'Win' in os else '',
'win_vc': win_toolchain + '/VC' if 'Win' in os else '',
}.iteritems():
if v:
args[k] = '"%s"' % v
if extra_cflags:
args['extra_cflags'] = repr(extra_cflags).replace("'", '"')
if extra_ldflags:
args['extra_ldflags'] = repr(extra_ldflags).replace("'", '"')
gn_args = ' '.join('%s=%s' % (k,v) for (k,v) in sorted(args.iteritems()))
gn = skia_dir.join('bin', 'gn')
with api.context(cwd=skia_dir):
api.run(api.python,
'fetch-gn',
script=skia_dir.join('bin', 'fetch-gn'),
infra_step=True)
if 'CheckGeneratedFiles' in extra_tokens:
env['PATH'] = '%s:%%(PATH)s' % skia_dir.join('bin')
api.run(api.python,
'fetch-clang-format',
script=skia_dir.join('bin', 'fetch-clang-format'),
infra_step=True)
with api.env(env):
if ccache:
api.run(api.step, 'ccache stats-start', cmd=[ccache, '-s'])
api.run(api.step, 'gn gen',
cmd=[gn, 'gen', out_dir, '--args=' + gn_args])
api.run(api.step, 'ninja', cmd=['ninja', '-C', out_dir])
if ccache:
api.run(api.step, 'ccache stats-end', cmd=[ccache, '-s'])
def copy_build_products(api, src, dst):
util.copy_listed_files(api, src, dst, util.DEFAULT_BUILD_PRODUCTS)
extra_tokens = api.vars.extra_tokens
os = api.vars.builder_cfg.get('os', '')
if 'SwiftShader' in extra_tokens:
util.copy_listed_files(api,
src.join('swiftshader_out'),
api.vars.swarming_out_dir.join('swiftshader_out'),
util.DEFAULT_BUILD_PRODUCTS)
if os == 'Mac' and any('SAN' in t for t in extra_tokens):
# The XSAN dylibs are in
# Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib
# /clang/11.0.0/lib/darwin, where 11.0.0 could change in future versions.
xcode_clang_ver_dirs = api.file.listdir(
'find XCode Clang version',
api.vars.cache_dir.join(
'Xcode.app', 'Contents', 'Developer', 'Toolchains',
'XcodeDefault.xctoolchain', 'usr', 'lib', 'clang'),
test_data=['11.0.0'])
assert len(xcode_clang_ver_dirs) == 1
dylib_dir = xcode_clang_ver_dirs[0].join('lib', 'darwin')
dylibs = api.file.glob_paths('find xSAN dylibs', dylib_dir,
'libclang_rt.*san_osx_dynamic.dylib',
test_data=[
'libclang_rt.asan_osx_dynamic.dylib',
'libclang_rt.tsan_osx_dynamic.dylib',
'libclang_rt.ubsan_osx_dynamic.dylib',
])
for f in dylibs:
api.file.copy('copy %s' % api.path.basename(f), f, dst)