xref: /aosp_15_r20/external/toolchain-utils/build_chromeos.py (revision 760c253c1ed00ce9abd48f8546f08516e57485fe)
1*760c253cSXin Li#!/usr/bin/env python3
2*760c253cSXin Li# -*- coding: utf-8 -*-
3*760c253cSXin Li#
4*760c253cSXin Li# Copyright 2020 The ChromiumOS Authors
5*760c253cSXin Li# Use of this source code is governed by a BSD-style license that can be
6*760c253cSXin Li# found in the LICENSE file.
7*760c253cSXin Li
8*760c253cSXin Li"""Script to checkout the ChromeOS source.
9*760c253cSXin Li
10*760c253cSXin LiThis script sets up the ChromeOS source in the given directory, matching a
11*760c253cSXin Liparticular release of ChromeOS.
12*760c253cSXin Li"""
13*760c253cSXin Li
14*760c253cSXin Li
15*760c253cSXin Li__author__ = (
16*760c253cSXin Li    "[email protected] (Ahmad Sharif) "
17*760c253cSXin Li    "[email protected] (Luis Lozano) "
18*760c253cSXin Li    "[email protected] (Raymes Khoury) "
19*760c253cSXin Li    "[email protected] (Han Shen)"
20*760c253cSXin Li)
21*760c253cSXin Li
22*760c253cSXin Liimport argparse
23*760c253cSXin Liimport os
24*760c253cSXin Liimport sys
25*760c253cSXin Li
26*760c253cSXin Lifrom cros_utils import command_executer
27*760c253cSXin Lifrom cros_utils import logger
28*760c253cSXin Lifrom cros_utils import misc
29*760c253cSXin Li
30*760c253cSXin Li
31*760c253cSXin Lidef Usage(parser, message):
32*760c253cSXin Li    print("ERROR: %s" % message)
33*760c253cSXin Li    parser.print_help()
34*760c253cSXin Li    sys.exit(0)
35*760c253cSXin Li
36*760c253cSXin Li
37*760c253cSXin Lidef Main(argv):
38*760c253cSXin Li    """Build ChromeOS."""
39*760c253cSXin Li    # Common initializations
40*760c253cSXin Li    cmd_executer = command_executer.GetCommandExecuter()
41*760c253cSXin Li
42*760c253cSXin Li    parser = argparse.ArgumentParser()
43*760c253cSXin Li    parser.add_argument(
44*760c253cSXin Li        "--chromeos_root",
45*760c253cSXin Li        dest="chromeos_root",
46*760c253cSXin Li        help="Target directory for ChromeOS installation.",
47*760c253cSXin Li    )
48*760c253cSXin Li    parser.add_argument(
49*760c253cSXin Li        "--clobber_chroot",
50*760c253cSXin Li        dest="clobber_chroot",
51*760c253cSXin Li        action="store_true",
52*760c253cSXin Li        help="Delete the chroot and start fresh",
53*760c253cSXin Li        default=False,
54*760c253cSXin Li    )
55*760c253cSXin Li    parser.add_argument(
56*760c253cSXin Li        "--clobber_board",
57*760c253cSXin Li        dest="clobber_board",
58*760c253cSXin Li        action="store_true",
59*760c253cSXin Li        help="Delete the board and start fresh",
60*760c253cSXin Li        default=False,
61*760c253cSXin Li    )
62*760c253cSXin Li    parser.add_argument(
63*760c253cSXin Li        "--rebuild",
64*760c253cSXin Li        dest="rebuild",
65*760c253cSXin Li        action="store_true",
66*760c253cSXin Li        help="Rebuild all board packages except the toolchain.",
67*760c253cSXin Li        default=False,
68*760c253cSXin Li    )
69*760c253cSXin Li    parser.add_argument(
70*760c253cSXin Li        "--cflags",
71*760c253cSXin Li        dest="cflags",
72*760c253cSXin Li        default="",
73*760c253cSXin Li        help="CFLAGS for the ChromeOS packages",
74*760c253cSXin Li    )
75*760c253cSXin Li    parser.add_argument(
76*760c253cSXin Li        "--cxxflags",
77*760c253cSXin Li        dest="cxxflags",
78*760c253cSXin Li        default="",
79*760c253cSXin Li        help="CXXFLAGS for the ChromeOS packages",
80*760c253cSXin Li    )
81*760c253cSXin Li    parser.add_argument(
82*760c253cSXin Li        "--ldflags",
83*760c253cSXin Li        dest="ldflags",
84*760c253cSXin Li        default="",
85*760c253cSXin Li        help="LDFLAGS for the ChromeOS packages",
86*760c253cSXin Li    )
87*760c253cSXin Li    parser.add_argument(
88*760c253cSXin Li        "--board", dest="board", help="ChromeOS target board, e.g. x86-generic"
89*760c253cSXin Li    )
90*760c253cSXin Li    parser.add_argument(
91*760c253cSXin Li        "--package", dest="package", help="The package needs to be built"
92*760c253cSXin Li    )
93*760c253cSXin Li    parser.add_argument(
94*760c253cSXin Li        "--label",
95*760c253cSXin Li        dest="label",
96*760c253cSXin Li        help="Optional label symlink to point to build dir.",
97*760c253cSXin Li    )
98*760c253cSXin Li    parser.add_argument(
99*760c253cSXin Li        "--dev",
100*760c253cSXin Li        dest="dev",
101*760c253cSXin Li        default=False,
102*760c253cSXin Li        action="store_true",
103*760c253cSXin Li        help=(
104*760c253cSXin Li            "Make the final image in dev mode (eg writable, "
105*760c253cSXin Li            "more space on image). Defaults to False."
106*760c253cSXin Li        ),
107*760c253cSXin Li    )
108*760c253cSXin Li    parser.add_argument(
109*760c253cSXin Li        "--debug",
110*760c253cSXin Li        dest="debug",
111*760c253cSXin Li        default=False,
112*760c253cSXin Li        action="store_true",
113*760c253cSXin Li        help=(
114*760c253cSXin Li            'Optional. Build chrome browser with "-g -O0". '
115*760c253cSXin Li            "Notice, this also turns on '--dev'. "
116*760c253cSXin Li            "Defaults to False."
117*760c253cSXin Li        ),
118*760c253cSXin Li    )
119*760c253cSXin Li    parser.add_argument(
120*760c253cSXin Li        "--env", dest="env", default="", help="Env to pass to build_packages."
121*760c253cSXin Li    )
122*760c253cSXin Li    parser.add_argument(
123*760c253cSXin Li        "--vanilla",
124*760c253cSXin Li        dest="vanilla",
125*760c253cSXin Li        default=False,
126*760c253cSXin Li        action="store_true",
127*760c253cSXin Li        help="Use default ChromeOS toolchain.",
128*760c253cSXin Li    )
129*760c253cSXin Li    parser.add_argument(
130*760c253cSXin Li        "--vanilla_image",
131*760c253cSXin Li        dest="vanilla_image",
132*760c253cSXin Li        default=False,
133*760c253cSXin Li        action="store_true",
134*760c253cSXin Li        help=(
135*760c253cSXin Li            "Use prebuild packages for building the image. "
136*760c253cSXin Li            "It also implies the --vanilla option is set."
137*760c253cSXin Li        ),
138*760c253cSXin Li    )
139*760c253cSXin Li
140*760c253cSXin Li    options = parser.parse_args(argv[1:])
141*760c253cSXin Li
142*760c253cSXin Li    if options.chromeos_root is None:
143*760c253cSXin Li        Usage(parser, "--chromeos_root must be set")
144*760c253cSXin Li    options.chromeos_root = os.path.expanduser(options.chromeos_root)
145*760c253cSXin Li    scripts_dir = os.path.join(options.chromeos_root, "src", "scripts")
146*760c253cSXin Li    if not os.path.isdir(scripts_dir):
147*760c253cSXin Li        Usage(
148*760c253cSXin Li            parser,
149*760c253cSXin Li            "--chromeos_root must be set up first. Use setup_chromeos.py",
150*760c253cSXin Li        )
151*760c253cSXin Li
152*760c253cSXin Li    if options.board is None:
153*760c253cSXin Li        Usage(parser, "--board must be set")
154*760c253cSXin Li
155*760c253cSXin Li    if options.debug:
156*760c253cSXin Li        options.dev = True
157*760c253cSXin Li
158*760c253cSXin Li    build_packages_env = options.env
159*760c253cSXin Li    if build_packages_env.find("EXTRA_BOARD_FLAGS=") != -1:
160*760c253cSXin Li        logger.GetLogger().LogFatal(
161*760c253cSXin Li            (
162*760c253cSXin Li                'Passing "EXTRA_BOARD_FLAGS" in "--env" is not supported. '
163*760c253cSXin Li                "This flags is used internally by this script. "
164*760c253cSXin Li                "Contact the author for more detail."
165*760c253cSXin Li            )
166*760c253cSXin Li        )
167*760c253cSXin Li
168*760c253cSXin Li    if options.rebuild:
169*760c253cSXin Li        build_packages_env += " EXTRA_BOARD_FLAGS=-e"
170*760c253cSXin Li        # EXTRA_BOARD_FLAGS=-e should clean up the object files for the chrome
171*760c253cSXin Li        # browser but it doesn't. So do it here.
172*760c253cSXin Li        misc.RemoveChromeBrowserObjectFiles(
173*760c253cSXin Li            options.chromeos_root, options.board
174*760c253cSXin Li        )
175*760c253cSXin Li
176*760c253cSXin Li    # Build with afdo_use by default.
177*760c253cSXin Li    # To change the default use --env="USE=-afdo_use".
178*760c253cSXin Li    build_packages_env = misc.MergeEnvStringWithDict(
179*760c253cSXin Li        build_packages_env, {"USE": "chrome_internal afdo_use -cros-debug"}
180*760c253cSXin Li    )
181*760c253cSXin Li
182*760c253cSXin Li    build_packages_command = misc.GetBuildPackagesCommand(
183*760c253cSXin Li        board=options.board, usepkg=options.vanilla_image, debug=options.debug
184*760c253cSXin Li    )
185*760c253cSXin Li
186*760c253cSXin Li    if options.package:
187*760c253cSXin Li        build_packages_command += " {0}".format(options.package)
188*760c253cSXin Li
189*760c253cSXin Li    build_image_command = misc.GetBuildImageCommand(options.board, options.dev)
190*760c253cSXin Li
191*760c253cSXin Li    if options.vanilla or options.vanilla_image:
192*760c253cSXin Li        command = misc.GetSetupBoardCommand(
193*760c253cSXin Li            options.board,
194*760c253cSXin Li            usepkg=options.vanilla_image,
195*760c253cSXin Li            force=options.clobber_board,
196*760c253cSXin Li        )
197*760c253cSXin Li        command += "; " + build_packages_env + " " + build_packages_command
198*760c253cSXin Li        command += "&& " + build_packages_env + " " + build_image_command
199*760c253cSXin Li        ret = cmd_executer.ChrootRunCommand(options.chromeos_root, command)
200*760c253cSXin Li        return ret
201*760c253cSXin Li
202*760c253cSXin Li    # Setup board
203*760c253cSXin Li    if (
204*760c253cSXin Li        not os.path.isdir(
205*760c253cSXin Li            options.chromeos_root + "/chroot/build/" + options.board
206*760c253cSXin Li        )
207*760c253cSXin Li        or options.clobber_board
208*760c253cSXin Li    ):
209*760c253cSXin Li        # Run build_tc.py from binary package
210*760c253cSXin Li        ret = cmd_executer.ChrootRunCommand(
211*760c253cSXin Li            options.chromeos_root,
212*760c253cSXin Li            misc.GetSetupBoardCommand(
213*760c253cSXin Li                options.board, force=options.clobber_board
214*760c253cSXin Li            ),
215*760c253cSXin Li        )
216*760c253cSXin Li        logger.GetLogger().LogFatalIf(ret, "setup_board failed")
217*760c253cSXin Li    else:
218*760c253cSXin Li        logger.GetLogger().LogOutput(
219*760c253cSXin Li            "Did not setup_board " "because it already exists"
220*760c253cSXin Li        )
221*760c253cSXin Li
222*760c253cSXin Li    if options.debug:
223*760c253cSXin Li        # Perform 2-step build_packages to build a debug chrome browser.
224*760c253cSXin Li
225*760c253cSXin Li        # Firstly, build everything that chromeos-chrome depends on normally.
226*760c253cSXin Li        if options.rebuild:
227*760c253cSXin Li            # Give warning about "--rebuild" and "--debug". Under this combination,
228*760c253cSXin Li            # only dependencies of "chromeos-chrome" get rebuilt.
229*760c253cSXin Li            logger.GetLogger().LogWarning(
230*760c253cSXin Li                '--rebuild" does not correctly re-build every package when '
231*760c253cSXin Li                '"--debug" is enabled. '
232*760c253cSXin Li            )
233*760c253cSXin Li
234*760c253cSXin Li            # Replace EXTRA_BOARD_FLAGS=-e with "-e --onlydeps"
235*760c253cSXin Li            build_packages_env = build_packages_env.replace(
236*760c253cSXin Li                "EXTRA_BOARD_FLAGS=-e", 'EXTRA_BOARD_FLAGS="-e --onlydeps"'
237*760c253cSXin Li            )
238*760c253cSXin Li        else:
239*760c253cSXin Li            build_packages_env += " EXTRA_BOARD_FLAGS=--onlydeps"
240*760c253cSXin Li
241*760c253cSXin Li        ret = cmd_executer.ChrootRunCommand(
242*760c253cSXin Li            options.chromeos_root,
243*760c253cSXin Li            'CFLAGS="$(portageq-%s envvar CFLAGS) %s" '
244*760c253cSXin Li            'CXXFLAGS="$(portageq-%s envvar CXXFLAGS) %s" '
245*760c253cSXin Li            'LDFLAGS="$(portageq-%s envvar LDFLAGS) %s" '
246*760c253cSXin Li            "CHROME_ORIGIN=SERVER_SOURCE "
247*760c253cSXin Li            "%s "
248*760c253cSXin Li            "%s --skip_chroot_upgrade"
249*760c253cSXin Li            "chromeos-chrome"
250*760c253cSXin Li            % (
251*760c253cSXin Li                options.board,
252*760c253cSXin Li                options.cflags,
253*760c253cSXin Li                options.board,
254*760c253cSXin Li                options.cxxflags,
255*760c253cSXin Li                options.board,
256*760c253cSXin Li                options.ldflags,
257*760c253cSXin Li                build_packages_env,
258*760c253cSXin Li                build_packages_command,
259*760c253cSXin Li            ),
260*760c253cSXin Li        )
261*760c253cSXin Li
262*760c253cSXin Li        logger.GetLogger().LogFatalIf(
263*760c253cSXin Li            ret,
264*760c253cSXin Li            "build_packages failed while trying to build chromeos-chrome deps.",
265*760c253cSXin Li        )
266*760c253cSXin Li
267*760c253cSXin Li        # Secondly, build chromeos-chrome using debug mode.
268*760c253cSXin Li        # Replace '--onlydeps' with '--nodeps'.
269*760c253cSXin Li        if options.rebuild:
270*760c253cSXin Li            build_packages_env = build_packages_env.replace(
271*760c253cSXin Li                'EXTRA_BOARD_FLAGS="-e --onlydeps"',
272*760c253cSXin Li                "EXTRA_BOARD_FLAGS=--nodeps",
273*760c253cSXin Li            )
274*760c253cSXin Li        else:
275*760c253cSXin Li            build_packages_env = build_packages_env.replace(
276*760c253cSXin Li                "EXTRA_BOARD_FLAGS=--onlydeps", "EXTRA_BOARD_FLAGS=--nodeps"
277*760c253cSXin Li            )
278*760c253cSXin Li        ret = cmd_executer.ChrootRunCommand(
279*760c253cSXin Li            options.chromeos_root,
280*760c253cSXin Li            'CFLAGS="$(portageq-%s envvar CFLAGS) %s" '
281*760c253cSXin Li            'CXXFLAGS="$(portageq-%s envvar CXXFLAGS) %s" '
282*760c253cSXin Li            'LDFLAGS="$(portageq-%s envvar LDFLAGS) %s" '
283*760c253cSXin Li            "CHROME_ORIGIN=SERVER_SOURCE BUILDTYPE=Debug "
284*760c253cSXin Li            "%s "
285*760c253cSXin Li            "%s --skip_chroot_upgrade"
286*760c253cSXin Li            "chromeos-chrome"
287*760c253cSXin Li            % (
288*760c253cSXin Li                options.board,
289*760c253cSXin Li                options.cflags,
290*760c253cSXin Li                options.board,
291*760c253cSXin Li                options.cxxflags,
292*760c253cSXin Li                options.board,
293*760c253cSXin Li                options.ldflags,
294*760c253cSXin Li                build_packages_env,
295*760c253cSXin Li                build_packages_command,
296*760c253cSXin Li            ),
297*760c253cSXin Li        )
298*760c253cSXin Li        logger.GetLogger().LogFatalIf(
299*760c253cSXin Li            ret,
300*760c253cSXin Li            "build_packages failed while trying to build debug chromeos-chrome.",
301*760c253cSXin Li        )
302*760c253cSXin Li
303*760c253cSXin Li        # Now, we have built chromeos-chrome and all dependencies.
304*760c253cSXin Li        # Finally, remove '-e' from EXTRA_BOARD_FLAGS,
305*760c253cSXin Li        # otherwise, chromeos-chrome gets rebuilt.
306*760c253cSXin Li        build_packages_env = build_packages_env.replace(
307*760c253cSXin Li            "EXTRA_BOARD_FLAGS=--nodeps", ""
308*760c253cSXin Li        )
309*760c253cSXin Li
310*760c253cSXin Li        # Up to now, we have a debug built chromos-chrome browser.
311*760c253cSXin Li        # Fall through to build the rest of the world.
312*760c253cSXin Li
313*760c253cSXin Li    # Build packages
314*760c253cSXin Li    ret = cmd_executer.ChrootRunCommand(
315*760c253cSXin Li        options.chromeos_root,
316*760c253cSXin Li        'CFLAGS="$(portageq-%s envvar CFLAGS) %s" '
317*760c253cSXin Li        'CXXFLAGS="$(portageq-%s envvar CXXFLAGS) %s" '
318*760c253cSXin Li        'LDFLAGS="$(portageq-%s envvar LDFLAGS) %s" '
319*760c253cSXin Li        "CHROME_ORIGIN=SERVER_SOURCE "
320*760c253cSXin Li        "%s "
321*760c253cSXin Li        "%s --skip_chroot_upgrade"
322*760c253cSXin Li        % (
323*760c253cSXin Li            options.board,
324*760c253cSXin Li            options.cflags,
325*760c253cSXin Li            options.board,
326*760c253cSXin Li            options.cxxflags,
327*760c253cSXin Li            options.board,
328*760c253cSXin Li            options.ldflags,
329*760c253cSXin Li            build_packages_env,
330*760c253cSXin Li            build_packages_command,
331*760c253cSXin Li        ),
332*760c253cSXin Li    )
333*760c253cSXin Li
334*760c253cSXin Li    logger.GetLogger().LogFatalIf(ret, "build_packages failed")
335*760c253cSXin Li    if options.package:
336*760c253cSXin Li        return 0
337*760c253cSXin Li    # Build image
338*760c253cSXin Li    ret = cmd_executer.ChrootRunCommand(
339*760c253cSXin Li        options.chromeos_root, build_packages_env + " " + build_image_command
340*760c253cSXin Li    )
341*760c253cSXin Li
342*760c253cSXin Li    logger.GetLogger().LogFatalIf(ret, "build_image failed")
343*760c253cSXin Li
344*760c253cSXin Li    flags_file_name = "flags.txt"
345*760c253cSXin Li    flags_file_path = "%s/src/build/images/%s/latest/%s" % (
346*760c253cSXin Li        options.chromeos_root,
347*760c253cSXin Li        options.board,
348*760c253cSXin Li        flags_file_name,
349*760c253cSXin Li    )
350*760c253cSXin Li    with open(flags_file_path, "w", encoding="utf-8") as flags_file:
351*760c253cSXin Li        flags_file.write("CFLAGS=%s\n" % options.cflags)
352*760c253cSXin Li        flags_file.write("CXXFLAGS=%s\n" % options.cxxflags)
353*760c253cSXin Li        flags_file.write("LDFLAGS=%s\n" % options.ldflags)
354*760c253cSXin Li
355*760c253cSXin Li    if options.label:
356*760c253cSXin Li        image_dir_path = "%s/src/build/images/%s/latest" % (
357*760c253cSXin Li            options.chromeos_root,
358*760c253cSXin Li            options.board,
359*760c253cSXin Li        )
360*760c253cSXin Li        real_image_dir_path = os.path.realpath(image_dir_path)
361*760c253cSXin Li        command = "ln -sf -T %s %s/%s" % (
362*760c253cSXin Li            os.path.basename(real_image_dir_path),
363*760c253cSXin Li            os.path.dirname(real_image_dir_path),
364*760c253cSXin Li            options.label,
365*760c253cSXin Li        )
366*760c253cSXin Li
367*760c253cSXin Li        ret = cmd_executer.RunCommand(command)
368*760c253cSXin Li        logger.GetLogger().LogFatalIf(
369*760c253cSXin Li            ret, "Failed to apply symlink label %s" % options.label
370*760c253cSXin Li        )
371*760c253cSXin Li
372*760c253cSXin Li    return ret
373*760c253cSXin Li
374*760c253cSXin Li
375*760c253cSXin Liif __name__ == "__main__":
376*760c253cSXin Li    retval = Main(sys.argv)
377*760c253cSXin Li    sys.exit(retval)
378