build_chromeos.py revision f81680c018729fd4499e1e200d04b48c4b90127c
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
78  options = parser.parse_args(argv[1:])[0]
79
80  if options.chromeos_root is None:
81    Usage(parser, "--chromeos_root must be set")
82
83  if options.board is None:
84    Usage(parser, "--board must be set")
85
86  if options.debug:
87    options.dev = True
88
89  build_packages_env = options.env
90  if build_packages_env.find('EXTRA_BOARD_FLAGS=') != -1:
91    logger.GetLogger().LogFatal(
92      ('Passing "EXTRA_BOARD_FLAGS" in "--env" is not supported. '
93       'This flags is used internally by this script. '
94       'Contact the author for more detail.'))
95
96  if options.rebuild == True:
97    build_packages_env += " EXTRA_BOARD_FLAGS=-e"
98    # EXTRA_BOARD_FLAGS=-e should clean up the object files for the chrome
99    # browser but it doesn't. So do it here.
100    misc.RemoveChromeBrowserObjectFiles(options.chromeos_root, options.board)
101
102  build_packages_env = misc.MergeEnvStringWithDict(build_packages_env,
103                                                   {"USE": "chrome_internal"})
104
105  options.chromeos_root = os.path.expanduser(options.chromeos_root)
106
107  build_packages_command = misc.GetBuildPackagesCommand(
108    board=options.board, usepkg=False, debug=options.debug)
109
110  if options.package:
111    build_packages_command += " {0}".format(options.package)
112
113  build_image_command = misc.GetBuildImageCommand(options.board, options.dev)
114
115  if options.vanilla == True:
116    command = misc.GetSetupBoardCommand(options.board,
117                                        usepkg=False,
118                                        force=options.clobber_board)
119    command += "; " + build_packages_env + " " + build_packages_command
120    command += "&& " + build_packages_env + " " + build_image_command
121    ret = cmd_executer.ChrootRunCommand(options.chromeos_root, command)
122    return ret
123
124  # Setup board
125  if not os.path.isdir(options.chromeos_root + "/chroot/build/"
126                       + options.board) or options.clobber_board:
127    # Run build_tc.py from binary package
128    rootdir = misc.GetRoot(argv[0])[0]
129    version_number = misc.GetRoot(rootdir)[1]
130    ret = cmd_executer.ChrootRunCommand(
131        options.chromeos_root,
132        misc.GetSetupBoardCommand(options.board,
133                                   force=options.clobber_board))
134    logger.GetLogger().LogFatalIf(ret, "setup_board failed")
135  else:
136    logger.GetLogger().LogOutput("Did not setup_board "
137                                 "because it already exists")
138
139  if options.debug:
140    # Perform 2-step build_packages to build a debug chrome browser.
141
142    # Firstly, build everything that chromeos-chrome depends on normally.
143    if options.rebuild == True:
144      # Give warning about "--rebuild" and "--debug". Under this combination,
145      # only dependencies of "chromeos-chrome" get rebuilt.
146      logger.GetLogger().LogWarning(
147        "\"--rebuild\" does not correctly re-build every package when "
148        "\"--debug\" is enabled. ")
149
150      # Replace EXTRA_BOARD_FLAGS=-e with "-e --onlydeps"
151      build_packages_env = build_packages_env.replace(
152        'EXTRA_BOARD_FLAGS=-e', 'EXTRA_BOARD_FLAGS=\"-e --onlydeps\"')
153    else:
154      build_packages_env += ' EXTRA_BOARD_FLAGS=--onlydeps'
155
156    ret = cmd_executer.ChrootRunCommand(
157      options.chromeos_root,
158      "CFLAGS=\"$(portageq-%s envvar CFLAGS) %s\" "
159      "CXXFLAGS=\"$(portageq-%s envvar CXXFLAGS) %s\" "
160      "LDFLAGS=\"$(portageq-%s envvar LDFLAGS) %s\" "
161      "CHROME_ORIGIN=SERVER_SOURCE "
162      "%s "
163      "%s "
164      "chromeos-chrome"
165      % (options.board, options.cflags,
166         options.board, options.cxxflags,
167         options.board, options.ldflags,
168         build_packages_env,
169         build_packages_command))
170
171    logger.GetLogger().LogFatalIf(\
172      ret, "build_packages failed while trying to build chromeos-chrome deps.")
173
174    # Secondly, build chromeos-chrome using debug mode.
175    # Replace '--onlydeps' with '--nodeps'.
176    if options.rebuild == True:
177      build_packages_env = build_packages_env.replace(
178        'EXTRA_BOARD_FLAGS=\"-e --onlydeps\"', 'EXTRA_BOARD_FLAGS=--nodeps')
179    else:
180      build_packages_env = build_packages_env.replace(
181        'EXTRA_BOARD_FLAGS=--onlydeps', 'EXTRA_BOARD_FLAGS=--nodeps')
182    ret = cmd_executer.ChrootRunCommand(
183      options.chromeos_root,
184      "CFLAGS=\"$(portageq-%s envvar CFLAGS) %s\" "
185      "CXXFLAGS=\"$(portageq-%s envvar CXXFLAGS) %s\" "
186      "LDFLAGS=\"$(portageq-%s envvar LDFLAGS) %s\" "
187      "CHROME_ORIGIN=SERVER_SOURCE BUILDTYPE=Debug "
188      "%s "
189      "%s "
190      "chromeos-chrome"
191      % (options.board, options.cflags,
192         options.board, options.cxxflags,
193         options.board, options.ldflags,
194         build_packages_env,
195         build_packages_command))
196    logger.GetLogger().LogFatalIf(
197      ret, "build_packages failed while trying to build debug chromeos-chrome.")
198
199    # Now, we have built chromeos-chrome and all dependencies.
200    # Finally, remove '-e' from EXTRA_BOARD_FLAGS,
201    # otherwise, chromeos-chrome gets rebuilt.
202    build_packages_env = build_packages_env.replace(\
203      'EXTRA_BOARD_FLAGS=--nodeps', '')
204
205    # Up to now, we have a debug built chromos-chrome browser.
206    # Fall through to build the rest of the world.
207
208  # Build packages
209  ret = cmd_executer.ChrootRunCommand(
210      options.chromeos_root,
211      "CFLAGS=\"$(portageq-%s envvar CFLAGS) %s\" "
212      "CXXFLAGS=\"$(portageq-%s envvar CXXFLAGS) %s\" "
213      "LDFLAGS=\"$(portageq-%s envvar LDFLAGS) %s\" "
214      "CHROME_ORIGIN=SERVER_SOURCE "
215      "%s "
216      "%s"
217      % (options.board, options.cflags,
218         options.board, options.cxxflags,
219         options.board, options.ldflags,
220         build_packages_env,
221         build_packages_command))
222
223  logger.GetLogger().LogFatalIf(ret, "build_packages failed")
224  if options.package:
225    return 0
226  # Build image
227  ret = cmd_executer.ChrootRunCommand(options.chromeos_root,
228                                      build_packages_env + " " +
229                                      build_image_command)
230
231  logger.GetLogger().LogFatalIf(ret, "build_image failed")
232
233  flags_file_name = "flags.txt"
234  flags_file_path = ("%s/src/build/images/%s/latest/%s" %
235                     (options.chromeos_root,
236                      options.board,
237                      flags_file_name))
238  flags_file = open(flags_file_path, "wb")
239  flags_file.write("CFLAGS=%s\n" % options.cflags)
240  flags_file.write("CXXFLAGS=%s\n" % options.cxxflags)
241  flags_file.write("LDFLAGS=%s\n" % options.ldflags)
242  flags_file.close()
243
244  if options.label:
245    image_dir_path = ("%s/src/build/images/%s/latest" %
246                  (options.chromeos_root,
247                   options.board))
248    real_image_dir_path = os.path.realpath(image_dir_path)
249    command = ("ln -sf -T %s %s/%s" %
250               (os.path.basename(real_image_dir_path),
251                os.path.dirname(real_image_dir_path),
252                options.label))
253
254    ret = cmd_executer.RunCommand(command)
255    logger.GetLogger().LogFatalIf(ret, "Failed to apply symlink label %s" %
256                                  options.label)
257
258  return ret
259
260if __name__ == "__main__":
261  retval = Main(sys.argv)
262  sys.exit(retval)
263