build_chrome_browser.py revision 88272d479f2761cc1906fea564c73033f77a6270
1#!/usr/bin/python2
2#
3# Copyright 2010 Google Inc. All Rights Reserved.
4"""Script to checkout the ChromeOS source.
5
6This script sets up the ChromeOS source in the given directory, matching a
7particular release of ChromeOS.
8"""
9
10from __future__ import print_function
11
12__author__ = 'raymes@google.com (Raymes Khoury)'
13
14import argparse
15import os
16import sys
17
18from cros_utils import command_executer
19from cros_utils import logger
20from cros_utils import misc
21
22
23def Usage(parser, message):
24  print('ERROR: %s' % message)
25  parser.print_help()
26  sys.exit(0)
27
28
29def Main(argv):
30  """Build Chrome browser."""
31
32  cmd_executer = command_executer.GetCommandExecuter()
33
34  parser = argparse.ArgumentParser()
35  parser.add_argument('--chromeos_root',
36                      dest='chromeos_root',
37                      help='Target directory for ChromeOS installation.')
38  parser.add_argument('--version', dest='version')
39  parser.add_argument('--clean',
40                      dest='clean',
41                      default=False,
42                      action='store_true',
43                      help=('Clean the /var/cache/chromeos-chrome/'
44                            'chrome-src/src/out_$board dir'))
45  parser.add_argument('--env',
46                      dest='env',
47                      default='',
48                      help='Use the following env')
49  parser.add_argument('--ebuild_version',
50                      dest='ebuild_version',
51                      help='Use this ebuild instead of the default one.')
52  parser.add_argument('--cflags',
53                      dest='cflags',
54                      default='',
55                      help='CFLAGS for the ChromeOS packages')
56  parser.add_argument('--cxxflags',
57                      dest='cxxflags',
58                      default='',
59                      help='CXXFLAGS for the ChromeOS packages')
60  parser.add_argument('--ldflags',
61                      dest='ldflags',
62                      default='',
63                      help='LDFLAGS for the ChromeOS packages')
64  parser.add_argument('--board',
65                      dest='board',
66                      help='ChromeOS target board, e.g. x86-generic')
67  parser.add_argument('--no_build_image',
68                      dest='no_build_image',
69                      default=False,
70                      action='store_true',
71                      help=('Skip build image after building browser.'
72                            'Defaults to False.'))
73  parser.add_argument('--label',
74                      dest='label',
75                      help='Optional label to apply to the ChromeOS image.')
76  parser.add_argument('--build_image_args',
77                      default='',
78                      dest='build_image_args',
79                      help='Optional arguments to build_image.')
80  parser.add_argument('--cros_workon',
81                      dest='cros_workon',
82                      help='Build using external source tree.')
83  parser.add_argument('--dev',
84                      dest='dev',
85                      default=False,
86                      action='store_true',
87                      help=('Build a dev (eg. writable/large) image. '
88                            'Defaults to False.'))
89  parser.add_argument('--debug',
90                      dest='debug',
91                      default=False,
92                      action='store_true',
93                      help=('Build chrome browser using debug mode. '
94                            'This option implies --dev. Defaults to false.'))
95  parser.add_argument('--verbose',
96                      dest='verbose',
97                      default=False,
98                      action='store_true',
99                      help='Build with verbose information.')
100
101  options = parser.parse_args(argv)
102
103  if options.chromeos_root is None:
104    Usage(parser, '--chromeos_root must be set')
105
106  if options.board is None:
107    Usage(parser, '--board must be set')
108
109  if options.version is None:
110    logger.GetLogger().LogOutput('No Chrome version given so '
111                                 'using the default checked in version.')
112    chrome_version = ''
113  else:
114    chrome_version = 'CHROME_VERSION=%s' % options.version
115
116  if options.dev and options.no_build_image:
117    logger.GetLogger().LogOutput(
118        "\"--dev\" is meaningless if \"--no_build_image\" is given.")
119
120  if options.debug:
121    options.dev = True
122
123  options.chromeos_root = misc.CanonicalizePath(options.chromeos_root)
124
125  unmask_env = 'ACCEPT_KEYWORDS=~*'
126  if options.ebuild_version:
127    ebuild_version = '=%s' % options.ebuild_version
128    options.env = '%s %s' % (options.env, unmask_env)
129  else:
130    ebuild_version = 'chromeos-chrome'
131
132  if options.cros_workon and not (
133      os.path.isdir(options.cros_workon) and os.path.exists(os.path.join(
134          options.cros_workon, 'src/chromeos/chromeos.gyp'))):
135    Usage(parser, '--cros_workon must be a valid chromium browser checkout.')
136
137  if options.verbose:
138    options.env = misc.MergeEnvStringWithDict(
139        options.env, {'USE': 'chrome_internal verbose'})
140  else:
141    options.env = misc.MergeEnvStringWithDict(options.env,
142                                              {'USE': 'chrome_internal'})
143  if options.debug:
144    options.env = misc.MergeEnvStringWithDict(options.env,
145                                              {'BUILDTYPE': 'Debug'})
146
147  if options.clean:
148    misc.RemoveChromeBrowserObjectFiles(options.chromeos_root, options.board)
149
150  chrome_origin = 'SERVER_SOURCE'
151  if options.cros_workon:
152    chrome_origin = 'LOCAL_SOURCE'
153    command = 'cros_workon --board={0} start chromeos-chrome'.format(
154        options.board)
155    ret = cmd_executer.ChrootRunCommandWOutput(options.chromeos_root, command)
156
157    # cros_workon start returns non-zero if chromeos-chrome is already a
158    # cros_workon package.
159    if ret[0] and ret[2].find(
160        'WARNING : Already working on chromeos-base/chromeos-chrome') == -1:
161      logger.GetLogger().LogFatal('cros_workon chromeos-chrome failed.')
162
163    # Return value is non-zero means we do find the "Already working on..."
164    # message, keep the information, so later on we do not revert the
165    # cros_workon status.
166    cros_workon_keep = (ret[0] != 0)
167
168  # Emerge the browser
169  emerge_browser_command = ('CHROME_ORIGIN={0} {1} '
170                            'CFLAGS="$(portageq-{2} envvar CFLAGS) {3}" '
171                            'LDFLAGS="$(portageq-{2} envvar LDFLAGS) {4}" '
172                            'CXXFLAGS="$(portageq-{2} envvar CXXFLAGS) {5}" '
173                            '{6} emerge-{2} --buildpkg {7}').format(
174                                chrome_origin, chrome_version, options.board,
175                                options.cflags, options.ldflags,
176                                options.cxxflags, options.env, ebuild_version)
177
178  cros_sdk_options = ''
179  if options.cros_workon:
180    cros_sdk_options = '--chrome_root={0}'.format(options.cros_workon)
181
182  ret = cmd_executer.ChrootRunCommand(options.chromeos_root,
183                                      emerge_browser_command,
184                                      cros_sdk_options=cros_sdk_options)
185
186  logger.GetLogger().LogFatalIf(ret, 'build_packages failed')
187
188  if options.cros_workon and not cros_workon_keep:
189    command = 'cros_workon --board={0} stop chromeos-chrome'.format(
190        options.board)
191    ret = cmd_executer.ChrootRunCommand(options.chromeos_root, command)
192    # cros_workon failed, not a fatal one, just report it.
193    if ret:
194      print('cros_workon stop chromeos-chrome failed.')
195
196  if options.no_build_image:
197    return ret
198
199  # Finally build the image
200  ret = cmd_executer.ChrootRunCommand(
201      options.chromeos_root,
202      '{0} {1} {2} {3}'.format(unmask_env,
203                               options.env,
204                               misc.GetBuildImageCommand(options.board,
205                                                         dev=options.dev),
206                               options.build_image_args))
207
208  logger.GetLogger().LogFatalIf(ret, 'build_image failed')
209
210  flags_file_name = 'chrome_flags.txt'
211  flags_file_path = '{0}/src/build/images/{1}/latest/{2}'.format(
212      options.chromeos_root, options.board, flags_file_name)
213  flags_file = open(flags_file_path, 'wb')
214  flags_file.write('CFLAGS={0}\n'.format(options.cflags))
215  flags_file.write('CXXFLAGS={0}\n'.format(options.cxxflags))
216  flags_file.write('LDFLAGS={0}\n'.format(options.ldflags))
217  flags_file.close()
218
219  if options.label:
220    image_dir_path = '{0}/src/build/images/{1}/latest'.format(
221        options.chromeos_root, options.board)
222    real_image_dir_path = os.path.realpath(image_dir_path)
223    command = 'ln -sf -T {0} {1}/{2}'.format(
224        os.path.basename(real_image_dir_path),\
225        os.path.dirname(real_image_dir_path),\
226        options.label)
227
228    ret = cmd_executer.RunCommand(command)
229    logger.GetLogger().LogFatalIf(ret, 'Failed to apply symlink label %s' %
230                                  options.label)
231
232  return ret
233
234
235if __name__ == '__main__':
236  retval = Main(sys.argv[1:])
237  sys.exit(retval)
238