build_chromeos.py revision 09b027f5ee8c44f0b965392a4020bef144c48d75
1#!/usr/bin/python
2#
3# Copyright 2010 Google Inc. All Rights Reserved.
4
5"""Script to checkout the ChromeOS source.
6
7This script sets up the ChromeOS source in the given directory, matching a
8particular release of ChromeOS.
9"""
10
11__author__ = ("asharif@google.com (Ahmad Sharif) "
12              "llozano@google.com (Luis Lozano) "
13              "raymes@google.com (Raymes Khoury) "
14              "shenhan@google.com (Han Shen)")
15
16import optparse
17import os
18import sys
19
20import tc_enter_chroot
21from utils import command_executer
22from utils import logger
23from utils import misc
24
25
26def Usage(parser, message):
27  print "ERROR: " + message
28  parser.print_help()
29  sys.exit(0)
30
31
32def Main(argv):
33  """Build ChromeOS."""
34  # Common initializations
35  cmd_executer = command_executer.GetCommandExecuter()
36
37  parser = optparse.OptionParser()
38  parser.add_option("--chromeos_root", dest="chromeos_root",
39                    help="Target directory for ChromeOS installation.")
40  parser.add_option("--clobber_chroot", dest="clobber_chroot",
41                    action="store_true", help=
42                    "Delete the chroot and start fresh", default=False)
43  parser.add_option("--clobber_board", dest="clobber_board",
44                    action="store_true",
45                    help="Delete the board and start fresh", default=False)
46  parser.add_option("--rebuild", dest="rebuild",
47                    action="store_true",
48                    help="Rebuild all board packages except the toolchain.",
49                    default=False)
50  parser.add_option("--cflags", dest="cflags", default="",
51                    help="CFLAGS for the ChromeOS packages")
52  parser.add_option("--cxxflags", dest="cxxflags", default="",
53                    help="CXXFLAGS for the ChromeOS packages")
54  parser.add_option("--ldflags", dest="ldflags", default="",
55                    help="LDFLAGS for the ChromeOS packages")
56  parser.add_option("--board", dest="board",
57                    help="ChromeOS target board, e.g. x86-generic")
58  parser.add_option("--package", dest="package",
59                    help="The package needs to be built")
60  parser.add_option("--label", dest="label",
61                    help="Optional label symlink to point to build dir.")
62  parser.add_option("--dev", dest="dev", default=False, action="store_true",
63                    help=("Make the final image in dev mode (eg writable, "
64                          "more space on image). Defaults to False."))
65  parser.add_option("--debug", dest="debug", default=False, action="store_true",
66                    help=("Optional. Build chrome browser with \"-g -O0\". "
67                          "Notice, this also turns on \'--dev\'. "
68                          "Defaults to False."))
69  parser.add_option("--env",
70                    dest="env",
71                    default="",
72                    help="Env to pass to build_packages.")
73  parser.add_option("--vanilla", dest="vanilla",
74                    default=False,
75                    action="store_true",
76                    help="Use default ChromeOS toolchain.")
77  parser.add_option("--vanilla_image", dest="vanilla_image",
78                    default=False,
79                    action="store_true",
80                    help=("Use prebuild packages for building the image. "
81                          "It also implies the --vanilla option is set."))
82
83  options = parser.parse_args(argv[1:])[0]
84
85  if options.chromeos_root is None:
86    Usage(parser, "--chromeos_root must be set")
87  options.chromeos_root = os.path.expanduser(options.chromeos_root)
88  scripts_dir = os.path.join(options.chromeos_root, 'src', 'scripts')
89  if not os.path.isdir(scripts_dir):
90    Usage(parser, "--chromeos_root must be set up first. Use setup_chromeos.py")
91
92  if options.board is None:
93    Usage(parser, "--board must be set")
94
95  if options.debug:
96    options.dev = True
97
98  build_packages_env = options.env
99  if build_packages_env.find('EXTRA_BOARD_FLAGS=') != -1:
100    logger.GetLogger().LogFatal(
101      ('Passing "EXTRA_BOARD_FLAGS" in "--env" is not supported. '
102       'This flags is used internally by this script. '
103       'Contact the author for more detail.'))
104
105  if options.rebuild == True:
106    build_packages_env += " EXTRA_BOARD_FLAGS=-e"
107    # EXTRA_BOARD_FLAGS=-e should clean up the object files for the chrome
108    # browser but it doesn't. So do it here.
109    misc.RemoveChromeBrowserObjectFiles(options.chromeos_root, options.board)
110
111  # Build with afdo_use by default.
112  # To change the default use --env="USE=-afdo_use".
113  build_packages_env = misc.MergeEnvStringWithDict(
114    build_packages_env,
115    {"USE": "chrome_internal afdo_use"})
116
117  build_packages_command = misc.GetBuildPackagesCommand(
118    board=options.board, usepkg=options.vanilla_image, debug=options.debug)
119
120  if options.package:
121    build_packages_command += " {0}".format(options.package)
122
123  build_image_command = misc.GetBuildImageCommand(options.board, options.dev)
124
125  if options.vanilla or options.vanilla_image:
126    command = misc.GetSetupBoardCommand(options.board,
127                                        usepkg=options.vanilla_image,
128                                        force=options.clobber_board)
129    command += "; " + build_packages_env + " " + build_packages_command
130    command += "&& " + build_packages_env + " " + build_image_command
131    ret = cmd_executer.ChrootRunCommand(options.chromeos_root, command)
132    return ret
133
134  # Setup board
135  if not os.path.isdir(options.chromeos_root + "/chroot/build/"
136                       + options.board) or options.clobber_board:
137    # Run build_tc.py from binary package
138    rootdir = misc.GetRoot(argv[0])[0]
139    version_number = misc.GetRoot(rootdir)[1]
140    ret = cmd_executer.ChrootRunCommand(
141        options.chromeos_root,
142        misc.GetSetupBoardCommand(options.board,
143                                   force=options.clobber_board))
144    logger.GetLogger().LogFatalIf(ret, "setup_board failed")
145  else:
146    logger.GetLogger().LogOutput("Did not setup_board "
147                                 "because it already exists")
148
149  if options.debug:
150    # Perform 2-step build_packages to build a debug chrome browser.
151
152    # Firstly, build everything that chromeos-chrome depends on normally.
153    if options.rebuild == True:
154      # Give warning about "--rebuild" and "--debug". Under this combination,
155      # only dependencies of "chromeos-chrome" get rebuilt.
156      logger.GetLogger().LogWarning(
157        "\"--rebuild\" does not correctly re-build every package when "
158        "\"--debug\" is enabled. ")
159
160      # Replace EXTRA_BOARD_FLAGS=-e with "-e --onlydeps"
161      build_packages_env = build_packages_env.replace(
162        'EXTRA_BOARD_FLAGS=-e', 'EXTRA_BOARD_FLAGS=\"-e --onlydeps\"')
163    else:
164      build_packages_env += ' EXTRA_BOARD_FLAGS=--onlydeps'
165
166    ret = cmd_executer.ChrootRunCommand(
167      options.chromeos_root,
168      "CFLAGS=\"$(portageq-%s envvar CFLAGS) %s\" "
169      "CXXFLAGS=\"$(portageq-%s envvar CXXFLAGS) %s\" "
170      "LDFLAGS=\"$(portageq-%s envvar LDFLAGS) %s\" "
171      "CHROME_ORIGIN=SERVER_SOURCE "
172      "%s "
173      "%s --skip_chroot_upgrade"
174      "chromeos-chrome"
175      % (options.board, options.cflags,
176         options.board, options.cxxflags,
177         options.board, options.ldflags,
178         build_packages_env,
179         build_packages_command))
180
181    logger.GetLogger().LogFatalIf(\
182      ret, "build_packages failed while trying to build chromeos-chrome deps.")
183
184    # Secondly, build chromeos-chrome using debug mode.
185    # Replace '--onlydeps' with '--nodeps'.
186    if options.rebuild == True:
187      build_packages_env = build_packages_env.replace(
188        'EXTRA_BOARD_FLAGS=\"-e --onlydeps\"', 'EXTRA_BOARD_FLAGS=--nodeps')
189    else:
190      build_packages_env = build_packages_env.replace(
191        'EXTRA_BOARD_FLAGS=--onlydeps', 'EXTRA_BOARD_FLAGS=--nodeps')
192    ret = cmd_executer.ChrootRunCommand(
193      options.chromeos_root,
194      "CFLAGS=\"$(portageq-%s envvar CFLAGS) %s\" "
195      "CXXFLAGS=\"$(portageq-%s envvar CXXFLAGS) %s\" "
196      "LDFLAGS=\"$(portageq-%s envvar LDFLAGS) %s\" "
197      "CHROME_ORIGIN=SERVER_SOURCE BUILDTYPE=Debug "
198      "%s "
199      "%s --skip_chroot_upgrade"
200      "chromeos-chrome"
201      % (options.board, options.cflags,
202         options.board, options.cxxflags,
203         options.board, options.ldflags,
204         build_packages_env,
205         build_packages_command))
206    logger.GetLogger().LogFatalIf(
207      ret, "build_packages failed while trying to build debug chromeos-chrome.")
208
209    # Now, we have built chromeos-chrome and all dependencies.
210    # Finally, remove '-e' from EXTRA_BOARD_FLAGS,
211    # otherwise, chromeos-chrome gets rebuilt.
212    build_packages_env = build_packages_env.replace(\
213      'EXTRA_BOARD_FLAGS=--nodeps', '')
214
215    # Up to now, we have a debug built chromos-chrome browser.
216    # Fall through to build the rest of the world.
217
218  # Build packages
219  ret = cmd_executer.ChrootRunCommand(
220      options.chromeos_root,
221      "CFLAGS=\"$(portageq-%s envvar CFLAGS) %s\" "
222      "CXXFLAGS=\"$(portageq-%s envvar CXXFLAGS) %s\" "
223      "LDFLAGS=\"$(portageq-%s envvar LDFLAGS) %s\" "
224      "CHROME_ORIGIN=SERVER_SOURCE "
225      "%s "
226      "%s --skip_chroot_upgrade"
227      % (options.board, options.cflags,
228         options.board, options.cxxflags,
229         options.board, options.ldflags,
230         build_packages_env,
231         build_packages_command))
232
233  logger.GetLogger().LogFatalIf(ret, "build_packages failed")
234  if options.package:
235    return 0
236  # Build image
237  ret = cmd_executer.ChrootRunCommand(options.chromeos_root,
238                                      build_packages_env + " " +
239                                      build_image_command)
240
241  logger.GetLogger().LogFatalIf(ret, "build_image failed")
242
243  flags_file_name = "flags.txt"
244  flags_file_path = ("%s/src/build/images/%s/latest/%s" %
245                     (options.chromeos_root,
246                      options.board,
247                      flags_file_name))
248  flags_file = open(flags_file_path, "wb")
249  flags_file.write("CFLAGS=%s\n" % options.cflags)
250  flags_file.write("CXXFLAGS=%s\n" % options.cxxflags)
251  flags_file.write("LDFLAGS=%s\n" % options.ldflags)
252  flags_file.close()
253
254  if options.label:
255    image_dir_path = ("%s/src/build/images/%s/latest" %
256                  (options.chromeos_root,
257                   options.board))
258    real_image_dir_path = os.path.realpath(image_dir_path)
259    command = ("ln -sf -T %s %s/%s" %
260               (os.path.basename(real_image_dir_path),
261                os.path.dirname(real_image_dir_path),
262                options.label))
263
264    ret = cmd_executer.RunCommand(command)
265    logger.GetLogger().LogFatalIf(ret, "Failed to apply symlink label %s" %
266                                  options.label)
267
268  return ret
269
270if __name__ == "__main__":
271  retval = Main(sys.argv)
272  sys.exit(retval)
273