blob: ad092aaf174ee53bbc0b3ec2f458304787401d4f [file] [log] [blame]
shenhan8e8b0c22013-02-19 22:34:16 +00001#!/usr/bin/python
bjanakiraman7f4a4852013-02-15 04:35:28 +00002#
Rahul Chaudhry8ac4ec02014-11-01 09:31:15 -07003# Copyright 2010 The Chromium OS Authors. All rights reserved.
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
bjanakiraman7f4a4852013-02-15 04:35:28 +00006
7"""Script to build the ChromeOS toolchain.
8
9This script sets up the toolchain if you give it the gcctools directory.
10"""
11
12__author__ = "asharif@google.com (Ahmad Sharif)"
13
asharif80c6e552013-02-15 04:35:40 +000014import getpass
bjanakiraman7f4a4852013-02-15 04:35:28 +000015import optparse
asharif17621302013-02-15 04:46:35 +000016import os
bjanakiraman7f4a4852013-02-15 04:35:28 +000017import sys
asharifc97199a2013-02-15 22:48:45 +000018import tempfile
kbaclawski20082a02013-02-16 02:12:57 +000019
asharif252df0f2013-02-15 04:46:28 +000020import tc_enter_chroot
raymes01959ae2013-02-15 04:50:07 +000021from utils import command_executer
shenhanad803432013-02-16 03:14:51 +000022from utils import constants
kbaclawski20082a02013-02-16 02:12:57 +000023from utils import misc
bjanakiraman7f4a4852013-02-15 04:35:28 +000024
asharif5a9bb462013-02-15 04:50:57 +000025
asharifc97199a2013-02-15 22:48:45 +000026class ToolchainPart(object):
27 def __init__(self, name, source_path, chromeos_root, board, incremental,
llozanof2726d22013-03-09 01:29:37 +000028 build_env, gcc_enable_ccache=False):
asharifc97199a2013-02-15 22:48:45 +000029 self._name = name
kbaclawski20082a02013-02-16 02:12:57 +000030 self._source_path = misc.CanonicalizePath(source_path)
asharifc97199a2013-02-15 22:48:45 +000031 self._chromeos_root = chromeos_root
32 self._board = board
kbaclawski20082a02013-02-16 02:12:57 +000033 self._ctarget = misc.GetCtargetFromBoard(self._board,
asharif77bd80d2013-02-15 22:49:32 +000034 self._chromeos_root)
carrote6f773c2013-02-19 22:34:44 +000035 self.tag = "%s-%s" % (name, self._ctarget)
asharifc97199a2013-02-15 22:48:45 +000036 self._ce = command_executer.GetCommandExecuter()
37 self._mask_file = os.path.join(
38 self._chromeos_root,
39 "chroot",
40 "etc/portage/package.mask/cross-%s" % self._ctarget)
41 self._new_mask_file = None
42
Han Shene4b6f222013-11-22 10:02:38 -080043 self._chroot_source_path = os.path.join(constants.MOUNTED_TOOLCHAIN_ROOT,
llozano85b37152013-02-16 03:14:57 +000044 self._name).lstrip("/")
asharifc97199a2013-02-15 22:48:45 +000045 self._incremental = incremental
46 self._build_env = build_env
llozanof2726d22013-03-09 01:29:37 +000047 self._gcc_enable_ccache = gcc_enable_ccache
asharifc97199a2013-02-15 22:48:45 +000048
49 def RunSetupBoardIfNecessary(self):
50 cross_symlink = os.path.join(
51 self._chromeos_root,
52 "chroot",
carrotccae6272013-02-19 22:34:51 +000053 "usr/local/bin/emerge-%s" % self._board)
asharifc97199a2013-02-15 22:48:45 +000054 if not os.path.exists(cross_symlink):
Rahul Chaudhry8ac4ec02014-11-01 09:31:15 -070055 command = ("%s/setup_board --board=%s" %
56 (misc.CHROMEOS_SCRIPTS_DIR, self._board))
asharifca3c6c12013-02-15 23:17:54 +000057 self._ce.ChrootRunCommand(self._chromeos_root, command)
asharifc97199a2013-02-15 22:48:45 +000058
59 def Build(self):
shenhanbecf6242013-02-19 20:43:32 +000060 rv = 1
asharifc97199a2013-02-15 22:48:45 +000061 try:
asharif7dd6d862013-02-15 23:17:46 +000062 self.UninstallTool()
asharifc97199a2013-02-15 22:48:45 +000063 self.MoveMaskFile()
cmtice80d257f2013-02-15 23:44:51 +000064 self.MountSources(False)
asharif9e3cf6e2013-02-16 03:13:38 +000065 self.RemoveCompiledFile()
shenhanbecf6242013-02-19 20:43:32 +000066 rv = self.BuildTool()
asharifc97199a2013-02-15 22:48:45 +000067 finally:
68 self.UnMoveMaskFile()
llozano9b84cb62013-03-11 21:08:31 +000069 return rv
asharifc97199a2013-02-15 22:48:45 +000070
71 def RemoveCompiledFile(self):
72 compiled_file = os.path.join(self._chromeos_root,
73 "chroot",
74 "var/tmp/portage/cross-%s" % self._ctarget,
75 "%s-9999" % self._name,
76 ".compiled")
asharif9e3cf6e2013-02-16 03:13:38 +000077 command = "rm -f %s" % compiled_file
asharifc97199a2013-02-15 22:48:45 +000078 self._ce.RunCommand(command)
79
cmtice80d257f2013-02-15 23:44:51 +000080 def MountSources(self, unmount_source):
asharifc97199a2013-02-15 22:48:45 +000081 mount_points = []
82 mounted_source_path = os.path.join(self._chromeos_root,
83 "chroot",
84 self._chroot_source_path)
85 src_mp = tc_enter_chroot.MountPoint(
86 self._source_path,
87 mounted_source_path,
88 getpass.getuser(),
89 "ro")
90 mount_points.append(src_mp)
91
92 build_suffix = "build-%s" % self._ctarget
93 build_dir = "%s-%s" % (self._source_path, build_suffix)
94
95 if not self._incremental and os.path.exists(build_dir):
96 command = "rm -rf %s/*" % build_dir
97 self._ce.RunCommand(command)
98
99 # Create a -build directory for the objects.
100 command = "mkdir -p %s" % build_dir
101 self._ce.RunCommand(command)
102
103 mounted_build_dir = os.path.join(
104 self._chromeos_root, "chroot", "%s-%s" %
105 (self._chroot_source_path, build_suffix))
106 build_mp = tc_enter_chroot.MountPoint(
107 build_dir,
108 mounted_build_dir,
109 getpass.getuser())
110 mount_points.append(build_mp)
111
cmtice80d257f2013-02-15 23:44:51 +0000112 if unmount_source:
113 unmount_statuses = [mp.UnMount() == 0 for mp in mount_points]
asharifc97199a2013-02-15 22:48:45 +0000114 assert all(unmount_statuses), "Could not unmount all mount points!"
cmtice80d257f2013-02-15 23:44:51 +0000115 else:
116 mount_statuses = [mp.DoMount() == 0 for mp in mount_points]
117
118 if not all(mount_statuses):
119 mounted = [mp for mp, status in zip(mount_points, mount_statuses) if status]
120 unmount_statuses = [mp.UnMount() == 0 for mp in mounted]
121 assert all(unmount_statuses), "Could not unmount all mount points!"
122
asharifc97199a2013-02-15 22:48:45 +0000123
asharif7dd6d862013-02-15 23:17:46 +0000124 def UninstallTool(self):
125 command = "sudo CLEAN_DELAY=0 emerge -C cross-%s/%s" % (self._ctarget, self._name)
asharifca3c6c12013-02-15 23:17:54 +0000126 self._ce.ChrootRunCommand(self._chromeos_root, command)
asharif7dd6d862013-02-15 23:17:46 +0000127
asharifc97199a2013-02-15 22:48:45 +0000128 def BuildTool(self):
129 env = self._build_env
asharif9e499162013-02-16 02:41:39 +0000130 # FEATURES=buildpkg adds minutes of time so we disable it.
shenhanfdc0f572013-02-19 18:48:36 +0000131 # TODO(shenhan): keep '-sandbox' for a while for compatibility, then remove
132 # it after a while.
133 features = "nostrip userpriv userfetch -usersandbox -sandbox noclean -buildpkg"
asharifc97199a2013-02-15 22:48:45 +0000134 env["FEATURES"] = features
135
136 if self._incremental:
137 env["FEATURES"] += " keepwork"
138
cmticecbc868a2013-02-21 22:52:46 +0000139 if "USE" in env:
140 env["USE"] += " multislot mounted_%s" % self._name
141 else:
142 env["USE"] = "multislot mounted_%s" % self._name
143
llozanof2726d22013-03-09 01:29:37 +0000144 # Disable ccache in our compilers. cache may be problematic for us.
145 # It ignores compiler environments settings and it is not clear if
146 # the cache hit algorithm verifies all the compiler binaries or
147 # just the driver.
148 if self._name == "gcc" and not self._gcc_enable_ccache:
149 env["USE"] += " -wrapper_ccache"
150
asharifc97199a2013-02-15 22:48:45 +0000151 env["%s_SOURCE_PATH" % self._name.upper()] = (
152 os.path.join("/", self._chroot_source_path))
153 env["ACCEPT_KEYWORDS"] = "~*"
154 env_string = " ".join(["%s=\"%s\"" % var for var in env.items()])
155 command = "emerge =cross-%s/%s-9999" % (self._ctarget, self._name)
156 full_command = "sudo %s %s" % (env_string, command)
Luis Lozano4cea9de2013-03-20 12:32:56 -0700157 rv = self._ce.ChrootRunCommand(self._chromeos_root, full_command)
158 if rv != 0:
159 return rv
160 if self._name == "gcc":
161 command = ("sudo cp -r /usr/lib/gcc/%s /build/%s/usr/lib/gcc/." %
162 (self._ctarget, self._board))
163 rv = self._ce.ChrootRunCommand(self._chromeos_root, command)
164 return rv
asharifc97199a2013-02-15 22:48:45 +0000165
asharifc97199a2013-02-15 22:48:45 +0000166 def MoveMaskFile(self):
167 self._new_mask_file = None
168 if os.path.isfile(self._mask_file):
169 self._new_mask_file = tempfile.mktemp()
170 command = "sudo mv %s %s" % (self._mask_file, self._new_mask_file)
171 self._ce.RunCommand(command)
172
173 def UnMoveMaskFile(self):
174 if self._new_mask_file:
175 command = "sudo mv %s %s" % (self._new_mask_file, self._mask_file)
176 self._ce.RunCommand(command)
bjanakiraman7f4a4852013-02-15 04:35:28 +0000177
bjanakiraman7f4a4852013-02-15 04:35:28 +0000178
asharif0d3535a2013-02-15 04:50:33 +0000179def Main(argv):
asharif19c73dd2013-02-15 04:35:37 +0000180 """The main function."""
asharif5a9bb462013-02-15 04:50:57 +0000181 # Common initializations
asharif19c73dd2013-02-15 04:35:37 +0000182 parser = optparse.OptionParser()
asharifc97199a2013-02-15 22:48:45 +0000183 parser.add_option("-c",
184 "--chromeos_root",
185 dest="chromeos_root",
asharifbcdd4e52013-02-16 01:05:17 +0000186 default="../../",
asharifc97199a2013-02-15 22:48:45 +0000187 help=("ChromeOS root checkout directory"
188 " uses ../.. if none given."))
189 parser.add_option("-g",
190 "--gcc_dir",
191 dest="gcc_dir",
192 help="The directory where gcc resides.")
shenhan8e8b0c22013-02-19 22:34:16 +0000193 parser.add_option("--binutils_dir",
194 dest="binutils_dir",
195 help="The directory where binutils resides.")
cmtice80d257f2013-02-15 23:44:51 +0000196 parser.add_option("-x",
197 "--gdb_dir",
198 dest="gdb_dir",
199 help="The directory where gdb resides.")
asharifc97199a2013-02-15 22:48:45 +0000200 parser.add_option("-b",
201 "--board",
202 dest="board",
203 default="x86-agz",
204 help="The target board.")
205 parser.add_option("-n",
206 "--noincremental",
207 dest="noincremental",
208 default=False,
asharifd751e252013-02-15 04:35:52 +0000209 action="store_true",
asharifc97199a2013-02-15 22:48:45 +0000210 help="Use FEATURES=keepwork to do incremental builds.")
cmticee59ac272013-02-19 20:20:09 +0000211 parser.add_option("--cflags",
212 dest="cflags",
213 default="",
214 help="Build a compiler with specified CFLAGS")
215 parser.add_option("--cxxflags",
216 dest="cxxflags",
217 default="",
218 help="Build a compiler with specified CXXFLAGS")
carrot2b549ca2013-02-19 22:45:25 +0000219 parser.add_option("--cflags_for_target",
220 dest="cflags_for_target",
221 default="",
222 help="Build the target libraries with specified flags")
223 parser.add_option("--cxxflags_for_target",
224 dest="cxxflags_for_target",
225 default="",
226 help="Build the target libraries with specified flags")
cmticee59ac272013-02-19 20:20:09 +0000227 parser.add_option("--ldflags",
228 dest="ldflags",
229 default="",
230 help="Build a compiler with specified LDFLAGS")
asharifc97199a2013-02-15 22:48:45 +0000231 parser.add_option("-d",
232 "--debug",
233 dest="debug",
234 default=False,
asharifd751e252013-02-15 04:35:52 +0000235 action="store_true",
cmticee59ac272013-02-19 20:20:09 +0000236 help="Build a compiler with -g3 -O0 appended to both"
237 " CFLAGS and CXXFLAGS.")
asharif86968c42013-02-15 23:44:37 +0000238 parser.add_option("-m",
239 "--mount_only",
240 dest="mount_only",
241 default=False,
242 action="store_true",
243 help="Just mount the tool directories.")
cmtice80d257f2013-02-15 23:44:51 +0000244 parser.add_option("-u",
245 "--unmount_only",
246 dest="unmount_only",
247 default=False,
248 action="store_true",
249 help="Just unmount the tool directories.")
cmticecbc868a2013-02-21 22:52:46 +0000250 parser.add_option("--extra_use_flags",
251 dest="extra_use_flags",
252 default="",
253 help="Extra flag for USE, to be passed to the ebuild. "
254 "('multislot' and 'mounted_<tool>' are always passed.)")
llozanof2726d22013-03-09 01:29:37 +0000255 parser.add_option("--gcc_enable_ccache",
256 dest="gcc_enable_ccache",
257 default=False,
258 action="store_true",
259 help="Enable ccache for the gcc invocations")
bjanakiraman7f4a4852013-02-15 04:35:28 +0000260
asharifc97199a2013-02-15 22:48:45 +0000261 options, _ = parser.parse_args(argv)
asharif17621302013-02-15 04:46:35 +0000262
kbaclawski20082a02013-02-16 02:12:57 +0000263 chromeos_root = misc.CanonicalizePath(options.chromeos_root)
cmtice80d257f2013-02-15 23:44:51 +0000264 if options.gcc_dir:
kbaclawski20082a02013-02-16 02:12:57 +0000265 gcc_dir = misc.CanonicalizePath(options.gcc_dir)
Luis Lozano4cea9de2013-03-20 12:32:56 -0700266 assert gcc_dir and os.path.isdir(gcc_dir), "gcc_dir does not exist!"
shenhan8e8b0c22013-02-19 22:34:16 +0000267 if options.binutils_dir:
268 binutils_dir = misc.CanonicalizePath(options.binutils_dir)
Luis Lozano4cea9de2013-03-20 12:32:56 -0700269 assert os.path.isdir(binutils_dir), "binutils_dir does not exist!"
cmtice80d257f2013-02-15 23:44:51 +0000270 if options.gdb_dir:
kbaclawski20082a02013-02-16 02:12:57 +0000271 gdb_dir = misc.CanonicalizePath(options.gdb_dir)
Luis Lozano4cea9de2013-03-20 12:32:56 -0700272 assert os.path.isdir(gdb_dir), "gdb_dir does not exist!"
cmtice80d257f2013-02-15 23:44:51 +0000273 if options.unmount_only:
274 options.mount_only = False
275 elif options.mount_only:
276 options.unmount_only = False
asharifc97199a2013-02-15 22:48:45 +0000277 build_env = {}
cmticee59ac272013-02-19 20:20:09 +0000278 if options.cflags:
carrot255fd462013-02-19 22:43:16 +0000279 build_env["CFLAGS"] = "`portageq envvar CFLAGS` " + options.cflags
cmticee59ac272013-02-19 20:20:09 +0000280 if options.cxxflags:
carrot255fd462013-02-19 22:43:16 +0000281 build_env["CXXFLAGS"] = "`portageq envvar CXXFLAGS` " + options.cxxflags
carrot2b549ca2013-02-19 22:45:25 +0000282 if options.cflags_for_target:
283 build_env["CFLAGS_FOR_TARGET"] = options.cflags_for_target
284 if options.cxxflags_for_target:
285 build_env["CXXFLAGS_FOR_TARGET"] = options.cxxflags_for_target
carrot255fd462013-02-19 22:43:16 +0000286 if options.ldflags:
cmticee59ac272013-02-19 20:20:09 +0000287 build_env["LDFLAGS"] = options.ldflags
asharifc97199a2013-02-15 22:48:45 +0000288 if options.debug:
289 debug_flags = "-g3 -O0"
cmticee59ac272013-02-19 20:20:09 +0000290 if "CFLAGS" in build_env:
291 build_env["CFLAGS"] += " %s" % (debug_flags)
292 else:
293 build_env["CFLAGS"] = debug_flags
294 if "CXXFLAGS" in build_env:
295 build_env["CXXFLAGS"] += " %s" % (debug_flags)
296 else:
297 build_env["CXXFLAGS"] = debug_flags
cmticecbc868a2013-02-21 22:52:46 +0000298 if options.extra_use_flags:
299 build_env["USE"] = options.extra_use_flags
bjanakiraman7f4a4852013-02-15 04:35:28 +0000300
asharif86968c42013-02-15 23:44:37 +0000301 # Create toolchain parts
carrote6f773c2013-02-19 22:34:44 +0000302 toolchain_parts = {}
asharif86968c42013-02-15 23:44:37 +0000303 for board in options.board.split(","):
304 if options.gcc_dir:
asharifc97199a2013-02-15 22:48:45 +0000305 tp = ToolchainPart("gcc", gcc_dir, chromeos_root, board,
llozanof2726d22013-03-09 01:29:37 +0000306 not options.noincremental, build_env,
307 options.gcc_enable_ccache)
carrote6f773c2013-02-19 22:34:44 +0000308 toolchain_parts[tp.tag] = tp
309 tp.RunSetupBoardIfNecessary()
shenhan8e8b0c22013-02-19 22:34:16 +0000310 if options.binutils_dir:
311 tp = ToolchainPart("binutils", binutils_dir, chromeos_root, board,
312 not options.noincremental, build_env)
carrote6f773c2013-02-19 22:34:44 +0000313 toolchain_parts[tp.tag] = tp
314 tp.RunSetupBoardIfNecessary()
cmtice80d257f2013-02-15 23:44:51 +0000315 if options.gdb_dir:
316 tp = ToolchainPart("gdb", gdb_dir, chromeos_root, board,
317 not options.noincremental, build_env)
carrote6f773c2013-02-19 22:34:44 +0000318 toolchain_parts[tp.tag] = tp
319 tp.RunSetupBoardIfNecessary()
asharif86968c42013-02-15 23:44:37 +0000320
shenhanbecf6242013-02-19 20:43:32 +0000321 rv = 0
asharif86968c42013-02-15 23:44:37 +0000322 try:
carrote6f773c2013-02-19 22:34:44 +0000323 for tag in toolchain_parts:
324 tp = toolchain_parts[tag]
cmtice80d257f2013-02-15 23:44:51 +0000325 if options.mount_only or options.unmount_only:
326 tp.MountSources(options.unmount_only)
asharif86968c42013-02-15 23:44:37 +0000327 else:
shenhanbecf6242013-02-19 20:43:32 +0000328 rv = rv + tp.Build()
asharifc97199a2013-02-15 22:48:45 +0000329 finally:
330 print "Exiting..."
llozano5fee82f2013-03-11 17:59:40 +0000331 return rv
asharif19c73dd2013-02-15 04:35:37 +0000332
333if __name__ == "__main__":
asharif2198c512013-02-15 09:21:35 +0000334 retval = Main(sys.argv)
335 sys.exit(retval)