blob: 9b90f55c19627573ae77415892bdd646450a43f4 [file] [log] [blame]
Zhizhou Yang81d651f2020-02-10 16:51:20 -08001#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
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.
Zhizhou Yang81d651f2020-02-10 16:51:20 -08006
bjanakiraman7f4a4852013-02-15 04:35:28 +00007"""Script to build the ChromeOS toolchain.
8
9This script sets up the toolchain if you give it the gcctools directory.
10"""
11
Caroline Tice88272d42016-01-13 09:48:29 -080012from __future__ import print_function
13
Luis Lozanof2a3ef42015-12-15 13:49:30 -080014__author__ = 'asharif@google.com (Ahmad Sharif)'
bjanakiraman7f4a4852013-02-15 04:35:28 +000015
Caroline Tice88272d42016-01-13 09:48:29 -080016import argparse
asharif80c6e552013-02-15 04:35:40 +000017import getpass
asharif17621302013-02-15 04:46:35 +000018import os
bjanakiraman7f4a4852013-02-15 04:35:28 +000019import sys
asharifc97199a2013-02-15 22:48:45 +000020import tempfile
kbaclawski20082a02013-02-16 02:12:57 +000021
asharif252df0f2013-02-15 04:46:28 +000022import tc_enter_chroot
Caroline Tice88272d42016-01-13 09:48:29 -080023from cros_utils import command_executer
24from cros_utils import constants
25from cros_utils import misc
bjanakiraman7f4a4852013-02-15 04:35:28 +000026
asharif5a9bb462013-02-15 04:50:57 +000027
asharifc97199a2013-02-15 22:48:45 +000028class ToolchainPart(object):
Caroline Tice88272d42016-01-13 09:48:29 -080029 """Class to hold the toolchain pieces."""
Luis Lozanof2a3ef42015-12-15 13:49:30 -080030
31 def __init__(self,
32 name,
33 source_path,
34 chromeos_root,
35 board,
36 incremental,
37 build_env,
38 gcc_enable_ccache=False):
asharifc97199a2013-02-15 22:48:45 +000039 self._name = name
kbaclawski20082a02013-02-16 02:12:57 +000040 self._source_path = misc.CanonicalizePath(source_path)
asharifc97199a2013-02-15 22:48:45 +000041 self._chromeos_root = chromeos_root
42 self._board = board
Luis Lozanof2a3ef42015-12-15 13:49:30 -080043 self._ctarget = misc.GetCtargetFromBoard(self._board, self._chromeos_root)
Rahul Chaudhry215c12f2014-11-04 15:18:47 -080044 self._gcc_libs_dest = misc.GetGccLibsDestForBoard(self._board,
Luis Lozanof2a3ef42015-12-15 13:49:30 -080045 self._chromeos_root)
46 self.tag = '%s-%s' % (name, self._ctarget)
asharifc97199a2013-02-15 22:48:45 +000047 self._ce = command_executer.GetCommandExecuter()
Caroline Ticef6ef4392017-04-06 17:16:05 -070048 self._mask_file = os.path.join(
49 self._chromeos_root, 'chroot',
50 'etc/portage/package.mask/cross-%s' % self._ctarget)
asharifc97199a2013-02-15 22:48:45 +000051 self._new_mask_file = None
52
Han Shene4b6f222013-11-22 10:02:38 -080053 self._chroot_source_path = os.path.join(constants.MOUNTED_TOOLCHAIN_ROOT,
Luis Lozanof2a3ef42015-12-15 13:49:30 -080054 self._name).lstrip('/')
asharifc97199a2013-02-15 22:48:45 +000055 self._incremental = incremental
56 self._build_env = build_env
llozanof2726d22013-03-09 01:29:37 +000057 self._gcc_enable_ccache = gcc_enable_ccache
asharifc97199a2013-02-15 22:48:45 +000058
59 def RunSetupBoardIfNecessary(self):
Luis Lozanof2a3ef42015-12-15 13:49:30 -080060 cross_symlink = os.path.join(self._chromeos_root, 'chroot',
61 'usr/local/bin/emerge-%s' % self._board)
asharifc97199a2013-02-15 22:48:45 +000062 if not os.path.exists(cross_symlink):
Alex Klein3cef3162019-01-11 14:16:58 -070063 command = 'setup_board --board=%s' % self._board
asharifca3c6c12013-02-15 23:17:54 +000064 self._ce.ChrootRunCommand(self._chromeos_root, command)
asharifc97199a2013-02-15 22:48:45 +000065
66 def Build(self):
shenhanbecf6242013-02-19 20:43:32 +000067 rv = 1
asharifc97199a2013-02-15 22:48:45 +000068 try:
asharif7dd6d862013-02-15 23:17:46 +000069 self.UninstallTool()
asharifc97199a2013-02-15 22:48:45 +000070 self.MoveMaskFile()
cmtice80d257f2013-02-15 23:44:51 +000071 self.MountSources(False)
asharif9e3cf6e2013-02-16 03:13:38 +000072 self.RemoveCompiledFile()
shenhanbecf6242013-02-19 20:43:32 +000073 rv = self.BuildTool()
asharifc97199a2013-02-15 22:48:45 +000074 finally:
75 self.UnMoveMaskFile()
llozano9b84cb62013-03-11 21:08:31 +000076 return rv
asharifc97199a2013-02-15 22:48:45 +000077
78 def RemoveCompiledFile(self):
Luis Lozanof2a3ef42015-12-15 13:49:30 -080079 compiled_file = os.path.join(self._chromeos_root, 'chroot',
80 'var/tmp/portage/cross-%s' % self._ctarget,
81 '%s-9999' % self._name, '.compiled')
82 command = 'rm -f %s' % compiled_file
asharifc97199a2013-02-15 22:48:45 +000083 self._ce.RunCommand(command)
84
cmtice80d257f2013-02-15 23:44:51 +000085 def MountSources(self, unmount_source):
asharifc97199a2013-02-15 22:48:45 +000086 mount_points = []
Luis Lozanof2a3ef42015-12-15 13:49:30 -080087 mounted_source_path = os.path.join(self._chromeos_root, 'chroot',
asharifc97199a2013-02-15 22:48:45 +000088 self._chroot_source_path)
Luis Lozanof2a3ef42015-12-15 13:49:30 -080089 src_mp = tc_enter_chroot.MountPoint(self._source_path, mounted_source_path,
90 getpass.getuser(), 'ro')
asharifc97199a2013-02-15 22:48:45 +000091 mount_points.append(src_mp)
92
Luis Lozanof2a3ef42015-12-15 13:49:30 -080093 build_suffix = 'build-%s' % self._ctarget
94 build_dir = '%s-%s' % (self._source_path, build_suffix)
asharifc97199a2013-02-15 22:48:45 +000095
96 if not self._incremental and os.path.exists(build_dir):
Luis Lozanof2a3ef42015-12-15 13:49:30 -080097 command = 'rm -rf %s/*' % build_dir
asharifc97199a2013-02-15 22:48:45 +000098 self._ce.RunCommand(command)
99
100 # Create a -build directory for the objects.
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800101 command = 'mkdir -p %s' % build_dir
asharifc97199a2013-02-15 22:48:45 +0000102 self._ce.RunCommand(command)
103
Zhizhou Yang81d651f2020-02-10 16:51:20 -0800104 mounted_build_dir = os.path.join(
105 self._chromeos_root, 'chroot',
106 '%s-%s' % (self._chroot_source_path, build_suffix))
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800107 build_mp = tc_enter_chroot.MountPoint(build_dir, mounted_build_dir,
108 getpass.getuser())
asharifc97199a2013-02-15 22:48:45 +0000109 mount_points.append(build_mp)
110
cmtice80d257f2013-02-15 23:44:51 +0000111 if unmount_source:
112 unmount_statuses = [mp.UnMount() == 0 for mp in mount_points]
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800113 assert all(unmount_statuses), 'Could not unmount all mount points!'
cmtice80d257f2013-02-15 23:44:51 +0000114 else:
115 mount_statuses = [mp.DoMount() == 0 for mp in mount_points]
116
117 if not all(mount_statuses):
Caroline Ticef6ef4392017-04-06 17:16:05 -0700118 mounted = [
119 mp for mp, status in zip(mount_points, mount_statuses) if status
120 ]
cmtice80d257f2013-02-15 23:44:51 +0000121 unmount_statuses = [mp.UnMount() == 0 for mp in mounted]
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800122 assert all(unmount_statuses), 'Could not unmount all mount points!'
asharifc97199a2013-02-15 22:48:45 +0000123
asharif7dd6d862013-02-15 23:17:46 +0000124 def UninstallTool(self):
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800125 command = 'sudo CLEAN_DELAY=0 emerge -C cross-%s/%s' % (self._ctarget,
126 self._name)
asharifca3c6c12013-02-15 23:17:54 +0000127 self._ce.ChrootRunCommand(self._chromeos_root, command)
asharif7dd6d862013-02-15 23:17:46 +0000128
asharifc97199a2013-02-15 22:48:45 +0000129 def BuildTool(self):
130 env = self._build_env
asharif9e499162013-02-16 02:41:39 +0000131 # FEATURES=buildpkg adds minutes of time so we disable it.
shenhanfdc0f572013-02-19 18:48:36 +0000132 # TODO(shenhan): keep '-sandbox' for a while for compatibility, then remove
133 # it after a while.
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800134 features = ('nostrip userpriv userfetch -usersandbox -sandbox noclean '
135 '-buildpkg')
136 env['FEATURES'] = features
asharifc97199a2013-02-15 22:48:45 +0000137
138 if self._incremental:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800139 env['FEATURES'] += ' keepwork'
asharifc97199a2013-02-15 22:48:45 +0000140
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800141 if 'USE' in env:
142 env['USE'] += ' multislot mounted_%s' % self._name
cmticecbc868a2013-02-21 22:52:46 +0000143 else:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800144 env['USE'] = 'multislot mounted_%s' % self._name
cmticecbc868a2013-02-21 22:52:46 +0000145
llozanof2726d22013-03-09 01:29:37 +0000146 # Disable ccache in our compilers. cache may be problematic for us.
147 # It ignores compiler environments settings and it is not clear if
148 # the cache hit algorithm verifies all the compiler binaries or
149 # just the driver.
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800150 if self._name == 'gcc' and not self._gcc_enable_ccache:
151 env['USE'] += ' -wrapper_ccache'
llozanof2726d22013-03-09 01:29:37 +0000152
Zhizhou Yang81d651f2020-02-10 16:51:20 -0800153 env['%s_SOURCE_PATH' % self._name.upper()] = (
154 os.path.join('/', self._chroot_source_path))
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800155 env['ACCEPT_KEYWORDS'] = '~*'
Zhizhou Yang81d651f2020-02-10 16:51:20 -0800156 env_string = ' '.join(['%s="%s"' % var for var in env.items()])
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800157 command = 'emerge =cross-%s/%s-9999' % (self._ctarget, self._name)
158 full_command = 'sudo %s %s' % (env_string, command)
Luis Lozano4cea9de2013-03-20 12:32:56 -0700159 rv = self._ce.ChrootRunCommand(self._chromeos_root, full_command)
160 if rv != 0:
161 return rv
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800162 if self._name == 'gcc':
Caroline Ticef6ef4392017-04-06 17:16:05 -0700163 command = ('sudo cp -r /usr/lib/gcc/%s %s' % (self._ctarget,
164 self._gcc_libs_dest))
Luis Lozano4cea9de2013-03-20 12:32:56 -0700165 rv = self._ce.ChrootRunCommand(self._chromeos_root, command)
166 return rv
asharifc97199a2013-02-15 22:48:45 +0000167
asharifc97199a2013-02-15 22:48:45 +0000168 def MoveMaskFile(self):
169 self._new_mask_file = None
170 if os.path.isfile(self._mask_file):
171 self._new_mask_file = tempfile.mktemp()
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800172 command = 'sudo mv %s %s' % (self._mask_file, self._new_mask_file)
asharifc97199a2013-02-15 22:48:45 +0000173 self._ce.RunCommand(command)
174
175 def UnMoveMaskFile(self):
176 if self._new_mask_file:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800177 command = 'sudo mv %s %s' % (self._new_mask_file, self._mask_file)
asharifc97199a2013-02-15 22:48:45 +0000178 self._ce.RunCommand(command)
bjanakiraman7f4a4852013-02-15 04:35:28 +0000179
bjanakiraman7f4a4852013-02-15 04:35:28 +0000180
asharif0d3535a2013-02-15 04:50:33 +0000181def Main(argv):
asharif19c73dd2013-02-15 04:35:37 +0000182 """The main function."""
asharif5a9bb462013-02-15 04:50:57 +0000183 # Common initializations
Caroline Tice88272d42016-01-13 09:48:29 -0800184 parser = argparse.ArgumentParser()
Caroline Ticef6ef4392017-04-06 17:16:05 -0700185 parser.add_argument(
186 '-c',
187 '--chromeos_root',
188 dest='chromeos_root',
189 default='../../',
190 help=('ChromeOS root checkout directory'
191 ' uses ../.. if none given.'))
192 parser.add_argument(
193 '-g',
194 '--gcc_dir',
195 dest='gcc_dir',
196 help='The directory where gcc resides.')
197 parser.add_argument(
198 '--binutils_dir',
199 dest='binutils_dir',
200 help='The directory where binutils resides.')
201 parser.add_argument(
202 '-x',
203 '--gdb_dir',
204 dest='gdb_dir',
205 help='The directory where gdb resides.')
206 parser.add_argument(
207 '-b',
208 '--board',
209 dest='board',
210 default='x86-alex',
211 help='The target board.')
212 parser.add_argument(
213 '-n',
214 '--noincremental',
215 dest='noincremental',
216 default=False,
217 action='store_true',
218 help='Use FEATURES=keepwork to do incremental builds.')
219 parser.add_argument(
220 '--cflags',
221 dest='cflags',
222 default='',
223 help='Build a compiler with specified CFLAGS')
224 parser.add_argument(
225 '--cxxflags',
226 dest='cxxflags',
227 default='',
228 help='Build a compiler with specified CXXFLAGS')
229 parser.add_argument(
230 '--cflags_for_target',
231 dest='cflags_for_target',
232 default='',
233 help='Build the target libraries with specified flags')
234 parser.add_argument(
235 '--cxxflags_for_target',
236 dest='cxxflags_for_target',
237 default='',
238 help='Build the target libraries with specified flags')
239 parser.add_argument(
240 '--ldflags',
241 dest='ldflags',
242 default='',
243 help='Build a compiler with specified LDFLAGS')
244 parser.add_argument(
245 '-d',
246 '--debug',
247 dest='debug',
248 default=False,
249 action='store_true',
250 help='Build a compiler with -g3 -O0 appended to both'
251 ' CFLAGS and CXXFLAGS.')
252 parser.add_argument(
253 '-m',
254 '--mount_only',
255 dest='mount_only',
256 default=False,
257 action='store_true',
258 help='Just mount the tool directories.')
259 parser.add_argument(
260 '-u',
261 '--unmount_only',
262 dest='unmount_only',
263 default=False,
264 action='store_true',
265 help='Just unmount the tool directories.')
266 parser.add_argument(
267 '--extra_use_flags',
268 dest='extra_use_flags',
269 default='',
270 help='Extra flag for USE, to be passed to the ebuild. '
271 "('multislot' and 'mounted_<tool>' are always passed.)")
272 parser.add_argument(
273 '--gcc_enable_ccache',
274 dest='gcc_enable_ccache',
275 default=False,
276 action='store_true',
277 help='Enable ccache for the gcc invocations')
bjanakiraman7f4a4852013-02-15 04:35:28 +0000278
Caroline Tice88272d42016-01-13 09:48:29 -0800279 options = parser.parse_args(argv)
asharif17621302013-02-15 04:46:35 +0000280
kbaclawski20082a02013-02-16 02:12:57 +0000281 chromeos_root = misc.CanonicalizePath(options.chromeos_root)
cmtice80d257f2013-02-15 23:44:51 +0000282 if options.gcc_dir:
kbaclawski20082a02013-02-16 02:12:57 +0000283 gcc_dir = misc.CanonicalizePath(options.gcc_dir)
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800284 assert gcc_dir and os.path.isdir(gcc_dir), 'gcc_dir does not exist!'
shenhan8e8b0c22013-02-19 22:34:16 +0000285 if options.binutils_dir:
286 binutils_dir = misc.CanonicalizePath(options.binutils_dir)
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800287 assert os.path.isdir(binutils_dir), 'binutils_dir does not exist!'
cmtice80d257f2013-02-15 23:44:51 +0000288 if options.gdb_dir:
kbaclawski20082a02013-02-16 02:12:57 +0000289 gdb_dir = misc.CanonicalizePath(options.gdb_dir)
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800290 assert os.path.isdir(gdb_dir), 'gdb_dir does not exist!'
cmtice80d257f2013-02-15 23:44:51 +0000291 if options.unmount_only:
292 options.mount_only = False
293 elif options.mount_only:
294 options.unmount_only = False
asharifc97199a2013-02-15 22:48:45 +0000295 build_env = {}
cmticee59ac272013-02-19 20:20:09 +0000296 if options.cflags:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800297 build_env['CFLAGS'] = '`portageq envvar CFLAGS` ' + options.cflags
cmticee59ac272013-02-19 20:20:09 +0000298 if options.cxxflags:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800299 build_env['CXXFLAGS'] = '`portageq envvar CXXFLAGS` ' + options.cxxflags
carrot2b549ca2013-02-19 22:45:25 +0000300 if options.cflags_for_target:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800301 build_env['CFLAGS_FOR_TARGET'] = options.cflags_for_target
carrot2b549ca2013-02-19 22:45:25 +0000302 if options.cxxflags_for_target:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800303 build_env['CXXFLAGS_FOR_TARGET'] = options.cxxflags_for_target
carrot255fd462013-02-19 22:43:16 +0000304 if options.ldflags:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800305 build_env['LDFLAGS'] = options.ldflags
asharifc97199a2013-02-15 22:48:45 +0000306 if options.debug:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800307 debug_flags = '-g3 -O0'
308 if 'CFLAGS' in build_env:
309 build_env['CFLAGS'] += ' %s' % (debug_flags)
cmticee59ac272013-02-19 20:20:09 +0000310 else:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800311 build_env['CFLAGS'] = debug_flags
312 if 'CXXFLAGS' in build_env:
313 build_env['CXXFLAGS'] += ' %s' % (debug_flags)
cmticee59ac272013-02-19 20:20:09 +0000314 else:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800315 build_env['CXXFLAGS'] = debug_flags
cmticecbc868a2013-02-21 22:52:46 +0000316 if options.extra_use_flags:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800317 build_env['USE'] = options.extra_use_flags
bjanakiraman7f4a4852013-02-15 04:35:28 +0000318
asharif86968c42013-02-15 23:44:37 +0000319 # Create toolchain parts
carrote6f773c2013-02-19 22:34:44 +0000320 toolchain_parts = {}
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800321 for board in options.board.split(','):
asharif86968c42013-02-15 23:44:37 +0000322 if options.gcc_dir:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800323 tp = ToolchainPart('gcc', gcc_dir, chromeos_root, board,
llozanof2726d22013-03-09 01:29:37 +0000324 not options.noincremental, build_env,
325 options.gcc_enable_ccache)
carrote6f773c2013-02-19 22:34:44 +0000326 toolchain_parts[tp.tag] = tp
327 tp.RunSetupBoardIfNecessary()
shenhan8e8b0c22013-02-19 22:34:16 +0000328 if options.binutils_dir:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800329 tp = ToolchainPart('binutils', binutils_dir, chromeos_root, board,
shenhan8e8b0c22013-02-19 22:34:16 +0000330 not options.noincremental, build_env)
carrote6f773c2013-02-19 22:34:44 +0000331 toolchain_parts[tp.tag] = tp
332 tp.RunSetupBoardIfNecessary()
cmtice80d257f2013-02-15 23:44:51 +0000333 if options.gdb_dir:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800334 tp = ToolchainPart('gdb', gdb_dir, chromeos_root, board,
cmtice80d257f2013-02-15 23:44:51 +0000335 not options.noincremental, build_env)
carrote6f773c2013-02-19 22:34:44 +0000336 toolchain_parts[tp.tag] = tp
337 tp.RunSetupBoardIfNecessary()
asharif86968c42013-02-15 23:44:37 +0000338
shenhanbecf6242013-02-19 20:43:32 +0000339 rv = 0
asharif86968c42013-02-15 23:44:37 +0000340 try:
carrote6f773c2013-02-19 22:34:44 +0000341 for tag in toolchain_parts:
342 tp = toolchain_parts[tag]
cmtice80d257f2013-02-15 23:44:51 +0000343 if options.mount_only or options.unmount_only:
344 tp.MountSources(options.unmount_only)
asharif86968c42013-02-15 23:44:37 +0000345 else:
shenhanbecf6242013-02-19 20:43:32 +0000346 rv = rv + tp.Build()
asharifc97199a2013-02-15 22:48:45 +0000347 finally:
Caroline Tice88272d42016-01-13 09:48:29 -0800348 print('Exiting...')
llozano5fee82f2013-03-11 17:59:40 +0000349 return rv
asharif19c73dd2013-02-15 04:35:37 +0000350
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800351
352if __name__ == '__main__':
Caroline Tice88272d42016-01-13 09:48:29 -0800353 retval = Main(sys.argv[1:])
asharif2198c512013-02-15 09:21:35 +0000354 sys.exit(retval)