• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2016 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import default_flavor
6
7"""GN flavor utils, used for building Skia with GN."""
8class GNFlavorUtils(default_flavor.DefaultFlavorUtils):
9  def _run(self, title, cmd, infra_step=False, **kwargs):
10    return self.m.run(self.m.step, title, cmd=cmd,
11               infra_step=infra_step, **kwargs)
12
13  def _py(self, title, script, infra_step=True, args=()):
14    return self.m.run(self.m.python, title, script=script, args=args,
15               infra_step=infra_step)
16
17  def build_command_buffer(self):
18    self.m.run(self.m.python, 'build command_buffer',
19        script=self.m.vars.skia_dir.join('tools', 'build_command_buffer.py'),
20        args=[
21          '--chrome-dir', self.m.vars.checkout_root,
22          '--output-dir', self.m.vars.skia_out.join(self.m.vars.configuration),
23          '--no-sync', '--make-output-dir'])
24
25  def compile(self, unused_target):
26    """Build Skia with GN."""
27    compiler      = self.m.vars.builder_cfg.get('compiler',      '')
28    configuration = self.m.vars.builder_cfg.get('configuration', '')
29    extra_config  = self.m.vars.builder_cfg.get('extra_config',  '')
30    os            = self.m.vars.builder_cfg.get('os',            '')
31    target_arch   = self.m.vars.builder_cfg.get('target_arch',   '')
32
33    clang_linux   = str(self.m.vars.slave_dir.join('clang_linux'))
34    linux_vulkan_sdk   = str(self.m.vars.slave_dir.join('linux_vulkan_sdk'))
35    win_toolchain = str(self.m.vars.slave_dir.join(
36      't', 'depot_tools', 'win_toolchain', 'vs_files',
37      'd3cb0e37bdd120ad0ac4650b674b09e81be45616'))
38    win_vulkan_sdk = str(self.m.vars.slave_dir.join('win_vulkan_sdk'))
39
40    cc, cxx = None, None
41    extra_cflags = []
42    extra_ldflags = []
43
44    if compiler == 'Clang' and self.m.vars.is_linux:
45      cc  = clang_linux + '/bin/clang'
46      cxx = clang_linux + '/bin/clang++'
47      extra_cflags .append('-B%s/bin' % clang_linux)
48      extra_ldflags.append('-B%s/bin' % clang_linux)
49      extra_ldflags.append('-fuse-ld=lld')
50    elif compiler == 'Clang':
51      cc, cxx = 'clang', 'clang++'
52    elif compiler == 'GCC':
53      cc, cxx = 'gcc', 'g++'
54
55    if compiler != 'MSVC' and configuration == 'Debug':
56      extra_cflags.append('-O1')
57
58    if extra_config == 'Exceptions':
59      extra_cflags.append('/EHsc')
60    if extra_config == 'Fast':
61      extra_cflags.extend(['-march=native', '-fomit-frame-pointer', '-O3',
62                           '-ffp-contract=off'])
63    if extra_config.startswith('SK'):
64      extra_cflags.append('-D' + extra_config)
65    if extra_config == 'MSAN':
66      extra_ldflags.append('-L' + clang_linux + '/msan')
67
68    args = {}
69
70    if configuration != 'Debug':
71      args['is_debug'] = 'false'
72    if extra_config == 'ANGLE':
73      args['skia_use_angle'] = 'true'
74    if extra_config == 'CommandBuffer':
75      self.m.run.run_once(self.build_command_buffer)
76    if extra_config == 'GDI':
77      args['skia_use_gdi'] = 'true'
78    if extra_config == 'MSAN':
79      args['skia_enable_gpu']     = 'false'
80      args['skia_use_fontconfig'] = 'false'
81    if extra_config == 'ASAN':
82      args['skia_enable_spirv_validation'] = 'false'
83    if extra_config == 'Mesa':
84      args['skia_use_mesa'] = 'true'
85    if extra_config == 'Mini':
86      args.update({
87        'is_component_build':     'true',   # Proves we can link a coherent .so.
88        'is_official_build':      'true',   # No debug symbols, no tools.
89        'skia_enable_effects':    'false',
90        'skia_enable_gpu':        'true',
91        'skia_enable_pdf':        'false',
92        'skia_use_expat':         'false',
93        'skia_use_libjpeg_turbo': 'false',
94        'skia_use_libpng':        'false',
95        'skia_use_libwebp':       'false',
96        'skia_use_zlib':          'false',
97      })
98    if extra_config == 'NoGPU':
99      args['skia_enable_gpu'] = 'false'
100    if extra_config == 'Shared':
101      args['is_component_build'] = 'true'
102    if extra_config == 'Vulkan':
103      args['skia_enable_vulkan_debug_layers'] = 'false'
104      if self.m.vars.is_linux:
105        args['skia_vulkan_sdk'] = '"%s"' % linux_vulkan_sdk
106      if 'Win' in os:
107        args['skia_vulkan_sdk'] = '"%s"' % win_vulkan_sdk
108
109    for (k,v) in {
110      'cc':  cc,
111      'cxx': cxx,
112      'sanitize': extra_config if 'SAN' in extra_config else '',
113      'target_cpu': target_arch,
114      'target_os': 'ios' if 'iOS' in extra_config else '',
115      'windk': win_toolchain if 'Win' in os else '',
116    }.iteritems():
117      if v:
118        args[k] = '"%s"' % v
119    if extra_cflags:
120      args['extra_cflags'] = repr(extra_cflags).replace("'", '"')
121    if extra_ldflags:
122      args['extra_ldflags'] = repr(extra_ldflags).replace("'", '"')
123
124    gn_args = ' '.join('%s=%s' % (k,v) for (k,v) in sorted(args.iteritems()))
125
126    gn    = 'gn.exe'    if 'Win' in os else 'gn'
127    ninja = 'ninja.exe' if 'Win' in os else 'ninja'
128    gn = self.m.vars.skia_dir.join('bin', gn)
129
130    with self.m.context(cwd=self.m.vars.skia_dir):
131      self._py('fetch-gn', self.m.vars.skia_dir.join('bin', 'fetch-gn'))
132      self._run('gn gen', [gn, 'gen', self.out_dir, '--args=' + gn_args])
133      self._run('ninja', [ninja, '-C', self.out_dir])
134
135  def copy_extra_build_products(self, swarming_out_dir):
136    configuration = self.m.vars.builder_cfg.get('configuration', '')
137    extra_config  = self.m.vars.builder_cfg.get('extra_config',  '')
138    os            = self.m.vars.builder_cfg.get('os',            '')
139
140    win_vulkan_sdk = str(self.m.vars.slave_dir.join('win_vulkan_sdk'))
141    if 'Win' in os and extra_config == 'Vulkan':
142      self.m.run.copy_build_products(
143          win_vulkan_sdk,
144          swarming_out_dir.join('out', configuration + '_x64'))
145
146  def step(self, name, cmd):
147    app = self.m.vars.skia_out.join(self.m.vars.configuration, cmd[0])
148    cmd = [app] + cmd[1:]
149    env = self.m.context.env
150
151    clang_linux = str(self.m.vars.slave_dir.join('clang_linux'))
152    extra_config = self.m.vars.builder_cfg.get('extra_config', '')
153
154    if 'SAN' in extra_config:
155      # Sanitized binaries may want to run clang_linux/bin/llvm-symbolizer.
156      env['PATH'] = '%%(PATH)s:%s' % clang_linux + '/bin'
157    elif self.m.vars.is_linux:
158      cmd = ['catchsegv'] + cmd
159
160    if 'ASAN' == extra_config:
161      env[ 'ASAN_OPTIONS'] = 'symbolize=1 detect_leaks=1'
162      env[ 'LSAN_OPTIONS'] = 'symbolize=1 print_suppressions=1'
163      env['UBSAN_OPTIONS'] = 'symbolize=1 print_stacktrace=1'
164
165    if 'MSAN' == extra_config:
166      # Find the MSAN-built libc++.
167      env['LD_LIBRARY_PATH'] = clang_linux + '/msan'
168
169    to_symbolize = ['dm', 'nanobench']
170    if name in to_symbolize and self.m.vars.is_linux:
171      # Convert path objects or placeholders into strings such that they can
172      # be passed to symbolize_stack_trace.py
173      args = [self.m.vars.slave_dir] + [str(x) for x in cmd]
174      with self.m.context(cwd=self.m.vars.skia_dir, env=env):
175        self._py('symbolized %s' % name,
176                 self.module.resource('symbolize_stack_trace.py'),
177                 args=args,
178                 infra_step=False)
179
180    else:
181      with self.m.context(env=env):
182        self._run(name, cmd)
183