Home | History | Annotate | Download | only in flavor
      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 
      5 import default_flavor
      6 
      7 """GN flavor utils, used for building Skia with GN."""
      8 class 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