327 строки
11 KiB
Python
327 строки
11 KiB
Python
import sys
|
|
import json
|
|
import urllib2
|
|
import urllib
|
|
import re
|
|
import os
|
|
import shutil
|
|
import socket
|
|
import utils
|
|
import puller
|
|
import platform
|
|
from utils import Run
|
|
|
|
import tarfile
|
|
import zipfile
|
|
socket.setdefaulttimeout(120)
|
|
|
|
class Environment(object):
|
|
def __init__(self):
|
|
self.env_ = os.environ.copy()
|
|
self.add("CC", "gcc")
|
|
self.add("CXX", "g++")
|
|
self.add("LINK", "g++")
|
|
self.ccoption = []
|
|
|
|
def add(self, name, data):
|
|
self.env_[name] = data
|
|
|
|
def addCCOption(self, option):
|
|
self.ccoption.append(option)
|
|
|
|
def get(self):
|
|
env = self.env_.copy()
|
|
if len(self.ccoption) > 0:
|
|
env["CC"] += " " + " ".join(self.ccoption)
|
|
env["CXX"] += " " + " ".join(self.ccoption)
|
|
return env
|
|
|
|
class Builder(object):
|
|
|
|
def __init__(self, config, folder):
|
|
self.env = Environment()
|
|
self.config = config
|
|
self.folder = folder
|
|
|
|
#if platform.system() == "Darwin":
|
|
# self.installClang()
|
|
# self.env.add("CC", os.path.abspath("clang-3.3/bin/clang"))
|
|
# self.env.add("CXX", os.path.abspath("clang-3.3/bin/clang++"))
|
|
# self.env.add("LINK", os.path.abspath("clang-3.3/bin/clang++"))
|
|
|
|
def installClang(self):
|
|
# The standard clang version on mac is outdated.
|
|
# Retrieve a better one.
|
|
|
|
if os.path.exists("clang-3.3"):
|
|
return
|
|
|
|
urllib.urlretrieve("http://llvm.org/releases/3.3/clang+llvm-3.3-x86_64-apple-darwin12.tar.gz", "./clang-3.3.tar.gz")
|
|
tar = tarfile.open("clang-3.3.tar.gz")
|
|
tar.extractall(".")
|
|
tar.close()
|
|
|
|
shutil.move("clang+llvm-3.3-x86_64-apple-darwin12", "clang-3.3")
|
|
|
|
os.unlink("clang-3.3.tar.gz")
|
|
|
|
def unlinkBinary(self):
|
|
try:
|
|
os.unlink(self.binary())
|
|
except:
|
|
pass
|
|
|
|
def unlinkObjdir(self):
|
|
try:
|
|
shutil.rmtree(self.objdir())
|
|
except:
|
|
pass
|
|
|
|
def successfullyBuild(self):
|
|
return os.path.isfile(self.binary())
|
|
|
|
def reconf(self):
|
|
return
|
|
|
|
def build(self, puller):
|
|
self.unlinkBinary()
|
|
|
|
self.make()
|
|
|
|
if not self.successfullyBuild():
|
|
self.reconf()
|
|
self.make()
|
|
|
|
assert self.successfullyBuild()
|
|
|
|
info = self.retrieveInfo()
|
|
info["revision"] = puller.identify()
|
|
# Deafult 'shell' to True only if it isn't set yet!
|
|
if 'shell' not in info:
|
|
info["shell"] = True
|
|
info["binary"] = os.path.abspath(self.binary())
|
|
|
|
fp = open(os.path.join(self.folder, "info.json"), "w")
|
|
json.dump(info, fp)
|
|
fp.close()
|
|
|
|
class MozillaBuilder(Builder):
|
|
def __init__(self, config, folder):
|
|
super(MozillaBuilder, self).__init__(config, folder);
|
|
|
|
if platform.architecture()[0] == "64bit" and self.config == "32bit":
|
|
self.env.add("AR",'ar')
|
|
self.env.add("CROSS_COMPILE", '1')
|
|
self.env.addCCOption("-m32")
|
|
|
|
def retrieveInfo(self):
|
|
info = {}
|
|
info["engine_type"] = "firefox"
|
|
return info
|
|
|
|
def objdir(self):
|
|
return os.path.join(self.folder, 'js', 'src', 'Opt')
|
|
|
|
def binary(self):
|
|
return os.path.join(self.objdir(), 'dist', 'bin', 'js')
|
|
|
|
def reconf(self):
|
|
# Step 1. autoconf.
|
|
with utils.FolderChanger(os.path.join(self.folder, 'js', 'src')):
|
|
if platform.system() == "Darwin":
|
|
utils.Shell("autoconf213")
|
|
elif platform.system() == "Linux":
|
|
utils.Shell("autoconf2.13")
|
|
elif platform.system() == "Windows":
|
|
utils.Shell("autoconf-2.13")
|
|
|
|
# Step 2. configure
|
|
if not os.path.exists(os.path.join(self.folder, 'js', 'src', 'Opt')):
|
|
os.mkdir(os.path.join(self.folder, 'js', 'src', 'Opt'))
|
|
with utils.FolderChanger(os.path.join(self.folder, 'js', 'src', 'Opt')):
|
|
args = ['--enable-optimize', '--disable-debug']
|
|
if platform.architecture()[0] == "64bit" and self.config == "32bit":
|
|
if platform.system() == "Darwin":
|
|
args.append("--target=i686-apple-darwin10.0.0")
|
|
elif platform.system() == "Linux":
|
|
args.append("--target=i686-pc-linux-gnu")
|
|
else:
|
|
assert False
|
|
|
|
Run(['../configure'] + args, self.env.get())
|
|
return True
|
|
|
|
def make(self):
|
|
if not os.path.exists(os.path.join(self.folder, 'js', 'src', 'Opt')):
|
|
return
|
|
utils.Shell("make -j6 -C " + os.path.join(self.folder, 'js', 'src', 'Opt'))
|
|
|
|
class WebkitBuilder(Builder):
|
|
def retrieveInfo(self):
|
|
with utils.chdir(os.path.join(self.folder)):
|
|
objdir = os.path.abspath(os.path.join('WebKitBuild', 'Release'))
|
|
|
|
info = {}
|
|
info["engine_type"] = "webkit"
|
|
info["env"] = {'DYLD_FRAMEWORK_PATH': objdir}
|
|
return info
|
|
|
|
def patch(self):
|
|
patch = os.path.join(os.path.dirname(os.path.realpath(__file__)), "jsc.patch")
|
|
|
|
with utils.FolderChanger(self.folder):
|
|
# Hack 1: Remove reporting errors for warnings that currently are present.
|
|
Run(["sed","-i.bac","s/GCC_TREAT_WARNINGS_AS_ERRORS = YES;/GCC_TREAT_WARNINGS_AS_ERRORS=NO;/","Source/JavaScriptCore/Configurations/Base.xcconfig"])
|
|
Run(["sed","-i.bac","s/GCC_TREAT_WARNINGS_AS_ERRORS = YES;/GCC_TREAT_WARNINGS_AS_ERRORS=NO;/","Source/bmalloc/Configurations/Base.xcconfig"])
|
|
Run(["sed","-i.bac","s/GCC_TREAT_WARNINGS_AS_ERRORS = YES;/GCC_TREAT_WARNINGS_AS_ERRORS=NO;/","Source/WTF/Configurations/Base.xcconfig"])
|
|
Run(["sed","-i.bac","s/std::numeric_limits<unsigned char>::max()/255/","Source/bmalloc/bmalloc/Line.h"])
|
|
Run(["sed","-i.bac","s/std::numeric_limits<unsigned char>::max()/255/","Source/bmalloc/bmalloc/Page.h"])
|
|
Run(["patch","Source/JavaScriptCore/jsc.cpp", patch])
|
|
|
|
# Hack 2: This check fails currently. Disable checking to still have a build.
|
|
os.remove("Tools/Scripts/check-for-weak-vtables-and-externals")
|
|
|
|
def clean(self):
|
|
with utils.FolderChanger(self.folder):
|
|
Run(["svn","revert","Tools/Scripts/check-for-weak-vtables-and-externals"])
|
|
|
|
Run(["svn","revert","Source/JavaScriptCore/Configurations/Base.xcconfig"])
|
|
Run(["svn","revert","Source/bmalloc/Configurations/Base.xcconfig"])
|
|
Run(["svn","revert","Source/WTF/Configurations/Base.xcconfig"])
|
|
Run(["svn","revert","Source/bmalloc/bmalloc/Line.h"])
|
|
Run(["svn","revert","Source/bmalloc/bmalloc/Page.h"])
|
|
Run(["svn","revert","Source/JavaScriptCore/jsc.cpp"])
|
|
|
|
def make(self):
|
|
try:
|
|
self.patch()
|
|
with utils.FolderChanger(os.path.join(self.folder, 'Tools', 'Scripts')):
|
|
args = ['/usr/bin/perl', 'build-jsc']
|
|
if self.config == '32bit':
|
|
args += ['--32-bit']
|
|
Run(args, self.env.get())
|
|
finally:
|
|
self.clean()
|
|
|
|
def objdir(self):
|
|
return os.path.join(self.folder, 'WebKitBuild', 'Release')
|
|
|
|
def binary(self):
|
|
return os.path.join(self.objdir(), 'jsc')
|
|
|
|
class V8Builder(Builder):
|
|
def __init__(self, config, folder):
|
|
super(V8Builder, self).__init__(config, folder)
|
|
|
|
self.env.add("GYP_DEFINES", "clang=1")
|
|
|
|
def retrieveInfo(self):
|
|
info = {}
|
|
info["engine_type"] = "chrome"
|
|
info["args"] = ['--expose-gc']
|
|
return info
|
|
|
|
def make(self):
|
|
args = ['make', '-j6', '-C', os.path.join(self.folder, 'v8')]
|
|
if self.config == '32bit':
|
|
args += ['ia32.release']
|
|
elif self.config == '64bit':
|
|
args += ['x64.release']
|
|
else:
|
|
assert True
|
|
|
|
Run(args, self.env.get())
|
|
|
|
def objdir(self):
|
|
if self.config == '64bit':
|
|
return os.path.join(self.folder, 'v8', 'out', 'x64.release')
|
|
elif self.config == '32bit':
|
|
return os.path.join(self.folder, 'v8', 'out', 'ia32.release')
|
|
else:
|
|
assert False
|
|
|
|
def binary(self):
|
|
return os.path.join(self.objdir(), 'd8')
|
|
|
|
class ServoBuilder(Builder):
|
|
def __init__(self, config, folder):
|
|
super(ServoBuilder, self).__init__(config, folder);
|
|
# Some other config here
|
|
|
|
def retrieveInfo(self):
|
|
info = {}
|
|
info["engine_type"] = "servo"
|
|
info['shell'] = False
|
|
return info
|
|
|
|
def objdir(self):
|
|
return os.path.join(self.folder, 'target')
|
|
|
|
def binary(self):
|
|
return os.path.join(self.objdir(), 'release', 'servo')
|
|
|
|
def make(self):
|
|
with utils.FolderChanger(self.folder):
|
|
args = [os.path.join('.', 'mach'), 'build' ,'--release']
|
|
Run(args, self.env.get())
|
|
|
|
def getBuilder(config, path):
|
|
# fingerprint the known builders
|
|
if os.path.exists(os.path.join(path, "js", "src")):
|
|
return MozillaBuilder(config, path)
|
|
if os.path.exists(os.path.join(path, "Source", "JavaScriptCore")):
|
|
return WebkitBuilder(config, path)
|
|
if os.path.exists(os.path.join(path, "v8", "LICENSE.v8")):
|
|
return V8Builder(config, path)
|
|
if os.path.exists(os.path.join(path, "components", "servo")):
|
|
return ServoBuilder(config, path)
|
|
|
|
raise Exception("Unknown builder")
|
|
|
|
if __name__ == "__main__":
|
|
from optparse import OptionParser
|
|
parser = OptionParser(usage="usage: %prog [options]")
|
|
|
|
parser.add_option("-s", "--source", dest="repo",
|
|
help="The url of the repo to fetch or one of the known repos name. (mozilla, v8 and webkit are supported.)", default='mozilla')
|
|
|
|
parser.add_option("-r", "--rev", dest="revision",
|
|
help="Force this revision to get build")
|
|
|
|
parser.add_option("-o", "--output", dest="output",
|
|
help="download to DIR, default=output/", metavar="DIR", default='output')
|
|
|
|
parser.add_option("-c", "--config", dest="config",
|
|
help="default, 32bit, 64bit", default='default')
|
|
|
|
parser.add_option("-f", "--force", dest="force", action="store_true", default=False,
|
|
help="Force runs even without source changes")
|
|
|
|
(options, args) = parser.parse_args()
|
|
|
|
if options.repo is None:
|
|
print "Please provide the source repository to pull"
|
|
exit()
|
|
|
|
if not options.output.endswith("/"):
|
|
options.output += "/"
|
|
|
|
if options.config not in ["default", "32bit", "64bit"]:
|
|
print "Please provide a valid config"
|
|
exit()
|
|
|
|
if options.config == "default":
|
|
options.config, _ = platform.architecture()
|
|
|
|
if options.config == "64bit" and platform.architecture()[0] == "32bit":
|
|
print "Cannot compile a 64bit binary on 32bit architecture"
|
|
exit()
|
|
|
|
puller = puller.getPuller(options.repo, options.output)
|
|
puller.update(options.revision)
|
|
|
|
builder = getBuilder(options.config, options.output)
|
|
if options.force:
|
|
builder.unlinkObjdir()
|
|
builder.build(puller)
|