blob: 8ab4ab63c9c2052e198671b6bcaaed9c99d400d4 [file] [log] [blame]
bjanakiraman7f4a4852013-02-15 04:35:28 +00001#!/usr/bin/python2.6
2#
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)
asharifc97199a2013-02-15 22:48:45 +000033 self._ce = command_executer.GetCommandExecuter()
34 self._mask_file = os.path.join(
35 self._chromeos_root,
36 "chroot",
37 "etc/portage/package.mask/cross-%s" % self._ctarget)
38 self._new_mask_file = None
39
shenhanad803432013-02-16 03:14:51 +000040 self._chroot_source_path = os.path.join(constants.mounted_toolchain_root,
llozano85b37152013-02-16 03:14:57 +000041 self._name).lstrip("/")
asharifc97199a2013-02-15 22:48:45 +000042 self._incremental = incremental
43 self._build_env = build_env
44
45 def RunSetupBoardIfNecessary(self):
46 cross_symlink = os.path.join(
47 self._chromeos_root,
48 "chroot",
49 "usr/local/portage/crossdev/cross-%s" % self._ctarget)
50 if not os.path.exists(cross_symlink):
51 command = "./setup_board --board=%s" % self._board
asharifca3c6c12013-02-15 23:17:54 +000052 self._ce.ChrootRunCommand(self._chromeos_root, command)
asharifc97199a2013-02-15 22:48:45 +000053
54 def Build(self):
55 self.RunSetupBoardIfNecessary()
56
57 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()
asharifc97199a2013-02-15 22:48:45 +000062 self.BuildTool()
63 finally:
64 self.UnMoveMaskFile()
asharifc97199a2013-02-15 22:48:45 +000065
66 def RemoveCompiledFile(self):
67 compiled_file = os.path.join(self._chromeos_root,
68 "chroot",
69 "var/tmp/portage/cross-%s" % self._ctarget,
70 "%s-9999" % self._name,
71 ".compiled")
asharif9e3cf6e2013-02-16 03:13:38 +000072 command = "rm -f %s" % compiled_file
asharifc97199a2013-02-15 22:48:45 +000073 self._ce.RunCommand(command)
74
cmtice80d257f2013-02-15 23:44:51 +000075 def MountSources(self, unmount_source):
asharifc97199a2013-02-15 22:48:45 +000076 mount_points = []
77 mounted_source_path = os.path.join(self._chromeos_root,
78 "chroot",
79 self._chroot_source_path)
80 src_mp = tc_enter_chroot.MountPoint(
81 self._source_path,
82 mounted_source_path,
83 getpass.getuser(),
84 "ro")
85 mount_points.append(src_mp)
86
87 build_suffix = "build-%s" % self._ctarget
88 build_dir = "%s-%s" % (self._source_path, build_suffix)
89
90 if not self._incremental and os.path.exists(build_dir):
91 command = "rm -rf %s/*" % build_dir
92 self._ce.RunCommand(command)
93
94 # Create a -build directory for the objects.
95 command = "mkdir -p %s" % build_dir
96 self._ce.RunCommand(command)
97
98 mounted_build_dir = os.path.join(
99 self._chromeos_root, "chroot", "%s-%s" %
100 (self._chroot_source_path, build_suffix))
101 build_mp = tc_enter_chroot.MountPoint(
102 build_dir,
103 mounted_build_dir,
104 getpass.getuser())
105 mount_points.append(build_mp)
106
cmtice80d257f2013-02-15 23:44:51 +0000107 if unmount_source:
108 unmount_statuses = [mp.UnMount() == 0 for mp in mount_points]
asharifc97199a2013-02-15 22:48:45 +0000109 assert all(unmount_statuses), "Could not unmount all mount points!"
cmtice80d257f2013-02-15 23:44:51 +0000110 else:
111 mount_statuses = [mp.DoMount() == 0 for mp in mount_points]
112
113 if not all(mount_statuses):
114 mounted = [mp for mp, status in zip(mount_points, mount_statuses) if status]
115 unmount_statuses = [mp.UnMount() == 0 for mp in mounted]
116 assert all(unmount_statuses), "Could not unmount all mount points!"
117
asharifc97199a2013-02-15 22:48:45 +0000118
asharif7dd6d862013-02-15 23:17:46 +0000119 def UninstallTool(self):
120 command = "sudo CLEAN_DELAY=0 emerge -C cross-%s/%s" % (self._ctarget, self._name)
asharifca3c6c12013-02-15 23:17:54 +0000121 self._ce.ChrootRunCommand(self._chromeos_root, command)
asharif7dd6d862013-02-15 23:17:46 +0000122
asharifc97199a2013-02-15 22:48:45 +0000123 def BuildTool(self):
124 env = self._build_env
asharif9e499162013-02-16 02:41:39 +0000125 # FEATURES=buildpkg adds minutes of time so we disable it.
shenhanfdc0f572013-02-19 18:48:36 +0000126 # TODO(shenhan): keep '-sandbox' for a while for compatibility, then remove
127 # it after a while.
128 features = "nostrip userpriv userfetch -usersandbox -sandbox noclean -buildpkg"
asharifc97199a2013-02-15 22:48:45 +0000129 env["FEATURES"] = features
130
131 if self._incremental:
132 env["FEATURES"] += " keepwork"
133
134 env["USE"] = "multislot mounted_%s" % self._name
135 env["%s_SOURCE_PATH" % self._name.upper()] = (
136 os.path.join("/", self._chroot_source_path))
137 env["ACCEPT_KEYWORDS"] = "~*"
138 env_string = " ".join(["%s=\"%s\"" % var for var in env.items()])
139 command = "emerge =cross-%s/%s-9999" % (self._ctarget, self._name)
140 full_command = "sudo %s %s" % (env_string, command)
asharifca3c6c12013-02-15 23:17:54 +0000141 self._ce.ChrootRunCommand(self._chromeos_root, full_command)
asharifc97199a2013-02-15 22:48:45 +0000142
asharifc97199a2013-02-15 22:48:45 +0000143 def MoveMaskFile(self):
144 self._new_mask_file = None
145 if os.path.isfile(self._mask_file):
146 self._new_mask_file = tempfile.mktemp()
147 command = "sudo mv %s %s" % (self._mask_file, self._new_mask_file)
148 self._ce.RunCommand(command)
149
150 def UnMoveMaskFile(self):
151 if self._new_mask_file:
152 command = "sudo mv %s %s" % (self._new_mask_file, self._mask_file)
153 self._ce.RunCommand(command)
bjanakiraman7f4a4852013-02-15 04:35:28 +0000154
bjanakiraman7f4a4852013-02-15 04:35:28 +0000155
asharif0d3535a2013-02-15 04:50:33 +0000156def Main(argv):
asharif19c73dd2013-02-15 04:35:37 +0000157 """The main function."""
asharif5a9bb462013-02-15 04:50:57 +0000158 # Common initializations
asharif19c73dd2013-02-15 04:35:37 +0000159 parser = optparse.OptionParser()
asharifc97199a2013-02-15 22:48:45 +0000160 parser.add_option("-c",
161 "--chromeos_root",
162 dest="chromeos_root",
asharifbcdd4e52013-02-16 01:05:17 +0000163 default="../../",
asharifc97199a2013-02-15 22:48:45 +0000164 help=("ChromeOS root checkout directory"
165 " uses ../.. if none given."))
166 parser.add_option("-g",
167 "--gcc_dir",
168 dest="gcc_dir",
169 help="The directory where gcc resides.")
cmtice80d257f2013-02-15 23:44:51 +0000170 parser.add_option("-x",
171 "--gdb_dir",
172 dest="gdb_dir",
173 help="The directory where gdb resides.")
asharifc97199a2013-02-15 22:48:45 +0000174 parser.add_option("-b",
175 "--board",
176 dest="board",
177 default="x86-agz",
178 help="The target board.")
179 parser.add_option("-n",
180 "--noincremental",
181 dest="noincremental",
182 default=False,
asharifd751e252013-02-15 04:35:52 +0000183 action="store_true",
asharifc97199a2013-02-15 22:48:45 +0000184 help="Use FEATURES=keepwork to do incremental builds.")
cmticee59ac272013-02-19 20:20:09 +0000185 parser.add_option("--cflags",
186 dest="cflags",
187 default="",
188 help="Build a compiler with specified CFLAGS")
189 parser.add_option("--cxxflags",
190 dest="cxxflags",
191 default="",
192 help="Build a compiler with specified CXXFLAGS")
193 parser.add_option("--ldflags",
194 dest="ldflags",
195 default="",
196 help="Build a compiler with specified LDFLAGS")
asharifc97199a2013-02-15 22:48:45 +0000197 parser.add_option("-d",
198 "--debug",
199 dest="debug",
200 default=False,
asharifd751e252013-02-15 04:35:52 +0000201 action="store_true",
cmticee59ac272013-02-19 20:20:09 +0000202 help="Build a compiler with -g3 -O0 appended to both"
203 " CFLAGS and CXXFLAGS.")
asharif86968c42013-02-15 23:44:37 +0000204 parser.add_option("-m",
205 "--mount_only",
206 dest="mount_only",
207 default=False,
208 action="store_true",
209 help="Just mount the tool directories.")
cmtice80d257f2013-02-15 23:44:51 +0000210 parser.add_option("-u",
211 "--unmount_only",
212 dest="unmount_only",
213 default=False,
214 action="store_true",
215 help="Just unmount the tool directories.")
asharif86968c42013-02-15 23:44:37 +0000216
bjanakiraman7f4a4852013-02-15 04:35:28 +0000217
asharifc97199a2013-02-15 22:48:45 +0000218 options, _ = parser.parse_args(argv)
asharif17621302013-02-15 04:46:35 +0000219
kbaclawski20082a02013-02-16 02:12:57 +0000220 chromeos_root = misc.CanonicalizePath(options.chromeos_root)
cmtice80d257f2013-02-15 23:44:51 +0000221 if options.gcc_dir:
kbaclawski20082a02013-02-16 02:12:57 +0000222 gcc_dir = misc.CanonicalizePath(options.gcc_dir)
cmtice80d257f2013-02-15 23:44:51 +0000223 if options.gdb_dir:
kbaclawski20082a02013-02-16 02:12:57 +0000224 gdb_dir = misc.CanonicalizePath(options.gdb_dir)
cmtice80d257f2013-02-15 23:44:51 +0000225 if options.unmount_only:
226 options.mount_only = False
227 elif options.mount_only:
228 options.unmount_only = False
asharifc97199a2013-02-15 22:48:45 +0000229 build_env = {}
cmticee59ac272013-02-19 20:20:09 +0000230 if options.cflags:
231 build_env["CFLAGS"] = options.cflags
232 if options.cxxflags:
233 build_env["CXXFLAGS"] = options.cxxflags
234 if options.cxxflags:
235 build_env["LDFLAGS"] = options.ldflags
asharifc97199a2013-02-15 22:48:45 +0000236 if options.debug:
237 debug_flags = "-g3 -O0"
cmticee59ac272013-02-19 20:20:09 +0000238 if "CFLAGS" in build_env:
239 build_env["CFLAGS"] += " %s" % (debug_flags)
240 else:
241 build_env["CFLAGS"] = debug_flags
242 if "CXXFLAGS" in build_env:
243 build_env["CXXFLAGS"] += " %s" % (debug_flags)
244 else:
245 build_env["CXXFLAGS"] = debug_flags
bjanakiraman7f4a4852013-02-15 04:35:28 +0000246
asharif86968c42013-02-15 23:44:37 +0000247 # Create toolchain parts
248 toolchain_parts = []
249 for board in options.board.split(","):
250 if options.gcc_dir:
asharifc97199a2013-02-15 22:48:45 +0000251 tp = ToolchainPart("gcc", gcc_dir, chromeos_root, board,
252 not options.noincremental, build_env)
asharif86968c42013-02-15 23:44:37 +0000253 toolchain_parts.append(tp)
cmtice80d257f2013-02-15 23:44:51 +0000254 if options.gdb_dir:
255 tp = ToolchainPart("gdb", gdb_dir, chromeos_root, board,
256 not options.noincremental, build_env)
257 toolchain_parts.append(tp)
asharif86968c42013-02-15 23:44:37 +0000258
259 try:
260 for tp in toolchain_parts:
cmtice80d257f2013-02-15 23:44:51 +0000261 if options.mount_only or options.unmount_only:
262 tp.MountSources(options.unmount_only)
asharif86968c42013-02-15 23:44:37 +0000263 else:
264 tp.Build()
asharifc97199a2013-02-15 22:48:45 +0000265 finally:
266 print "Exiting..."
267 return 0
asharif0d3535a2013-02-15 04:50:33 +0000268
asharif19c73dd2013-02-15 04:35:37 +0000269
270if __name__ == "__main__":
asharif2198c512013-02-15 09:21:35 +0000271 retval = Main(sys.argv)
272 sys.exit(retval)