1# Copyright 2018 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 5DOCKER_IMAGE = 'gcr.io/skia-public/canvaskit-emsdk:3.1.3_v1' 6INNER_BUILD_SCRIPT = '/SRC/skia/infra/canvaskit/build_canvaskit.sh' 7 8 9def compile_fn(api, checkout_root, _ignore): 10 skia_dir = checkout_root.join('skia') 11 out_dir = api.vars.cache_dir.join('docker', 'canvaskit') 12 configuration = api.vars.builder_cfg.get('configuration', '') 13 extra = api.vars.builder_cfg.get('extra_config', '') 14 15 # We want to make sure the directories exist and were created by chrome-bot, 16 # because if that isn't the case, docker will make them and they will be 17 # owned by root, which causes mysterious failures. To mitigate this risk 18 # further, we don't use the same out_dir as everyone else (thus the _ignore) 19 # param. Instead, we use a "canvaskit" subdirectory in the "docker" named_cache. 20 api.file.ensure_directory('mkdirs out_dir', out_dir, mode=0o777) 21 22 # Download the emsdk binaries (we won't actually use the ones on the Docker 23 # image anymore, now that we have proper GN support) 24 with api.context(cwd=skia_dir): 25 api.run(api.python, 'activate-emsdk', 26 script=skia_dir.join('bin', 'activate-emsdk'), 27 infra_step=True) 28 29 # This uses the emscripten sdk docker image and says "run the 30 # build_canvaskit.sh helper script in there". Additionally, it binds two 31 # folders: the Skia checkout to /SRC and the output directory to /OUT 32 # The called helper script will make the compile happen and put the 33 # output in the right spot. The neat thing is that since the Skia checkout 34 # (and, by extension, the build script) is not a part of the image, but 35 # bound in at runtime, we don't have to re-build the image, except when the 36 # toolchain changes. 37 # Of note, the wasm build doesn't re-use any intermediate steps from the 38 # previous builds, so it's essentially a build from scratch every time. 39 cmd = ['docker', 'run', '--rm', '--volume', '%s:/SRC' % checkout_root, 40 '--volume', '%s:/OUT' % out_dir, 41 DOCKER_IMAGE, INNER_BUILD_SCRIPT] 42 if 'CPU' in extra: 43 cmd.append('cpu') # It defaults to gpu 44 45 if configuration == 'Debug': 46 cmd.append('debug') # It defaults to Release 47 # Override DOCKER_CONFIG set by Kitchen. 48 env = {'DOCKER_CONFIG': '/home/chrome-bot/.docker'} 49 with api.env(env): 50 api.run( 51 api.step, 52 'Build CanvasKit with Docker', 53 cmd=cmd) 54 55 56CANVASKIT_BUILD_PRODUCTS = [ 57 'canvaskit.*' 58] 59 60 61def copy_build_products(api, _ignore, dst): 62 out_dir = api.vars.cache_dir.join('docker', 'canvaskit') 63 # We don't use the normal copy_listed_files because it uses 64 # shutil.move, which attempts to delete the previous file, which 65 # doesn't work because the docker created outputs are read-only and 66 # owned by root (aka only docker images). It's likely safe to change 67 # the shutil.move in the original script to a non-deleting thing 68 # (like copy or copyfile), but there's some subtle behavior differences 69 # especially with directories, that kjlubick felt it best not to risk it. 70 api.python.inline( 71 name='copy wasm output', 72 program='''import errno 73import glob 74import os 75import shutil 76import sys 77 78src = sys.argv[1] 79dst = sys.argv[2] 80build_products = %s 81 82try: 83 os.makedirs(dst) 84except OSError as e: 85 if e.errno != errno.EEXIST: 86 raise 87 88for pattern in build_products: 89 path = os.path.join(src, pattern) 90 for f in glob.glob(path): 91 dst_path = os.path.join(dst, os.path.relpath(f, src)) 92 if not os.path.isdir(os.path.dirname(dst_path)): 93 os.makedirs(os.path.dirname(dst_path)) 94 print('Copying build product %%s to %%s' %% (f, dst_path)) 95 # Because Docker usually has some strange permissions (like root 96 # ownership), we'd rather not keep those around. copyfile doesn't 97 # keep the metadata around, so that helps us. 98 shutil.copyfile(f, dst_path) 99''' % str(CANVASKIT_BUILD_PRODUCTS), 100 args=[out_dir, dst], 101 infra_step=True) 102