blob: 51af1d817b2c6e09732447a56b0c8b1a9c5ddc8c [file] [log] [blame]
Ahmad Sharif4467f002012-12-20 12:09:49 -08001#!/usr/bin/python
Ahmad Shariffd356fb2012-05-07 12:02:16 -07002#
3# Copyright 2010 Google Inc. All Rights Reserved.
4
5"""Utilities for toolchain build."""
6
7__author__ = "asharif@google.com (Ahmad Sharif)"
8
Ahmad Shariff395c262012-10-09 17:48:09 -07009from contextlib import contextmanager
Ahmad Shariffd356fb2012-05-07 12:02:16 -070010import os
11import re
Ahmad Sharif4467f002012-12-20 12:09:49 -080012import shutil
13import sys
14import time
15
16import lock_machine
Ahmad Shariff395c262012-10-09 17:48:09 -070017
Ahmad Shariffd356fb2012-05-07 12:02:16 -070018import command_executer
19import logger
Ahmad Shariff395c262012-10-09 17:48:09 -070020
21
22def GetChromeOSVersionFromLSBVersion(lsb_version):
Ahmad Sharif4467f002012-12-20 12:09:49 -080023 """Get Chromeos version from Lsb version."""
Ahmad Shariff395c262012-10-09 17:48:09 -070024 ce = command_executer.GetCommandExecuter()
25 command = "git ls-remote http://git.chromium.org/chromiumos/manifest.git"
26 ret, out, _ = ce.RunCommand(command, return_output=True,
27 print_to_console=False)
28 assert ret == 0, "Command %s failed" % command
29 lower = []
30 for line in out.splitlines():
Ahmad Sharif4467f002012-12-20 12:09:49 -080031 mo = re.search(r"refs/heads/release-R(\d+)-(\d+)\.B", line)
Ahmad Shariff395c262012-10-09 17:48:09 -070032 if mo:
33 revision = int(mo.group(1))
34 build = int(mo.group(2))
35 lsb_build = int(lsb_version.split(".")[0])
36 if lsb_build > build:
37 lower.append(revision)
38 lower = sorted(lower)
39 if lower:
40 return "R%d-%s" % (lower[-1] + 1, lsb_version)
41 else:
42 return "Unknown"
Ahmad Shariffd356fb2012-05-07 12:02:16 -070043
44
45def ApplySubs(string, *substitutions):
46 for pattern, replacement in substitutions:
47 string = re.sub(pattern, replacement, string)
48 return string
49
50
Ahmad Sharif4467f002012-12-20 12:09:49 -080051def UnitToNumber(unit_num, base=1000):
52 """Convert a number with unit to float."""
Ahmad Sharif5ae8a5c2012-05-18 10:59:51 -070053 unit_dict = {"kilo": base,
54 "mega": base**2,
55 "giga": base**3}
Ahmad Sharif4467f002012-12-20 12:09:49 -080056 unit_num = unit_num.lower()
57 mo = re.search(r"(\d*)(.+)?", unit_num)
Ahmad Sharif5ae8a5c2012-05-18 10:59:51 -070058 number = mo.group(1)
59 unit = mo.group(2)
Ahmad Shariff395c262012-10-09 17:48:09 -070060 if not unit:
61 return float(number)
Ahmad Sharif5ae8a5c2012-05-18 10:59:51 -070062 for k, v in unit_dict.items():
63 if k.startswith(unit):
64 return float(number) * v
65 raise Exception("Unit: %s not found in byte: %s!" %
66 (unit,
Ahmad Sharif4467f002012-12-20 12:09:49 -080067 unit_num))
Ahmad Sharif5ae8a5c2012-05-18 10:59:51 -070068
69
Ahmad Shariffd356fb2012-05-07 12:02:16 -070070def GetFilenameFromString(string):
71 return ApplySubs(string,
Ahmad Sharif4467f002012-12-20 12:09:49 -080072 (r"/", "__"),
73 (r"\s", "_"),
74 (r"[\^\$=\"\\\?]", ""),
75 )
Ahmad Shariffd356fb2012-05-07 12:02:16 -070076
77
78def GetRoot(scr_name):
79 """Break up pathname into (dir+name)."""
80 abs_path = os.path.abspath(scr_name)
81 return (os.path.dirname(abs_path), os.path.basename(abs_path))
82
83
Ahmad Sharif4467f002012-12-20 12:09:49 -080084def GetChromeOSKeyFile(chromeos_root):
85 return os.path.join(chromeos_root,
86 "src",
87 "scripts",
88 "mod_for_test_scripts",
89 "ssh_keys",
90 "testing_rsa")
91
92
Ahmad Sharif5ae8a5c2012-05-18 10:59:51 -070093def GetChrootPath(chromeos_root):
94 return os.path.join(chromeos_root,
95 "chroot")
96
97
98def GetInsideChrootPath(chromeos_root, file_path):
99 if not file_path.startswith(GetChrootPath(chromeos_root)):
100 raise Exception("File: %s doesn't seem to be in the chroot: %s" %
101 (file_path,
102 chromeos_root))
103 return file_path[len(GetChrootPath(chromeos_root)):]
104
105
106def GetOutsideChrootPath(chromeos_root, file_path):
107 return os.path.join(GetChrootPath(chromeos_root),
108 file_path.lstrip("/"))
109
110
Ahmad Shariffd356fb2012-05-07 12:02:16 -0700111def FormatQuotedCommand(command):
112 return ApplySubs(command,
113 ("\"", "\\\""))
114
115
116def FormatCommands(commands):
117 return ApplySubs(str(commands),
118 ("&&", "&&\n"),
119 (";", ";\n"),
Ahmad Sharif4467f002012-12-20 12:09:49 -0800120 (r"\n+\s*", "\n"))
Ahmad Shariffd356fb2012-05-07 12:02:16 -0700121
122
123def GetImageDir(chromeos_root, board):
124 return os.path.join(chromeos_root,
125 "src",
126 "build",
127 "images",
128 board)
129
130
131def LabelLatestImage(chromeos_root, board, label):
132 image_dir = GetImageDir(chromeos_root, board)
133 latest_image_dir = os.path.join(image_dir, "latest")
134 latest_image_dir = os.path.realpath(latest_image_dir)
135 latest_image_dir = os.path.basename(latest_image_dir)
136 with WorkingDirectory(image_dir):
137 command = "ln -sf -T %s %s" % (latest_image_dir, label)
138 ce = command_executer.GetCommandExecuter()
139 return ce.RunCommand(command)
140
141
142def DoesLabelExist(chromeos_root, board, label):
143 image_label = os.path.join(GetImageDir(chromeos_root, board),
144 label)
145 return os.path.exists(image_label)
146
147
Luis Lozanof81680c2013-03-15 14:44:13 -0700148def GetBuildPackagesCommand(board, usepkg=False, debug=False):
Ahmad Shariffd356fb2012-05-07 12:02:16 -0700149 if usepkg:
150 usepkg_flag = "--usepkg"
151 else:
152 usepkg_flag = "--nousepkg"
Luis Lozanof81680c2013-03-15 14:44:13 -0700153 if debug:
154 withdebug_flag = '--withdebug'
155 else:
156 withdebug_flag = '--nowithdebug'
Ahmad Shariffd356fb2012-05-07 12:02:16 -0700157 return ("./build_packages %s --withdev --withtest --withautotest "
Luis Lozanof81680c2013-03-15 14:44:13 -0700158 "--skip_toolchain_update %s --board=%s" %
159 (usepkg_flag, withdebug_flag, board))
Ahmad Shariffd356fb2012-05-07 12:02:16 -0700160
161
Luis Lozanof81680c2013-03-15 14:44:13 -0700162def GetBuildImageCommand(board, dev=False):
163 dev_args = ""
164 if dev:
165 dev_args = "--noenable_rootfs_verification --disk_layout=2gb-rootfs"
166 return "./build_image --board=%s %s test" % (board, dev_args)
Ahmad Shariffd356fb2012-05-07 12:02:16 -0700167
168def GetSetupBoardCommand(board, gcc_version=None, binutils_version=None,
169 usepkg=None, force=None):
Ahmad Sharif4467f002012-12-20 12:09:49 -0800170 """Get setup_board command."""
Ahmad Shariffd356fb2012-05-07 12:02:16 -0700171 options = []
172
173 if gcc_version:
174 options.append("--gcc_version=%s" % gcc_version)
175
176 if binutils_version:
177 options.append("--binutils_version=%s" % binutils_version)
178
179 if usepkg:
180 options.append("--usepkg")
181 else:
182 options.append("--nousepkg")
183
184 if force:
185 options.append("--force")
186
187 return "./setup_board --board=%s %s" % (board, " ".join(options))
188
189
190def CanonicalizePath(path):
191 path = os.path.expanduser(path)
192 path = os.path.realpath(path)
193 return path
194
195
196def GetCtargetFromBoard(board, chromeos_root):
Ahmad Sharif4467f002012-12-20 12:09:49 -0800197 """Get Ctarget from board."""
Ahmad Shariffd356fb2012-05-07 12:02:16 -0700198 base_board = board.split("_")[0]
199 command = ("source "
200 "../platform/dev/toolchain_utils.sh; get_ctarget_from_board %s" %
201 base_board)
202 ce = command_executer.GetCommandExecuter()
Ahmad Shariff395c262012-10-09 17:48:09 -0700203 ret, out, _ = ce.ChrootRunCommand(chromeos_root,
204 command,
205 return_output=True)
Ahmad Shariffd356fb2012-05-07 12:02:16 -0700206 if ret != 0:
207 raise ValueError("Board %s is invalid!" % board)
Ahmad Shariff395c262012-10-09 17:48:09 -0700208 # Remove ANSI escape sequences.
209 out = StripANSIEscapeSequences(out)
Ahmad Shariffd356fb2012-05-07 12:02:16 -0700210 return out.strip()
211
212
Ahmad Shariff395c262012-10-09 17:48:09 -0700213def StripANSIEscapeSequences(string):
Ahmad Sharif4467f002012-12-20 12:09:49 -0800214 string = re.sub(r"\x1b\[[0-9]*[a-zA-Z]", "", string)
Ahmad Shariff395c262012-10-09 17:48:09 -0700215 return string
216
217
Ahmad Shariffd356fb2012-05-07 12:02:16 -0700218def GetChromeSrcDir():
219 return "var/cache/distfiles/target/chrome-src/src"
220
221
222def GetEnvStringFromDict(env_dict):
223 return " ".join(["%s=\"%s\"" % var for var in env_dict.items()])
224
225
Ahmad Shariff395c262012-10-09 17:48:09 -0700226def MergeEnvStringWithDict(env_string, env_dict, prepend=True):
Ahmad Sharif4467f002012-12-20 12:09:49 -0800227 """Merge env string with dict."""
Ahmad Shariff395c262012-10-09 17:48:09 -0700228 if not env_string.strip():
229 return GetEnvStringFromDict(env_dict)
230 override_env_list = []
231 ce = command_executer.GetCommandExecuter()
232 for k, v in env_dict.items():
233 v = v.strip("\"'")
234 if prepend:
235 new_env = "%s=\"%s $%s\"" % (k, v, k)
236 else:
237 new_env = "%s=\"$%s %s\"" % (k, k, v)
238 command = "; ".join([env_string, new_env, "echo $%s" % k])
239 ret, out, _ = ce.RunCommand(command, return_output=True)
240 override_env_list.append("%s=%r" % (k, out.strip()))
241 ret = env_string + " " + " ".join(override_env_list)
242 return ret.strip()
243
244
Ahmad Shariffd356fb2012-05-07 12:02:16 -0700245def GetAllImages(chromeos_root, board):
246 ce = command_executer.GetCommandExecuter()
247 command = ("find %s/src/build/images/%s -name chromiumos_test_image.bin" %
248 (chromeos_root, board))
Ahmad Shariff395c262012-10-09 17:48:09 -0700249 ret, out, _ = ce.RunCommand(command, return_output=True)
250 assert ret == 0, "Could not run command: %s" % command
Ahmad Shariffd356fb2012-05-07 12:02:16 -0700251 return out.splitlines()
252
253
Ahmad Sharif4467f002012-12-20 12:09:49 -0800254def AcquireLock(lock_file, timeout=1200):
255 """Acquire a lock with timeout."""
256 start_time = time.time()
257 locked = False
258 abs_path = os.path.abspath(lock_file)
259 dir_path = os.path.dirname(abs_path)
260 sleep_time = min(10, timeout/10.0)
Luis Lozanof81680c2013-03-15 14:44:13 -0700261 reason = "pid: {0}, commad: {1}".format(os.getpid(),
262 sys.argv[0])
Ahmad Sharif4467f002012-12-20 12:09:49 -0800263 if not os.path.exists(dir_path):
264 try:
Luis Lozanof81680c2013-03-15 14:44:13 -0700265 with lock_machine.FileCreationMask(0002):
266 os.makedirs(dir_path)
Ahmad Sharif4467f002012-12-20 12:09:49 -0800267 except OSError:
268 print "Cannot create dir {0}, exiting...".format(dir_path)
269 exit(0)
270 while True:
Luis Lozanof81680c2013-03-15 14:44:13 -0700271 locked = (lock_machine.Lock(lock_file).NonBlockingLock(True, reason))
Ahmad Sharif4467f002012-12-20 12:09:49 -0800272 if locked:
273 break
274 time.sleep(sleep_time)
275 if time.time() - start_time > timeout:
276 logger.GetLogger().LogWarning(
277 "Could not acquire lock on this file: {0} within {1} seconds."
278 "Manually remove the file if you think the lock is stale"
279 .format(abs_path, timeout))
280 break
281 return locked
282
283
284def ReleaseLock(lock_file):
285 lock_file = os.path.abspath(lock_file)
286 ret = lock_machine.Lock(lock_file).Unlock(True)
287 assert ret, ("Could not unlock {0},"
288 "Please remove it manually".format(lock_file))
289
290
291def IsFloat(text):
292 if text is None:
293 return False
294 try:
295 float(text)
296 return True
297 except ValueError:
298 return False
299
300def RemoveChromeBrowserObjectFiles(chromeos_root, board):
301 """ Remove any object files from all the posible locations """
302 out_dir = os.path.join(
303 GetChrootPath(chromeos_root),
304 "var/cache/chromeos-chrome/chrome-src/src/out_%s" % board)
305 if os.path.exists(out_dir):
306 shutil.rmtree(out_dir)
307 logger.GetLogger().LogCmd("rm -rf %s" % out_dir)
308 out_dir = os.path.join(
309 GetChrootPath(chromeos_root),
310 "var/cache/chromeos-chrome/chrome-src-internal/src/out_%s" % board)
311 if os.path.exists(out_dir):
312 shutil.rmtree(out_dir)
313 logger.GetLogger().LogCmd("rm -rf %s" % out_dir)
314
Ahmad Shariffd356fb2012-05-07 12:02:16 -0700315@contextmanager
316def WorkingDirectory(new_dir):
Ahmad Sharif4467f002012-12-20 12:09:49 -0800317 """Get the working directory."""
Ahmad Shariffd356fb2012-05-07 12:02:16 -0700318 old_dir = os.getcwd()
319 if old_dir != new_dir:
320 msg = "cd %s" % new_dir
321 logger.GetLogger().LogCmd(msg)
322 os.chdir(new_dir)
323 yield new_dir
324 if old_dir != new_dir:
325 msg = "cd %s" % old_dir
326 logger.GetLogger().LogCmd(msg)
327 os.chdir(old_dir)
Han Shen91445322013-03-20 13:43:31 -0700328
329def HasGitStagedChanges(git_dir):
330 """Return True if git repository has staged changes."""
331 command = 'cd {0} && git diff --quiet --cached --exit-code HEAD'.format(
332 git_dir)
333 return command_executer.GetCommandExecuter().RunCommand(
334 command, print_to_console=False)
335
336def HasGitUnstagedChanges(git_dir):
337 """Return True if git repository has un-staged changes."""
338 command = 'cd {0} && git diff --quiet --exit-code HEAD'.format(git_dir)
339 return command_executer.GetCommandExecuter().RunCommand(
340 command, print_to_console=False)
341
342def HasGitUntrackedChanges(git_dir):
343 """Return True if git repository has un-tracked changes."""
344 command = 'cd {0} && test -z $(git ls-files --exclude-standard --others)' \
345 .format(git_dir)
346 return command_executer.GetCommandExecuter().RunCommand(
347 command,print_to_console=False)
348
349def IsGitTreeClean(git_dir):
350 if HasGitStagedChanges(git_dir):
351 logger.GetLogger().LogWarning("Git tree has staged changes.")
352 return False
353 if HasGitUnstagedChanges(git_dir):
354 logger.GetLogger().LogWarning("Git tree has unstaged changes.")
355 return False
356 if HasGitUntrackedChanges(git_dir):
357 logger.GetLogger().LogWarning("Git tree has un-tracked changes.")
358 return False
359 return True
360
361def GetGitChangesAsList(git_dir, path=None, staged=False):
362 command = 'cd {0} && git diff --name-only'.format(git_dir)
363 if staged:
364 command = command + ' --cached'
365 if path:
366 command = command + ' -- ' + path
367 ec, out, err = command_executer.GetCommandExecuter().RunCommand(
368 command, return_output=True, print_to_console=False)
369 rv = []
370 for line in out.splitlines():
371 rv.append(line)
372 return rv