Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create `mach bootstrap` based on Mozilla's mozboot bootstrapper #12916

Merged
merged 2 commits into from Sep 8, 2016
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

@@ -2,6 +2,7 @@ version: 1.0.{build}

environment:
RUST_BACKTRACE: 1
HOME: '%APPVEYOR_BUILD_FOLDER%'
# The appveyor image we use has a pretty huge set of things installed... we make the
# initial PATH something sane so we know what to expect
PATH: "C:\\windows\\system32;\
@@ -45,26 +46,6 @@ cache:
install:
- if %TARGET:*-msvc=msvc%==msvc set BUILD_ENV=msvc
- if %TARGET:*-gnu=gnu%==gnu set BUILD_ENV=gnu
- ps: 'if ($env:BUILD_ENV -eq "msvc") {
Start-FileDownload "http://servo-rust.s3.amazonaws.com/build/openssl-and-ffmpeg.zip" -ErrorAction Stop ;
Start-FileDownload "http://servo-rust.s3.amazonaws.com/build/ninja.zip" -ErrorAction Stop ;
Start-FileDownload "http://servo-rust.s3.amazonaws.com/build/MozillaBuildSetup-2.2.0.exe" -ErrorAction Stop ;
.\MozillaBuildSetup-2.2.0.exe /S | Out-Null ;
7z x openssl-and-ffmpeg.zip | Out-Null ;
7z x ninja.zip | Out-Null ;
Copy-Item C:\mozilla-build\yasm\yasm.exe C:\mozilla-build\msys\bin ;
Copy-Item C:\mozilla-build\mozmake\mozmake.exe C:\mozilla-build\msys\bin ;
$env:MOZTOOLS_PATH="C:\mozilla-build\msys\bin" ;
$env:NATIVE_WIN32_PYTHON="C:/Python27/python.exe" ;
$env:PATH="$pwd\ninja;$env:PATH" ;
$env:OPENSSL_INCLUDE_DIR="$pwd\openssl-bin\openssl-1.0.1t-vs2015\include" ;
$env:OPENSSL_LIB_DIR="$pwd\openssl-bin\openssl-1.0.1t-vs2015\lib64" ;
$env:OPENSSL_LIBS="ssleay32MD:libeay32MD" ;
$env:FFMPEG_INCLUDE_DIR="$pwd\ffmpeg-bin\include" ;
$env:FFMPEG_LIB_DIR="$pwd\ffmpeg-bin\lib" ;
$env:FFMPEG_LIBS="avformat:avcodec:avutil" ;
}'
- if %BUILD_ENV%==msvc call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64\vcvars64.bat"
- if %BUILD_ENV%==gnu set PATH=C:\msys64\mingw64\bin;C:\msys64\usr\bin\;%PATH%
- if %BUILD_ENV%==gnu set MSYSTEM=MINGW64
- if %BUILD_ENV%==gnu set MSYS=winsymlinks=lnk
@@ -87,10 +68,7 @@ install:
# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))

build_script:
- echo PATH %PATH%
- echo VSINSTALLDIR %VSINSTALLDIR%
- echo MOZTOOLS_PATH %MOZTOOLS_PATH%
- if %BUILD_ENV%==msvc cd %APPVEYOR_BUILD_FOLDER% && 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%==msvc mach build -d -v && mach test-unit
- if %BUILD_ENV%==gnu bash -lc "./mach build -d -v && ./mach test-unit"

test: off
@@ -19,6 +19,7 @@
import sys
import StringIO
import tarfile
import zipfile
import urllib2

from mach.decorators import (
@@ -101,7 +102,10 @@ def download_bytes(desc, src):


def extract(src, dst, movedir=None):
tarfile.open(src).extractall(dst)
if src.endswith(".zip"):
zipfile.ZipFile(src).extractall(dst)
else:
tarfile.open(src).extractall(dst)

if movedir:
for f in os.listdir(movedir):
@@ -126,6 +130,24 @@ def env(self):
else:
print("export LD_LIBRARY_PATH=%s" % env["LD_LIBRARY_PATH"])

@Command('bootstrap',
description='Install required packages for building.',
category='bootstrap')
@CommandArgument('--interactive', "-i",
action='store_true',
help='Need to answer any (Y/n) interactive prompts.')
@CommandArgument('--android',
action='store_true',
help='Install required packages for Android')
@CommandArgument('--force', '-f',
action='store_true',
help='Force reinstall packages')
def bootstrap(self, android=False, interactive=False, force=False):
from servo.bootstrapper.bootstrap import Bootstrapper

bootstrapper = Bootstrapper()
bootstrapper.bootstrap(android=android, interactive=interactive, force=force)

@Command('bootstrap-rust',
description='Download the Rust compiler',
category='bootstrap')
@@ -0,0 +1,3 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
@@ -0,0 +1,62 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.

from __future__ import print_function, unicode_literals

import distutils
import subprocess


class BaseBootstrapper(object):
"""Base class for system bootstrappers."""

def __init__(self, interactive=False):
self.package_manager_updated = False
self.interactive = interactive

def ensure_system_packages(self):
'''
Check for missing packages.
'''
raise NotImplementedError('%s must implement ensure_system_packages()' %
__name__)

def install_system_packages(self):
'''
Install packages required to build Servo.
'''
raise NotImplementedError('%s must implement install_system_packages()' %
__name__)

def install_mobile_android_packages(self):
'''
Install packages required to build Servo for Android.
'''
raise NotImplementedError('Cannot bootstrap Servo for Android: '
'%s does not yet implement install_mobile_android_packages()'
% __name__)

def which(self, name):
"""Python implementation of which.

This comment has been minimized.

@wafflespeanut

wafflespeanut Sep 2, 2016

Member

Can't we just use distutils.spawn.find_executable? (like we do in mach_bootstrap.py)

This comment has been minimized.

@UK992

UK992 Sep 2, 2016

Author Contributor

done

It returns the path of an executable or None if it couldn't be found.
"""
return distutils.spawn.find_executable(name)

def check_output(self, *args, **kwargs):
"""Run subprocess.check_output."""
return subprocess.check_output(*args, **kwargs)

def _ensure_package_manager_updated(self):
if self.package_manager_updated:
return

self._update_package_manager()
self.package_manager_updated = True

def _update_package_manager(self):
"""Updates the package manager's manifests/package list.
This should be defined in child classes.
"""
@@ -0,0 +1,41 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.

from __future__ import print_function

import sys

from windows_gnu import WindowsGnuBootstrapper
from windows_msvc import WindowsMsvcBootstrapper


class Bootstrapper(object):
"""Main class that performs system bootstrap."""

def __init__(self):
self.instance = None
cls = None
args = {}

if sys.platform.startswith('msys'):
cls = WindowsGnuBootstrapper

elif sys.platform.startswith('win32'):
cls = WindowsMsvcBootstrapper

if cls is None:
sys.exit('Bootstrap support is not yet available for your OS.')

self.instance = cls(**args)

def bootstrap(self, android=False, interactive=False, force=False):
self.instance.interactive = interactive
self.instance.force = force

if android:
self.instance.install_mobile_android_packages()
elif force:
self.instance.install_system_packages()
else:
self.instance.ensure_system_packages()
@@ -0,0 +1,28 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.

# Listed all packages for different platforms in one file

WINDOWS_GNU = [
"mingw-w64-x86_64-toolchain",
"mingw-w64-x86_64-freetype",
"mingw-w64-x86_64-icu",
"mingw-w64-x86_64-nspr",
"mingw-w64-x86_64-ca-certificates",
"mingw-w64-x86_64-expat",
"mingw-w64-x86_64-cmake",
"tar",
"diffutils",
"patch",
"patchutils",
"make",
"python2-setuptools",
]

WINDOWS_MSVC = [
"cmake-3.6.1",
"ninja-1.7.1",
"openssl-1.0.1t-vs2015",
"moztools-0.0.1-5",
]
@@ -0,0 +1,75 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

import sys
import subprocess

from base import BaseBootstrapper
from packages import WINDOWS_GNU as deps


class WindowsGnuBootstrapper(BaseBootstrapper):
'''Bootstrapper for msys2 based environments for building in Windows.'''

def __init__(self, **kwargs):
BaseBootstrapper.__init__(self, **kwargs)

if not self.which('pacman'):
raise NotImplementedError('The Windows bootstrapper only works with msys2 with pacman. Get msys2 at '
'http://msys2.github.io/')

def ensure_system_packages(self):
install_packages = []
for p in deps:
command = ['pacman', '-Qs', p]
if self.run_check(command):
install_packages += [p]
if install_packages:
install_packages(install_packages)

def install_system_packages(self, packages=deps):
self._ensure_package_manager_updated()
self.pacman_install(*packages)

def install_mobile_android_packages(self):
sys.exit('We do not support building Android on Windows. Sorry!')

def _update_package_manager(self):
self.pacman_update()

def run(self, command):
subprocess.check_call(command, stdin=sys.stdin)

def run_check(self, command):
return subprocess.call(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

def pacman_update(self):
command = ['pacman', '--sync', '--refresh']
self.run(command)

def pacman_upgrade(self):
command = ['pacman', '--sync', '--refresh', '--sysupgrade']
self.run(command)

def pacman_install(self, *packages):
command = ['pacman', '--sync']
if not self.force:
command.append('--needed')
if not self.interactive:
command.append('--noconfirm')
command.extend(packages)
self.run(command)

# downgrade GCC to 5.4.0-1
gcc_type = ["gcc", "gcc-ada", "gcc-fortran", "gcc-libgfortran", "gcc-libs", "gcc-objc"]
gcc_version = "5.4.0-1"
mingw_url = "http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-{}-{}-any.pkg.tar.xz"
gcc_list = []
for gcc in gcc_type:
gcc_list += [mingw_url.format(gcc, gcc_version)]
downgrade_command = ['pacman', '-U']
if not self.interactive:
downgrade_command.append('--noconfirm')
downgrade_command.extend(gcc_list)
self.run(downgrade_command)
@@ -0,0 +1,86 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

import os
import sys
import shutil
from distutils import spawn

from base import BaseBootstrapper
from packages import WINDOWS_MSVC as deps


class WindowsMsvcBootstrapper(BaseBootstrapper):
'''Bootstrapper for MSVC building on Windows.'''

def __init__(self, **kwargs):
BaseBootstrapper.__init__(self, **kwargs)

def ensure_system_packages(self):
self.install_system_packages()

def install_system_packages(self, packages=deps):
from servo.bootstrap_commands import extract, download_file

deps_dir = os.path.join(".servo", "msvc-dependencies")
deps_url = "https://servo-rust.s3.amazonaws.com/msvc-deps/"
first_run = True

if self.force:
if os.path.isdir(deps_dir):
shutil.rmtree(deps_dir)

if not os.path.isdir(deps_dir):
os.makedirs(deps_dir)

# Read file with installed dependencies, if exist
installed_deps_file = os.path.join(deps_dir, "installed-dependencies.txt")
if os.path.exists(installed_deps_file):
installed_deps = [l.strip() for l in open(installed_deps_file)]
else:
installed_deps = []

# list of dependencies that need to be updated
update_deps = list(set(packages) - set(installed_deps))

for dep in packages:
dep_name = dep.split("-")[0]

# Don't download CMake if already exists in PATH
if dep_name == "cmake":
if spawn.find_executable(dep_name):
continue

dep_dir = os.path.join(deps_dir, dep_name)
# if not installed or need to be updated
if not os.path.exists(dep_dir) or dep in update_deps:
if first_run:
print "Installing missing MSVC dependencies..."
first_run = False

dep_version_dir = os.path.join(deps_dir, dep)

if os.path.exists(dep_version_dir):
shutil.rmtree(dep_version_dir)

dep_zip = dep_version_dir + ".zip"
if not os.path.isfile(dep_zip):
download_file(dep, "%s%s.zip" % (deps_url, dep), dep_zip)

print "Extracting %s..." % dep,
extract(dep_zip, deps_dir)
print "done"

# Delete directory if exist
if os.path.exists(dep_dir):
shutil.rmtree(dep_dir)
os.rename(dep_version_dir, dep_dir)

# Write in installed-dependencies.txt file
with open(installed_deps_file, 'w') as installed_file:
for line in packages:
installed_file.write(line + "\n")

def install_mobile_android_packages(self):
sys.exit('We do not support building Android on Windows. Sorry!')
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.