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