blob: 31faa449fd7c47849ec15abb0b91006837b25d58 [file] [log] [blame]
shenhan8e8b0c22013-02-19 22:34:16 +00001#!/usr/bin/python
bjanakiraman7f4a4852013-02-15 04:35:28 +00002#
3# Copyright 2010 Google Inc. All Rights Reserved.
4
5"""Script to build the ChromeOS toolchain.
6
7This script sets up the toolchain if you give it the gcctools directory.
8"""
9
10__author__ = "asharif@google.com (Ahmad Sharif)"
11
asharif80c6e552013-02-15 04:35:40 +000012import getpass
bjanakiraman7f4a4852013-02-15 04:35:28 +000013import optparse
asharif17621302013-02-15 04:46:35 +000014import os
bjanakiraman7f4a4852013-02-15 04:35:28 +000015import sys
asharifc97199a2013-02-15 22:48:45 +000016import tempfile
kbaclawski20082a02013-02-16 02:12:57 +000017
asharif252df0f2013-02-15 04:46:28 +000018import tc_enter_chroot
raymes01959ae2013-02-15 04:50:07 +000019from utils import command_executer
shenhanad803432013-02-16 03:14:51 +000020from utils import constants
kbaclawski20082a02013-02-16 02:12:57 +000021from utils import misc
bjanakiraman7f4a4852013-02-15 04:35:28 +000022
asharif5a9bb462013-02-15 04:50:57 +000023
asharifc97199a2013-02-15 22:48:45 +000024class ToolchainPart(object):
25 def __init__(self, name, source_path, chromeos_root, board, incremental,
26 build_env):
27 self._name = name
kbaclawski20082a02013-02-16 02:12:57 +000028 self._source_path = misc.CanonicalizePath(source_path)
asharifc97199a2013-02-15 22:48:45 +000029 self._chromeos_root = chromeos_root
30 self._board = board
kbaclawski20082a02013-02-16 02:12:57 +000031 self._ctarget = misc.GetCtargetFromBoard(self._board,
asharif77bd80d2013-02-15 22:49:32 +000032 self._chromeos_root)
carrote6f773c2013-02-19 22:34:44 +000033 self.tag = "%s-%s" % (name, self._ctarget)
asharifc97199a2013-02-15 22:48:45 +000034 self._ce = command_executer.GetCommandExecuter()
35 self._mask_file = os.path.join(
36 self._chromeos_root,
37 "chroot",
38 "etc/portage/package.mask/cross-%s" % self._ctarget)
39 self._new_mask_file = None
40
shenhanad803432013-02-16 03:14:51 +000041 self._chroot_source_path = os.path.join(constants.mounted_toolchain_root,
llozano85b37152013-02-16 03:14:57 +000042 self._name).lstrip("/")
asharifc97199a2013-02-15 22:48:45 +000043 self._incremental = incremental
44 self._build_env = build_env
45
46 def RunSetupBoardIfNecessary(self):
47 cross_symlink = os.path.join(
48 self._chromeos_root,
49 "chroot",
carrotccae6272013-02-19 22:34:51 +000050 "usr/local/bin/emerge-%s" % self._board)
asharifc97199a2013-02-15 22:48:45 +000051 if not os.path.exists(cross_symlink):
52 command = "./setup_board --board=%s" % self._board
asharifca3c6c12013-02-15 23:17:54 +000053 self._ce.ChrootRunCommand(self._chromeos_root, command)
asharifc97199a2013-02-15 22:48:45 +000054
55 def Build(self):
shenhanbecf6242013-02-19 20:43:32 +000056 rv = 1
asharifc97199a2013-02-15 22:48:45 +000057 try:
asharif7dd6d862013-02-15 23:17:46 +000058 self.UninstallTool()
asharifc97199a2013-02-15 22:48:45 +000059 self.MoveMaskFile()
cmtice80d257f2013-02-15 23:44:51 +000060 self.MountSources(False)
asharif9e3cf6e2013-02-16 03:13:38 +000061 self.RemoveCompiledFile()
shenhanbecf6242013-02-19 20:43:32 +000062 rv = self.BuildTool()
asharifc97199a2013-02-15 22:48:45 +000063 finally:
64 self.UnMoveMaskFile()
shenhanbecf6242013-02-19 20:43:32 +000065 return rv
asharifc97199a2013-02-15 22:48:45 +000066
67 def RemoveCompiledFile(self):
68 compiled_file = os.path.join(self._chromeos_root,
69 "chroot",
70 "var/tmp/portage/cross-%s" % self._ctarget,
71 "%s-9999" % self._name,
72 ".compiled")
asharif9e3cf6e2013-02-16 03:13:38 +000073 command = "rm -f %s" % compiled_file
asharifc97199a2013-02-15 22:48:45 +000074 self._ce.RunCommand(command)
75
cmtice80d257f2013-02-15 23:44:51 +000076 def MountSources(self, unmount_source):
asharifc97199a2013-02-15 22:48:45 +000077 mount_points = []
78 mounted_source_path = os.path.join(self._chromeos_root,
79 "chroot",
80 self._chroot_source_path)
81 src_mp = tc_enter_chroot.MountPoint(
82 self._source_path,
83 mounted_source_path,
84 getpass.getuser(),
85 "ro")
86 mount_points.append(src_mp)
87
88 build_suffix = "build-%s" % self._ctarget
89 build_dir = "%s-%s" % (self._source_path, build_suffix)
90
91 if not self._incremental and os.path.exists(build_dir):
92 command = "rm -rf %s/*" % build_dir
93 self._ce.RunCommand(command)
94
95 # Create a -build directory for the objects.
96 command = "mkdir -p %s" % build_dir
97 self._ce.RunCommand(command)
98
99 mounted_build_dir = os.path.join(
100 self._chromeos_root, "chroot", "%s-%s" %
101 (self._chroot_source_path, build_suffix))
102 build_mp = tc_enter_chroot.MountPoint(
103 build_dir,
104 mounted_build_dir,
105 getpass.getuser())
106 mount_points.append(build_mp)
107
cmtice80d257f2013-02-15 23:44:51 +0000108 if unmount_source:
109 unmount_statuses = [mp.UnMount() == 0 for mp in mount_points]
asharifc97199a2013-02-15 22:48:45 +0000110 assert all(unmount_statuses), "Could not unmount all mount points!"
cmtice80d257f2013-02-15 23:44:51 +0000111 else:
112 mount_statuses = [mp.DoMount() == 0 for mp in mount_points]
113
114 if not all(mount_statuses):
115 mounted = [mp for mp, status in zip(mount_points, mount_statuses) if status]
116 unmount_statuses = [mp.UnMount() == 0 for mp in mounted]
117 assert all(unmount_statuses), "Could not unmount all mount points!"
118
asharifc97199a2013-02-15 22:48:45 +0000119
asharif7dd6d862013-02-15 23:17:46 +0000120 def UninstallTool(self):
121 command = "sudo CLEAN_DELAY=0 emerge -C cross-%s/%s" % (self._ctarget, self._name)
asharifca3c6c12013-02-15 23:17:54 +0000122 self._ce.ChrootRunCommand(self._chromeos_root, command)
asharif7dd6d862013-02-15 23:17:46 +0000123
asharifc97199a2013-02-15 22:48:45 +0000124 def BuildTool(self):
125 env = self._build_env
asharif9e499162013-02-16 02:41:39 +0000126 # FEATURES=buildpkg adds minutes of time so we disable it.
shenhanfdc0f572013-02-19 18:48:36 +0000127 # TODO(shenhan): keep '-sandbox' for a while for compatibility, then remove
128 # it after a while.
129 features = "nostrip userpriv userfetch -usersandbox -sandbox noclean -buildpkg"
asharifc97199a2013-02-15 22:48:45 +0000130 env["FEATURES"] = features
131
132 if self._incremental:
133 env["FEATURES"] += " keepwork"
134
cmticecbc868a2013-02-21 22:52:46 +0000135 if "USE" in env:
136 env["USE"] += " multislot mounted_%s" % self._name
137 else:
138 env["USE"] = "multislot mounted_%s" % self._name
139
asharifc97199a2013-02-15 22:48:45 +0000140 env["%s_SOURCE_PATH" % self._name.upper()] = (
141 os.path.join("/", self._chroot_source_path))
142 env["ACCEPT_KEYWORDS"] = "~*"
143 env_string = " ".join(["%s=\"%s\"" % var for var in env.items()])
144 command = "emerge =cross-%s/%s-9999" % (self._ctarget, self._name)
145 full_command = "sudo %s %s" % (env_string, command)
shenhanbecf6242013-02-19 20:43:32 +0000146 return self._ce.ChrootRunCommand(self._chromeos_root, full_command)
asharifc97199a2013-02-15 22:48:45 +0000147
asharifc97199a2013-02-15 22:48:45 +0000148 def MoveMaskFile(self):
149 self._new_mask_file = None
150 if os.path.isfile(self._mask_file):
151 self._new_mask_file = tempfile.mktemp()
152 command = "sudo mv %s %s" % (self._mask_file, self._new_mask_file)
153 self._ce.RunCommand(command)
154
155 def UnMoveMaskFile(self):
156 if self._new_mask_file:
157 command = "sudo mv %s %s" % (self._new_mask_file, self._mask_file)
158 self._ce.RunCommand(command)
bjanakiraman7f4a4852013-02-15 04:35:28 +0000159
bjanakiraman7f4a4852013-02-15 04:35:28 +0000160
asharif0d3535a2013-02-15 04:50:33 +0000161def Main(argv):
asharif19c73dd2013-02-15 04:35:37 +0000162 """The main function."""
asharif5a9bb462013-02-15 04:50:57 +0000163 # Common initializations
asharif19c73dd2013-02-15 04:35:37 +0000164 parser = optparse.OptionParser()
asharifc97199a2013-02-15 22:48:45 +0000165 parser.add_option("-c",
166 "--chromeos_root",
167 dest="chromeos_root",
asharifbcdd4e52013-02-16 01:05:17 +0000168 default="../../",
asharifc97199a2013-02-15 22:48:45 +0000169 help=("ChromeOS root checkout directory"
170 " uses ../.. if none given."))
171 parser.add_option("-g",
172 "--gcc_dir",
173 dest="gcc_dir",
174 help="The directory where gcc resides.")
shenhan8e8b0c22013-02-19 22:34:16 +0000175 parser.add_option("--binutils_dir",
176 dest="binutils_dir",
177 help="The directory where binutils resides.")
cmtice80d257f2013-02-15 23:44:51 +0000178 parser.add_option("-x",
179 "--gdb_dir",
180 dest="gdb_dir",
181 help="The directory where gdb resides.")
asharifc97199a2013-02-15 22:48:45 +0000182 parser.add_option("-b",
183 "--board",
184 dest="board",
185 default="x86-agz",
186 help="The target board.")
187 parser.add_option("-n",
188 "--noincremental",
189 dest="noincremental",
190 default=False,
asharifd751e252013-02-15 04:35:52 +0000191 action="store_true",
asharifc97199a2013-02-15 22:48:45 +0000192 help="Use FEATURES=keepwork to do incremental builds.")
cmticee59ac272013-02-19 20:20:09 +0000193 parser.add_option("--cflags",
194 dest="cflags",
195 default="",
196 help="Build a compiler with specified CFLAGS")
197 parser.add_option("--cxxflags",
198 dest="cxxflags",
199 default="",
200 help="Build a compiler with specified CXXFLAGS")
carrot2b549ca2013-02-19 22:45:25 +0000201 parser.add_option("--cflags_for_target",
202 dest="cflags_for_target",
203 default="",
204 help="Build the target libraries with specified flags")
205 parser.add_option("--cxxflags_for_target",
206 dest="cxxflags_for_target",
207 default="",
208 help="Build the target libraries with specified flags")
cmticee59ac272013-02-19 20:20:09 +0000209 parser.add_option("--ldflags",
210 dest="ldflags",
211 default="",
212 help="Build a compiler with specified LDFLAGS")
asharifc97199a2013-02-15 22:48:45 +0000213 parser.add_option("-d",
214 "--debug",
215 dest="debug",
216 default=False,
asharifd751e252013-02-15 04:35:52 +0000217 action="store_true",
cmticee59ac272013-02-19 20:20:09 +0000218 help="Build a compiler with -g3 -O0 appended to both"
219 " CFLAGS and CXXFLAGS.")
asharif86968c42013-02-15 23:44:37 +0000220 parser.add_option("-m",
221 "--mount_only",
222 dest="mount_only",
223 default=False,
224 action="store_true",
225 help="Just mount the tool directories.")
cmtice80d257f2013-02-15 23:44:51 +0000226 parser.add_option("-u",
227 "--unmount_only",
228 dest="unmount_only",
229 default=False,
230 action="store_true",
231 help="Just unmount the tool directories.")
cmticecbc868a2013-02-21 22:52:46 +0000232 parser.add_option("--extra_use_flags",
233 dest="extra_use_flags",
234 default="",
235 help="Extra flag for USE, to be passed to the ebuild. "
236 "('multislot' and 'mounted_<tool>' are always passed.)")
asharif86968c42013-02-15 23:44:37 +0000237
bjanakiraman7f4a4852013-02-15 04:35:28 +0000238
asharifc97199a2013-02-15 22:48:45 +0000239 options, _ = parser.parse_args(argv)
asharif17621302013-02-15 04:46:35 +0000240
kbaclawski20082a02013-02-16 02:12:57 +0000241 chromeos_root = misc.CanonicalizePath(options.chromeos_root)
cmtice80d257f2013-02-15 23:44:51 +0000242 if options.gcc_dir:
kbaclawski20082a02013-02-16 02:12:57 +0000243 gcc_dir = misc.CanonicalizePath(options.gcc_dir)
shenhan8e8b0c22013-02-19 22:34:16 +0000244 if options.binutils_dir:
245 binutils_dir = misc.CanonicalizePath(options.binutils_dir)
cmtice80d257f2013-02-15 23:44:51 +0000246 if options.gdb_dir:
kbaclawski20082a02013-02-16 02:12:57 +0000247 gdb_dir = misc.CanonicalizePath(options.gdb_dir)
cmtice80d257f2013-02-15 23:44:51 +0000248 if options.unmount_only:
249 options.mount_only = False
250 elif options.mount_only:
251 options.unmount_only = False
asharifc97199a2013-02-15 22:48:45 +0000252 build_env = {}
cmticee59ac272013-02-19 20:20:09 +0000253 if options.cflags:
carrot255fd462013-02-19 22:43:16 +0000254 build_env["CFLAGS"] = "`portageq envvar CFLAGS` " + options.cflags
cmticee59ac272013-02-19 20:20:09 +0000255 if options.cxxflags:
carrot255fd462013-02-19 22:43:16 +0000256 build_env["CXXFLAGS"] = "`portageq envvar CXXFLAGS` " + options.cxxflags
carrot2b549ca2013-02-19 22:45:25 +0000257 if options.cflags_for_target:
258 build_env["CFLAGS_FOR_TARGET"] = options.cflags_for_target
259 if options.cxxflags_for_target:
260 build_env["CXXFLAGS_FOR_TARGET"] = options.cxxflags_for_target
carrot255fd462013-02-19 22:43:16 +0000261 if options.ldflags:
cmticee59ac272013-02-19 20:20:09 +0000262 build_env["LDFLAGS"] = options.ldflags
asharifc97199a2013-02-15 22:48:45 +0000263 if options.debug:
264 debug_flags = "-g3 -O0"
cmticee59ac272013-02-19 20:20:09 +0000265 if "CFLAGS" in build_env:
266 build_env["CFLAGS"] += " %s" % (debug_flags)
267 else:
268 build_env["CFLAGS"] = debug_flags
269 if "CXXFLAGS" in build_env:
270 build_env["CXXFLAGS"] += " %s" % (debug_flags)
271 else:
272 build_env["CXXFLAGS"] = debug_flags
cmticecbc868a2013-02-21 22:52:46 +0000273 if options.extra_use_flags:
274 build_env["USE"] = options.extra_use_flags
bjanakiraman7f4a4852013-02-15 04:35:28 +0000275
asharif86968c42013-02-15 23:44:37 +0000276 # Create toolchain parts
carrote6f773c2013-02-19 22:34:44 +0000277 toolchain_parts = {}
asharif86968c42013-02-15 23:44:37 +0000278 for board in options.board.split(","):
279 if options.gcc_dir:
asharifc97199a2013-02-15 22:48:45 +0000280 tp = ToolchainPart("gcc", gcc_dir, chromeos_root, board,
281 not options.noincremental, build_env)
carrote6f773c2013-02-19 22:34:44 +0000282 toolchain_parts[tp.tag] = tp
283 tp.RunSetupBoardIfNecessary()
shenhan8e8b0c22013-02-19 22:34:16 +0000284 if options.binutils_dir:
285 tp = ToolchainPart("binutils", binutils_dir, chromeos_root, board,
286 not options.noincremental, build_env)
carrote6f773c2013-02-19 22:34:44 +0000287 toolchain_parts[tp.tag] = tp
288 tp.RunSetupBoardIfNecessary()
cmtice80d257f2013-02-15 23:44:51 +0000289 if options.gdb_dir:
290 tp = ToolchainPart("gdb", gdb_dir, chromeos_root, board,
291 not options.noincremental, build_env)
carrote6f773c2013-02-19 22:34:44 +0000292 toolchain_parts[tp.tag] = tp
293 tp.RunSetupBoardIfNecessary()
asharif86968c42013-02-15 23:44:37 +0000294
shenhanbecf6242013-02-19 20:43:32 +0000295 rv = 0
asharif86968c42013-02-15 23:44:37 +0000296 try:
carrote6f773c2013-02-19 22:34:44 +0000297 for tag in toolchain_parts:
298 tp = toolchain_parts[tag]
cmtice80d257f2013-02-15 23:44:51 +0000299 if options.mount_only or options.unmount_only:
300 tp.MountSources(options.unmount_only)
asharif86968c42013-02-15 23:44:37 +0000301 else:
shenhanbecf6242013-02-19 20:43:32 +0000302 rv = rv + tp.Build()
asharifc97199a2013-02-15 22:48:45 +0000303 finally:
304 print "Exiting..."
shenhanbecf6242013-02-19 20:43:32 +0000305 return rv
asharif19c73dd2013-02-15 04:35:37 +0000306
307if __name__ == "__main__":
asharif2198c512013-02-15 09:21:35 +0000308 retval = Main(sys.argv)
309 sys.exit(retval)