blob: f9ecb8ebbf05430becae610f29e8a0e03dc7a900 [file] [log] [blame]
Ahmad Sharif4467f002012-12-20 12:09:49 -08001#!/usr/bin/python
Yunlian Jiangb0a02f42013-08-22 09:55:54 -07002
3# Copyright (c) 2013 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.
Ahmad Shariffd356fb2012-05-07 12:02:16 -07006
7"""Utilities for toolchain build."""
8
9__author__ = "asharif@google.com (Ahmad Sharif)"
10
Ahmad Shariff395c262012-10-09 17:48:09 -070011from contextlib import contextmanager
Ahmad Shariffd356fb2012-05-07 12:02:16 -070012import os
13import re
Ahmad Sharif4467f002012-12-20 12:09:49 -080014import shutil
15import sys
16import time
17
18import lock_machine
Ahmad Shariff395c262012-10-09 17:48:09 -070019
Ahmad Shariffd356fb2012-05-07 12:02:16 -070020import command_executer
21import logger
Ahmad Shariff395c262012-10-09 17:48:09 -070022
23
24def GetChromeOSVersionFromLSBVersion(lsb_version):
Ahmad Sharif4467f002012-12-20 12:09:49 -080025 """Get Chromeos version from Lsb version."""
Ahmad Shariff395c262012-10-09 17:48:09 -070026 ce = command_executer.GetCommandExecuter()
27 command = "git ls-remote http://git.chromium.org/chromiumos/manifest.git"
28 ret, out, _ = ce.RunCommand(command, return_output=True,
29 print_to_console=False)
30 assert ret == 0, "Command %s failed" % command
31 lower = []
32 for line in out.splitlines():
Ahmad Sharif4467f002012-12-20 12:09:49 -080033 mo = re.search(r"refs/heads/release-R(\d+)-(\d+)\.B", line)
Ahmad Shariff395c262012-10-09 17:48:09 -070034 if mo:
35 revision = int(mo.group(1))
36 build = int(mo.group(2))
37 lsb_build = int(lsb_version.split(".")[0])
38 if lsb_build > build:
39 lower.append(revision)
40 lower = sorted(lower)
41 if lower:
42 return "R%d-%s" % (lower[-1] + 1, lsb_version)
43 else:
44 return "Unknown"
Ahmad Shariffd356fb2012-05-07 12:02:16 -070045
46
47def ApplySubs(string, *substitutions):
48 for pattern, replacement in substitutions:
49 string = re.sub(pattern, replacement, string)
50 return string
51
52
Ahmad Sharif4467f002012-12-20 12:09:49 -080053def UnitToNumber(unit_num, base=1000):
54 """Convert a number with unit to float."""
Ahmad Sharif5ae8a5c2012-05-18 10:59:51 -070055 unit_dict = {"kilo": base,
56 "mega": base**2,
57 "giga": base**3}
Ahmad Sharif4467f002012-12-20 12:09:49 -080058 unit_num = unit_num.lower()
59 mo = re.search(r"(\d*)(.+)?", unit_num)
Ahmad Sharif5ae8a5c2012-05-18 10:59:51 -070060 number = mo.group(1)
61 unit = mo.group(2)
Ahmad Shariff395c262012-10-09 17:48:09 -070062 if not unit:
63 return float(number)
Ahmad Sharif5ae8a5c2012-05-18 10:59:51 -070064 for k, v in unit_dict.items():
65 if k.startswith(unit):
66 return float(number) * v
67 raise Exception("Unit: %s not found in byte: %s!" %
68 (unit,
Ahmad Sharif4467f002012-12-20 12:09:49 -080069 unit_num))
Ahmad Sharif5ae8a5c2012-05-18 10:59:51 -070070
71
Ahmad Shariffd356fb2012-05-07 12:02:16 -070072def GetFilenameFromString(string):
73 return ApplySubs(string,
Ahmad Sharif4467f002012-12-20 12:09:49 -080074 (r"/", "__"),
75 (r"\s", "_"),
76 (r"[\^\$=\"\\\?]", ""),
77 )
Ahmad Shariffd356fb2012-05-07 12:02:16 -070078
79
80def GetRoot(scr_name):
81 """Break up pathname into (dir+name)."""
82 abs_path = os.path.abspath(scr_name)
83 return (os.path.dirname(abs_path), os.path.basename(abs_path))
84
85
Ahmad Sharif4467f002012-12-20 12:09:49 -080086def GetChromeOSKeyFile(chromeos_root):
87 return os.path.join(chromeos_root,
88 "src",
89 "scripts",
90 "mod_for_test_scripts",
91 "ssh_keys",
92 "testing_rsa")
93
94
Ahmad Sharif5ae8a5c2012-05-18 10:59:51 -070095def GetChrootPath(chromeos_root):
96 return os.path.join(chromeos_root,
97 "chroot")
98
99
100def GetInsideChrootPath(chromeos_root, file_path):
101 if not file_path.startswith(GetChrootPath(chromeos_root)):
102 raise Exception("File: %s doesn't seem to be in the chroot: %s" %
103 (file_path,
104 chromeos_root))
105 return file_path[len(GetChrootPath(chromeos_root)):]
106
107
108def GetOutsideChrootPath(chromeos_root, file_path):
109 return os.path.join(GetChrootPath(chromeos_root),
110 file_path.lstrip("/"))
111
112
Ahmad Shariffd356fb2012-05-07 12:02:16 -0700113def FormatQuotedCommand(command):
114 return ApplySubs(command,
115 ("\"", "\\\""))
116
117
118def FormatCommands(commands):
119 return ApplySubs(str(commands),
120 ("&&", "&&\n"),
121 (";", ";\n"),
Ahmad Sharif4467f002012-12-20 12:09:49 -0800122 (r"\n+\s*", "\n"))
Ahmad Shariffd356fb2012-05-07 12:02:16 -0700123
124
125def GetImageDir(chromeos_root, board):
126 return os.path.join(chromeos_root,
127 "src",
128 "build",
129 "images",
130 board)
131
132
133def LabelLatestImage(chromeos_root, board, label):
134 image_dir = GetImageDir(chromeos_root, board)
135 latest_image_dir = os.path.join(image_dir, "latest")
136 latest_image_dir = os.path.realpath(latest_image_dir)
137 latest_image_dir = os.path.basename(latest_image_dir)
138 with WorkingDirectory(image_dir):
139 command = "ln -sf -T %s %s" % (latest_image_dir, label)
140 ce = command_executer.GetCommandExecuter()
141 return ce.RunCommand(command)
142
143
144def DoesLabelExist(chromeos_root, board, label):
145 image_label = os.path.join(GetImageDir(chromeos_root, board),
146 label)
147 return os.path.exists(image_label)
148
149
Luis Lozanof81680c2013-03-15 14:44:13 -0700150def GetBuildPackagesCommand(board, usepkg=False, debug=False):
Ahmad Shariffd356fb2012-05-07 12:02:16 -0700151 if usepkg:
152 usepkg_flag = "--usepkg"
153 else:
154 usepkg_flag = "--nousepkg"
Luis Lozanof81680c2013-03-15 14:44:13 -0700155 if debug:
156 withdebug_flag = '--withdebug'
157 else:
158 withdebug_flag = '--nowithdebug'
Ahmad Shariffd356fb2012-05-07 12:02:16 -0700159 return ("./build_packages %s --withdev --withtest --withautotest "
Yunlian Jiangb0a02f42013-08-22 09:55:54 -0700160 "--skip_toolchain_update %s --board=%s "
161 "--accept_licenses=@CHROMEOS" %
Luis Lozanof81680c2013-03-15 14:44:13 -0700162 (usepkg_flag, withdebug_flag, board))
Ahmad Shariffd356fb2012-05-07 12:02:16 -0700163
164
Luis Lozanof81680c2013-03-15 14:44:13 -0700165def GetBuildImageCommand(board, dev=False):
166 dev_args = ""
167 if dev:
168 dev_args = "--noenable_rootfs_verification --disk_layout=2gb-rootfs"
169 return "./build_image --board=%s %s test" % (board, dev_args)
Ahmad Shariffd356fb2012-05-07 12:02:16 -0700170
171def GetSetupBoardCommand(board, gcc_version=None, binutils_version=None,
172 usepkg=None, force=None):
Ahmad Sharif4467f002012-12-20 12:09:49 -0800173 """Get setup_board command."""
Ahmad Shariffd356fb2012-05-07 12:02:16 -0700174 options = []
175
176 if gcc_version:
177 options.append("--gcc_version=%s" % gcc_version)
178
179 if binutils_version:
180 options.append("--binutils_version=%s" % binutils_version)
181
182 if usepkg:
183 options.append("--usepkg")
184 else:
185 options.append("--nousepkg")
186
187 if force:
188 options.append("--force")
189
Yunlian Jiangb0a02f42013-08-22 09:55:54 -0700190 options.append("--accept_licenses=@CHROMEOS")
191
Ahmad Shariffd356fb2012-05-07 12:02:16 -0700192 return "./setup_board --board=%s %s" % (board, " ".join(options))
193
194
195def CanonicalizePath(path):
196 path = os.path.expanduser(path)
197 path = os.path.realpath(path)
198 return path
199
200
201def GetCtargetFromBoard(board, chromeos_root):
Ahmad Sharif4467f002012-12-20 12:09:49 -0800202 """Get Ctarget from board."""
Ahmad Shariffd356fb2012-05-07 12:02:16 -0700203 base_board = board.split("_")[0]
204 command = ("source "
205 "../platform/dev/toolchain_utils.sh; get_ctarget_from_board %s" %
206 base_board)
207 ce = command_executer.GetCommandExecuter()
Ahmad Shariff395c262012-10-09 17:48:09 -0700208 ret, out, _ = ce.ChrootRunCommand(chromeos_root,
209 command,
210 return_output=True)
Ahmad Shariffd356fb2012-05-07 12:02:16 -0700211 if ret != 0:
212 raise ValueError("Board %s is invalid!" % board)
Ahmad Shariff395c262012-10-09 17:48:09 -0700213 # Remove ANSI escape sequences.
214 out = StripANSIEscapeSequences(out)
Ahmad Shariffd356fb2012-05-07 12:02:16 -0700215 return out.strip()
216
217
Ahmad Shariff395c262012-10-09 17:48:09 -0700218def StripANSIEscapeSequences(string):
Ahmad Sharif4467f002012-12-20 12:09:49 -0800219 string = re.sub(r"\x1b\[[0-9]*[a-zA-Z]", "", string)
Ahmad Shariff395c262012-10-09 17:48:09 -0700220 return string
221
222
Ahmad Shariffd356fb2012-05-07 12:02:16 -0700223def GetChromeSrcDir():
224 return "var/cache/distfiles/target/chrome-src/src"
225
226
227def GetEnvStringFromDict(env_dict):
228 return " ".join(["%s=\"%s\"" % var for var in env_dict.items()])
229
230
Ahmad Shariff395c262012-10-09 17:48:09 -0700231def MergeEnvStringWithDict(env_string, env_dict, prepend=True):
Ahmad Sharif4467f002012-12-20 12:09:49 -0800232 """Merge env string with dict."""
Ahmad Shariff395c262012-10-09 17:48:09 -0700233 if not env_string.strip():
234 return GetEnvStringFromDict(env_dict)
235 override_env_list = []
236 ce = command_executer.GetCommandExecuter()
237 for k, v in env_dict.items():
238 v = v.strip("\"'")
239 if prepend:
240 new_env = "%s=\"%s $%s\"" % (k, v, k)
241 else:
242 new_env = "%s=\"$%s %s\"" % (k, k, v)
243 command = "; ".join([env_string, new_env, "echo $%s" % k])
244 ret, out, _ = ce.RunCommand(command, return_output=True)
245 override_env_list.append("%s=%r" % (k, out.strip()))
246 ret = env_string + " " + " ".join(override_env_list)
247 return ret.strip()
248
249
Ahmad Shariffd356fb2012-05-07 12:02:16 -0700250def GetAllImages(chromeos_root, board):
251 ce = command_executer.GetCommandExecuter()
252 command = ("find %s/src/build/images/%s -name chromiumos_test_image.bin" %
253 (chromeos_root, board))
Ahmad Shariff395c262012-10-09 17:48:09 -0700254 ret, out, _ = ce.RunCommand(command, return_output=True)
255 assert ret == 0, "Could not run command: %s" % command
Ahmad Shariffd356fb2012-05-07 12:02:16 -0700256 return out.splitlines()
257
258
Ahmad Sharif4467f002012-12-20 12:09:49 -0800259def AcquireLock(lock_file, timeout=1200):
260 """Acquire a lock with timeout."""
261 start_time = time.time()
262 locked = False
263 abs_path = os.path.abspath(lock_file)
264 dir_path = os.path.dirname(abs_path)
265 sleep_time = min(10, timeout/10.0)
Luis Lozanof81680c2013-03-15 14:44:13 -0700266 reason = "pid: {0}, commad: {1}".format(os.getpid(),
267 sys.argv[0])
Ahmad Sharif4467f002012-12-20 12:09:49 -0800268 if not os.path.exists(dir_path):
269 try:
Luis Lozanof81680c2013-03-15 14:44:13 -0700270 with lock_machine.FileCreationMask(0002):
271 os.makedirs(dir_path)
Ahmad Sharif4467f002012-12-20 12:09:49 -0800272 except OSError:
273 print "Cannot create dir {0}, exiting...".format(dir_path)
274 exit(0)
275 while True:
Luis Lozanof81680c2013-03-15 14:44:13 -0700276 locked = (lock_machine.Lock(lock_file).NonBlockingLock(True, reason))
Ahmad Sharif4467f002012-12-20 12:09:49 -0800277 if locked:
278 break
279 time.sleep(sleep_time)
280 if time.time() - start_time > timeout:
281 logger.GetLogger().LogWarning(
282 "Could not acquire lock on this file: {0} within {1} seconds."
283 "Manually remove the file if you think the lock is stale"
284 .format(abs_path, timeout))
285 break
286 return locked
287
288
289def ReleaseLock(lock_file):
290 lock_file = os.path.abspath(lock_file)
291 ret = lock_machine.Lock(lock_file).Unlock(True)
292 assert ret, ("Could not unlock {0},"
293 "Please remove it manually".format(lock_file))
294
295
296def IsFloat(text):
297 if text is None:
298 return False
299 try:
300 float(text)
301 return True
302 except ValueError:
303 return False
304
305def RemoveChromeBrowserObjectFiles(chromeos_root, board):
306 """ Remove any object files from all the posible locations """
307 out_dir = os.path.join(
308 GetChrootPath(chromeos_root),
309 "var/cache/chromeos-chrome/chrome-src/src/out_%s" % board)
310 if os.path.exists(out_dir):
311 shutil.rmtree(out_dir)
312 logger.GetLogger().LogCmd("rm -rf %s" % out_dir)
313 out_dir = os.path.join(
314 GetChrootPath(chromeos_root),
315 "var/cache/chromeos-chrome/chrome-src-internal/src/out_%s" % board)
316 if os.path.exists(out_dir):
317 shutil.rmtree(out_dir)
318 logger.GetLogger().LogCmd("rm -rf %s" % out_dir)
319
Ahmad Shariffd356fb2012-05-07 12:02:16 -0700320@contextmanager
321def WorkingDirectory(new_dir):
Ahmad Sharif4467f002012-12-20 12:09:49 -0800322 """Get the working directory."""
Ahmad Shariffd356fb2012-05-07 12:02:16 -0700323 old_dir = os.getcwd()
324 if old_dir != new_dir:
325 msg = "cd %s" % new_dir
326 logger.GetLogger().LogCmd(msg)
327 os.chdir(new_dir)
328 yield new_dir
329 if old_dir != new_dir:
330 msg = "cd %s" % old_dir
331 logger.GetLogger().LogCmd(msg)
332 os.chdir(old_dir)
Han Shen91445322013-03-20 13:43:31 -0700333
334def HasGitStagedChanges(git_dir):
335 """Return True if git repository has staged changes."""
336 command = 'cd {0} && git diff --quiet --cached --exit-code HEAD'.format(
337 git_dir)
338 return command_executer.GetCommandExecuter().RunCommand(
339 command, print_to_console=False)
340
341def HasGitUnstagedChanges(git_dir):
342 """Return True if git repository has un-staged changes."""
343 command = 'cd {0} && git diff --quiet --exit-code HEAD'.format(git_dir)
344 return command_executer.GetCommandExecuter().RunCommand(
345 command, print_to_console=False)
346
347def HasGitUntrackedChanges(git_dir):
348 """Return True if git repository has un-tracked changes."""
349 command = 'cd {0} && test -z $(git ls-files --exclude-standard --others)' \
350 .format(git_dir)
351 return command_executer.GetCommandExecuter().RunCommand(
352 command,print_to_console=False)
353
354def IsGitTreeClean(git_dir):
355 if HasGitStagedChanges(git_dir):
356 logger.GetLogger().LogWarning("Git tree has staged changes.")
357 return False
358 if HasGitUnstagedChanges(git_dir):
359 logger.GetLogger().LogWarning("Git tree has unstaged changes.")
360 return False
361 if HasGitUntrackedChanges(git_dir):
362 logger.GetLogger().LogWarning("Git tree has un-tracked changes.")
363 return False
364 return True
365
366def GetGitChangesAsList(git_dir, path=None, staged=False):
367 command = 'cd {0} && git diff --name-only'.format(git_dir)
368 if staged:
369 command = command + ' --cached'
370 if path:
371 command = command + ' -- ' + path
372 ec, out, err = command_executer.GetCommandExecuter().RunCommand(
373 command, return_output=True, print_to_console=False)
374 rv = []
375 for line in out.splitlines():
376 rv.append(line)
377 return rv