1#!/usr/bin/env python3 2# -*- coding: utf-8 -*- 3# 4# Copyright 2020 The Chromium OS Authors. All rights reserved. 5# Use of this source code is governed by a BSD-style license that can be 6# found in the LICENSE file. 7 8"""Script to checkout the ChromeOS source. 9 10This script sets up the ChromeOS source in the given directory, matching a 11particular release of ChromeOS. 12""" 13 14from __future__ import print_function 15 16__author__ = ('asharif@google.com (Ahmad Sharif) ' 17 'llozano@google.com (Luis Lozano) ' 18 'raymes@google.com (Raymes Khoury) ' 19 'shenhan@google.com (Han Shen)') 20 21import argparse 22import os 23import sys 24 25from cros_utils import command_executer 26from cros_utils import logger 27from cros_utils import misc 28 29 30def Usage(parser, message): 31 print('ERROR: %s' % message) 32 parser.print_help() 33 sys.exit(0) 34 35 36def Main(argv): 37 """Build ChromeOS.""" 38 # Common initializations 39 cmd_executer = command_executer.GetCommandExecuter() 40 41 parser = argparse.ArgumentParser() 42 parser.add_argument( 43 '--chromeos_root', 44 dest='chromeos_root', 45 help='Target directory for ChromeOS installation.') 46 parser.add_argument( 47 '--clobber_chroot', 48 dest='clobber_chroot', 49 action='store_true', 50 help='Delete the chroot and start fresh', 51 default=False) 52 parser.add_argument( 53 '--clobber_board', 54 dest='clobber_board', 55 action='store_true', 56 help='Delete the board and start fresh', 57 default=False) 58 parser.add_argument( 59 '--rebuild', 60 dest='rebuild', 61 action='store_true', 62 help='Rebuild all board packages except the toolchain.', 63 default=False) 64 parser.add_argument( 65 '--cflags', 66 dest='cflags', 67 default='', 68 help='CFLAGS for the ChromeOS packages') 69 parser.add_argument( 70 '--cxxflags', 71 dest='cxxflags', 72 default='', 73 help='CXXFLAGS for the ChromeOS packages') 74 parser.add_argument( 75 '--ldflags', 76 dest='ldflags', 77 default='', 78 help='LDFLAGS for the ChromeOS packages') 79 parser.add_argument( 80 '--board', dest='board', help='ChromeOS target board, e.g. x86-generic') 81 parser.add_argument( 82 '--package', dest='package', help='The package needs to be built') 83 parser.add_argument( 84 '--label', 85 dest='label', 86 help='Optional label symlink to point to build dir.') 87 parser.add_argument( 88 '--dev', 89 dest='dev', 90 default=False, 91 action='store_true', 92 help=('Make the final image in dev mode (eg writable, ' 93 'more space on image). Defaults to False.')) 94 parser.add_argument( 95 '--debug', 96 dest='debug', 97 default=False, 98 action='store_true', 99 help=('Optional. Build chrome browser with "-g -O0". ' 100 "Notice, this also turns on '--dev'. " 101 'Defaults to False.')) 102 parser.add_argument( 103 '--env', dest='env', default='', help='Env to pass to build_packages.') 104 parser.add_argument( 105 '--vanilla', 106 dest='vanilla', 107 default=False, 108 action='store_true', 109 help='Use default ChromeOS toolchain.') 110 parser.add_argument( 111 '--vanilla_image', 112 dest='vanilla_image', 113 default=False, 114 action='store_true', 115 help=('Use prebuild packages for building the image. ' 116 'It also implies the --vanilla option is set.')) 117 118 options = parser.parse_args(argv[1:]) 119 120 if options.chromeos_root is None: 121 Usage(parser, '--chromeos_root must be set') 122 options.chromeos_root = os.path.expanduser(options.chromeos_root) 123 scripts_dir = os.path.join(options.chromeos_root, 'src', 'scripts') 124 if not os.path.isdir(scripts_dir): 125 Usage(parser, '--chromeos_root must be set up first. Use setup_chromeos.py') 126 127 if options.board is None: 128 Usage(parser, '--board must be set') 129 130 if options.debug: 131 options.dev = True 132 133 build_packages_env = options.env 134 if build_packages_env.find('EXTRA_BOARD_FLAGS=') != -1: 135 logger.GetLogger().LogFatal( 136 ('Passing "EXTRA_BOARD_FLAGS" in "--env" is not supported. ' 137 'This flags is used internally by this script. ' 138 'Contact the author for more detail.')) 139 140 if options.rebuild: 141 build_packages_env += ' EXTRA_BOARD_FLAGS=-e' 142 # EXTRA_BOARD_FLAGS=-e should clean up the object files for the chrome 143 # browser but it doesn't. So do it here. 144 misc.RemoveChromeBrowserObjectFiles(options.chromeos_root, options.board) 145 146 # Build with afdo_use by default. 147 # To change the default use --env="USE=-afdo_use". 148 build_packages_env = misc.MergeEnvStringWithDict( 149 build_packages_env, {'USE': 'chrome_internal afdo_use -cros-debug'}) 150 151 build_packages_command = misc.GetBuildPackagesCommand( 152 board=options.board, usepkg=options.vanilla_image, debug=options.debug) 153 154 if options.package: 155 build_packages_command += ' {0}'.format(options.package) 156 157 build_image_command = misc.GetBuildImageCommand(options.board, options.dev) 158 159 if options.vanilla or options.vanilla_image: 160 command = misc.GetSetupBoardCommand( 161 options.board, 162 usepkg=options.vanilla_image, 163 force=options.clobber_board) 164 command += '; ' + build_packages_env + ' ' + build_packages_command 165 command += '&& ' + build_packages_env + ' ' + build_image_command 166 ret = cmd_executer.ChrootRunCommand(options.chromeos_root, command) 167 return ret 168 169 # Setup board 170 if not os.path.isdir(options.chromeos_root + '/chroot/build/' + 171 options.board) or options.clobber_board: 172 # Run build_tc.py from binary package 173 ret = cmd_executer.ChrootRunCommand( 174 options.chromeos_root, 175 misc.GetSetupBoardCommand(options.board, force=options.clobber_board)) 176 logger.GetLogger().LogFatalIf(ret, 'setup_board failed') 177 else: 178 logger.GetLogger().LogOutput('Did not setup_board ' 179 'because it already exists') 180 181 if options.debug: 182 # Perform 2-step build_packages to build a debug chrome browser. 183 184 # Firstly, build everything that chromeos-chrome depends on normally. 185 if options.rebuild: 186 # Give warning about "--rebuild" and "--debug". Under this combination, 187 # only dependencies of "chromeos-chrome" get rebuilt. 188 logger.GetLogger().LogWarning( 189 '--rebuild" does not correctly re-build every package when ' 190 '"--debug" is enabled. ') 191 192 # Replace EXTRA_BOARD_FLAGS=-e with "-e --onlydeps" 193 build_packages_env = build_packages_env.replace( 194 'EXTRA_BOARD_FLAGS=-e', 'EXTRA_BOARD_FLAGS="-e --onlydeps"') 195 else: 196 build_packages_env += ' EXTRA_BOARD_FLAGS=--onlydeps' 197 198 ret = cmd_executer.ChrootRunCommand( 199 options.chromeos_root, 'CFLAGS="$(portageq-%s envvar CFLAGS) %s" ' 200 'CXXFLAGS="$(portageq-%s envvar CXXFLAGS) %s" ' 201 'LDFLAGS="$(portageq-%s envvar LDFLAGS) %s" ' 202 'CHROME_ORIGIN=SERVER_SOURCE ' 203 '%s ' 204 '%s --skip_chroot_upgrade' 205 'chromeos-chrome' % (options.board, options.cflags, options.board, 206 options.cxxflags, options.board, options.ldflags, 207 build_packages_env, build_packages_command)) 208 209 logger.GetLogger().LogFatalIf(\ 210 ret, 'build_packages failed while trying to build chromeos-chrome deps.') 211 212 # Secondly, build chromeos-chrome using debug mode. 213 # Replace '--onlydeps' with '--nodeps'. 214 if options.rebuild: 215 build_packages_env = build_packages_env.replace( 216 'EXTRA_BOARD_FLAGS="-e --onlydeps"', 'EXTRA_BOARD_FLAGS=--nodeps') 217 else: 218 build_packages_env = build_packages_env.replace( 219 'EXTRA_BOARD_FLAGS=--onlydeps', 'EXTRA_BOARD_FLAGS=--nodeps') 220 ret = cmd_executer.ChrootRunCommand( 221 options.chromeos_root, 'CFLAGS="$(portageq-%s envvar CFLAGS) %s" ' 222 'CXXFLAGS="$(portageq-%s envvar CXXFLAGS) %s" ' 223 'LDFLAGS="$(portageq-%s envvar LDFLAGS) %s" ' 224 'CHROME_ORIGIN=SERVER_SOURCE BUILDTYPE=Debug ' 225 '%s ' 226 '%s --skip_chroot_upgrade' 227 'chromeos-chrome' % (options.board, options.cflags, options.board, 228 options.cxxflags, options.board, options.ldflags, 229 build_packages_env, build_packages_command)) 230 logger.GetLogger().LogFatalIf( 231 ret, 232 'build_packages failed while trying to build debug chromeos-chrome.') 233 234 # Now, we have built chromeos-chrome and all dependencies. 235 # Finally, remove '-e' from EXTRA_BOARD_FLAGS, 236 # otherwise, chromeos-chrome gets rebuilt. 237 build_packages_env = build_packages_env.replace(\ 238 'EXTRA_BOARD_FLAGS=--nodeps', '') 239 240 # Up to now, we have a debug built chromos-chrome browser. 241 # Fall through to build the rest of the world. 242 243 # Build packages 244 ret = cmd_executer.ChrootRunCommand( 245 options.chromeos_root, 'CFLAGS="$(portageq-%s envvar CFLAGS) %s" ' 246 'CXXFLAGS="$(portageq-%s envvar CXXFLAGS) %s" ' 247 'LDFLAGS="$(portageq-%s envvar LDFLAGS) %s" ' 248 'CHROME_ORIGIN=SERVER_SOURCE ' 249 '%s ' 250 '%s --skip_chroot_upgrade' % 251 (options.board, options.cflags, options.board, options.cxxflags, 252 options.board, options.ldflags, build_packages_env, 253 build_packages_command)) 254 255 logger.GetLogger().LogFatalIf(ret, 'build_packages failed') 256 if options.package: 257 return 0 258 # Build image 259 ret = cmd_executer.ChrootRunCommand( 260 options.chromeos_root, build_packages_env + ' ' + build_image_command) 261 262 logger.GetLogger().LogFatalIf(ret, 'build_image failed') 263 264 flags_file_name = 'flags.txt' 265 flags_file_path = ('%s/src/build/images/%s/latest/%s' % 266 (options.chromeos_root, options.board, flags_file_name)) 267 with open(flags_file_path, 'w', encoding='utf-8') as flags_file: 268 flags_file.write('CFLAGS=%s\n' % options.cflags) 269 flags_file.write('CXXFLAGS=%s\n' % options.cxxflags) 270 flags_file.write('LDFLAGS=%s\n' % options.ldflags) 271 272 if options.label: 273 image_dir_path = ('%s/src/build/images/%s/latest' % (options.chromeos_root, 274 options.board)) 275 real_image_dir_path = os.path.realpath(image_dir_path) 276 command = ('ln -sf -T %s %s/%s' % (os.path.basename(real_image_dir_path), 277 os.path.dirname(real_image_dir_path), 278 options.label)) 279 280 ret = cmd_executer.RunCommand(command) 281 logger.GetLogger().LogFatalIf( 282 ret, 'Failed to apply symlink label %s' % options.label) 283 284 return ret 285 286 287if __name__ == '__main__': 288 retval = Main(sys.argv) 289 sys.exit(retval) 290