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
from sys import stdout
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 tarfile
import importlib
@ -23,6 +23,7 @@ except ImportError:
def shprint(command, *args, **kwargs):
kwargs["_iter"] = True
kwargs["_out_bufsize"] = 1
kwargs["_err_to_out"] = True
#kwargs["_err_to_out"] = True
for line in command(*args, **kwargs):
stdout.write(line)
@ -60,7 +61,7 @@ class Context(object):
print("No iphone SDK installed")
ok = False
else:
iphoneos = iphoneos[0].split()[-1]
iphoneos = iphoneos[0].split()[-1].replace("iphoneos", "")
self.sdkver = iphoneos
# get the latest iphonesimulator version
@ -69,7 +70,7 @@ class Context(object):
ok = False
print("Error: No iphonesimulator SDK installed")
else:
iphonesim = iphonesim[0].split()[-1]
iphonesim = iphonesim[0].split()[-1].replace("iphonesimulator", "")
self.sdksimver = iphonesim
# get the path for Developer
@ -77,7 +78,7 @@ class Context(object):
sh.xcode_select("-print-path").strip())
# path to the iOS SDK
self.iossdkroot = "{}/SDKs.iPhoneOS{}.sdk".format(
self.iossdkroot = "{}/SDKs/iPhoneOS{}.sdk".format(
self.devroot, self.sdkver)
# root of the toolchain
@ -116,10 +117,18 @@ class Context(object):
ensure_dir(self.dist_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):
version = None
url = None
depends = []
# API available for recipes
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)
def copy_file(self, filename, dest):
print("Copy {} to {}".format(filename, dest))
filename = join(self.recipe_dir, filename)
dest = join(self.build_dir, 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):
"""
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:
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
def name(self):
@ -226,6 +249,9 @@ class Recipe(object):
# Public Recipe API to be subclassed if needed
def init_with_ctx(self, ctx):
self.ctx = ctx
def execute(self):
print("Download {}".format(self.name))
self.download()
@ -238,15 +264,19 @@ class Recipe(object):
fn = self.archive_fn
if not exists(fn):
self.download_file(self.url.format(version=self.version), fn)
self.archive_root = self.get_archive_rootdir(self.archive_fn)
def extract(self):
# recipe tmp directory
archive_root = self.get_archive_rootdir(self.archive_fn)
for arch in self.ctx.archs:
print("Extract {} for {}".format(self.name, arch))
self.extract_arch(arch, archive_root)
def extract_arch(self, arch, archive_root):
build_dir = join(self.ctx.build_dir, arch)
if exists(join(build_dir, archive_root)):
continue
return
ensure_dir(build_dir)
self.extract_file(self.archive_fn, build_dir)
@ -254,24 +284,34 @@ class Recipe(object):
archive_root = self.get_archive_rootdir(self.archive_fn)
for arch in self.ctx.archs:
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)
print("Build {} for {}".format(self.name, arch))
self.build_arch(arch)
print("Postbuild {} for {}".format(self.name, arch))
self.postbuild_arch(arch)
self.delete_marker("building")
def prebuild_arch(self, arch):
print("Prebuild {} for {}".format(self.name, arch))
prebuild = "prebuild_{}".format(arch)
if hasattr(self, prebuild):
getattr(self, prebuild)()
def build_arch(self, arch):
print("Build {} for {}".format(self.name, arch))
build = "build_{}".format(arch)
if hasattr(self, build):
getattr(self, build)()
def postbuild_arch(self, arch):
print("Postbuild {} for {}".format(self.name, arch))
postbuild = "postbuild_{}".format(arch)
if hasattr(self, postbuild):
getattr(self, postbuild)()
@ -284,11 +324,11 @@ def list_recipes():
if isdir(fn):
yield name
def compile_recipe(name, ctx):
def build_recipe(name, ctx):
mod = importlib.import_module("recipes.{}".format(name))
recipe = mod.recipe
recipe.recipe_dir = join(ctx.root_dir, "recipes", name)
recipe.ctx = ctx
recipe.init_with_ctx(ctx)
recipe.execute()
@ -304,4 +344,4 @@ if __name__ == "__main__":
args = parser.parse_args()
ctx = Context()
print list(list_recipes())
compile_recipe("hostpython", ctx)
build_recipe("libffi", ctx)