1#!/usr/bin/env python3 2# Copyright (C) 2017 The Android Open Source Project 3# 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15 16from __future__ import absolute_import 17from __future__ import division 18from __future__ import print_function 19 20import argparse 21import os 22import platform 23import subprocess 24import sys 25 26from compat import iteritems, quote 27 28MAC_BUILD_CONFIGS = { 29 'mac_debug': ('is_clang=true', 'is_debug=true'), 30 'mac_release': ('is_clang=true', 'is_debug=false'), 31 'mac_asan': ('is_clang=true', 'is_debug=false', 'is_asan=true'), 32 'mac_tsan': ('is_clang=true', 'is_debug=false', 'is_tsan=true'), 33 'mac_ubsan': ('is_clang=true', 'is_debug=false', 'is_ubsan=true'), 34} 35 36ANDROID_BUILD_CONFIGS = { 37 'android_debug': ('target_os="android"', 'is_clang=true', 'is_debug=true'), 38 'android_release': 39 ('target_os="android"', 'is_clang=true', 'is_debug=false'), 40 'android_release_incl_heapprofd': 41 ('target_os="android"', 'is_clang=true', 'is_debug=false', 42 'extra_cflags="-funwind-tables"', 'android_api_level=29'), 43 'android_asan': ('target_os="android"', 'is_clang=true', 'is_debug=false', 44 'is_asan=true'), 45 'android_lsan': ('target_os="android"', 'is_clang=true', 'is_debug=false', 46 'is_lsan=true'), 47} 48 49ANDROID_ARCHS = ('arm', 'arm64') 50 51LINUX_BUILD_CONFIGS = { 52 'linux_gcc_debug': ('is_clang=false', 'is_debug=true'), 53 'linux_gcc_release': ('is_clang=false', 'is_debug=false'), 54 'linux_clang_debug': ('is_clang=true', 'is_debug=true'), 55 'linux_clang_release': ('is_clang=true', 'is_debug=false'), 56 'linux_asan': ('is_clang=true', 'is_debug=false', 'is_asan=true'), 57 'linux_lsan': ('is_clang=true', 'is_debug=false', 'is_lsan=true'), 58 'linux_msan': ('is_clang=true', 'is_debug=false', 'is_msan=true'), 59 'linux_tsan': ('is_clang=true', 'is_debug=false', 'is_tsan=true'), 60 'linux_ubsan': ('is_clang=true', 'is_debug=false', 'is_ubsan=true'), 61 'linux_fuzzer': ('is_clang=true', 'is_debug=false', 'is_fuzzer=true', 62 'is_asan=true'), 63} 64 65LINUX_ARCHS = ('arm64',) 66 67ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 68 69 70def main(): 71 parser = argparse.ArgumentParser() 72 parser.add_argument('--ccache', action='store_true', default=False) 73 parser.add_argument('--host-only', action='store_true', default=False) 74 parser.add_argument('--android', action='store_true', default=False) 75 parser.add_argument( 76 '--export-compile-commands', action="store_true", default=False) 77 parser.add_argument('--build', metavar='TARGET') 78 args = parser.parse_args() 79 80 configs = {} 81 if not args.host_only: 82 if args.android: 83 for config_name, gn_args in iteritems(ANDROID_BUILD_CONFIGS): 84 for arch in ANDROID_ARCHS: 85 full_config_name = '%s_%s' % (config_name, arch) 86 configs[full_config_name] = gn_args + ('target_cpu="%s"' % arch,) 87 for config_name, gn_args in iteritems(LINUX_BUILD_CONFIGS): 88 if dict(a.split('=') for a in gn_args).get('is_clang', None) == 'true': 89 continue 90 for arch in LINUX_ARCHS: 91 full_config_name = '%s_%s' % (config_name, arch) 92 configs[full_config_name] = gn_args + ('target_cpu="%s"' % arch, 93 'target_os="linux"') 94 95 system = platform.system().lower() 96 if system == 'linux': 97 configs.update(LINUX_BUILD_CONFIGS) 98 elif system == 'darwin': 99 configs.update(MAC_BUILD_CONFIGS) 100 else: 101 assert False, 'Unsupported system %r' % system 102 103 if args.ccache: 104 for config_name, gn_args in iteritems(configs): 105 configs[config_name] = gn_args + ('cc_wrapper="ccache"',) 106 107 out_base_dir = os.path.join(ROOT_DIR, 'out') 108 if not os.path.isdir(out_base_dir): 109 os.mkdir(out_base_dir) 110 111 gn = os.path.join(ROOT_DIR, 'tools', 'gn') 112 113 for config_name, gn_args in iteritems(configs): 114 print('\n\033[32mBuilding %-20s[%s]\033[0m' % (config_name, 115 ','.join(gn_args))) 116 out_dir = os.path.join(ROOT_DIR, 'out', config_name) 117 if not os.path.isdir(out_dir): 118 os.mkdir(out_dir) 119 gn_cmd = (gn, 'gen', out_dir, '--args=%s' % (' '.join(gn_args)), '--check') 120 if args.export_compile_commands: 121 gn_cmd += ('--export-compile-commands',) 122 print(' '.join(quote(c) for c in gn_cmd)) 123 subprocess.check_call(gn_cmd, cwd=ROOT_DIR) 124 if args.build: 125 ninja = os.path.join(ROOT_DIR, 'tools', 'ninja') 126 ninja_cmd = (ninja, '-C', '.', args.build) 127 subprocess.check_call(ninja_cmd, cwd=out_dir) 128 129 130if __name__ == '__main__': 131 sys.exit(main()) 132