diff options
Diffstat (limited to 'python')
-rw-r--r-- | python/servo/build_commands.py | 105 | ||||
-rw-r--r-- | python/servo/command_base.py | 22 | ||||
-rw-r--r-- | python/servo/testing_commands.py | 11 | ||||
-rw-r--r-- | python/servo/win32_toast.py | 45 | ||||
-rw-r--r-- | python/tidy/servo_tidy/tidy.py | 19 |
5 files changed, 143 insertions, 59 deletions
diff --git a/python/servo/build_commands.py b/python/servo/build_commands.py index 275b2309f2e..708640208b8 100644 --- a/python/servo/build_commands.py +++ b/python/servo/build_commands.py @@ -23,7 +23,7 @@ from mach.decorators import ( Command, ) -from servo.command_base import CommandBase, cd, call, BIN_SUFFIX +from servo.command_base import CommandBase, cd, call, BIN_SUFFIX, host_triple def format_duration(seconds): @@ -42,26 +42,31 @@ def notify_linux(title, text): def notify_win(title, text): - from ctypes import Structure, windll, POINTER, sizeof - from ctypes.wintypes import DWORD, HANDLE, WINFUNCTYPE, BOOL, UINT + try: + from servo.win32_toast import WindowsToast + w = WindowsToast() + w.balloon_tip(title, text) + except: + from ctypes import Structure, windll, POINTER, sizeof + from ctypes.wintypes import DWORD, HANDLE, WINFUNCTYPE, BOOL, UINT - class FLASHWINDOW(Structure): - _fields_ = [("cbSize", UINT), - ("hwnd", HANDLE), - ("dwFlags", DWORD), - ("uCount", UINT), - ("dwTimeout", DWORD)] + class FLASHWINDOW(Structure): + _fields_ = [("cbSize", UINT), + ("hwnd", HANDLE), + ("dwFlags", DWORD), + ("uCount", UINT), + ("dwTimeout", DWORD)] - FlashWindowExProto = WINFUNCTYPE(BOOL, POINTER(FLASHWINDOW)) - FlashWindowEx = FlashWindowExProto(("FlashWindowEx", windll.user32)) - FLASHW_CAPTION = 0x01 - FLASHW_TRAY = 0x02 - FLASHW_TIMERNOFG = 0x0C + FlashWindowExProto = WINFUNCTYPE(BOOL, POINTER(FLASHWINDOW)) + FlashWindowEx = FlashWindowExProto(("FlashWindowEx", windll.user32)) + FLASHW_CAPTION = 0x01 + FLASHW_TRAY = 0x02 + FLASHW_TIMERNOFG = 0x0C - params = FLASHWINDOW(sizeof(FLASHWINDOW), - windll.kernel32.GetConsoleWindow(), - FLASHW_CAPTION | FLASHW_TRAY | FLASHW_TIMERNOFG, 3, 0) - FlashWindowEx(params) + params = FLASHWINDOW(sizeof(FLASHWINDOW), + windll.kernel32.GetConsoleWindow(), + FLASHW_CAPTION | FLASHW_TRAY | FLASHW_TIMERNOFG, 3, 0) + FlashWindowEx(params) def notify_darwin(title, text): @@ -86,11 +91,11 @@ def notify_darwin(title, text): raise Exception("Optional Python module 'pyobjc' is not installed.") -def notify_build_done(elapsed): +def notify_build_done(elapsed, success=True): """Generate desktop notification when build is complete and the elapsed build time was longer than 30 seconds.""" if elapsed > 30: - notify("Servo build", "Completed in %s" % format_duration(elapsed)) + notify("Servo build", "%s in %s" % ("Completed" if success else "FAILED", format_duration(elapsed))) def notify(title, text): @@ -100,7 +105,7 @@ def notify(title, text): platforms = { "linux": notify_linux, "linux2": notify_linux, - "win": notify_win, + "win32": notify_win, "darwin": notify_darwin } func = platforms.get(sys.platform) @@ -236,36 +241,52 @@ class MachCommands(CommandBase): cargo_binary = "cargo" + BIN_SUFFIX - if sys.platform == "win32" or sys.platform == "msys": - env["RUSTFLAGS"] = "-C link-args=-Wl,--subsystem,windows" + if sys.platform in ("win32", "msys"): + if "msvc" not in host_triple(): + env[b'RUSTFLAGS'] = b'-C link-args=-Wl,--subsystem,windows' status = call( [cargo_binary, "build"] + opts, env=env, cwd=self.servo_crate(), verbose=verbose) elapsed = time() - build_start - if sys.platform == "win32" or sys.platform == "msys": - shutil.copy(path.join(self.get_top_dir(), "components", "servo", "servo.exe.manifest"), - path.join(base_path, "debug" if dev else "release")) - - # On the Mac, set a lovely icon. This makes it easier to pick out the Servo binary in tools - # like Instruments.app. - if sys.platform == "darwin": - try: - import Cocoa - icon_path = path.join(self.get_top_dir(), "resources", "servo.png") - icon = Cocoa.NSImage.alloc().initWithContentsOfFile_(icon_path) - if icon is not None: - Cocoa.NSWorkspace.sharedWorkspace().setIcon_forFile_options_(icon, - servo_path, - 0) - except ImportError: - pass + # Do some additional things if the build succeeded + if status == 0: + if sys.platform in ("win32", "msys"): + servo_exe_dir = path.join(base_path, "debug" if dev else "release") + # On windows, copy in our manifest + shutil.copy(path.join(self.get_top_dir(), "components", "servo", "servo.exe.manifest"), + servo_exe_dir) + if "msvc" in host_triple(): + # on msvc builds, use editbin to change the subsystem to windows + call(["editbin", "/nologo", "/subsystem:windows", path.join(servo_exe_dir, "servo.exe")], + verbose=verbose) + # on msvc, we need to copy in some DLLs in to the servo.exe dir + for ssl_lib in ["ssleay32md.dll", "libeay32md.dll"]: + shutil.copy(path.join(os.getenv('OPENSSL_LIB_DIR'), "../bin64", ssl_lib), + servo_exe_dir) + for ffmpeg_lib in ["avutil-55.dll", "avformat-57.dll", "avcodec-57.dll", "swresample-2.dll"]: + shutil.copy(path.join(os.getenv('FFMPEG_LIB_DIR'), "../bin", ffmpeg_lib), + servo_exe_dir) + + elif sys.platform == "darwin": + # On the Mac, set a lovely icon. This makes it easier to pick out the Servo binary in tools + # like Instruments.app. + try: + import Cocoa + icon_path = path.join(self.get_top_dir(), "resources", "servo.png") + icon = Cocoa.NSImage.alloc().initWithContentsOfFile_(icon_path) + if icon is not None: + Cocoa.NSWorkspace.sharedWorkspace().setIcon_forFile_options_(icon, + servo_path, + 0) + except ImportError: + pass # Generate Desktop Notification if elapsed-time > some threshold value - notify_build_done(elapsed) + notify_build_done(elapsed, status == 0) - print("Build completed in %s" % format_duration(elapsed)) + print("Build %s in %s" % ("Completed" if status == 0 else "FAILED", format_duration(elapsed))) return status @Command('build-cef', diff --git a/python/servo/command_base.py b/python/servo/command_base.py index 99dc78235ed..556f1e14e59 100644 --- a/python/servo/command_base.py +++ b/python/servo/command_base.py @@ -116,16 +116,6 @@ def host_triple(): return "%s-%s" % (cpu_type, os_type) -def call(*args, **kwargs): - """Wrap `subprocess.call`, printing the command if verbose=True.""" - verbose = kwargs.pop('verbose', False) - if verbose: - print(' '.join(args[0])) - # we have to use shell=True in order to get PATH handling - # when looking for the binary on Windows - return subprocess.call(*args, shell=sys.platform == 'win32', **kwargs) - - def normalize_env(env): # There is a bug in subprocess where it doesn't like unicode types in # environment variables. Here, ensure all unicode are converted to @@ -144,6 +134,18 @@ def normalize_env(env): return normalized_env +def call(*args, **kwargs): + """Wrap `subprocess.call`, printing the command if verbose=True.""" + verbose = kwargs.pop('verbose', False) + if verbose: + print(' '.join(args[0])) + if 'env' in kwargs: + kwargs['env'] = normalize_env(kwargs['env']) + # we have to use shell=True in order to get PATH handling + # when looking for the binary on Windows + return subprocess.call(*args, shell=sys.platform == 'win32', **kwargs) + + def check_call(*args, **kwargs): """Wrap `subprocess.check_call`, printing the command if verbose=True. diff --git a/python/servo/testing_commands.py b/python/servo/testing_commands.py index 5eaad0ba7b9..ffc2dd3869e 100644 --- a/python/servo/testing_commands.py +++ b/python/servo/testing_commands.py @@ -25,7 +25,7 @@ from mach.decorators import ( Command, ) -from servo.command_base import CommandBase, call, check_call +from servo.command_base import CommandBase, call, check_call, host_triple from wptrunner import wptcommandline from update import updatecommandline from servo_tidy import tidy @@ -220,8 +220,13 @@ class MachCommands(CommandBase): env = self.build_env() env["RUST_BACKTRACE"] = "1" - if sys.platform == "win32" or sys.platform == "msys": - env["RUSTFLAGS"] = "-C link-args=-Wl,--subsystem,windows" + if sys.platform in ("win32", "msys"): + if "msvc" in host_triple(): + # on MSVC, we need some DLLs in the path. They were copied + # in to the servo.exe build dir, so just point PATH to that. + env["PATH"] = "%s%s%s" % (path.dirname(self.get_binary_path(False, False)), os.pathsep, env["PATH"]) + else: + env["RUSTFLAGS"] = "-C link-args=-Wl,--subsystem,windows" result = call(args, env=env, cwd=self.servo_crate()) if result != 0: diff --git a/python/servo/win32_toast.py b/python/servo/win32_toast.py new file mode 100644 index 00000000000..22a7ccd917f --- /dev/null +++ b/python/servo/win32_toast.py @@ -0,0 +1,45 @@ +# Copyright 2013 The Servo Project Developers. See the COPYRIGHT +# file at the top-level directory of this distribution. +# +# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +# option. This file may not be copied, modified, or distributed +# except according to those terms. + +from win32api import GetModuleHandle +from win32gui import WNDCLASS, RegisterClass, CreateWindow, UpdateWindow +from win32gui import DestroyWindow, LoadIcon, NIF_ICON, NIF_MESSAGE, NIF_TIP +from win32gui import Shell_NotifyIcon, NIM_ADD, NIM_MODIFY, NIF_INFO, NIIF_INFO +import win32con + + +class WindowsToast: + def __init__(self): + # Register window class; it's okay to do this multiple times + wc = WNDCLASS() + wc.lpszClassName = 'ServoTaskbarNotification' + wc.lpfnWndProc = {win32con.WM_DESTROY: self.OnDestroy, } + self.classAtom = RegisterClass(wc) + self.hinst = wc.hInstance = GetModuleHandle(None) + + def OnDestroy(self, hwnd, msg, wparam, lparam): + # We don't have to Shell_NotifyIcon to delete it, since + # we destroyed + pass + + def balloon_tip(self, title, msg): + style = win32con.WS_OVERLAPPED | win32con.WS_SYSMENU + hwnd = CreateWindow(self.classAtom, "Taskbar", style, 0, 0, + win32con.CW_USEDEFAULT, win32con.CW_USEDEFAULT, + 0, 0, self.hinst, None) + UpdateWindow(hwnd) + + hicon = LoadIcon(0, win32con.IDI_APPLICATION) + + nid = (hwnd, 0, NIF_ICON | NIF_MESSAGE | NIF_TIP, win32con.WM_USER + 20, hicon, 'Tooltip') + Shell_NotifyIcon(NIM_ADD, nid) + nid = (hwnd, 0, NIF_INFO, win32con.WM_USER + 20, hicon, 'Balloon Tooltip', msg, 200, title, NIIF_INFO) + Shell_NotifyIcon(NIM_MODIFY, nid) + + DestroyWindow(hwnd) diff --git a/python/tidy/servo_tidy/tidy.py b/python/tidy/servo_tidy/tidy.py index d6d6344db54..f4b893bda8c 100644 --- a/python/tidy/servo_tidy/tidy.py +++ b/python/tidy/servo_tidy/tidy.py @@ -202,8 +202,9 @@ def check_modeline(file_name, lines): def check_length(file_name, idx, line): - if file_name.endswith(".lock") or file_name.endswith(".json") or file_name.endswith(".html"): - raise StopIteration + for suffix in [".lock", ".json", ".html", ".toml"]: + if file_name.endswith(suffix): + raise StopIteration # Prefer shorter lines when shell scripting. if file_name.endswith(".sh"): max_length = 80 @@ -297,8 +298,18 @@ def check_lock(file_name, contents): # package names to be neglected (as named by cargo) exceptions = ["lazy_static"] - import toml - content = toml.loads(contents) + # toml.py has a bug(?) that we trip up in [metadata] sections; + # see https://github.com/uiri/toml/issues/61 + # This should only affect a very few lines (that have embedded ?branch=...), + # and most of them won't be in the repo + try: + import toml + content = toml.loads(contents) + except: + print "WARNING!" + print "WARNING! toml parsing failed for Cargo.lock, but ignoring..." + print "WARNING!" + raise StopIteration packages = {} for package in content.get("package", []): |