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): 10 self.m.run(self.m.step, title, cmd=cmd, 11 infra_step=infra_step) 12 13 def _py(self, title, script, infra_step=True, args=()): 14 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 os == 'Ubuntu': 45 cc = clang_linux + '/bin/clang' 46 cxx = clang_linux + '/bin/clang++' 47 extra_ldflags.append('-fuse-ld=lld') 48 elif compiler == 'Clang': 49 cc, cxx = 'clang', 'clang++' 50 elif compiler == 'GCC': 51 cc, cxx = 'gcc', 'g++' 52 53 if compiler != 'MSVC' and configuration == 'Debug': 54 extra_cflags.append('-O1') 55 56 if extra_config == 'Exceptions': 57 extra_cflags.append('/EHsc') 58 if extra_config == 'Fast': 59 extra_cflags.extend(['-march=native', '-fomit-frame-pointer', '-O3', 60 '-ffp-contract=off']) 61 if extra_config.startswith('SK'): 62 extra_cflags.append('-D' + extra_config) 63 if extra_config == 'MSAN': 64 extra_ldflags.append('-L' + clang_linux + '/msan') 65 66 args = {} 67 68 if configuration != 'Debug': 69 args['is_debug'] = 'false' 70 if extra_config == 'ANGLE': 71 args['skia_use_angle'] = 'true' 72 if extra_config == 'CommandBuffer': 73 self.m.run.run_once(self.build_command_buffer) 74 if extra_config == 'GDI': 75 args['skia_use_gdi'] = 'true' 76 if extra_config == 'MSAN': 77 args['skia_use_fontconfig'] = 'false' 78 if extra_config == 'ASAN': 79 args['skia_enable_spirv_validation'] = 'false' 80 if extra_config == 'Mesa': 81 args['skia_use_mesa'] = 'true' 82 if extra_config == 'Mini': 83 args.update({ 84 'is_component_build': 'true', # Proves we can link a coherent .so. 85 'is_official_build': 'true', # No debug symbols, no tools. 86 'skia_enable_effects': 'false', 87 'skia_enable_gpu': 'false', 88 'skia_enable_pdf': 'false', 89 'skia_use_expat': 'false', 90 'skia_use_libjpeg_turbo': 'false', 91 'skia_use_libpng': 'false', 92 'skia_use_libwebp': 'false', 93 'skia_use_zlib': 'false', 94 }) 95 if extra_config == 'NoGPU': 96 args['skia_enable_gpu'] = 'false' 97 if extra_config == 'Shared': 98 args['is_component_build'] = 'true' 99 if extra_config == 'Vulkan': 100 args['skia_enable_vulkan_debug_layers'] = 'false' 101 if os == 'Ubuntu': 102 args['skia_vulkan_sdk'] = '"%s"' % linux_vulkan_sdk 103 if 'Win' in os: 104 args['skia_vulkan_sdk'] = '"%s"' % win_vulkan_sdk 105 106 for (k,v) in { 107 'cc': cc, 108 'cxx': cxx, 109 'sanitize': extra_config if 'SAN' in extra_config else '', 110 'target_cpu': target_arch, 111 'target_os': 'ios' if 'iOS' in extra_config else '', 112 'windk': win_toolchain if 'Win' in os else '', 113 }.iteritems(): 114 if v: 115 args[k] = '"%s"' % v 116 if extra_cflags: 117 args['extra_cflags'] = repr(extra_cflags).replace("'", '"') 118 if extra_ldflags: 119 args['extra_ldflags'] = repr(extra_ldflags).replace("'", '"') 120 121 gn_args = ' '.join('%s=%s' % (k,v) for (k,v) in sorted(args.iteritems())) 122 123 gn = 'gn.exe' if 'Win' in os else 'gn' 124 ninja = 'ninja.exe' if 'Win' in os else 'ninja' 125 gn = self.m.vars.skia_dir.join('bin', gn) 126 127 with self.m.step.context({'cwd': self.m.vars.skia_dir}): 128 self._py('fetch-gn', self.m.vars.skia_dir.join('bin', 'fetch-gn')) 129 self._run('gn gen', [gn, 'gen', self.out_dir, '--args=' + gn_args]) 130 self._run('ninja', [ninja, '-C', self.out_dir]) 131 132 def copy_extra_build_products(self, swarming_out_dir): 133 configuration = self.m.vars.builder_cfg.get('configuration', '') 134 extra_config = self.m.vars.builder_cfg.get('extra_config', '') 135 os = self.m.vars.builder_cfg.get('os', '') 136 137 win_vulkan_sdk = str(self.m.vars.slave_dir.join('win_vulkan_sdk')) 138 if 'Win' in os and extra_config == 'Vulkan': 139 self.m.run.copy_build_products( 140 win_vulkan_sdk, 141 swarming_out_dir.join('out', configuration + '_x64')) 142 143 def step(self, name, cmd): 144 app = self.m.vars.skia_out.join(self.m.vars.configuration, cmd[0]) 145 cmd = [app] + cmd[1:] 146 env = self.m.step.get_from_context('env', {}) 147 148 clang_linux = str(self.m.vars.slave_dir.join('clang_linux')) 149 extra_config = self.m.vars.builder_cfg.get('extra_config', '') 150 151 if 'SAN' in extra_config: 152 # Sanitized binaries may want to run clang_linux/bin/llvm-symbolizer. 153 env['PATH'] = '%%(PATH)s:%s' % clang_linux + '/bin' 154 elif 'Ubuntu' == self.m.vars.builder_cfg.get('os', ''): 155 cmd = ['catchsegv'] + cmd 156 157 if 'ASAN' == extra_config: 158 env[ 'ASAN_OPTIONS'] = 'symbolize=1 detect_leaks=1' 159 env[ 'LSAN_OPTIONS'] = 'symbolize=1 print_suppressions=1' 160 env['UBSAN_OPTIONS'] = 'symbolize=1 print_stacktrace=1' 161 162 if 'MSAN' == extra_config: 163 # Find the MSAN-built libc++. 164 env['LD_LIBRARY_PATH'] = clang_linux + '/msan' 165 166 to_symbolize = ['dm', 'nanobench'] 167 if name in to_symbolize and 'Ubuntu' in self.m.vars.builder_cfg['os']: 168 # Convert path objects or placeholders into strings such that they can 169 # be passed to symbolize_stack_trace.py 170 args = [self.m.vars.slave_dir] + [str(x) for x in cmd] 171 with self.m.step.context({'cwd': self.m.vars.skia_dir, 'env': env}): 172 self._py('symbolized %s' % name, 173 self.m.vars.infrabots_dir.join('recipe_modules', 'core', 174 'resources', 'symbolize_stack_trace.py'), 175 args=args, 176 infra_step=False) 177 178 else: 179 with self.m.step.context({'env': env}): 180 self._run(name, cmd) 181