blob: 22dc7d3158196f1dd61d5d94e67123bd009661ea [file] [log] [blame]
Han Shen91445322013-03-20 13:43:31 -07001#!/usr/bin/python
Han Shen819f8622014-04-08 16:57:38 -07002"""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 compiler
12## for the chromeos root. The script tries to find a valid chromeos tree all
13## 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 bootstrap
17## using the new binutils for the chromeos root. The script tries to find a
18## valid chromeos tree all the way up from your current working directory.
19./build_tool.py --binutils_branch=cros/mobile_toolchain_v17 \
20 --chromeos_root=/chromeos/dir --bootstrap
21
22## Same as above except only do it for board daisy - no bootstrapping involved.
23./build_tool.py --binutils_branch=cros/mobile_toolchain_v16 \
24 --chromeos_root=/chromeos/dir --board=daisy
25"""
Han Shen91445322013-03-20 13:43:31 -070026
27__author__ = 'shenhan@google.com (Han Shen)'
28
29import optparse
30import os
31import re
Han Shen91445322013-03-20 13:43:31 -070032import sys
33
Han Shen819f8622014-04-08 16:57:38 -070034import repo_to_repo
Han Shen91445322013-03-20 13:43:31 -070035from utils import command_executer
36from utils import logger
37from utils import misc
38
Han Shen819f8622014-04-08 16:57:38 -070039REPO_PATH_PATTERN = 'src/third_party/{0}'
40TEMP_BRANCH_NAME = 'internal_testing_branch_no_use'
41CHROMIUMOS_OVERLAY_PATH = 'src/third_party/chromiumos-overlay'
42EBUILD_PATH_PATTERN = 'src/third_party/chromiumos-overlay/sys-devel/{0}'
43
Han Shen91445322013-03-20 13:43:31 -070044
45class Bootstrapper(object):
Han Shen819f8622014-04-08 16:57:38 -070046 """Class that handles bootstrap process.
47 """
48
49 def __init__(self, chromeos_root, gcc_branch=None, gcc_dir=None,
50 binutils_branch=None, binutils_dir=None,
51 board=None, setup_tool_ebuild_file_only=False):
Han Shen91445322013-03-20 13:43:31 -070052 self._chromeos_root = chromeos_root
Han Shen819f8622014-04-08 16:57:38 -070053
54 self._gcc_branch = gcc_branch
55 self._gcc_branch_tree = None
Han Shen91445322013-03-20 13:43:31 -070056 self._gcc_dir = gcc_dir
Han Shen91445322013-03-20 13:43:31 -070057 self._gcc_ebuild_file = None
58 self._gcc_ebuild_file_name = None
Han Shen819f8622014-04-08 16:57:38 -070059
60 self._binutils_branch = binutils_branch
61 self._binutils_branch_tree = None
62 self._binutils_dir = binutils_dir
63 self._binutils_ebuild_file = None
64 self._binutils_ebuild_file_name = None
65
66 self._setup_tool_ebuild_file_only = setup_tool_ebuild_file_only
67
68 self._ce = command_executer.GetCommandExecuter()
69 self._logger = logger.GetLogger()
70 self._board = board
71
72 def IsTreeSame(self, t1, t2):
73 diff = 'diff -qr -x .git -x .svn "{0}" "{1}"'.format(t1, t2)
74 if self._ce.RunCommand(diff, print_to_console=False) == 0:
75 self._logger.LogOutput('"{0}" and "{1}" are the same."'.format(t1, t2))
76 return True
77 self._logger.LogWarning('"{0}" and "{1}" are different."'.format(t1, t2))
78 return False
Han Shen91445322013-03-20 13:43:31 -070079
80 def SubmitToLocalBranch(self):
Han Shen819f8622014-04-08 16:57:38 -070081 """Copy source code to the chromium source tree and submit it locally."""
82 if self._gcc_dir:
83 if not self.SubmitToolToLocalBranch(
84 tool_name='gcc', tool_dir=self._gcc_dir):
85 return False
86 self._gcc_branch = TEMP_BRANCH_NAME
Han Shen91445322013-03-20 13:43:31 -070087
Han Shen819f8622014-04-08 16:57:38 -070088 if self._binutils_dir:
89 if not self.SubmitToolToLocalBranch(
90 tool_name='binutils', tool_dir=self._binutils_dir):
91 return False
92 self._binutils_branch = TEMP_BRANCH_NAME
93
94 return True
95
96 def SubmitToolToLocalBranch(self, tool_name, tool_dir):
97 """Copy the source code to local chromium source tree.
98
99 Args:
100 tool_name: either 'gcc' or 'binutils'
101 tool_dir: the tool source dir to be used
102 Returns:
103 True if all succeeded False otherwise.
104 """
105
106 # The next few steps creates an internal branch to sync with the tool dir
Han Shen91445322013-03-20 13:43:31 -0700107 # user provided.
Han Shen819f8622014-04-08 16:57:38 -0700108 chrome_tool_dir = self.GetChromeOsToolDir(tool_name)
Han Shen91445322013-03-20 13:43:31 -0700109
110 # 0. Test to see if git tree is free of local changes.
Han Shen819f8622014-04-08 16:57:38 -0700111 if not misc.IsGitTreeClean(chrome_tool_dir):
Han Shen91445322013-03-20 13:43:31 -0700112 self._logger.LogError(
Han Shen819f8622014-04-08 16:57:38 -0700113 'Git repository "{0}" not clean, aborted.'.format(chrome_tool_dir))
Han Shen91445322013-03-20 13:43:31 -0700114 return False
115
116 # 1. Checkout/create a (new) branch for testing.
Han Shen819f8622014-04-08 16:57:38 -0700117 command = 'cd "{0}" && git checkout -B {1}'.format(
118 chrome_tool_dir, TEMP_BRANCH_NAME)
Han Shen91445322013-03-20 13:43:31 -0700119 ret = self._ce.RunCommand(command)
120 if ret:
121 self._logger.LogError('Failed to create a temp branch for test, aborted.')
122 return False
123
Han Shen819f8622014-04-08 16:57:38 -0700124 if self.IsTreeSame(tool_dir, chrome_tool_dir):
125 self._logger.LogOutput(
126 '"{0}" and "{1}" are the same, sync skipped.'.format(
127 tool_dir, chrome_tool_dir))
128 return True
Han Shen91445322013-03-20 13:43:31 -0700129
Han Shen819f8622014-04-08 16:57:38 -0700130 # 2. Sync sources from user provided tool dir to chromiumos tool git.
131 local_tool_repo = repo_to_repo.FileRepo(tool_dir)
132 chrome_tool_repo = repo_to_repo.GitRepo(chrome_tool_dir, TEMP_BRANCH_NAME)
133 chrome_tool_repo._root_dir = chrome_tool_dir
134 # Delete all stuff before start mapping.
135 self._ce.RunCommand('cd {0} && rm -rf *'.format(chrome_tool_dir))
136 local_tool_repo.MapSources(chrome_tool_repo.GetRoot())
137
138 # 3. Ensure after sync tree is the same.
139 if self.IsTreeSame(tool_dir, chrome_tool_dir):
Han Shen91445322013-03-20 13:43:31 -0700140 self._logger.LogOutput('Sync successfully done.')
Han Shen819f8622014-04-08 16:57:38 -0700141 else:
142 self._logger.LogError('Sync not successful, aborted.')
143 return False
Han Shen91445322013-03-20 13:43:31 -0700144
145 # 4. Commit all changes.
Han Shen819f8622014-04-08 16:57:38 -0700146 ret = chrome_tool_repo.CommitLocally(
147 'Synced with tool source tree at - "{0}".'.format(tool_dir))
Han Shen91445322013-03-20 13:43:31 -0700148 if ret:
149 self._logger.LogError('Commit to local branch "{0}" failed, aborted.'.
Han Shen819f8622014-04-08 16:57:38 -0700150 format(TEMP_BRANCH_NAME))
Han Shen91445322013-03-20 13:43:31 -0700151 return False
152 return True
153
154 def CheckoutBranch(self):
Han Shen819f8622014-04-08 16:57:38 -0700155 """Checkout working branch for the tools.
Han Shen91445322013-03-20 13:43:31 -0700156
Han Shen819f8622014-04-08 16:57:38 -0700157 Returns:
158 True: if operation succeeds.
159 """
Han Shen91445322013-03-20 13:43:31 -0700160
Han Shen819f8622014-04-08 16:57:38 -0700161 if self._gcc_branch:
162 rv = self.CheckoutToolBranch('gcc', self._gcc_branch)
163 if rv:
164 self._gcc_branch_tree = rv
165 else:
166 return False
167
168 if self._binutils_branch:
169 rv = self.CheckoutToolBranch('binutils', self._binutils_branch)
170 if rv:
171 self._binutils_branch_tree = rv
172 else:
173 return False
174
Han Shen91445322013-03-20 13:43:31 -0700175 return True
176
Han Shen819f8622014-04-08 16:57:38 -0700177 def CheckoutToolBranch(self, tool_name, tool_branch):
178 """Checkout the tool branch for a certain tool.
179
180 Args:
181 tool_name: either 'gcc' or 'binutils'
182 tool_branch: tool branch to use
183 Returns:
184 True: if operation succeeds. Otherwise False.
Han Shen91445322013-03-20 13:43:31 -0700185 """
Han Shen819f8622014-04-08 16:57:38 -0700186
187 chrome_tool_dir = self.GetChromeOsToolDir(tool_name)
188 command = 'cd "{0}" && git checkout {1}'.format(
189 chrome_tool_dir, tool_branch)
190 if not self._ce.RunCommand(command, print_to_console=True):
191 # Get 'TREE' value of this commit
192 command = ('cd "{0}" && git cat-file -p {1} '
193 '| grep -E "^tree [a-f0-9]+$" '
194 '| cut -d" " -f2').format(chrome_tool_dir, tool_branch)
195 ret, stdout, _ = self._ce.RunCommand(
196 command, return_output=True, print_to_console=False)
197 # Pipe operation always has a zero return value. So need to check if
198 # stdout is valid.
199 if not ret and stdout and re.match(
200 '[0-9a-h]{40}', stdout.strip(), re.IGNORECASE):
201 tool_branch_tree = stdout.strip()
202 self._logger.LogOutput('Find tree for {0} branch "{1}" - "{2}"'.format(
203 tool_name, tool_branch, tool_branch_tree))
204 return tool_branch_tree
205 self._logger.LogError(('Failed to checkout "{0}" or failed to '
206 'get tree value, aborted.').format(tool_branch))
207 return None
208
209 def FindEbuildFile(self):
210 """Find the ebuild files for the tools.
211
212 Returns:
213 True: if operation succeeds.
214 """
215
216 if self._gcc_branch:
217 (rv, ef, efn) = self.FindToolEbuildFile('gcc')
218 if rv:
219 self._gcc_ebuild_file = ef
220 self._gcc_ebuild_file_name = efn
221 else:
222 return False
223
224 if self._binutils_branch:
225 (rv, ef, efn) = self.FindToolEbuildFile('binutils')
226 if rv:
227 self._binutils_ebuild_file = ef
228 self._binutils_ebuild_file_name = efn
229 else:
230 return False
231
232 return True
233
234 def FindToolEbuildFile(self, tool_name):
235 """Find ebuild file for a specific tool.
236
237 Args:
238 tool_name: either "gcc" or "binutils".
239 Returns:
240 A triplet that consisits of whether operation succeeds or not,
241 tool ebuild file full path and tool ebuild file name.
242 """
243
244 # To get the active gcc ebuild file, we need a workable chroot first.
245 if not os.path.exists(
246 os.path.join(self._chromeos_root, 'chroot')) and self._ce.RunCommand(
247 'cd "{0}" && cros_sdk --create'.format(self._chromeos_root)):
248 self._logger.LogError(('Failed to install a initial chroot, aborted.\n'
249 'If previous bootstrap failed, do a '
250 '"cros_sdk --delete" to remove '
251 'in-complete chroot.'))
252 return (False, None, None)
253
254 rv, stdout, _ = self._ce.ChrootRunCommand(
255 self._chromeos_root, 'equery w sys-devel/{0}'.format(tool_name),
256 return_output=True, print_to_console=True)
257 if rv:
258 self._logger.LogError(
259 ('Failed to execute inside chroot '
260 '"equery w sys-devel/{0}", aborted.').format(tool_name))
261 return (False, None, None)
262 m = re.match(r'^.*/({0}/(.*\.ebuild))$'.format(
263 EBUILD_PATH_PATTERN.format(tool_name)), stdout)
264 if not m:
265 self._logger.LogError(
266 ('Failed to find {0} ebuild file, aborted. '
267 'If previous bootstrap failed, do a "cros_sdk --delete" to remove '
268 'in-complete chroot.').format(tool_name))
269 return (False, None, None)
270 tool_ebuild_file = os.path.join(self._chromeos_root, m.group(1))
271 tool_ebuild_file_name = m.group(2)
272
273 return (True, tool_ebuild_file, tool_ebuild_file_name)
274
275 def InplaceModifyEbuildFile(self):
276 """Modify the ebuild file.
277
278 Returns:
279 True if operation succeeds.
280 """
281
282 # Note we shall not use remote branch name (eg. "cros/gcc.gnu.org/...") in
283 # CROS_WORKON_COMMIT, we have to use GITHASH. So we call GitGetCommitHash on
284 # tool_branch.
285 if self._gcc_branch:
286 tool_branch_githash = misc.GitGetCommitHash(
287 self.GetChromeOsToolDir('gcc'), self._gcc_branch)
288 if not tool_branch_githash:
289 return False
290 if not self.InplaceModifyToolEbuildFile(
291 tool_branch_githash, self._gcc_branch_tree, self._gcc_ebuild_file):
292 return False
293
294 if self._binutils_branch:
295 tool_branch_githash = misc.GitGetCommitHash(
296 self.GetChromeOsToolDir('binutils'), self._binutils_branch)
297 if not self.InplaceModifyToolEbuildFile(
298 tool_branch_githash, self._binutils_branch_tree,
299 self._binutils_ebuild_file):
300 return False
301 return True
302
303 @staticmethod
304 def ResetToolEbuildFile(chromeos_root, tool_name):
305 """Reset tool ebuild file to clean state.
306
307 Args:
308 chromeos_root: chromeos source tree
309 tool_name: either "gcc" or "binutils"
310 Returns:
311 True if operation succeds.
312 """
313 rv = misc.GetGitChangesAsList(
314 os.path.join(chromeos_root, CHROMIUMOS_OVERLAY_PATH),
315 path=('sys-devel/{0}/{0}-*.ebuild'.format(tool_name)),
316 staged=False)
317 if rv:
318 cmd = 'cd {0} && git checkout --'.format(os.path.join(
319 chromeos_root, CHROMIUMOS_OVERLAY_PATH))
320 for g in rv:
321 cmd += ' ' + g
322 rv = command_executer.GetCommandExecuter().RunCommand(cmd)
323 if rv:
324 logger.GetLogger().LogWarning(
325 'Failed to reset the ebuild file. Please refer to log above.')
326 return False
327 else:
328 logger.GetLogger().LogWarning(
329 'Note - did not find any modified {0} ebuild file.'.format(tool_name))
330 # Fall through
331 return True
332
333 def GetChromeOsToolDir(self, tool_name):
334 """Return the chromeos git dir for a specific tool.
335
336 Args:
337 tool_name: either 'gcc' or 'binutils'.
338 Returns:
339 Absolute git path for the tool.
340 """
341
342 return os.path.join(
343 self._chromeos_root, REPO_PATH_PATTERN.format(tool_name))
344
345 def InplaceModifyToolEbuildFile(
346 self, tool_branch_githash, tool_branch_tree, tool_ebuild_file):
347 """Using sed to fill properly values into the ebuild file.
348
349 Args:
350 tool_branch_githash: githash for tool_branch
351 tool_branch_tree: treeish for the tool branch
352 tool_ebuild_file: tool ebuild file
353 Returns:
354 True: if operation succeeded.
355 """
356
357 command = ('sed -i '
358 '-e \'/^CROS_WORKON_COMMIT=".*"/i'
359 ' # The following line is modified by script.\' '
360 '-e \'s!^CROS_WORKON_COMMIT=".*"$!CROS_WORKON_COMMIT="{0}"!\' '
361 '-e \'/^CROS_WORKON_TREE=".*"/i'
362 ' # The following line is modified by script.\' '
363 '-e \'s!^CROS_WORKON_TREE=".*"$!CROS_WORKON_TREE="{1}"!\' '
364 '{2}').format(tool_branch_githash,
365 tool_branch_tree,
366 tool_ebuild_file)
Han Shen91445322013-03-20 13:43:31 -0700367 rv = self._ce.RunCommand(command)
368 if rv:
369 self._logger.LogError(
Han Shen819f8622014-04-08 16:57:38 -0700370 'Failed to modify commit and tree value for "{0}"", aborted.'.format(
371 tool_ebuild_file))
372 return False
373
374 # Warn that the ebuild file has been modified.
375 self._logger.LogWarning(
376 ('Ebuild file "{0}" is modified, to revert the file - \n'
377 'bootstrap_compiler.py --chromeos_root={1} '
378 '--reset_tool_ebuild_file').format(
379 tool_ebuild_file, self._chromeos_root))
380 return True
381
382 def DoBuildForBoard(self):
383 """Build tool for a specific board.
384
385 Returns:
386 True if operation succeeds.
387 """
388
389 if self._gcc_branch:
390 if not self.DoBuildToolForBoard('gcc'):
391 return False
392 if self._binutils_branch:
393 if not self.DoBuildToolForBoard('binutils'):
394 return False
395 return True
396
397 def DoBuildToolForBoard(self, tool_name):
398 """Build a specific tool for a specific board.
399
400 Args:
401 tool_name: either "gcc" or "binutils"
402 Returns:
403 True if operation succeeds.
404 """
405
406 if self._board == 'host':
407 command = 'sudo emerge sys-devel/{0}'.format(tool_name)
408 else:
409 target = misc.GetCtargetFromBoard(self._board, self._chromeos_root)
410 if not target:
411 self._logger.LogError('Unsupported board "{0}", aborted.'.format(
412 self._board))
413 return False
414 command = 'sudo emerge cross-{0}/{1}'.format(target, tool_name)
415
416 rv = self._ce.ChrootRunCommand(
417 self._chromeos_root,
418 command, return_output=False,
419 print_to_console=True)
420 if rv:
421 self._logger.LogError(
422 'Build {0} failed for "{1}", aborted.'.format(tool_name, self._board))
Han Shen91445322013-03-20 13:43:31 -0700423 return False
424 return True
425
426 def DoBootstrapping(self):
Han Shen819f8622014-04-08 16:57:38 -0700427 """Do bootstrapping the chroot.
428
429 Returns:
430 True if operation succeeds.
431 """
432
Han Shen91445322013-03-20 13:43:31 -0700433 logfile = os.path.join(self._chromeos_root, 'bootstrap.log')
Han Shen819f8622014-04-08 16:57:38 -0700434 command = 'cd "{0}" && cros_sdk --delete --bootstrap |& tee "{1}"'.format(
435 self._chromeos_root, logfile)
436 rv = self._ce.RunCommand(command, return_output=False,
437 print_to_console=True)
Han Shen91445322013-03-20 13:43:31 -0700438 if rv:
439 self._logger.LogError('Bootstrapping failed, log file - "{0}"\n'.format(
440 logfile))
441 return False
442
Han Shen819f8622014-04-08 16:57:38 -0700443 ## Workaround for - crbug/331713.
444 ## We do not test for success, failure is not important at this step.
445 self._ce.ChrootRunCommand(
446 self._chromeos_root, 'sudo emerge dev-util/pkgconfig',
447 return_output=False, print_to_console=True)
448
Han Shen91445322013-03-20 13:43:31 -0700449 self._logger.LogOutput('Bootstrap succeeded.')
450 return True
451
452 def Do(self):
Han Shen819f8622014-04-08 16:57:38 -0700453 """Entrance of the class.
454
455 Returns:
456 True if everything is ok.
457 """
458
459 if (self.SubmitToLocalBranch() and
460 self.CheckoutBranch() and
461 self.FindEbuildFile() and
462 self.InplaceModifyEbuildFile()):
463 if self._setup_tool_ebuild_file_only:
464 # Everything is done, we are good.
465 ret = True
466 else:
467 if self._board:
468 ret = self.DoBuildForBoard()
469 else:
470 # This implies '--bootstrap'.
471 ret = self.DoBootstrapping()
Han Shen91445322013-03-20 13:43:31 -0700472 else:
473 ret = False
Han Shen91445322013-03-20 13:43:31 -0700474 return ret
475
476
477def Main(argv):
478 parser = optparse.OptionParser()
479 parser.add_option('-c', '--chromeos_root', dest='chromeos_root',
Han Shen819f8622014-04-08 16:57:38 -0700480 help=('Optional. ChromeOs root dir. '
481 'When not specified, chromeos root will be deduced '
482 'from current working directory.'))
483 parser.add_option('--gcc_branch', dest='gcc_branch',
Han Shen91445322013-03-20 13:43:31 -0700484 help=('The branch to test against. '
485 'This branch must be a local branch '
486 'inside "src/third_party/gcc". '
Han Shen819f8622014-04-08 16:57:38 -0700487 'Notice, this must not be used with "--gcc_dir".'))
488 parser.add_option('--binutils_branch', dest='binutils_branch',
489 help=('The branch to test against binutils. '
490 'This branch must be a local branch '
491 'inside "src/third_party/binutils". '
492 'Notice, this must not be used with '
493 '"--binutils_dir".'))
Han Shen91445322013-03-20 13:43:31 -0700494 parser.add_option('-g', '--gcc_dir', dest='gcc_dir',
495 help=('Use a local gcc tree to do bootstrapping. '
Han Shen819f8622014-04-08 16:57:38 -0700496 'Notice, this must not be used with "--gcc_branch".'))
497 parser.add_option('--binutils_dir', dest='binutils_dir',
498 help=('Use a local binutils tree to do bootstrapping. '
499 'Notice, this must not be used with '
500 '"--binutils_branch".'))
Han Shen91445322013-03-20 13:43:31 -0700501 parser.add_option('--fixperm', dest='fixperm',
502 default=False, action='store_true',
503 help=('Fix the (notorious) permission error '
504 'while trying to bootstrap the chroot. '
505 'Note this takes an extra 10-15 minutes '
506 'and is only needed once per chromiumos tree.'))
Han Shen819f8622014-04-08 16:57:38 -0700507 parser.add_option('--setup_tool_ebuild_file_only',
508 dest='setup_tool_ebuild_file_only',
Han Shen91445322013-03-20 13:43:31 -0700509 default=False, action='store_true',
Han Shen819f8622014-04-08 16:57:38 -0700510 help=('Setup gcc and/or binutils ebuild file '
511 'to pick up the branch (--gcc/binutils_branch) or '
512 'use gcc and/or binutils source (--gcc/binutils_dir) '
513 'and exit. Keep chroot as is. This should not be '
514 'used with --gcc/binutils_dir/branch options.'))
515 parser.add_option('--reset_tool_ebuild_file', dest='reset_tool_ebuild_file',
Han Shen91445322013-03-20 13:43:31 -0700516 default=False, action='store_true',
517 help=('Reset the modification that is done by this script.'
518 'Note, when this script is running, it will modify '
Han Shen819f8622014-04-08 16:57:38 -0700519 'the active gcc/binutils ebuild file. Use this '
520 'option to reset (what this script has done) '
521 'and exit. This should not be used with -- '
522 'gcc/binutils_dir/branch options.'))
523 parser.add_option('--board', dest='board', default=None,
524 help=('Only build toolchain for a specific board. '
525 'Use "host" to build for host. '
526 'This does not perform a chroot bootstrap.'))
527 parser.add_option('--bootstrap', dest='bootstrap',
528 default=False, action='store_true',
529 help=('Performs a chroot bootstrap. '
530 'Note, this will *destroy* your current chroot.'))
531
Han Shen91445322013-03-20 13:43:31 -0700532 options = parser.parse_args(argv)[0]
Han Shen819f8622014-04-08 16:57:38 -0700533 # Trying to deduce chromeos root from current directory.
Han Shen91445322013-03-20 13:43:31 -0700534 if not options.chromeos_root:
Han Shen819f8622014-04-08 16:57:38 -0700535 logger.GetLogger().LogOutput('Trying to deduce chromeos root ...')
536 wdir = os.getcwd()
537 while wdir and wdir != '/':
538 if misc.IsChromeOsTree(wdir):
539 logger.GetLogger().LogOutput('Find chromeos_root: {}'.format(wdir))
540 options.chromeos_root = wdir
541 break
542 wdir = os.path.dirname(wdir)
543
544 if not options.chromeos_root:
545 parser.error('Missing or failing to deduce mandatory option "--chromeos".')
Han Shen91445322013-03-20 13:43:31 -0700546 return 1
547
548 options.chromeos_root = os.path.abspath(
Han Shen819f8622014-04-08 16:57:38 -0700549 os.path.expanduser(options.chromeos_root))
Han Shen91445322013-03-20 13:43:31 -0700550
551 if not os.path.isdir(options.chromeos_root):
552 logger.GetLogger().LogError(
Han Shen819f8622014-04-08 16:57:38 -0700553 '"{0}" does not exist.'.format(options.chromeos_root))
Han Shen91445322013-03-20 13:43:31 -0700554 return 1
555
556 if options.fixperm:
557 # Fix perm error before continuing.
Han Shen819f8622014-04-08 16:57:38 -0700558 cmd = (r'sudo find "{0}" \( -name ".cache" -type d -prune \) -o '
559 r'\( -name "chroot" -type d -prune \) -o '
560 r'\( -type f -exec chmod a+r {{}} \; \) -o '
561 r'\( -type d -exec chmod a+rx {{}} \; \)').format(
562 options.chromeos_root)
Han Shen91445322013-03-20 13:43:31 -0700563 logger.GetLogger().LogOutput(
Han Shen819f8622014-04-08 16:57:38 -0700564 'Fixing perm issues for chromeos root, this might take some time.')
Han Shen91445322013-03-20 13:43:31 -0700565 command_executer.GetCommandExecuter().RunCommand(cmd)
566
Han Shen819f8622014-04-08 16:57:38 -0700567 if options.reset_tool_ebuild_file:
568 if (options.gcc_dir or options.gcc_branch or
569 options.binutils_dir or options.binutils_branch):
Han Shen91445322013-03-20 13:43:31 -0700570 logger.GetLogger().LogWarning(
Han Shen819f8622014-04-08 16:57:38 -0700571 'Ignoring any "--gcc/binutils_dir" and/or "--gcc/binutils_branch".')
572 if options.setup_tool_ebuild_file_only:
573 logger.GetLogger().LogError(
574 ('Conflict options "--reset_tool_ebuild_file" '
575 'and "--setup_tool_ebuild_file_only".'))
Han Shen91445322013-03-20 13:43:31 -0700576 return 1
Han Shen819f8622014-04-08 16:57:38 -0700577 rv = Bootstrapper.ResetToolEbuildFile(options.chromeos_root, 'gcc')
578 rv1 = Bootstrapper.ResetToolEbuildFile(options.chromeos_root, 'binutils')
579 return 0 if (rv and rv1) else 1
Han Shen91445322013-03-20 13:43:31 -0700580
581 if options.gcc_dir:
582 options.gcc_dir = os.path.abspath(os.path.expanduser(options.gcc_dir))
583 if not os.path.isdir(options.gcc_dir):
584 logger.GetLogger().LogError(
Han Shen819f8622014-04-08 16:57:38 -0700585 '"{0}" does not exist.'.format(options.gcc_dir))
Han Shen91445322013-03-20 13:43:31 -0700586 return 1
587
Han Shen819f8622014-04-08 16:57:38 -0700588 if options.gcc_branch and options.gcc_dir:
589 parser.error('Only one of "--gcc_dir" and "--gcc_branch" can be specified.')
Han Shen91445322013-03-20 13:43:31 -0700590 return 1
Han Shen819f8622014-04-08 16:57:38 -0700591
592 if options.binutils_dir:
593 options.binutils_dir = os.path.abspath(
594 os.path.expanduser(options.binutils_dir))
595 if not os.path.isdir(options.binutils_dir):
596 logger.GetLogger().LogError(
597 '"{0}" does not exist.'.format(options.binutils_dir))
598 return 1
599
600 if options.binutils_branch and options.binutils_dir:
601 parser.error('Only one of "--binutils_dir" and '
602 '"--binutils_branch" can be specified.')
603 return 1
604
605 if (not (options.binutils_branch or options.binutils_dir or
606 options.gcc_branch or options.gcc_dir)):
607 parser.error(('At least one of "--gcc_dir", "--gcc_branch", '
608 '"--binutils_dir" and "--binutils_branch" must '
609 'be specified.'))
610 return 1
611
612 if not options.board and not options.bootstrap:
613 parser.error('You must specify either "--board" or "--bootstrap".')
614 return 1
615
616 if options.board and options.bootstrap:
617 parser.error('You must specify only one of "--board" and "--bootstrap".')
Han Shen91445322013-03-20 13:43:31 -0700618 return 1
619
620 if Bootstrapper(
Han Shen819f8622014-04-08 16:57:38 -0700621 options.chromeos_root,
622 gcc_branch=options.gcc_branch, gcc_dir=options.gcc_dir,
623 binutils_branch=options.binutils_branch,
624 binutils_dir=options.binutils_dir,
625 board=options.board,
626 setup_tool_ebuild_file_only=options.setup_tool_ebuild_file_only).Do():
Han Shen91445322013-03-20 13:43:31 -0700627 return 0
628 return 1
629
630
631if __name__ == '__main__':
632 retval = Main(sys.argv)
633 sys.exit(retval)