aboutsummaryrefslogtreecommitdiff
path: root/deprecated/build_tool.py
diff options
context:
space:
mode:
Diffstat (limited to 'deprecated/build_tool.py')
-rwxr-xr-xdeprecated/build_tool.py849
1 files changed, 849 insertions, 0 deletions
diff --git a/deprecated/build_tool.py b/deprecated/build_tool.py
new file mode 100755
index 00000000..0c2fff65
--- /dev/null
+++ b/deprecated/build_tool.py
@@ -0,0 +1,849 @@
+#!/usr/bin/env python2
+"""Script to bootstrap the chroot using new toolchain.
+
+This script allows you to build/install a customized version of gcc/binutils,
+either by specifying branch or a local directory.
+
+This script must be executed outside chroot.
+
+Below is some typical usage -
+
+## Build gcc located at /local/gcc/dir and do a bootstrap using the new
+## compiler for the chromeos root. The script tries to find a valid chromeos
+## tree all the way up from your current working directory.
+./build_tool.py --gcc_dir=/loca/gcc/dir --bootstrap
+
+## Build binutils, using remote branch "mobile_toolchain_v17" and do a
+## bootstrap using the new binutils for the chromeos root. The script tries to
+## find a valid chromeos tree all the way up from your current working
+## directory.
+./build_tool.py --binutils_branch=cros/mobile_toolchain_v17 \
+ --chromeos_root=/chromeos/dir --bootstrap
+
+## Same as above except only do it for board daisy - no bootstrapping involved.
+./build_tool.py --binutils_branch=cros/mobile_toolchain_v16 \
+ --chromeos_root=/chromeos/dir --board=daisy
+"""
+
+from __future__ import print_function
+
+__author__ = 'shenhan@google.com (Han Shen)'
+
+import argparse
+import os
+import re
+import sys
+
+from cros_utils import command_executer
+from cros_utils import logger
+from cros_utils import misc
+import repo_to_repo
+
+REPO_PATH_PATTERN = 'src/third_party/{0}'
+TEMP_BRANCH_NAME = 'internal_testing_branch_no_use'
+CHROMIUMOS_OVERLAY_PATH = 'src/third_party/chromiumos-overlay'
+EBUILD_PATH_PATTERN = 'src/third_party/chromiumos-overlay/sys-devel/{0}'
+
+
+class Bootstrapper(object):
+ """Class that handles bootstrap process."""
+
+ def __init__(self,
+ chromeos_root,
+ ndk_dir,
+ gcc_branch=None,
+ gcc_dir=None,
+ binutils_branch=None,
+ binutils_dir=None,
+ board=None,
+ disable_2nd_bootstrap=False,
+ setup_tool_ebuild_file_only=False):
+ self._chromeos_root = chromeos_root
+ self._ndk_dir = ndk_dir
+
+ self._gcc_branch = gcc_branch
+ self._gcc_branch_tree = None
+ self._gcc_dir = gcc_dir
+ self._gcc_ebuild_file = None
+ self._gcc_ebuild_file_name = None
+
+ self._binutils_branch = binutils_branch
+ self._binutils_branch_tree = None
+ self._binutils_dir = binutils_dir
+ self._binutils_ebuild_file = None
+ self._binutils_ebuild_file_name = None
+
+ self._setup_tool_ebuild_file_only = setup_tool_ebuild_file_only
+
+ self._ce = command_executer.GetCommandExecuter()
+ self._logger = logger.GetLogger()
+ self._board = board
+ self._disable_2nd_bootstrap = disable_2nd_bootstrap
+
+ def IsTreeSame(self, t1, t2):
+ diff = 'diff -qr -x .git -x .svn "{0}" "{1}"'.format(t1, t2)
+ if self._ce.RunCommand(diff, print_to_console=False) == 0:
+ self._logger.LogOutput('"{0}" and "{1}" are the same."'.format(t1, t2))
+ return True
+ self._logger.LogWarning('"{0}" and "{1}" are different."'.format(t1, t2))
+ return False
+
+ def SubmitToLocalBranch(self):
+ """Copy source code to the chromium source tree and submit it locally."""
+ if self._gcc_dir:
+ if not self.SubmitToolToLocalBranch(
+ tool_name='gcc', tool_dir=self._gcc_dir):
+ return False
+ self._gcc_branch = TEMP_BRANCH_NAME
+
+ if self._binutils_dir:
+ if not self.SubmitToolToLocalBranch(
+ tool_name='binutils', tool_dir=self._binutils_dir):
+ return False
+ self._binutils_branch = TEMP_BRANCH_NAME
+
+ return True
+
+ def SubmitToolToLocalBranch(self, tool_name, tool_dir):
+ """Copy the source code to local chromium source tree.
+
+ Args:
+ tool_name: either 'gcc' or 'binutils'
+ tool_dir: the tool source dir to be used
+
+ Returns:
+ True if all succeeded False otherwise.
+ """
+
+ # The next few steps creates an internal branch to sync with the tool dir
+ # user provided.
+ chrome_tool_dir = self.GetChromeOsToolDir(tool_name)
+
+ # 0. Test to see if git tree is free of local changes.
+ if not misc.IsGitTreeClean(chrome_tool_dir):
+ self._logger.LogError(
+ 'Git repository "{0}" not clean, aborted.'.format(chrome_tool_dir))
+ return False
+
+ # 1. Checkout/create a (new) branch for testing.
+ command = 'cd "{0}" && git checkout -B {1}'.format(chrome_tool_dir,
+ TEMP_BRANCH_NAME)
+ ret = self._ce.RunCommand(command)
+ if ret:
+ self._logger.LogError('Failed to create a temp branch for test, aborted.')
+ return False
+
+ if self.IsTreeSame(tool_dir, chrome_tool_dir):
+ self._logger.LogOutput('"{0}" and "{1}" are the same, sync skipped.'.
+ format(tool_dir, chrome_tool_dir))
+ return True
+
+ # 2. Sync sources from user provided tool dir to chromiumos tool git.
+ local_tool_repo = repo_to_repo.FileRepo(tool_dir)
+ chrome_tool_repo = repo_to_repo.GitRepo(chrome_tool_dir, TEMP_BRANCH_NAME)
+ chrome_tool_repo.SetRoot(chrome_tool_dir)
+ # Delete all stuff except '.git' before start mapping.
+ self._ce.RunCommand(
+ 'cd {0} && find . -maxdepth 1 -not -name ".git" -not -name "." '
+ r'\( -type f -exec rm {{}} \; -o '
+ r' -type d -exec rm -fr {{}} \; \)'.format(chrome_tool_dir))
+ local_tool_repo.MapSources(chrome_tool_repo.GetRoot())
+
+ # 3. Ensure after sync tree is the same.
+ if self.IsTreeSame(tool_dir, chrome_tool_dir):
+ self._logger.LogOutput('Sync successfully done.')
+ else:
+ self._logger.LogError('Sync not successful, aborted.')
+ return False
+
+ # 4. Commit all changes.
+ # 4.1 Try to get some information about the tool dir we are using.
+ cmd = 'cd {0} && git log -1 --pretty=oneline'.format(tool_dir)
+ tool_dir_extra_info = None
+ ret, tool_dir_extra_info, _ = self._ce.RunCommandWOutput(
+ cmd, print_to_console=False)
+ commit_message = 'Synced with tool source tree at - "{0}".'.format(tool_dir)
+ if not ret:
+ commit_message += '\nGit log for {0}:\n{1}'.format(
+ tool_dir, tool_dir_extra_info.strip())
+
+ if chrome_tool_repo.CommitLocally(commit_message):
+ self._logger.LogError('Commit to local branch "{0}" failed, aborted.'.
+ format(TEMP_BRANCH_NAME))
+ return False
+ return True
+
+ def CheckoutBranch(self):
+ """Checkout working branch for the tools.
+
+ Returns:
+ True: if operation succeeds.
+ """
+
+ if self._gcc_branch:
+ rv = self.CheckoutToolBranch('gcc', self._gcc_branch)
+ if rv:
+ self._gcc_branch_tree = rv
+ else:
+ return False
+
+ if self._binutils_branch:
+ rv = self.CheckoutToolBranch('binutils', self._binutils_branch)
+ if rv:
+ self._binutils_branch_tree = rv
+ else:
+ return False
+
+ return True
+
+ def CheckoutToolBranch(self, tool_name, tool_branch):
+ """Checkout the tool branch for a certain tool.
+
+ Args:
+ tool_name: either 'gcc' or 'binutils'
+ tool_branch: tool branch to use
+
+ Returns:
+ True: if operation succeeds. Otherwise False.
+ """
+
+ chrome_tool_dir = self.GetChromeOsToolDir(tool_name)
+ command = 'cd "{0}" && git checkout {1}'.format(chrome_tool_dir,
+ tool_branch)
+ if not self._ce.RunCommand(command, print_to_console=True):
+ # Get 'TREE' value of this commit
+ command = ('cd "{0}" && git cat-file -p {1} '
+ '| grep -E "^tree [a-f0-9]+$" '
+ '| cut -d" " -f2').format(chrome_tool_dir, tool_branch)
+ ret, stdout, _ = self._ce.RunCommandWOutput(
+ command, print_to_console=False)
+ # Pipe operation always has a zero return value. So need to check if
+ # stdout is valid.
+ if not ret and stdout and re.match('[0-9a-h]{40}',
+ stdout.strip(), re.IGNORECASE):
+ tool_branch_tree = stdout.strip()
+ self._logger.LogOutput('Find tree for {0} branch "{1}" - "{2}"'.format(
+ tool_name, tool_branch, tool_branch_tree))
+ return tool_branch_tree
+ self._logger.LogError(('Failed to checkout "{0}" or failed to '
+ 'get tree value, aborted.').format(tool_branch))
+ return None
+
+ def FindEbuildFile(self):
+ """Find the ebuild files for the tools.
+
+ Returns:
+ True: if operation succeeds.
+ """
+
+ if self._gcc_branch:
+ (rv, ef, efn) = self.FindToolEbuildFile('gcc')
+ if rv:
+ self._gcc_ebuild_file = ef
+ self._gcc_ebuild_file_name = efn
+ else:
+ return False
+
+ if self._binutils_branch:
+ (rv, ef, efn) = self.FindToolEbuildFile('binutils')
+ if rv:
+ self._binutils_ebuild_file = ef
+ self._binutils_ebuild_file_name = efn
+ else:
+ return False
+
+ return True
+
+ def FindToolEbuildFile(self, tool_name):
+ """Find ebuild file for a specific tool.
+
+ Args:
+ tool_name: either "gcc" or "binutils".
+
+ Returns:
+ A triplet that consisits of whether operation succeeds or not,
+ tool ebuild file full path and tool ebuild file name.
+ """
+
+ # To get the active gcc ebuild file, we need a workable chroot first.
+ if not os.path.exists(
+ os.path.join(self._chromeos_root, 'chroot')) and self._ce.RunCommand(
+ 'cd "{0}" && cros_sdk --create'.format(self._chromeos_root)):
+ self._logger.LogError(('Failed to install a initial chroot, aborted.\n'
+ 'If previous bootstrap failed, do a '
+ '"cros_sdk --delete" to remove '
+ 'in-complete chroot.'))
+ return (False, None, None)
+
+ rv, stdout, _ = self._ce.ChrootRunCommandWOutput(
+ self._chromeos_root,
+ 'equery w sys-devel/{0}'.format(tool_name),
+ print_to_console=True)
+ if rv:
+ self._logger.LogError(
+ ('Failed to execute inside chroot '
+ '"equery w sys-devel/{0}", aborted.').format(tool_name))
+ return (False, None, None)
+ m = re.match(r'^.*/({0}/(.*\.ebuild))$'.format(
+ EBUILD_PATH_PATTERN.format(tool_name)), stdout)
+ if not m:
+ self._logger.LogError(
+ ('Failed to find {0} ebuild file, aborted. '
+ 'If previous bootstrap failed, do a "cros_sdk --delete" to remove '
+ 'in-complete chroot.').format(tool_name))
+ return (False, None, None)
+ tool_ebuild_file = os.path.join(self._chromeos_root, m.group(1))
+ tool_ebuild_file_name = m.group(2)
+
+ return (True, tool_ebuild_file, tool_ebuild_file_name)
+
+ def InplaceModifyEbuildFile(self):
+ """Modify the ebuild file.
+
+ Returns:
+ True if operation succeeds.
+ """
+
+ # Note we shall not use remote branch name (eg. "cros/gcc.gnu.org/...") in
+ # CROS_WORKON_COMMIT, we have to use GITHASH. So we call GitGetCommitHash on
+ # tool_branch.
+ tool = None
+ toolbranch = None
+ if self._gcc_branch:
+ tool = 'gcc'
+ toolbranch = self._gcc_branch
+ tooltree = self._gcc_branch_tree
+ toolebuild = self._gcc_ebuild_file
+ elif self._binutils_branch:
+ tool = 'binutils'
+ toolbranch = self._binutils_branch
+ tooltree = self._binutils_branch_tree
+ toolebuild = self._binutils_ebuild_file
+
+ assert tool
+
+ # An example for the following variables would be:
+ # tooldir = '~/android/master-ndk/toolchain/gcc/gcc-4.9'
+ # tool_branch_githash = xxxxx
+ # toolcomponents = toolchain/gcc
+ tooldir = self.GetChromeOsToolDir(tool)
+ toolgithash = misc.GitGetCommitHash(tooldir, toolbranch)
+ if not toolgithash:
+ return False
+ toolcomponents = 'toolchain/{}'.format(tool)
+ return self.InplaceModifyToolEbuildFile(toolcomponents, toolgithash,
+ tooltree, toolebuild)
+
+ @staticmethod
+ def ResetToolEbuildFile(chromeos_root, tool_name):
+ """Reset tool ebuild file to clean state.
+
+ Args:
+ chromeos_root: chromeos source tree
+ tool_name: either "gcc" or "binutils"
+
+ Returns:
+ True if operation succeds.
+ """
+ rv = misc.GetGitChangesAsList(
+ os.path.join(chromeos_root, CHROMIUMOS_OVERLAY_PATH),
+ path=('sys-devel/{0}/{0}-*.ebuild'.format(tool_name)),
+ staged=False)
+ if rv:
+ cmd = 'cd {0} && git checkout --'.format(
+ os.path.join(chromeos_root, CHROMIUMOS_OVERLAY_PATH))
+ for g in rv:
+ cmd += ' ' + g
+ rv = command_executer.GetCommandExecuter().RunCommand(cmd)
+ if rv:
+ logger.GetLogger().LogWarning(
+ 'Failed to reset the ebuild file. Please refer to log above.')
+ return False
+ else:
+ logger.GetLogger().LogWarning(
+ 'Note - did not find any modified {0} ebuild file.'.format(tool_name))
+ # Fall through
+ return True
+
+ def GetChromeOsToolDir(self, tool_name):
+ """Return the chromeos git dir for a specific tool.
+
+ Note, after we unified ChromeOs and Android, the tool dir is under
+ ndk_dir/toolchain/[gcc,binutils].
+
+ Args:
+ tool_name: either 'gcc' or 'binutils'.
+
+ Returns:
+ Absolute git path for the tool.
+ """
+
+ tool_toppath = os.path.join(self._ndk_dir, 'toolchain', tool_name)
+ # There may be sub-directories like 'binutils-2.25', 'binutils-2.24',
+ # 'gcc-4.9', 'gcc-4.8', etc. find the newest binutils version.
+ cmd = ('find {} -maxdepth 1 -type d -name "{}-*" '
+ '| sort -r | head -1').format(tool_toppath, tool_name)
+ rv, out, _ = self._ce.RunCommandWOutput(cmd, print_to_console=False)
+ if rv:
+ return None
+ repo = out.strip()
+
+ # cros-workon eclass expects every CROS_WORKON_PROJECT ends with ".git".
+ self._ce.RunCommand(('cd $(dirname {0}) && '
+ 'ln -sf $(basename {0}) $(basename {0}).git').format(
+ repo, print_to_console=True))
+ return repo
+
+ def InplaceModifyToolEbuildFile(self, tool_components, tool_branch_githash,
+ tool_branch_tree, tool_ebuild_file):
+ """Using sed to fill properly values into the ebuild file.
+
+ Args:
+ tool_components: either "toolchain/gcc" or "toolchain/binutils"
+ tool_branch_githash: githash for tool_branch
+ tool_branch_tree: treeish for the tool branch
+ tool_ebuild_file: tool ebuild file
+
+ Returns:
+ True: if operation succeeded.
+ """
+
+ command = ('sed -i '
+ '-e \'/^CROS_WORKON_REPO=".*"/i'
+ ' # The following line is modified by script.\' '
+ '-e \'s!^CROS_WORKON_REPO=".*"$!CROS_WORKON_REPO="{0}"!\' '
+ '-e \'/^CROS_WORKON_PROJECT=".*"/i'
+ ' # The following line is modified by script.\' '
+ '-e \'s!^CROS_WORKON_PROJECT=.*$!CROS_WORKON_PROJECT="{1}"!\' '
+ '-e \'/^CROS_WORKON_COMMIT=".*"/i'
+ ' # The following line is modified by script.\' '
+ '-e \'s!^CROS_WORKON_COMMIT=".*"$!CROS_WORKON_COMMIT="{2}"!\' '
+ '-e \'/^CROS_WORKON_TREE=".*"/i'
+ ' # The following line is modified by script.\' '
+ '-e \'s!^CROS_WORKON_TREE=".*"$!CROS_WORKON_TREE="{3}"!\' '
+ '{4}').format('/home/{}/ndk-root'.format(os.environ['USER']),
+ tool_components, tool_branch_githash,
+ tool_branch_tree, tool_ebuild_file)
+ rv = self._ce.RunCommand(command)
+ if rv:
+ self._logger.LogError(
+ 'Failed to modify commit and tree value for "{0}"", aborted.'.format(
+ tool_ebuild_file))
+ return False
+
+ # Warn that the ebuild file has been modified.
+ self._logger.LogWarning(
+ ('Ebuild file "{0}" is modified, to revert the file - \n'
+ 'bootstrap_compiler.py --chromeos_root={1} '
+ '--reset_tool_ebuild_file').format(tool_ebuild_file,
+ self._chromeos_root))
+ return True
+
+ def DoBuildForBoard(self):
+ """Build tool for a specific board.
+
+ Returns:
+ True if operation succeeds.
+ """
+
+ if self._gcc_branch:
+ if not self.DoBuildToolForBoard('gcc'):
+ return False
+ if self._binutils_branch:
+ if not self.DoBuildToolForBoard('binutils'):
+ return False
+ return True
+
+ def DoBuildToolForBoard(self, tool_name):
+ """Build a specific tool for a specific board.
+
+ Args:
+ tool_name: either "gcc" or "binutils"
+
+ Returns:
+ True if operation succeeds.
+ """
+
+ chroot_ndk_root = os.path.join(self._chromeos_root, 'chroot', 'home',
+ os.environ['USER'], 'ndk-root')
+ self._ce.RunCommand('mkdir -p {}'.format(chroot_ndk_root))
+ if self._ce.RunCommand(
+ 'sudo mount --bind {} {}'.format(self._ndk_dir, chroot_ndk_root)):
+ self._logger.LogError('Failed to mount ndk dir into chroot')
+ return False
+
+ try:
+ boards_to_build = self._board.split(',')
+ target_built = set()
+ failed = []
+ for board in boards_to_build:
+ if board == 'host':
+ command = 'sudo emerge sys-devel/{0}'.format(tool_name)
+ else:
+ target = misc.GetCtargetFromBoard(board, self._chromeos_root)
+ if not target:
+ self._logger.LogError(
+ 'Unsupported board "{0}", skip.'.format(board))
+ failed.append(board)
+ continue
+ # Skip this board if we have already built for a board that has the
+ # same target.
+ if target in target_built:
+ self._logger.LogWarning(
+ 'Skipping toolchain for board "{}"'.format(board))
+ continue
+ target_built.add(target)
+ command = 'sudo emerge cross-{0}/{1}'.format(target, tool_name)
+
+ rv = self._ce.ChrootRunCommand(
+ self._chromeos_root, command, print_to_console=True)
+ if rv:
+ self._logger.LogError(
+ 'Build {0} failed for {1}, aborted.'.format(tool_name, board))
+ failed.append(board)
+ else:
+ self._logger.LogOutput(
+ 'Successfully built {0} for board {1}.'.format(tool_name, board))
+ finally:
+ # Make sure we un-mount ndk-root before we leave here, regardless of the
+ # build result of the tool. Otherwise we may inadvertently delete ndk-root
+ # dir, which is not part of the chroot and could be disastrous.
+ if chroot_ndk_root:
+ if self._ce.RunCommand('sudo umount {}'.format(chroot_ndk_root)):
+ self._logger.LogWarning(
+ ('Failed to umount "{}", please check '
+ 'before deleting chroot.').format(chroot_ndk_root))
+
+ # Clean up soft links created during build.
+ self._ce.RunCommand('cd {}/toolchain/{} && git clean -df'.format(
+ self._ndk_dir, tool_name))
+
+ if failed:
+ self._logger.LogError(
+ 'Failed to build {0} for the following board(s): "{1}"'.format(
+ tool_name, ' '.join(failed)))
+ return False
+ # All boards build successfully
+ return True
+
+ def DoBootstrapping(self):
+ """Do bootstrapping the chroot.
+
+ This step firstly downloads a prestine sdk, then use this sdk to build the
+ new sdk, finally use the new sdk to build every host package.
+
+ Returns:
+ True if operation succeeds.
+ """
+
+ logfile = os.path.join(self._chromeos_root, 'bootstrap.log')
+ command = 'cd "{0}" && cros_sdk --delete --bootstrap |& tee "{1}"'.format(
+ self._chromeos_root, logfile)
+ rv = self._ce.RunCommand(command, print_to_console=True)
+ if rv:
+ self._logger.LogError(
+ 'Bootstrapping failed, log file - "{0}"\n'.format(logfile))
+ return False
+
+ self._logger.LogOutput('Bootstrap succeeded.')
+ return True
+
+ def BuildAndInstallAmd64Host(self):
+ """Build amd64-host (host) packages.
+
+ Build all host packages in the newly-bootstrapped 'chroot' using *NEW*
+ toolchain.
+
+ So actually we perform 2 builds of all host packages -
+ 1. build new toolchain using old toolchain and build all host packages
+ using the newly built toolchain
+ 2. build the new toolchain again but using new toolchain built in step 1,
+ and build all host packages using the newly built toolchain
+
+ Returns:
+ True if operation succeeds.
+ """
+
+ cmd = 'cd {0} && cros_sdk -- -- ./build_sdk_board'.format(
+ self._chromeos_root)
+ rv = self._ce.RunCommand(cmd, print_to_console=True)
+ if rv:
+ self._logger.LogError('Build amd64-host failed.')
+ return False
+
+ # Package amd64-host into 'built-sdk.tar.xz'.
+ sdk_package = os.path.join(self._chromeos_root, 'built-sdk.tar.xz')
+ cmd = ('cd {0}/chroot/build/amd64-host && sudo XZ_OPT="-e9" '
+ 'tar --exclude="usr/lib/debug/*" --exclude="packages/*" '
+ '--exclude="tmp/*" --exclude="usr/local/build/autotest/*" '
+ '--sparse -I xz -vcf {1} . && sudo chmod a+r {1}').format(
+ self._chromeos_root, sdk_package)
+ rv = self._ce.RunCommand(cmd, print_to_console=True)
+ if rv:
+ self._logger.LogError('Failed to create "built-sdk.tar.xz".')
+ return False
+
+ # Install amd64-host into a new chroot.
+ cmd = ('cd {0} && cros_sdk --chroot new-sdk-chroot --download --replace '
+ '--nousepkg --url file://{1}').format(self._chromeos_root,
+ sdk_package)
+ rv = self._ce.RunCommand(cmd, print_to_console=True)
+ if rv:
+ self._logger.LogError('Failed to install "built-sdk.tar.xz".')
+ return False
+ self._logger.LogOutput(
+ 'Successfully installed built-sdk.tar.xz into a new chroot.\nAll done.')
+
+ # Rename the newly created new-sdk-chroot to chroot.
+ cmd = ('cd {0} && sudo mv chroot chroot-old && '
+ 'sudo mv new-sdk-chroot chroot').format(self._chromeos_root)
+ rv = self._ce.RunCommand(cmd, print_to_console=True)
+ return rv == 0
+
+ def Do(self):
+ """Entrance of the class.
+
+ Returns:
+ True if everything is ok.
+ """
+
+ if (self.SubmitToLocalBranch() and self.CheckoutBranch() and
+ self.FindEbuildFile() and self.InplaceModifyEbuildFile()):
+ if self._setup_tool_ebuild_file_only:
+ # Everything is done, we are good.
+ ret = True
+ else:
+ if self._board:
+ ret = self.DoBuildForBoard()
+ else:
+ # This implies '--bootstrap'.
+ ret = (self.DoBootstrapping() and (self._disable_2nd_bootstrap or
+ self.BuildAndInstallAmd64Host()))
+ else:
+ ret = False
+ return ret
+
+
+def Main(argv):
+ parser = argparse.ArgumentParser()
+ parser.add_argument(
+ '-c',
+ '--chromeos_root',
+ dest='chromeos_root',
+ help=('Optional. ChromeOs root dir. '
+ 'When not specified, chromeos root will be deduced'
+ ' from current working directory.'))
+ parser.add_argument(
+ '--ndk_dir',
+ dest='ndk_dir',
+ help=('Topmost android ndk dir, required. '
+ 'Do not need to include the "toolchain/*" part.'))
+ parser.add_argument(
+ '--gcc_branch',
+ dest='gcc_branch',
+ help=('The branch to test against. '
+ 'This branch must be a local branch '
+ 'inside "src/third_party/gcc". '
+ 'Notice, this must not be used with "--gcc_dir".'))
+ parser.add_argument(
+ '--binutils_branch',
+ dest='binutils_branch',
+ help=('The branch to test against binutils. '
+ 'This branch must be a local branch '
+ 'inside "src/third_party/binutils". '
+ 'Notice, this must not be used with '
+ '"--binutils_dir".'))
+ parser.add_argument(
+ '-g',
+ '--gcc_dir',
+ dest='gcc_dir',
+ help=('Use a local gcc tree to do bootstrapping. '
+ 'Notice, this must not be used with '
+ '"--gcc_branch".'))
+ parser.add_argument(
+ '--binutils_dir',
+ dest='binutils_dir',
+ help=('Use a local binutils tree to do bootstrapping. '
+ 'Notice, this must not be used with '
+ '"--binutils_branch".'))
+ parser.add_argument(
+ '--fixperm',
+ dest='fixperm',
+ default=False,
+ action='store_true',
+ help=('Fix the (notorious) permission error '
+ 'while trying to bootstrap the chroot. '
+ 'Note this takes an extra 10-15 minutes '
+ 'and is only needed once per chromiumos tree.'))
+ parser.add_argument(
+ '--setup_tool_ebuild_file_only',
+ dest='setup_tool_ebuild_file_only',
+ default=False,
+ action='store_true',
+ help=('Setup gcc and/or binutils ebuild file '
+ 'to pick up the branch (--gcc/binutils_branch) or '
+ 'use gcc and/or binutils source '
+ '(--gcc/binutils_dir) and exit. Keep chroot as is.'
+ ' This should not be used with '
+ '--gcc/binutils_dir/branch options.'))
+ parser.add_argument(
+ '--reset_tool_ebuild_file',
+ dest='reset_tool_ebuild_file',
+ default=False,
+ action='store_true',
+ help=('Reset the modification that is done by this '
+ 'script. Note, when this script is running, it '
+ 'will modify the active gcc/binutils ebuild file. '
+ 'Use this option to reset (what this script has '
+ 'done) and exit. This should not be used with -- '
+ 'gcc/binutils_dir/branch options.'))
+ parser.add_argument(
+ '--board',
+ dest='board',
+ default=None,
+ help=('Only build toolchain for specific board(s). '
+ 'Use "host" to build for host. '
+ 'Use "," to seperate multiple boards. '
+ 'This does not perform a chroot bootstrap.'))
+ parser.add_argument(
+ '--bootstrap',
+ dest='bootstrap',
+ default=False,
+ action='store_true',
+ help=('Performs a chroot bootstrap. '
+ 'Note, this will *destroy* your current chroot.'))
+ parser.add_argument(
+ '--disable-2nd-bootstrap',
+ dest='disable_2nd_bootstrap',
+ default=False,
+ action='store_true',
+ help=('Disable a second bootstrap '
+ '(build of amd64-host stage).'))
+
+ options = parser.parse_args(argv)
+ # Trying to deduce chromeos root from current directory.
+ if not options.chromeos_root:
+ logger.GetLogger().LogOutput('Trying to deduce chromeos root ...')
+ wdir = os.getcwd()
+ while wdir and wdir != '/':
+ if misc.IsChromeOsTree(wdir):
+ logger.GetLogger().LogOutput('Find chromeos_root: {}'.format(wdir))
+ options.chromeos_root = wdir
+ break
+ wdir = os.path.dirname(wdir)
+
+ if not options.chromeos_root:
+ parser.error('Missing or failing to deduce mandatory option "--chromeos".')
+ return 1
+
+ options.chromeos_root = os.path.abspath(
+ os.path.expanduser(options.chromeos_root))
+
+ if not os.path.isdir(options.chromeos_root):
+ logger.GetLogger().LogError(
+ '"{0}" does not exist.'.format(options.chromeos_root))
+ return 1
+
+ options.ndk_dir = os.path.expanduser(options.ndk_dir)
+ if not options.ndk_dir:
+ parser.error('Missing mandatory option "--ndk_dir".')
+ return 1
+
+ # Some tolerance regarding user input. We only need the ndk_root part, do not
+ # include toolchain/(gcc|binutils)/ part in this option.
+ options.ndk_dir = re.sub('/toolchain(/gcc|/binutils)?/?$', '',
+ options.ndk_dir)
+
+ if not (os.path.isdir(options.ndk_dir) and
+ os.path.isdir(os.path.join(options.ndk_dir, 'toolchain'))):
+ logger.GetLogger().LogError(
+ '"toolchain" directory not found under "{0}".'.format(options.ndk_dir))
+ return 1
+
+ if options.fixperm:
+ # Fix perm error before continuing.
+ cmd = (r'sudo find "{0}" \( -name ".cache" -type d -prune \) -o '
+ r'\( -name "chroot" -type d -prune \) -o '
+ r'\( -type f -exec chmod a+r {{}} \; \) -o '
+ r'\( -type d -exec chmod a+rx {{}} \; \)'
+ ).format(options.chromeos_root)
+ logger.GetLogger().LogOutput(
+ 'Fixing perm issues for chromeos root, this might take some time.')
+ command_executer.GetCommandExecuter().RunCommand(cmd)
+
+ if options.reset_tool_ebuild_file:
+ if (options.gcc_dir or options.gcc_branch or options.binutils_dir or
+ options.binutils_branch):
+ logger.GetLogger().LogWarning(
+ 'Ignoring any "--gcc/binutils_dir" and/or "--gcc/binutils_branch".')
+ if options.setup_tool_ebuild_file_only:
+ logger.GetLogger().LogError(
+ ('Conflict options "--reset_tool_ebuild_file" '
+ 'and "--setup_tool_ebuild_file_only".'))
+ return 1
+ rv = Bootstrapper.ResetToolEbuildFile(options.chromeos_root, 'gcc')
+ rv1 = Bootstrapper.ResetToolEbuildFile(options.chromeos_root, 'binutils')
+ return 0 if (rv and rv1) else 1
+
+ if options.gcc_dir:
+ options.gcc_dir = os.path.abspath(os.path.expanduser(options.gcc_dir))
+ if not os.path.isdir(options.gcc_dir):
+ logger.GetLogger().LogError(
+ '"{0}" does not exist.'.format(options.gcc_dir))
+ return 1
+
+ if options.gcc_branch and options.gcc_dir:
+ parser.error('Only one of "--gcc_dir" and "--gcc_branch" can be specified.')
+ return 1
+
+ if options.binutils_dir:
+ options.binutils_dir = os.path.abspath(
+ os.path.expanduser(options.binutils_dir))
+ if not os.path.isdir(options.binutils_dir):
+ logger.GetLogger().LogError(
+ '"{0}" does not exist.'.format(options.binutils_dir))
+ return 1
+
+ if options.binutils_branch and options.binutils_dir:
+ parser.error('Only one of "--binutils_dir" and '
+ '"--binutils_branch" can be specified.')
+ return 1
+
+ if (not (options.binutils_branch or options.binutils_dir or
+ options.gcc_branch or options.gcc_dir)):
+ parser.error(('At least one of "--gcc_dir", "--gcc_branch", '
+ '"--binutils_dir" and "--binutils_branch" must '
+ 'be specified.'))
+ return 1
+
+ if not options.board and not options.bootstrap:
+ parser.error('You must specify either "--board" or "--bootstrap".')
+ return 1
+
+ if (options.board and options.bootstrap and
+ not options.setup_tool_ebuild_file_only):
+ parser.error('You must specify only one of "--board" and "--bootstrap".')
+ return 1
+
+ if not options.bootstrap and options.disable_2nd_bootstrap:
+ parser.error('"--disable-2nd-bootstrap" has no effect '
+ 'without specifying "--bootstrap".')
+ return 1
+
+ if Bootstrapper(
+ options.chromeos_root,
+ options.ndk_dir,
+ gcc_branch=options.gcc_branch,
+ gcc_dir=options.gcc_dir,
+ binutils_branch=options.binutils_branch,
+ binutils_dir=options.binutils_dir,
+ board=options.board,
+ disable_2nd_bootstrap=options.disable_2nd_bootstrap,
+ setup_tool_ebuild_file_only=options.setup_tool_ebuild_file_only).Do():
+ return 0
+ return 1
+
+
+if __name__ == '__main__':
+ retval = Main(sys.argv[1:])
+ sys.exit(retval)