add the toolchain script.

This commit is contained in:
Mathieu Virbel 2015-02-02 05:22:13 +01:00
parent 18c67317fe
commit 5c4f42b1d4

View file

@ -8,7 +8,7 @@ This tool intend to replace all the previous tools/ in shell script.
import sys import sys
from sys import stdout from sys import stdout
from os.path import join, dirname, realpath, exists, isdir, basename from os.path import join, dirname, realpath, exists, isdir, basename
from os import listdir, unlink, makedirs, environ from os import listdir, unlink, makedirs, environ, chdir
import zipfile import zipfile
import tarfile import tarfile
import importlib import importlib
@ -23,6 +23,7 @@ except ImportError:
def shprint(command, *args, **kwargs): def shprint(command, *args, **kwargs):
kwargs["_iter"] = True kwargs["_iter"] = True
kwargs["_out_bufsize"] = 1 kwargs["_out_bufsize"] = 1
kwargs["_err_to_out"] = True
#kwargs["_err_to_out"] = True #kwargs["_err_to_out"] = True
for line in command(*args, **kwargs): for line in command(*args, **kwargs):
stdout.write(line) stdout.write(line)
@ -60,7 +61,7 @@ class Context(object):
print("No iphone SDK installed") print("No iphone SDK installed")
ok = False ok = False
else: else:
iphoneos = iphoneos[0].split()[-1] iphoneos = iphoneos[0].split()[-1].replace("iphoneos", "")
self.sdkver = iphoneos self.sdkver = iphoneos
# get the latest iphonesimulator version # get the latest iphonesimulator version
@ -69,7 +70,7 @@ class Context(object):
ok = False ok = False
print("Error: No iphonesimulator SDK installed") print("Error: No iphonesimulator SDK installed")
else: else:
iphonesim = iphonesim[0].split()[-1] iphonesim = iphonesim[0].split()[-1].replace("iphonesimulator", "")
self.sdksimver = iphonesim self.sdksimver = iphonesim
# get the path for Developer # get the path for Developer
@ -77,7 +78,7 @@ class Context(object):
sh.xcode_select("-print-path").strip()) sh.xcode_select("-print-path").strip())
# path to the iOS SDK # path to the iOS SDK
self.iossdkroot = "{}/SDKs.iPhoneOS{}.sdk".format( self.iossdkroot = "{}/SDKs/iPhoneOS{}.sdk".format(
self.devroot, self.sdkver) self.devroot, self.sdkver)
# root of the toolchain # root of the toolchain
@ -116,10 +117,18 @@ class Context(object):
ensure_dir(self.dist_dir) ensure_dir(self.dist_dir)
ensure_dir(self.install_dir) ensure_dir(self.install_dir)
# remove the most obvious flags that can break the compilation
self.env.pop("MACOSX_DEPLOYMENT_TARGET", None)
self.env.pop("PYTHONDONTWRITEBYTECODE", None)
self.env.pop("ARCHFLAGS", None)
self.env.pop("CFLAGS", None)
self.env.pop("LDFLAGS", None)
class Recipe(object): class Recipe(object):
version = None version = None
url = None url = None
depends = []
# API available for recipes # API available for recipes
def download_file(self, url, filename, cwd=None): def download_file(self, url, filename, cwd=None):
@ -186,10 +195,20 @@ class Recipe(object):
sh.patch("-t", "-d", self.build_dir, "-p1", "-i", filename) sh.patch("-t", "-d", self.build_dir, "-p1", "-i", filename)
def copy_file(self, filename, dest): def copy_file(self, filename, dest):
print("Copy {} to {}".format(filename, dest))
filename = join(self.recipe_dir, filename) filename = join(self.recipe_dir, filename)
dest = join(self.build_dir, dest) dest = join(self.build_dir, dest)
shutil.copy(filename, dest) shutil.copy(filename, dest)
def append_file(self, filename, dest):
print("Append {} to {}".format(filename, dest))
filename = join(self.recipe_dir, filename)
dest = join(self.build_dir, dest)
with open(filename, "rb") as fd:
data = fd.read()
with open(dest, "ab") as fd:
fd.write(data)
def has_marker(self, marker): def has_marker(self, marker):
""" """
Return True if the current build directory has the marker set Return True if the current build directory has the marker set
@ -203,10 +222,14 @@ class Recipe(object):
with open(join(self.build_dir, ".{}".format(marker)), "w") as fd: with open(join(self.build_dir, ".{}".format(marker)), "w") as fd:
fd.write("ok") fd.write("ok")
def marker(self, marker): def delete_marker(self, marker):
""" """
Return a context that will be executed only if the marker has been set Delete a specific marker
""" """
try:
unlink(join(self.build_dir, ".{}".format(marker)))
except:
pass
@property @property
def name(self): def name(self):
@ -226,6 +249,9 @@ class Recipe(object):
# Public Recipe API to be subclassed if needed # Public Recipe API to be subclassed if needed
def init_with_ctx(self, ctx):
self.ctx = ctx
def execute(self): def execute(self):
print("Download {}".format(self.name)) print("Download {}".format(self.name))
self.download() self.download()
@ -238,40 +264,54 @@ class Recipe(object):
fn = self.archive_fn fn = self.archive_fn
if not exists(fn): if not exists(fn):
self.download_file(self.url.format(version=self.version), fn) self.download_file(self.url.format(version=self.version), fn)
self.archive_root = self.get_archive_rootdir(self.archive_fn)
def extract(self): def extract(self):
# recipe tmp directory # recipe tmp directory
archive_root = self.get_archive_rootdir(self.archive_fn) archive_root = self.get_archive_rootdir(self.archive_fn)
for arch in self.ctx.archs: for arch in self.ctx.archs:
print("Extract {} for {}".format(self.name, arch)) print("Extract {} for {}".format(self.name, arch))
build_dir = join(self.ctx.build_dir, arch) self.extract_arch(arch, archive_root)
if exists(join(build_dir, archive_root)):
continue def extract_arch(self, arch, archive_root):
ensure_dir(build_dir) build_dir = join(self.ctx.build_dir, arch)
self.extract_file(self.archive_fn, build_dir) if exists(join(build_dir, archive_root)):
return
ensure_dir(build_dir)
self.extract_file(self.archive_fn, build_dir)
def build_all(self): def build_all(self):
archive_root = self.get_archive_rootdir(self.archive_fn) archive_root = self.get_archive_rootdir(self.archive_fn)
for arch in self.ctx.archs: for arch in self.ctx.archs:
self.build_dir = join(self.ctx.build_dir, arch, archive_root) self.build_dir = join(self.ctx.build_dir, arch, archive_root)
if self.has_marker("building"):
print("Warning: {} build for {} has been incomplete".format(
self.name, arch))
print("Warning: deleting the build and restarting.")
shutil.rmtree(self.build_dir)
self.extract_arch(arch, archive_root)
self.set_marker("building")
chdir(self.build_dir)
print("Prebuild {} for {}".format(self.name, arch))
self.prebuild_arch(arch) self.prebuild_arch(arch)
print("Build {} for {}".format(self.name, arch))
self.build_arch(arch) self.build_arch(arch)
print("Postbuild {} for {}".format(self.name, arch))
self.postbuild_arch(arch) self.postbuild_arch(arch)
self.delete_marker("building")
def prebuild_arch(self, arch): def prebuild_arch(self, arch):
print("Prebuild {} for {}".format(self.name, arch))
prebuild = "prebuild_{}".format(arch) prebuild = "prebuild_{}".format(arch)
if hasattr(self, prebuild): if hasattr(self, prebuild):
getattr(self, prebuild)() getattr(self, prebuild)()
def build_arch(self, arch): def build_arch(self, arch):
print("Build {} for {}".format(self.name, arch))
build = "build_{}".format(arch) build = "build_{}".format(arch)
if hasattr(self, build): if hasattr(self, build):
getattr(self, build)() getattr(self, build)()
def postbuild_arch(self, arch): def postbuild_arch(self, arch):
print("Postbuild {} for {}".format(self.name, arch))
postbuild = "postbuild_{}".format(arch) postbuild = "postbuild_{}".format(arch)
if hasattr(self, postbuild): if hasattr(self, postbuild):
getattr(self, postbuild)() getattr(self, postbuild)()
@ -284,11 +324,11 @@ def list_recipes():
if isdir(fn): if isdir(fn):
yield name yield name
def compile_recipe(name, ctx): def build_recipe(name, ctx):
mod = importlib.import_module("recipes.{}".format(name)) mod = importlib.import_module("recipes.{}".format(name))
recipe = mod.recipe recipe = mod.recipe
recipe.recipe_dir = join(ctx.root_dir, "recipes", name) recipe.recipe_dir = join(ctx.root_dir, "recipes", name)
recipe.ctx = ctx recipe.init_with_ctx(ctx)
recipe.execute() recipe.execute()
@ -304,4 +344,4 @@ if __name__ == "__main__":
args = parser.parse_args() args = parser.parse_args()
ctx = Context() ctx = Context()
print list(list_recipes()) print list(list_recipes())
compile_recipe("hostpython", ctx) build_recipe("libffi", ctx)