build_tool.py revision 88272d479f2761cc1906fea564c73033f77a6270
1#!/usr/bin/python2 2"""Script to bootstrap the chroot using new toolchain. 3 4This script allows you to build/install a customized version of gcc/binutils, 5either by specifying branch or a local directory. 6 7This script must be executed outside chroot. 8 9Below is some typical usage - 10 11## Build gcc located at /local/gcc/dir and do a bootstrap using the new 12## compiler for the chromeos root. The script tries to find a valid chromeos 13## tree all the way up from your current working directory. 14./build_tool.py --gcc_dir=/loca/gcc/dir --bootstrap 15 16## Build binutils, using remote branch "mobile_toolchain_v17" and do a 17## bootstrap using the new binutils for the chromeos root. The script tries to 18## find a valid chromeos tree all the way up from your current working 19## directory. 20./build_tool.py --binutils_branch=cros/mobile_toolchain_v17 \ 21 --chromeos_root=/chromeos/dir --bootstrap 22 23## Same as above except only do it for board daisy - no bootstrapping involved. 24./build_tool.py --binutils_branch=cros/mobile_toolchain_v16 \ 25 --chromeos_root=/chromeos/dir --board=daisy 26""" 27 28from __future__ import print_function 29 30__author__ = 'shenhan@google.com (Han Shen)' 31 32import argparse 33import os 34import re 35import sys 36 37import repo_to_repo 38from cros_utils import command_executer 39from cros_utils import logger 40from cros_utils import misc 41 42REPO_PATH_PATTERN = 'src/third_party/{0}' 43TEMP_BRANCH_NAME = 'internal_testing_branch_no_use' 44CHROMIUMOS_OVERLAY_PATH = 'src/third_party/chromiumos-overlay' 45EBUILD_PATH_PATTERN = 'src/third_party/chromiumos-overlay/sys-devel/{0}' 46 47 48class Bootstrapper(object): 49 """Class that handles bootstrap process.""" 50 51 def __init__(self, 52 chromeos_root, 53 gcc_branch=None, 54 gcc_dir=None, 55 binutils_branch=None, 56 binutils_dir=None, 57 board=None, 58 disable_2nd_bootstrap=False, 59 setup_tool_ebuild_file_only=False): 60 self._chromeos_root = chromeos_root 61 62 self._gcc_branch = gcc_branch 63 self._gcc_branch_tree = None 64 self._gcc_dir = gcc_dir 65 self._gcc_ebuild_file = None 66 self._gcc_ebuild_file_name = None 67 68 self._binutils_branch = binutils_branch 69 self._binutils_branch_tree = None 70 self._binutils_dir = binutils_dir 71 self._binutils_ebuild_file = None 72 self._binutils_ebuild_file_name = None 73 74 self._setup_tool_ebuild_file_only = setup_tool_ebuild_file_only 75 76 self._ce = command_executer.GetCommandExecuter() 77 self._logger = logger.GetLogger() 78 self._board = board 79 self._disable_2nd_bootstrap = disable_2nd_bootstrap 80 81 def IsTreeSame(self, t1, t2): 82 diff = 'diff -qr -x .git -x .svn "{0}" "{1}"'.format(t1, t2) 83 if self._ce.RunCommand(diff, print_to_console=False) == 0: 84 self._logger.LogOutput('"{0}" and "{1}" are the same."'.format(t1, t2)) 85 return True 86 self._logger.LogWarning('"{0}" and "{1}" are different."'.format(t1, t2)) 87 return False 88 89 def SubmitToLocalBranch(self): 90 """Copy source code to the chromium source tree and submit it locally.""" 91 if self._gcc_dir: 92 if not self.SubmitToolToLocalBranch(tool_name='gcc', 93 tool_dir=self._gcc_dir): 94 return False 95 self._gcc_branch = TEMP_BRANCH_NAME 96 97 if self._binutils_dir: 98 if not self.SubmitToolToLocalBranch(tool_name='binutils', 99 tool_dir=self._binutils_dir): 100 return False 101 self._binutils_branch = TEMP_BRANCH_NAME 102 103 return True 104 105 def SubmitToolToLocalBranch(self, tool_name, tool_dir): 106 """Copy the source code to local chromium source tree. 107 108 Args: 109 tool_name: either 'gcc' or 'binutils' 110 tool_dir: the tool source dir to be used 111 112 Returns: 113 True if all succeeded False otherwise. 114 """ 115 116 # The next few steps creates an internal branch to sync with the tool dir 117 # user provided. 118 chrome_tool_dir = self.GetChromeOsToolDir(tool_name) 119 120 # 0. Test to see if git tree is free of local changes. 121 if not misc.IsGitTreeClean(chrome_tool_dir): 122 self._logger.LogError('Git repository "{0}" not clean, aborted.'.format( 123 chrome_tool_dir)) 124 return False 125 126 # 1. Checkout/create a (new) branch for testing. 127 command = 'cd "{0}" && git checkout -B {1}'.format(chrome_tool_dir, 128 TEMP_BRANCH_NAME) 129 ret = self._ce.RunCommand(command) 130 if ret: 131 self._logger.LogError('Failed to create a temp branch for test, aborted.') 132 return False 133 134 if self.IsTreeSame(tool_dir, chrome_tool_dir): 135 self._logger.LogOutput( 136 '"{0}" and "{1}" are the same, sync skipped.'.format(tool_dir, 137 chrome_tool_dir)) 138 return True 139 140 # 2. Sync sources from user provided tool dir to chromiumos tool git. 141 local_tool_repo = repo_to_repo.FileRepo(tool_dir) 142 chrome_tool_repo = repo_to_repo.GitRepo(chrome_tool_dir, TEMP_BRANCH_NAME) 143 chrome_tool_repo.SetRoot(chrome_tool_dir) 144 # Delete all stuff except '.git' before start mapping. 145 self._ce.RunCommand( 146 'cd {0} && find . -maxdepth 1 -not -name ".git" -not -name "." ' 147 r'\( -type f -exec rm {{}} \; -o ' 148 r' -type d -exec rm -fr {{}} \; \)'.format(chrome_tool_dir)) 149 local_tool_repo.MapSources(chrome_tool_repo.GetRoot()) 150 151 # 3. Ensure after sync tree is the same. 152 if self.IsTreeSame(tool_dir, chrome_tool_dir): 153 self._logger.LogOutput('Sync successfully done.') 154 else: 155 self._logger.LogError('Sync not successful, aborted.') 156 return False 157 158 # 4. Commit all changes. 159 # 4.1 Try to get some information about the tool dir we are using. 160 cmd = 'cd {0} && git log -1 --pretty=oneline'.format(tool_dir) 161 tool_dir_extra_info = None 162 ret, tool_dir_extra_info, _ = self._ce.RunCommandWOutput( 163 cmd, 164 print_to_console=False) 165 commit_message = 'Synced with tool source tree at - "{0}".'.format(tool_dir) 166 if not ret: 167 commit_message += '\nGit log for {0}:\n{1}'.format(tool_dir, 168 tool_dir_extra_info) 169 170 if chrome_tool_repo.CommitLocally(commit_message): 171 self._logger.LogError( 172 'Commit to local branch "{0}" failed, aborted.'.format( 173 TEMP_BRANCH_NAME)) 174 return False 175 return True 176 177 def CheckoutBranch(self): 178 """Checkout working branch for the tools. 179 180 Returns: 181 True: if operation succeeds. 182 """ 183 184 if self._gcc_branch: 185 rv = self.CheckoutToolBranch('gcc', self._gcc_branch) 186 if rv: 187 self._gcc_branch_tree = rv 188 else: 189 return False 190 191 if self._binutils_branch: 192 rv = self.CheckoutToolBranch('binutils', self._binutils_branch) 193 if rv: 194 self._binutils_branch_tree = rv 195 else: 196 return False 197 198 return True 199 200 def CheckoutToolBranch(self, tool_name, tool_branch): 201 """Checkout the tool branch for a certain tool. 202 203 Args: 204 tool_name: either 'gcc' or 'binutils' 205 tool_branch: tool branch to use 206 207 Returns: 208 True: if operation succeeds. Otherwise False. 209 """ 210 211 chrome_tool_dir = self.GetChromeOsToolDir(tool_name) 212 command = 'cd "{0}" && git checkout {1}'.format(chrome_tool_dir, 213 tool_branch) 214 if not self._ce.RunCommand(command, print_to_console=True): 215 # Get 'TREE' value of this commit 216 command = ('cd "{0}" && git cat-file -p {1} ' 217 '| grep -E "^tree [a-f0-9]+$" ' 218 '| cut -d" " -f2').format(chrome_tool_dir, tool_branch) 219 ret, stdout, _ = self._ce.RunCommandWOutput(command, 220 print_to_console=False) 221 # Pipe operation always has a zero return value. So need to check if 222 # stdout is valid. 223 if not ret and stdout and re.match('[0-9a-h]{40}', stdout.strip(), 224 re.IGNORECASE): 225 tool_branch_tree = stdout.strip() 226 self._logger.LogOutput('Find tree for {0} branch "{1}" - "{2}"'.format( 227 tool_name, tool_branch, tool_branch_tree)) 228 return tool_branch_tree 229 self._logger.LogError(('Failed to checkout "{0}" or failed to ' 230 'get tree value, aborted.').format(tool_branch)) 231 return None 232 233 def FindEbuildFile(self): 234 """Find the ebuild files for the tools. 235 236 Returns: 237 True: if operation succeeds. 238 """ 239 240 if self._gcc_branch: 241 (rv, ef, efn) = self.FindToolEbuildFile('gcc') 242 if rv: 243 self._gcc_ebuild_file = ef 244 self._gcc_ebuild_file_name = efn 245 else: 246 return False 247 248 if self._binutils_branch: 249 (rv, ef, efn) = self.FindToolEbuildFile('binutils') 250 if rv: 251 self._binutils_ebuild_file = ef 252 self._binutils_ebuild_file_name = efn 253 else: 254 return False 255 256 return True 257 258 def FindToolEbuildFile(self, tool_name): 259 """Find ebuild file for a specific tool. 260 261 Args: 262 tool_name: either "gcc" or "binutils". 263 264 Returns: 265 A triplet that consisits of whether operation succeeds or not, 266 tool ebuild file full path and tool ebuild file name. 267 """ 268 269 # To get the active gcc ebuild file, we need a workable chroot first. 270 if not os.path.exists(os.path.join( 271 self._chromeos_root, 'chroot')) and self._ce.RunCommand( 272 'cd "{0}" && cros_sdk --create'.format(self._chromeos_root)): 273 self._logger.LogError(('Failed to install a initial chroot, aborted.\n' 274 'If previous bootstrap failed, do a ' 275 '"cros_sdk --delete" to remove ' 276 'in-complete chroot.')) 277 return (False, None, None) 278 279 rv, stdout, _ = self._ce.ChrootRunCommandWOutput( 280 self._chromeos_root, 281 'equery w sys-devel/{0}'.format(tool_name), 282 print_to_console=True) 283 if rv: 284 self._logger.LogError(('Failed to execute inside chroot ' 285 '"equery w sys-devel/{0}", aborted.').format( 286 tool_name)) 287 return (False, None, None) 288 m = re.match(r'^.*/({0}/(.*\.ebuild))$'.format(EBUILD_PATH_PATTERN.format( 289 tool_name)), stdout) 290 if not m: 291 self._logger.LogError( 292 ('Failed to find {0} ebuild file, aborted. ' 293 'If previous bootstrap failed, do a "cros_sdk --delete" to remove ' 294 'in-complete chroot.').format(tool_name)) 295 return (False, None, None) 296 tool_ebuild_file = os.path.join(self._chromeos_root, m.group(1)) 297 tool_ebuild_file_name = m.group(2) 298 299 return (True, tool_ebuild_file, tool_ebuild_file_name) 300 301 def InplaceModifyEbuildFile(self): 302 """Modify the ebuild file. 303 304 Returns: 305 True if operation succeeds. 306 """ 307 308 # Note we shall not use remote branch name (eg. "cros/gcc.gnu.org/...") in 309 # CROS_WORKON_COMMIT, we have to use GITHASH. So we call GitGetCommitHash on 310 # tool_branch. 311 if self._gcc_branch: 312 tool_branch_githash = misc.GitGetCommitHash( 313 self.GetChromeOsToolDir('gcc'), self._gcc_branch) 314 if not tool_branch_githash: 315 return False 316 if not self.InplaceModifyToolEbuildFile( 317 tool_branch_githash, self._gcc_branch_tree, self._gcc_ebuild_file): 318 return False 319 320 if self._binutils_branch: 321 tool_branch_githash = misc.GitGetCommitHash( 322 self.GetChromeOsToolDir('binutils'), self._binutils_branch) 323 if not self.InplaceModifyToolEbuildFile(tool_branch_githash, 324 self._binutils_branch_tree, 325 self._binutils_ebuild_file): 326 return False 327 return True 328 329 @staticmethod 330 def ResetToolEbuildFile(chromeos_root, tool_name): 331 """Reset tool ebuild file to clean state. 332 333 Args: 334 chromeos_root: chromeos source tree 335 tool_name: either "gcc" or "binutils" 336 337 Returns: 338 True if operation succeds. 339 """ 340 rv = misc.GetGitChangesAsList( 341 os.path.join(chromeos_root, CHROMIUMOS_OVERLAY_PATH), 342 path=('sys-devel/{0}/{0}-*.ebuild'.format(tool_name)), 343 staged=False) 344 if rv: 345 cmd = 'cd {0} && git checkout --'.format(os.path.join( 346 chromeos_root, CHROMIUMOS_OVERLAY_PATH)) 347 for g in rv: 348 cmd += ' ' + g 349 rv = command_executer.GetCommandExecuter().RunCommand(cmd) 350 if rv: 351 logger.GetLogger().LogWarning( 352 'Failed to reset the ebuild file. Please refer to log above.') 353 return False 354 else: 355 logger.GetLogger().LogWarning( 356 'Note - did not find any modified {0} ebuild file.'.format(tool_name)) 357 # Fall through 358 return True 359 360 def GetChromeOsToolDir(self, tool_name): 361 """Return the chromeos git dir for a specific tool. 362 363 Args: 364 tool_name: either 'gcc' or 'binutils'. 365 366 Returns: 367 Absolute git path for the tool. 368 """ 369 370 return os.path.join(self._chromeos_root, 371 REPO_PATH_PATTERN.format(tool_name)) 372 373 def InplaceModifyToolEbuildFile(self, tool_branch_githash, tool_branch_tree, 374 tool_ebuild_file): 375 """Using sed to fill properly values into the ebuild file. 376 377 Args: 378 tool_branch_githash: githash for tool_branch 379 tool_branch_tree: treeish for the tool branch 380 tool_ebuild_file: tool ebuild file 381 382 Returns: 383 True: if operation succeeded. 384 """ 385 386 command = ('sed -i ' 387 '-e \'/^CROS_WORKON_COMMIT=".*"/i' 388 ' # The following line is modified by script.\' ' 389 '-e \'s!^CROS_WORKON_COMMIT=".*"$!CROS_WORKON_COMMIT="{0}"!\' ' 390 '-e \'/^CROS_WORKON_TREE=".*"/i' 391 ' # The following line is modified by script.\' ' 392 '-e \'s!^CROS_WORKON_TREE=".*"$!CROS_WORKON_TREE="{1}"!\' ' 393 '{2}').format(tool_branch_githash, tool_branch_tree, 394 tool_ebuild_file) 395 rv = self._ce.RunCommand(command) 396 if rv: 397 self._logger.LogError( 398 'Failed to modify commit and tree value for "{0}"", aborted.'.format( 399 tool_ebuild_file)) 400 return False 401 402 # Warn that the ebuild file has been modified. 403 self._logger.LogWarning( 404 ('Ebuild file "{0}" is modified, to revert the file - \n' 405 'bootstrap_compiler.py --chromeos_root={1} ' 406 '--reset_tool_ebuild_file').format(tool_ebuild_file, 407 self._chromeos_root)) 408 return True 409 410 def DoBuildForBoard(self): 411 """Build tool for a specific board. 412 413 Returns: 414 True if operation succeeds. 415 """ 416 417 if self._gcc_branch: 418 if not self.DoBuildToolForBoard('gcc'): 419 return False 420 if self._binutils_branch: 421 if not self.DoBuildToolForBoard('binutils'): 422 return False 423 return True 424 425 def DoBuildToolForBoard(self, tool_name): 426 """Build a specific tool for a specific board. 427 428 Args: 429 tool_name: either "gcc" or "binutils" 430 431 Returns: 432 True if operation succeeds. 433 """ 434 435 boards_to_build = self._board.split(',') 436 437 failed = [] 438 for board in boards_to_build: 439 if board == 'host': 440 command = 'sudo emerge sys-devel/{0}'.format(tool_name) 441 else: 442 target = misc.GetCtargetFromBoard(board, self._chromeos_root) 443 if not target: 444 self._logger.LogError('Unsupported board "{0}", skip.'.format(board)) 445 failed.append(board) 446 continue 447 command = 'sudo emerge cross-{0}/{1}'.format(target, tool_name) 448 449 rv = self._ce.ChrootRunCommand(self._chromeos_root, 450 command, 451 print_to_console=True) 452 if rv: 453 self._logger.LogError('Build {0} failed for {1}, aborted.'.format( 454 tool_name, board)) 455 failed.append(board) 456 else: 457 self._logger.LogOutput('Successfully built {0} for board {1}.'.format( 458 tool_name, board)) 459 460 if failed: 461 self._logger.LogError( 462 'Failed to build {0} for the following board(s): "{1}"'.format( 463 tool_name, ' '.join(failed))) 464 return False 465 # All boards build successfully 466 return True 467 468 def DoBootstrapping(self): 469 """Do bootstrapping the chroot. 470 471 This step firstly downloads a prestine sdk, then use this sdk to build the 472 new sdk, finally use the new sdk to build every host package. 473 474 Returns: 475 True if operation succeeds. 476 """ 477 478 logfile = os.path.join(self._chromeos_root, 'bootstrap.log') 479 command = 'cd "{0}" && cros_sdk --delete --bootstrap |& tee "{1}"'.format( 480 self._chromeos_root, logfile) 481 rv = self._ce.RunCommand(command, print_to_console=True) 482 if rv: 483 self._logger.LogError('Bootstrapping failed, log file - "{0}"\n'.format( 484 logfile)) 485 return False 486 487 self._logger.LogOutput('Bootstrap succeeded.') 488 return True 489 490 def BuildAndInstallAmd64Host(self): 491 """Build amd64-host (host) packages. 492 493 Build all host packages in the newly-bootstrapped 'chroot' using *NEW* 494 toolchain. 495 496 So actually we perform 2 builds of all host packages - 497 1. build new toolchain using old toolchain and build all host packages 498 using the newly built toolchain 499 2. build the new toolchain again but using new toolchain built in step 1, 500 and build all host packages using the newly built toolchain 501 502 Returns: 503 True if operation succeeds. 504 """ 505 506 cmd = ('cd {0} && cros_sdk -- -- ./setup_board --board=amd64-host ' 507 '--accept_licenses=@CHROMEOS --skip_chroot_upgrade --nousepkg ' 508 '--reuse_pkgs_from_local_boards').format(self._chromeos_root) 509 rv = self._ce.RunCommand(cmd, print_to_console=True) 510 if rv: 511 self._logger.LogError('Build amd64-host failed.') 512 return False 513 514 # Package amd64-host into 'built-sdk.tar.xz'. 515 sdk_package = os.path.join(self._chromeos_root, 'built-sdk.tar.xz') 516 cmd = ('cd {0}/chroot/build/amd64-host && sudo XZ_OPT="-e9" ' 517 'tar --exclude="usr/lib/debug/*" --exclude="packages/*" ' 518 '--exclude="tmp/*" --exclude="usr/local/build/autotest/*" ' 519 '--sparse -I xz -vcf {1} . && sudo chmod a+r {1}').format( 520 self._chromeos_root, sdk_package) 521 rv = self._ce.RunCommand(cmd, print_to_console=True) 522 if rv: 523 self._logger.LogError('Failed to create "built-sdk.tar.xz".') 524 return False 525 526 # Install amd64-host into a new chroot. 527 cmd = ('cd {0} && cros_sdk --chroot new-sdk-chroot --download --replace ' 528 '--nousepkg --url file://{1}').format(self._chromeos_root, 529 sdk_package) 530 rv = self._ce.RunCommand(cmd, print_to_console=True) 531 if rv: 532 self._logger.LogError('Failed to install "built-sdk.tar.xz".') 533 return False 534 self._logger.LogOutput( 535 'Successfully installed built-sdk.tar.xz into a new chroot.\nAll done.') 536 537 # Rename the newly created new-sdk-chroot to chroot. 538 cmd = ('cd {0} && sudo mv chroot chroot-old && ' 539 'sudo mv new-sdk-chroot chroot').format(self._chromeos_root) 540 rv = self._ce.RunCommand(cmd, print_to_console=True) 541 return rv == 0 542 543 def Do(self): 544 """Entrance of the class. 545 546 Returns: 547 True if everything is ok. 548 """ 549 550 if (self.SubmitToLocalBranch() and self.CheckoutBranch() and 551 self.FindEbuildFile() and self.InplaceModifyEbuildFile()): 552 if self._setup_tool_ebuild_file_only: 553 # Everything is done, we are good. 554 ret = True 555 else: 556 if self._board: 557 ret = self.DoBuildForBoard() 558 else: 559 # This implies '--bootstrap'. 560 ret = (self.DoBootstrapping() and (self._disable_2nd_bootstrap or 561 self.BuildAndInstallAmd64Host())) 562 else: 563 ret = False 564 return ret 565 566 567def Main(argv): 568 parser = argparse.ArgumentParser() 569 parser.add_argument('-c', 570 '--chromeos_root', 571 dest='chromeos_root', 572 help=('Optional. ChromeOs root dir. ' 573 'When not specified, chromeos root will be deduced' 574 ' from current working directory.')) 575 parser.add_argument('--gcc_branch', 576 dest='gcc_branch', 577 help=('The branch to test against. ' 578 'This branch must be a local branch ' 579 'inside "src/third_party/gcc". ' 580 'Notice, this must not be used with "--gcc_dir".')) 581 parser.add_argument('--binutils_branch', 582 dest='binutils_branch', 583 help=('The branch to test against binutils. ' 584 'This branch must be a local branch ' 585 'inside "src/third_party/binutils". ' 586 'Notice, this must not be used with ' 587 '"--binutils_dir".')) 588 parser.add_argument('-g', 589 '--gcc_dir', 590 dest='gcc_dir', 591 help=('Use a local gcc tree to do bootstrapping. ' 592 'Notice, this must not be used with ' 593 '"--gcc_branch".')) 594 parser.add_argument('--binutils_dir', 595 dest='binutils_dir', 596 help=('Use a local binutils tree to do bootstrapping. ' 597 'Notice, this must not be used with ' 598 '"--binutils_branch".')) 599 parser.add_argument('--fixperm', 600 dest='fixperm', 601 default=False, 602 action='store_true', 603 help=('Fix the (notorious) permission error ' 604 'while trying to bootstrap the chroot. ' 605 'Note this takes an extra 10-15 minutes ' 606 'and is only needed once per chromiumos tree.')) 607 parser.add_argument('--setup_tool_ebuild_file_only', 608 dest='setup_tool_ebuild_file_only', 609 default=False, 610 action='store_true', 611 help=('Setup gcc and/or binutils ebuild file ' 612 'to pick up the branch (--gcc/binutils_branch) or ' 613 'use gcc and/or binutils source ' 614 '(--gcc/binutils_dir) and exit. Keep chroot as is.' 615 ' This should not be used with ' 616 '--gcc/binutils_dir/branch options.')) 617 parser.add_argument('--reset_tool_ebuild_file', 618 dest='reset_tool_ebuild_file', 619 default=False, 620 action='store_true', 621 help=('Reset the modification that is done by this ' 622 'script. Note, when this script is running, it ' 623 'will modify the active gcc/binutils ebuild file. ' 624 'Use this option to reset (what this script has ' 625 'done) and exit. This should not be used with -- ' 626 'gcc/binutils_dir/branch options.')) 627 parser.add_argument('--board', 628 dest='board', 629 default=None, 630 help=('Only build toolchain for specific board(s). ' 631 'Use "host" to build for host. ' 632 'Use "," to seperate multiple boards. ' 633 'This does not perform a chroot bootstrap.')) 634 parser.add_argument('--bootstrap', 635 dest='bootstrap', 636 default=False, 637 action='store_true', 638 help=('Performs a chroot bootstrap. ' 639 'Note, this will *destroy* your current chroot.')) 640 parser.add_argument('--disable-2nd-bootstrap', 641 dest='disable_2nd_bootstrap', 642 default=False, 643 action='store_true', 644 help=('Disable a second bootstrap ' 645 '(build of amd64-host stage).')) 646 647 options = parser.parse_args(argv) 648 # Trying to deduce chromeos root from current directory. 649 if not options.chromeos_root: 650 logger.GetLogger().LogOutput('Trying to deduce chromeos root ...') 651 wdir = os.getcwd() 652 while wdir and wdir != '/': 653 if misc.IsChromeOsTree(wdir): 654 logger.GetLogger().LogOutput('Find chromeos_root: {}'.format(wdir)) 655 options.chromeos_root = wdir 656 break 657 wdir = os.path.dirname(wdir) 658 659 if not options.chromeos_root: 660 parser.error('Missing or failing to deduce mandatory option "--chromeos".') 661 return 1 662 663 options.chromeos_root = os.path.abspath(os.path.expanduser( 664 options.chromeos_root)) 665 666 if not os.path.isdir(options.chromeos_root): 667 logger.GetLogger().LogError('"{0}" does not exist.'.format( 668 options.chromeos_root)) 669 return 1 670 671 if options.fixperm: 672 # Fix perm error before continuing. 673 cmd = ( 674 r'sudo find "{0}" \( -name ".cache" -type d -prune \) -o ' 675 r'\( -name "chroot" -type d -prune \) -o ' 676 r'\( -type f -exec chmod a+r {{}} \; \) -o ' 677 r'\( -type d -exec chmod a+rx {{}} \; \)').format(options.chromeos_root) 678 logger.GetLogger().LogOutput( 679 'Fixing perm issues for chromeos root, this might take some time.') 680 command_executer.GetCommandExecuter().RunCommand(cmd) 681 682 if options.reset_tool_ebuild_file: 683 if (options.gcc_dir or options.gcc_branch or options.binutils_dir or 684 options.binutils_branch): 685 logger.GetLogger().LogWarning( 686 'Ignoring any "--gcc/binutils_dir" and/or "--gcc/binutils_branch".') 687 if options.setup_tool_ebuild_file_only: 688 logger.GetLogger().LogError( 689 ('Conflict options "--reset_tool_ebuild_file" ' 690 'and "--setup_tool_ebuild_file_only".')) 691 return 1 692 rv = Bootstrapper.ResetToolEbuildFile(options.chromeos_root, 'gcc') 693 rv1 = Bootstrapper.ResetToolEbuildFile(options.chromeos_root, 'binutils') 694 return 0 if (rv and rv1) else 1 695 696 if options.gcc_dir: 697 options.gcc_dir = os.path.abspath(os.path.expanduser(options.gcc_dir)) 698 if not os.path.isdir(options.gcc_dir): 699 logger.GetLogger().LogError('"{0}" does not exist.'.format( 700 options.gcc_dir)) 701 return 1 702 703 if options.gcc_branch and options.gcc_dir: 704 parser.error('Only one of "--gcc_dir" and "--gcc_branch" can be specified.') 705 return 1 706 707 if options.binutils_dir: 708 options.binutils_dir = os.path.abspath(os.path.expanduser( 709 options.binutils_dir)) 710 if not os.path.isdir(options.binutils_dir): 711 logger.GetLogger().LogError('"{0}" does not exist.'.format( 712 options.binutils_dir)) 713 return 1 714 715 if options.binutils_branch and options.binutils_dir: 716 parser.error('Only one of "--binutils_dir" and ' 717 '"--binutils_branch" can be specified.') 718 return 1 719 720 if (not (options.binutils_branch or options.binutils_dir or options.gcc_branch 721 or options.gcc_dir)): 722 parser.error(('At least one of "--gcc_dir", "--gcc_branch", ' 723 '"--binutils_dir" and "--binutils_branch" must ' 724 'be specified.')) 725 return 1 726 727 if not options.board and not options.bootstrap: 728 parser.error('You must specify either "--board" or "--bootstrap".') 729 return 1 730 731 if (options.board and options.bootstrap and 732 not options.setup_tool_ebuild_file_only): 733 parser.error('You must specify only one of "--board" and "--bootstrap".') 734 return 1 735 736 if not options.bootstrap and options.disable_2nd_bootstrap: 737 parser.error('"--disable-2nd-bootstrap" has no effect ' 738 'without specifying "--bootstrap".') 739 return 1 740 741 if Bootstrapper( 742 options.chromeos_root, 743 gcc_branch=options.gcc_branch, 744 gcc_dir=options.gcc_dir, 745 binutils_branch=options.binutils_branch, 746 binutils_dir=options.binutils_dir, 747 board=options.board, 748 disable_2nd_bootstrap=options.disable_2nd_bootstrap, 749 setup_tool_ebuild_file_only=options.setup_tool_ebuild_file_only).Do(): 750 return 0 751 return 1 752 753 754if __name__ == '__main__': 755 retval = Main(sys.argv[1:]) 756 sys.exit(retval) 757