aboutsummaryrefslogtreecommitdiffstats
path: root/python
diff options
context:
space:
mode:
Diffstat (limited to 'python')
-rw-r--r--python/servo/build_commands.py105
-rw-r--r--python/servo/command_base.py22
-rw-r--r--python/servo/testing_commands.py11
-rw-r--r--python/servo/win32_toast.py45
-rw-r--r--python/tidy/servo_tidy/tidy.py19
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", []):