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