add alias for hostpython/python, that point to either 2 or 3 version depending of the previous compiled state.

This allows the recipe to point on an versionless python.
This commit is contained in:
Mathieu Virbel 2018-11-02 11:44:25 +01:00
parent 9762ee754c
commit 811cbd48a7
10 changed files with 130 additions and 40 deletions

15
recipes/hostpython.py Normal file
View file

@ -0,0 +1,15 @@
# -*- coding: utf-8 -*-
from toolchain import Recipe
class HostpythonAliasRecipe(Recipe):
is_alias = True
def init_after_import(self, ctx):
hostpython = ctx.state.get("hostpython")
if not hostpython:
print("WARNING: no hostpython set yet, so you need to specify")
print("WARNING: either hostpython2 or hostpython3 in your deps")
else:
self.depends = [hostpython]
recipe = HostpythonAliasRecipe()

View file

@ -5,7 +5,7 @@ import sh
import shutil
class HostpythonRecipe(Recipe):
class Hostpython2Recipe(Recipe):
version = "2.7.1"
url = "https://www.python.org/ftp/python/{version}/Python-{version}.tar.bz2"
depends = ["hostlibffi"]
@ -13,7 +13,9 @@ class HostpythonRecipe(Recipe):
archs = ["x86_64"]
def init_with_ctx(self, ctx):
super(HostpythonRecipe, self).init_with_ctx(ctx)
super(Hostpython2Recipe, self).init_with_ctx(ctx)
self.set_hostpython(self, 2.7)
self.ctx.so_suffix = ".so"
self.ctx.hostpython = join(self.ctx.dist_dir, "hostpython", "bin", "python")
self.ctx.hostpgen = join(self.ctx.dist_dir, "hostpython", "bin", "pgen")
print("Global: hostpython located at {}".format(self.ctx.hostpython))
@ -110,4 +112,4 @@ class HostpythonRecipe(Recipe):
join(self.ctx.dist_dir, "hostpython", "bin", "pgen"))
recipe = HostpythonRecipe()
recipe = Hostpython2Recipe()

View file

@ -14,6 +14,8 @@ class Hostpython3Recipe(Recipe):
def init_with_ctx(self, ctx):
super(Hostpython3Recipe, self).init_with_ctx(ctx)
self.set_hostpython(self, 3.7)
self.ctx.so_suffix = ".cpython-37m-darwin.so"
self.ctx.hostpython = join(self.ctx.dist_dir, "hostpython3", "bin", "python")
self.ctx.hostpgen = join(self.ctx.dist_dir, "hostpython3", "bin", "pgen")
print("Global: hostpython located at {}".format(self.ctx.hostpython))

View file

@ -9,9 +9,8 @@ class IosRecipe(CythonRecipe):
pbx_frameworks = ["MessageUI", "CoreMotion", "UIKit"]
def install(self):
self.install_python_package(name="ios.so", is_dir=False)
self.install_python_package(
name=self.so_filename("ios"), is_dir=False)
recipe = IosRecipe()

View file

@ -6,8 +6,8 @@ class KivyRecipe(CythonRecipe):
version = "1.10.1"
url = "https://github.com/kivy/kivy/archive/{version}.zip"
library = "libkivy.a"
depends = ["python", "sdl2", "sdl2_image", "sdl2_mixer", "sdl2_ttf", "ios",
"pyobjus"]
depends = ["sdl2", "sdl2_image", "sdl2_mixer", "sdl2_ttf", "ios",
"pyobjus", "python"]
pbx_frameworks = ["OpenGLES", "Accelerate"]
pre_build_ext = True
@ -40,4 +40,3 @@ class KivyRecipe(CythonRecipe):
recipe = KivyRecipe()

View file

@ -18,8 +18,9 @@ class PyobjusRecipe(CythonRecipe):
def cythonize_build(self):
# don't use the cythonize, pyobjus don't support method rewriting
pyver = "-{}".format(self.ctx.python_major)
shprint(sh.find, self.build_dir, "-iname", "*.pyx",
"-exec", "cython", "{}", ";")
"-exec", "cython", pyver, "{}", ";")
# ffi is installed somewhere else, this include doesn't work
# XXX ideally, we need to fix libffi installation...
shprint(sh.sed,
@ -28,5 +29,3 @@ class PyobjusRecipe(CythonRecipe):
"pyobjus/pyobjus.c")
recipe = PyobjusRecipe()

15
recipes/python.py Normal file
View file

@ -0,0 +1,15 @@
# -*- coding: utf-8 -*-
from toolchain import Recipe
class PythonAliasRecipe(Recipe):
is_alias = True
def init_after_import(self, ctx):
python = ctx.state.get("python")
if not python:
print("WARNING: no python set yet, so you need to specify")
print("WARNING: either python2 or python3 in your deps")
else:
self.depends = [python]
recipe = PythonAliasRecipe()

View file

@ -4,21 +4,21 @@ import sh
import os
class PythonRecipe(Recipe):
class Python2Recipe(Recipe):
version = "2.7.1"
url = "https://www.python.org/ftp/python/{version}/Python-{version}.tar.bz2"
depends = ["hostpython", "libffi", ]
depends = ["hostpython2", "libffi"]
optional_depends = ["openssl"]
library = "libpython2.7.a"
pbx_libraries = ["libz", "libbz2", "libsqlite3"]
def init_with_ctx(self, ctx):
super(PythonRecipe, self).init_with_ctx(ctx)
self.ctx.python_ver_dir = "python2.7"
self.ctx.python_prefix = join(ctx.dist_dir, "root", "python")
self.ctx.site_packages_dir = join(
ctx.dist_dir, "root", "python", "lib", ctx.python_ver_dir,
"site-packages")
super(Python2Recipe, self).init_with_ctx(ctx)
self.set_python(self, 2.7)
ctx.python_ver_dir = "python2.7"
ctx.python_prefix = join(ctx.dist_dir, "root", "python")
ctx.site_packages_dir = join(
ctx.python_prefix, "lib", ctx.python_ver_dir, "site-packages")
def prebuild_arch(self, arch):
# common to all archs
@ -149,4 +149,4 @@ class PythonRecipe(Recipe):
os.chdir(oldpwd)
recipe = PythonRecipe()
recipe = Python2Recipe()

View file

@ -15,11 +15,11 @@ class Python3Recipe(Recipe):
def init_with_ctx(self, ctx):
super(Python3Recipe, self).init_with_ctx(ctx)
self.ctx.python_ver_dir = "python3.7"
self.ctx.python_prefix = join(ctx.dist_dir, "root", "python")
self.ctx.site_packages_dir = join(
ctx.dist_dir, "root", "python", "lib", ctx.python_ver_dir,
"site-packages")
self.set_python(self, 3.7)
ctx.python_ver_dir = "python3.7"
ctx.python_prefix = join(ctx.dist_dir, "root", "python3")
ctx.site_packages_dir = join(
ctx.python_prefix, "lib", ctx.python_ver_dir, "site-packages")
def prebuild_arch(self, arch):
# common to all archs

View file

@ -306,6 +306,7 @@ class Context(object):
cython = None
sdkver = None
sdksimver = None
so_suffix = None # set by one of the hostpython
def __init__(self):
super(Context, self).__init__()
@ -413,20 +414,30 @@ class Context(object):
return "IDEBuildOperationMaxNumberOfConcurrentCompileTasks={}".format(self.num_cores)
class Recipe(object):
version = None
url = None
archs = []
depends = []
optional_depends = []
library = None
libraries = []
include_dir = None
include_per_arch = False
frameworks = []
sources = []
pbx_frameworks = []
pbx_libraries = []
props = {
"is_alias": False,
"version": None,
"url": None,
"archs": [],
"depends": [],
"optional_depends": [],
"library": None,
"libraries": [],
"include_dir": None,
"include_per_arch": False,
"frameworks": [],
"sources": [],
"pbx_frameworks": [],
"pbx_libraries": []
}
def __new__(cls):
for prop, value in cls.props.items():
if not hasattr(cls, prop):
setattr(cls, prop, value)
return super(Recipe, cls).__new__(cls)
# API available for recipes
def download_file(self, url, filename, cwd=None):
@ -560,6 +571,12 @@ class Recipe(object):
"""
return join(self.ctx.include_dir, "common", self.name)
def so_filename(self, name):
"""Return the filename of a library with the appropriate so suffix
(.so for Python 2.7, .cpython-37m-darwin for Python 3.7)
"""
return "{}{}".format(name, self.ctx.so_suffix)
@property
def name(self):
modname = self.__class__.__module__
@ -619,6 +636,37 @@ class Recipe(object):
arch = self.filtered_archs[0]
return arch.get_env()
def set_hostpython(self, instance, version):
state = self.ctx.state
hostpython = state.get("hostpython")
if hostpython is None:
state["hostpython"] = instance.name
state.sync()
elif hostpython != instance.name:
print("ERROR: Wanted to use {}".format(instance.name))
print("ERROR: but hostpython is already provided by {}.".format(
hostpython))
print("ERROR: You can have only one hostpython version compiled")
sys.exit(1)
self.ctx.python_major = int(version)
self.ctx.hostpython_ver = version
self.ctx.hostpython_recipe = instance
def set_python(self, instance, version):
state = self.ctx.state
python = state.get("python")
if python is None:
state["python"] = instance.name
state.sync()
elif python != instance.name:
print("ERROR: Wanted to use {}".format(instance.name))
print("ERROR: but python is already provided by {}.".format(
python))
print("ERROR: You can have only one python version compiled")
sys.exit(1)
self.ctx.python_ver = version
self.ctx.python_recipe = instance
@property
def archive_root(self):
key = "{}.archive_root".format(self.name)
@ -649,6 +697,12 @@ class Recipe(object):
raise ValueError("Invalid path passed into {}".format(envname))
return d
def init_after_import(cls, ctx):
"""This can be used to dynamically set some variables
depending of the state
"""
pass
@cache_execution
def download(self):
key = "{}.archive_root".format(self.name)
@ -875,6 +929,7 @@ class Recipe(object):
mod = importlib.import_module("recipes.{}".format(name))
recipe = mod.recipe
recipe.recipe_dir = join(ctx.root_dir, "recipes", name)
recipe.init_after_import(ctx)
if version:
recipe.version = version
@ -916,7 +971,7 @@ class PythonRecipe(Recipe):
"--prefix", iosbuild,
_env=env)
dest_dir = join(self.ctx.site_packages_dir, name)
self.remove_junk(iosbuild)
#self.remove_junk(iosbuild)
if is_dir:
if exists(dest_dir):
shutil.rmtree(dest_dir)
@ -944,6 +999,7 @@ class CythonRecipe(PythonRecipe):
filename = filename[len(self.build_dir) + 1:]
print("Cythonize {}".format(filename))
cmd = sh.Command(join(self.ctx.root_dir, "tools", "cythonize.py"))
hostpython = self.ctx.state.get("hostpython")
shprint(cmd, filename)
def cythonize_build(self):
@ -1021,6 +1077,9 @@ def build_recipes(names, ctx):
build_order = list(graph.find_order())
print("Build order is {}".format(build_order))
recipes = [Recipe.get_recipe(name, ctx) for name in build_order]
recipes = [recipe for recipe in recipes if not recipe.is_alias]
recipes_order = [recipe.name for recipe in recipes]
print("Recipe order is {}".format(recipes_order))
for recipe in recipes:
recipe.init_with_ctx(ctx)
for recipe in recipes: