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