1#!/usr/bin/env python3 2# -*- coding: utf-8 -*- 3# Copyright 2019 The Chromium OS Authors. All rights reserved. 4# Use of this source code is governed by a BSD-style license that can be 5# found in the LICENSE file. 6 7"""Build script that builds a binary from a bundle.""" 8 9from __future__ import print_function 10 11import argparse 12import os.path 13import re 14import subprocess 15import sys 16 17 18def parse_args(): 19 parser = argparse.ArgumentParser() 20 parser.add_argument( 21 '--config', 22 required=True, 23 choices=['cros.hardened', 'cros.nonhardened', 'cros.host', 'android']) 24 parser.add_argument('--use_ccache', required=True, choices=['true', 'false']) 25 parser.add_argument( 26 '--use_llvm_next', required=True, choices=['true', 'false']) 27 parser.add_argument('--output_file', required=True, type=str) 28 parser.add_argument( 29 '--static', 30 choices=['true', 'false'], 31 help='If true, produce a static wrapper. Autodetects a good value if ' 32 'unspecified.') 33 args = parser.parse_args() 34 35 if args.static is None: 36 args.static = 'cros' not in args.config 37 else: 38 args.static = args.static == 'true' 39 40 return args 41 42 43def calc_go_args(args, version, build_dir): 44 ldFlags = [ 45 '-X', 46 'main.ConfigName=' + args.config, 47 '-X', 48 'main.UseCCache=' + args.use_ccache, 49 '-X', 50 'main.UseLlvmNext=' + args.use_llvm_next, 51 '-X', 52 'main.Version=' + version, 53 ] 54 55 # If the wrapper is intended for Chrome OS, we need to use libc's exec. 56 extra_args = [] 57 if not args.static: 58 extra_args += ['-tags', 'libc_exec'] 59 60 if args.config == 'android': 61 # If android_llvm_next_flags.go DNE, we'll get an obscure "no 62 # llvmNextFlags" build error; complaining here is clearer. 63 if not os.path.exists( 64 os.path.join(build_dir, 'android_llvm_next_flags.go')): 65 sys.exit('In order to build the Android wrapper, you must have a local ' 66 'android_llvm_next_flags.go file; please see ' 67 'cros_llvm_next_flags.go.') 68 extra_args += ['-tags', 'android_llvm_next_flags'] 69 70 return [ 71 'go', 'build', '-o', 72 os.path.abspath(args.output_file), '-ldflags', ' '.join(ldFlags) 73 ] + extra_args 74 75 76def read_version(build_dir): 77 version_path = os.path.join(build_dir, 'VERSION') 78 if os.path.exists(version_path): 79 with open(version_path, 'r') as r: 80 return r.read() 81 82 last_commit_msg = subprocess.check_output( 83 ['git', '-C', build_dir, 'log', '-1', '--pretty=%B'], encoding='utf-8') 84 # Use last found change id to support reverts as well. 85 change_ids = re.findall(r'Change-Id: (\w+)', last_commit_msg) 86 if not change_ids: 87 sys.exit("Couldn't find Change-Id in last commit message.") 88 return change_ids[-1] 89 90 91def main(): 92 args = parse_args() 93 build_dir = os.path.dirname(__file__) 94 version = read_version(build_dir) 95 # Note: Go does not support using absolute package names. 96 # So we run go inside the directory of the the build file. 97 sys.exit( 98 subprocess.call(calc_go_args(args, version, build_dir), cwd=build_dir)) 99 100 101if __name__ == '__main__': 102 main() 103