blob: 92e018ce1d15b3b45d5a8907aa084368795a2d43 [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
asharif252df0f2013-02-15 04:46:28 +000017import tc_enter_chroot
raymes01959ae2013-02-15 04:50:07 +000018from utils import command_executer
bjanakiraman7f4a4852013-02-15 04:35:28 +000019from utils import utils
20
asharif5a9bb462013-02-15 04:50:57 +000021
asharifc97199a2013-02-15 22:48:45 +000022class ToolchainPart(object):
23 def __init__(self, name, source_path, chromeos_root, board, incremental,
24 build_env):
25 self._name = name
26 self._source_path = utils.CanonicalizePath(source_path)
27 self._chromeos_root = chromeos_root
28 self._board = board
asharif77bd80d2013-02-15 22:49:32 +000029 self._ctarget = utils.GetCtargetFromBoard(self._board,
30 self._chromeos_root)
asharifc97199a2013-02-15 22:48:45 +000031 self._ce = command_executer.GetCommandExecuter()
32 self._mask_file = os.path.join(
33 self._chromeos_root,
34 "chroot",
35 "etc/portage/package.mask/cross-%s" % self._ctarget)
36 self._new_mask_file = None
37
38 self._chroot_source_path = "usr/local/toolchain_root/%s" % self._name
39 self._incremental = incremental
40 self._build_env = build_env
41
42 def RunSetupBoardIfNecessary(self):
43 cross_symlink = os.path.join(
44 self._chromeos_root,
45 "chroot",
46 "usr/local/portage/crossdev/cross-%s" % self._ctarget)
47 if not os.path.exists(cross_symlink):
48 command = "./setup_board --board=%s" % self._board
asharifca3c6c12013-02-15 23:17:54 +000049 self._ce.ChrootRunCommand(self._chromeos_root, command)
asharifc97199a2013-02-15 22:48:45 +000050
51 def Build(self):
52 self.RunSetupBoardIfNecessary()
53
54 try:
asharif7dd6d862013-02-15 23:17:46 +000055 self.UninstallTool()
asharifc97199a2013-02-15 22:48:45 +000056 self.MoveMaskFile()
57 self.SwitchToBFD()
58 self.MountSources()
59 if not self._incremental:
60 self.RemoveCompiledFile()
61 self.BuildTool()
62 finally:
63 self.UnMoveMaskFile()
64 self.SwitchToOriginalLD()
65
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")
72 command = "rm -rf %s" % compiled_file
73 self._ce.RunCommand(command)
74
75 def MountSources(self):
76 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
107 mount_statuses = [mp.DoMount() == 0 for mp in mount_points]
108
109 if not all(mount_statuses):
110 mounted = [mp for mp, status in zip(mount_points, mount_statuses) if status]
111 unmount_statuses = [mp.UnMount() == 0 for mp in mounted]
112 assert all(unmount_statuses), "Could not unmount all mount points!"
113
asharif7dd6d862013-02-15 23:17:46 +0000114 def UninstallTool(self):
115 command = "sudo CLEAN_DELAY=0 emerge -C cross-%s/%s" % (self._ctarget, self._name)
asharifca3c6c12013-02-15 23:17:54 +0000116 self._ce.ChrootRunCommand(self._chromeos_root, command)
asharif7dd6d862013-02-15 23:17:46 +0000117
asharifc97199a2013-02-15 22:48:45 +0000118 def BuildTool(self):
119 env = self._build_env
120 features = "nostrip userpriv userfetch -sandbox noclean"
121 env["FEATURES"] = features
122
123 if self._incremental:
124 env["FEATURES"] += " keepwork"
125
126 env["USE"] = "multislot mounted_%s" % self._name
127 env["%s_SOURCE_PATH" % self._name.upper()] = (
128 os.path.join("/", self._chroot_source_path))
129 env["ACCEPT_KEYWORDS"] = "~*"
130 env_string = " ".join(["%s=\"%s\"" % var for var in env.items()])
131 command = "emerge =cross-%s/%s-9999" % (self._ctarget, self._name)
132 full_command = "sudo %s %s" % (env_string, command)
asharifca3c6c12013-02-15 23:17:54 +0000133 self._ce.ChrootRunCommand(self._chromeos_root, full_command)
asharifc97199a2013-02-15 22:48:45 +0000134
135 def SwitchToBFD(self):
136 command = "sudo binutils-config %s-2.21" % self._ctarget
asharifca3c6c12013-02-15 23:17:54 +0000137 self._ce.ChrootRunCommand(self._chromeos_root, command)
asharifc97199a2013-02-15 22:48:45 +0000138
139 def SwitchToOriginalLD(self):
140 pass
141
142 def MoveMaskFile(self):
143 self._new_mask_file = None
144 if os.path.isfile(self._mask_file):
145 self._new_mask_file = tempfile.mktemp()
146 command = "sudo mv %s %s" % (self._mask_file, self._new_mask_file)
147 self._ce.RunCommand(command)
148
149 def UnMoveMaskFile(self):
150 if self._new_mask_file:
151 command = "sudo mv %s %s" % (self._new_mask_file, self._mask_file)
152 self._ce.RunCommand(command)
bjanakiraman7f4a4852013-02-15 04:35:28 +0000153
bjanakiraman7f4a4852013-02-15 04:35:28 +0000154
asharif0d3535a2013-02-15 04:50:33 +0000155def Main(argv):
asharif19c73dd2013-02-15 04:35:37 +0000156 """The main function."""
asharif5a9bb462013-02-15 04:50:57 +0000157 # Common initializations
asharif19c73dd2013-02-15 04:35:37 +0000158 parser = optparse.OptionParser()
asharifc97199a2013-02-15 22:48:45 +0000159 parser.add_option("-c",
160 "--chromeos_root",
161 dest="chromeos_root",
162 help=("ChromeOS root checkout directory"
163 " uses ../.. if none given."))
164 parser.add_option("-g",
165 "--gcc_dir",
166 dest="gcc_dir",
167 help="The directory where gcc resides.")
168 parser.add_option("-b",
169 "--board",
170 dest="board",
171 default="x86-agz",
172 help="The target board.")
173 parser.add_option("-n",
174 "--noincremental",
175 dest="noincremental",
176 default=False,
asharifd751e252013-02-15 04:35:52 +0000177 action="store_true",
asharifc97199a2013-02-15 22:48:45 +0000178 help="Use FEATURES=keepwork to do incremental builds.")
179 parser.add_option("-d",
180 "--debug",
181 dest="debug",
182 default=False,
asharifd751e252013-02-15 04:35:52 +0000183 action="store_true",
asharifc97199a2013-02-15 22:48:45 +0000184 help="Build a compiler with -g3 -O0.")
asharif86968c42013-02-15 23:44:37 +0000185 parser.add_option("-m",
186 "--mount_only",
187 dest="mount_only",
188 default=False,
189 action="store_true",
190 help="Just mount the tool directories.")
191
bjanakiraman7f4a4852013-02-15 04:35:28 +0000192
asharifc97199a2013-02-15 22:48:45 +0000193 options, _ = parser.parse_args(argv)
asharif17621302013-02-15 04:46:35 +0000194
asharifc97199a2013-02-15 22:48:45 +0000195 chromeos_root = utils.CanonicalizePath(options.chromeos_root)
196 gcc_dir = utils.CanonicalizePath(options.gcc_dir)
197 build_env = {}
198 if options.debug:
199 debug_flags = "-g3 -O0"
200 build_env["CFLAGS"] = debug_flags
201 build_env["CXXFLAGS"] = debug_flags
bjanakiraman7f4a4852013-02-15 04:35:28 +0000202
asharif86968c42013-02-15 23:44:37 +0000203 # Create toolchain parts
204 toolchain_parts = []
205 for board in options.board.split(","):
206 if options.gcc_dir:
asharifc97199a2013-02-15 22:48:45 +0000207 tp = ToolchainPart("gcc", gcc_dir, chromeos_root, board,
208 not options.noincremental, build_env)
asharif86968c42013-02-15 23:44:37 +0000209 toolchain_parts.append(tp)
210
211 try:
212 for tp in toolchain_parts:
213 if options.mount_only:
214 tp.MountSources()
215 else:
216 tp.Build()
asharifc97199a2013-02-15 22:48:45 +0000217 finally:
218 print "Exiting..."
219 return 0
asharif0d3535a2013-02-15 04:50:33 +0000220
asharif19c73dd2013-02-15 04:35:37 +0000221
222if __name__ == "__main__":
asharif2198c512013-02-15 09:21:35 +0000223 retval = Main(sys.argv)
224 sys.exit(retval)