diff options
-rw-r--r-- | README.md | 12 | ||||
-rw-r--r-- | appveyor.yml | 2 | ||||
-rwxr-xr-x | mach | 69 | ||||
-rw-r--r-- | python/mach_bootstrap.py | 22 | ||||
-rw-r--r-- | python/servo/command_base.py | 5 | ||||
-rw-r--r-- | tests/wpt/run.py | 5 | ||||
-rw-r--r-- | tests/wpt/web-platform-tests/tools/sslutils/openssl.py | 8 |
7 files changed, 104 insertions, 19 deletions
diff --git a/README.md b/README.md index 531f90607f2..eb4bce6fbad 100644 --- a/README.md +++ b/README.md @@ -135,16 +135,14 @@ pacman -U --noconfirm $GCC_URL-$GCC_EXT $GCC_URL-ada-$GCC_EXT \ easy_install-2.7 pip virtualenv ``` -Open a new MSYS shell window as Administrator and remove the Python binaries (they -are not compatible with our `mach` driver script yet, unfortunately): +Add the following line to the end of `.profile` in your home directory: -```sh -cd /mingw64/bin -mv python2.exe python2-mingw64.exe -mv python2.7.exe python2.7-mingw64.exe +``` +export PATH=/c/Python27:$PATH ``` -Now, open a MINGW64 (not MSYS!) shell window, and you should be able to build servo as usual! +Now, open a MINGW64 (not MSYS!) shell window, and you should be able to build +servo as usual! #### Cross-compilation for Android diff --git a/appveyor.yml b/appveyor.yml index a313b572d5b..642954ff02b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -68,6 +68,6 @@ install: build_script: - if %BUILD_ENV%==msvc mach build -d -v && mach test-unit - - if %BUILD_ENV%==gnu bash -lc "cd $APPVEYOR_BUILD_FOLDER; ./mach build -d -v && ./mach test-unit" + - if %BUILD_ENV%==gnu bash -lc "export PATH=/c/Python27:$PATH; cd $APPVEYOR_BUILD_FOLDER; ./mach build -d -v && ./mach test-unit" test: off @@ -6,14 +6,16 @@ # The beginning of this script is both valid shell and valid python, # such that the script starts with the shell and is reexecuted with # the right python. -'''which' python2.7 > /dev/null 2> /dev/null && exec python2.7 "$0" "$@" || exec python "$0" "$@" +''':' && if [ ! -z "$MSYSTEM" ] ; then exec python "$0" "$@" ; else which python2.7 > /dev/null 2> /dev/null && exec python2.7 "$0" "$@" || exec python "$0" "$@" ; fi ''' from __future__ import print_function, unicode_literals + import os import sys + def main(args): topdir = os.path.abspath(os.path.dirname(sys.argv[0])) sys.path.insert(0, os.path.join(topdir, "python")) @@ -21,5 +23,70 @@ def main(args): mach = mach_bootstrap.bootstrap(topdir) sys.exit(mach.run(sys.argv[1:])) + if __name__ == '__main__': + if sys.platform == 'win32': + # This is a complete hack to work around the fact that Windows + # multiprocessing needs to import the original module (ie: this + # file), but only works if it has a .py extension. + # + # We do this by a sort of two-level function interposing. The first + # level interposes forking.get_command_line() with our version defined + # in my_get_command_line(). Our version of get_command_line will + # replace the command string with the contents of the fork_interpose() + # function to be used in the subprocess. + # + # The subprocess then gets an interposed imp.find_module(), which we + # hack up to find 'mach' without the .py extension, since we already + # know where it is (it's us!). If we're not looking for 'mach', then + # the original find_module will suffice. + # + # See also: http://bugs.python.org/issue19946 + # And: https://bugzilla.mozilla.org/show_bug.cgi?id=914563 + import inspect + from multiprocessing import forking + global orig_command_line + + def fork_interpose(): + import imp + import os + import sys + orig_find_module = imp.find_module + def my_find_module(name, dirs): + if name == 'mach': + path = os.path.join(dirs[0], 'mach') + f = open(path) + return (f, path, ('', 'r', imp.PY_SOURCE)) + return orig_find_module(name, dirs) + + # Don't allow writing bytecode file for mach module. + orig_load_module = imp.load_module + def my_load_module(name, file, path, description): + # multiprocess.forking invokes imp.load_module manually and + # hard-codes the name __parents_main__ as the module name. + if name == '__parents_main__': + old_bytecode = sys.dont_write_bytecode + sys.dont_write_bytecode = True + try: + return orig_load_module(name, file, path, description) + finally: + sys.dont_write_bytecode = old_bytecode + + return orig_load_module(name, file, path, description) + + imp.find_module = my_find_module + imp.load_module = my_load_module + from multiprocessing.forking import main; main() + + def my_get_command_line(): + fork_code, lineno = inspect.getsourcelines(fork_interpose) + # Remove the first line (for 'def fork_interpose():') and the three + # levels of indentation (12 spaces). + fork_string = ''.join(x[12:] for x in fork_code[1:]) + cmdline = orig_command_line() + cmdline[2] = fork_string + return cmdline + orig_command_line = forking.get_command_line + forking.get_command_line = my_get_command_line + main(sys.argv) diff --git a/python/mach_bootstrap.py b/python/mach_bootstrap.py index bd1f42417ad..c2d35278dae 100644 --- a/python/mach_bootstrap.py +++ b/python/mach_bootstrap.py @@ -76,9 +76,16 @@ CATEGORIES = { } # Possible names of executables -PYTHON_NAMES = ["python-2.7", "python2.7", "python2", "python"] -VIRTUALENV_NAMES = ["virtualenv-2.7", "virtualenv2.7", "virtualenv2", "virtualenv"] -PIP_NAMES = ["pip-2.7", "pip2.7", "pip2", "pip"] +# NOTE: Windows Python doesn't provide versioned executables, so we must use +# the plain names. On MSYS, we still use Windows Python. +if sys.platform in ['msys', 'win32']: + PYTHON_NAMES = ["python"] + VIRTUALENV_NAMES = ["virtualenv"] + PIP_NAMES = ["pip"] +else: + PYTHON_NAMES = ["python-2.7", "python2.7", "python2", "python"] + VIRTUALENV_NAMES = ["virtualenv-2.7", "virtualenv2.7", "virtualenv2", "virtualenv"] + PIP_NAMES = ["pip-2.7", "pip2.7", "pip2", "pip"] def _get_exec_path(names, is_valid_path=lambda _path: True): @@ -197,10 +204,11 @@ def bootstrap(topdir): # We don't support MinGW Python if os.path.join(os.sep, 'mingw64', 'bin') in sys.executable: - print('Cannot run mach with MinGW Python.') - print('\nPlease rename following files:') - print(' /mingw64/bin/python2.exe -> /mingw64/bin/python2-mingw64.exe') - print(' /mingw64/bin/python2.7.exe -> /mingw64/bin/python2.7-mingw64.exe') + print('Cannot run mach with MinGW or MSYS Python.') + print('\nPlease add the path to Windows Python (usually /c/Python27) to your path.') + print('You can do this by appending the line:') + print(' export PATH=/c/Python27:$PATH') + print('to your ~/.profile.') sys.exit(1) # Ensure we are running Python 2.7+. We put this check here so we generate a diff --git a/python/servo/command_base.py b/python/servo/command_base.py index c6ea363dd05..a67ea0b208d 100644 --- a/python/servo/command_base.py +++ b/python/servo/command_base.py @@ -107,7 +107,10 @@ def host_triple(): elif os_type == "android": os_type = "linux-androideabi" elif os_type == "windows": - os_type = "pc-windows-msvc" + if os.getenv("MSYSTEM") is None: + os_type = "pc-windows-msvc" + else: + os_type = "pc-windows-gnu" elif os_type.startswith("mingw64_nt-") or os_type.startswith("cygwin_nt-"): os_type = "pc-windows-gnu" elif os_type == "freebsd": diff --git a/tests/wpt/run.py b/tests/wpt/run.py index 0ee62500f73..b1b158e63ab 100644 --- a/tests/wpt/run.py +++ b/tests/wpt/run.py @@ -49,7 +49,10 @@ def set_defaults(paths, kwargs): if kwargs["binary"] is None: bin_dir = "release" if kwargs["release"] else "debug" - bin_path = servo_path("target", bin_dir, "servo") + bin_name = "servo" + if sys.platform == "win32": + bin_name += ".exe" + bin_path = servo_path("target", bin_dir, bin_name) kwargs["binary"] = bin_path diff --git a/tests/wpt/web-platform-tests/tools/sslutils/openssl.py b/tests/wpt/web-platform-tests/tools/sslutils/openssl.py index 26ed711356d..1b636f02272 100644 --- a/tests/wpt/web-platform-tests/tools/sslutils/openssl.py +++ b/tests/wpt/web-platform-tests/tools/sslutils/openssl.py @@ -57,7 +57,13 @@ class OpenSSL(object): self.cmd += ["-config", self.conf_path] self.cmd += list(args) - env = os.environ.copy() + # Copy the environment, converting to plain strings. Windows + # StartProcess is picky about all the keys/values being plain strings, + # but at least in MSYS shells, the os.environ dictionary can be mixed. + env = {} + for k, v in os.environ.iteritems(): + env[k.encode("utf8")] = v.encode("utf8") + if self.base_conf_path is not None: env["OPENSSL_CONF"] = self.base_conf_path.encode("utf8") |