From 577dea036ed6a59ecfad22b9f0a7085e417da5a9 Mon Sep 17 00:00:00 2001 From: Mathieu Virbel Date: Sun, 1 Feb 2015 18:35:28 +0100 Subject: [PATCH] first pass with a brand new tool. starting to write the hostpython recipe --- recipes/__init__.py | 0 recipes/__init__.pyc | Bin 0 -> 136 bytes recipes/audiostream.py | 7 + recipes/hostpython/ModulesSetup | 52 ++++ recipes/hostpython/ModulesSetup.mobile | 2 + recipes/hostpython/__init__.py | 40 +++ recipes/hostpython/__init__.pyc | Bin 0 -> 1964 bytes recipes/hostpython/_scproxy.py | 10 + recipes/hostpython/ctypes_duplicate.patch | 34 +++ recipes/hostpython/dynload.patch | 24 ++ recipes/hostpython/environ_symbol_fix.patch | 24 ++ recipes/hostpython/pyconfig.patch | 159 ++++++++++ recipes/hostpython/setuppath.patch | 11 + recipes/hostpython/ssize-t-max.patch | 17 ++ recipes/hostpython/static-_sqlite3.patch | 25 ++ recipes/hostpython/xcompile.patch | 138 +++++++++ toolchain.py | 307 ++++++++++++++++++++ 17 files changed, 850 insertions(+) create mode 100644 recipes/__init__.py create mode 100644 recipes/__init__.pyc create mode 100644 recipes/audiostream.py create mode 100644 recipes/hostpython/ModulesSetup create mode 100644 recipes/hostpython/ModulesSetup.mobile create mode 100644 recipes/hostpython/__init__.py create mode 100644 recipes/hostpython/__init__.pyc create mode 100644 recipes/hostpython/_scproxy.py create mode 100644 recipes/hostpython/ctypes_duplicate.patch create mode 100644 recipes/hostpython/dynload.patch create mode 100644 recipes/hostpython/environ_symbol_fix.patch create mode 100644 recipes/hostpython/pyconfig.patch create mode 100644 recipes/hostpython/setuppath.patch create mode 100644 recipes/hostpython/ssize-t-max.patch create mode 100644 recipes/hostpython/static-_sqlite3.patch create mode 100644 recipes/hostpython/xcompile.patch create mode 100644 toolchain.py diff --git a/recipes/__init__.py b/recipes/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/recipes/__init__.pyc b/recipes/__init__.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1200419d9379b939cc7b8b8edee6c5e83a4d17e4 GIT binary patch literal 136 zcmZSn%**v-_UVvh1}I4z4l78UE4WR~RX zC+DZ6>SyK`>t|<{RqBEmMXAY|1*ygQ@$s2?nI-Y@dIgmw96((*x%nxjIjMFavx|Y4 F0RZHR9jgEU literal 0 HcmV?d00001 diff --git a/recipes/audiostream.py b/recipes/audiostream.py new file mode 100644 index 0000000..51fded8 --- /dev/null +++ b/recipes/audiostream.py @@ -0,0 +1,7 @@ +from toolchain import Recipe + +class AudiostreamRecipe(Recipe): + version = "master" + url = "https://github.com/kivy/audiostream/archive/{version}.zip" + +recipe = AudiostreamRecipe() diff --git a/recipes/hostpython/ModulesSetup b/recipes/hostpython/ModulesSetup new file mode 100644 index 0000000..77a934a --- /dev/null +++ b/recipes/hostpython/ModulesSetup @@ -0,0 +1,52 @@ +posix posixmodule.c # posix (UNIX) system calls +errno errnomodule.c # posix (UNIX) errno values +pwd pwdmodule.c # this is needed to find out the user's home dir + # if $HOME is not set +_sre _sre.c # Fredrik Lundh's new regular expressions +_codecs _codecsmodule.c # access to the builtin codecs and codec registry +zipimport zipimport.c +_symtable symtablemodule.c +array arraymodule.c # array objects +cmath cmathmodule.c # -lm # complex math library functions +math mathmodule.c # -lm # math library functions, e.g. sin() +_struct _struct.c # binary structure packing/unpacking +time timemodule.c # -lm # time operations and variables +operator operator.c # operator.add() and similar goodies +_weakref _weakref.c # basic weak reference support +_random _randommodule.c # Random number generator +_collections _collectionsmodule.c # Container types +itertools itertoolsmodule.c # Functions creating iterators for efficient looping +strop stropmodule.c # String manipulations +_functools _functoolsmodule.c # Tools for working with functions and callable objects +_elementtree -I$(srcdir)/Modules/expat -DHAVE_EXPAT_CONFIG_H -DUSE_PYEXPAT_CAPI _elementtree.c # elementtree accelerator +datetime datetimemodule.c # date/time type +_bisect _bisectmodule.c # Bisection algorithms +fcntl fcntlmodule.c # fcntl(2) and ioctl(2) +select selectmodule.c # select(2); not on ancient System V +_socket socketmodule.c +_md5 md5module.c md5.c +_sha shamodule.c +_sha256 sha256module.c +_sha512 sha512module.c +binascii binascii.c +parser parsermodule.c +cStringIO cStringIO.c +cPickle cPickle.c +zlib zlibmodule.c -I$(prefix)/include -L$(exec_prefix)/lib -lz +xxsubtype xxsubtype.c +unicodedata unicodedata.c # static Unicode character database + +# Theses modules are used by Kivy inside other module +# json in Settings, _io by zipfile... +_json _json.c +_io _io/bufferedio.c _io/bytesio.c _io/fileio.c _io/iobase.c _io/_iomodule.c _io/stringio.c _io/textio.c +_heapq _heapqmodule.c + +# Special inclusion for sqlite3 +_sqlite3 -DSQLITE_OMIT_LOAD_EXTENSION _sqlite/cache.c _sqlite/microprotocols.c _sqlite/row.c _sqlite/connection.c _sqlite/module.c _sqlite/statement.c _sqlite/cursor.c _sqlite/prepare_protocol.c _sqlite/util.c + +# Include expat +pyexpat expat/xmlparse.c expat/xmlrole.c expat/xmltok.c pyexpat.c -I$(srcdir)/Modules/expat -DHAVE_EXPAT_CONFIG_H -DUSE_PYEXPAT_CAPI + +# Future (used by numpy) +future_builtins future_builtins.c diff --git a/recipes/hostpython/ModulesSetup.mobile b/recipes/hostpython/ModulesSetup.mobile new file mode 100644 index 0000000..826bf1c --- /dev/null +++ b/recipes/hostpython/ModulesSetup.mobile @@ -0,0 +1,2 @@ +# Ctypes +_ctypes _ctypes/_ctypes.c _ctypes/callbacks.c _ctypes/callproc.c _ctypes/stgdict.c _ctypes/cfield.c -I$(srcdir)/../../build/include/ffi diff --git a/recipes/hostpython/__init__.py b/recipes/hostpython/__init__.py new file mode 100644 index 0000000..364b4f1 --- /dev/null +++ b/recipes/hostpython/__init__.py @@ -0,0 +1,40 @@ +from toolchain import Recipe, shprint +from os.path import join +import sh + +class HostpythonRecipe(Recipe): + version = "2.7.1" + url = "https://www.python.org/ftp/python/{version}/Python-{version}.tar.bz2" + + def prebuild_arch(self, arch): + # common to all archs + if not self.has_marker("patched"): + self.apply_patch("ssize-t-max.patch") + self.apply_patch("dynload.patch") + self.apply_patch("static-_sqlite3.patch") + self.copy_file("ModulesSetup", "Modules/Setup.local") + self.copy_file("_scproxy.py", "Lib/_scproxy.py") + #self.copy_file("Setup.dist", "Modules/Setup.dist") + self.set_marker("patched") + super(HostpythonRecipe, self).prebuild_arch(arch) + + def build_i386(self): + sdk_path = sh.xcrun( + "--sdk", "macosx", + "--show-sdk-path").splitlines()[0] + + build_env = self.ctx.env.copy() + build_env["CC"] = "clang -Qunused-arguments -fcolor-diagnostics" + build_env["LDFLAGS"] = "-lsqlite3" + build_env["CFLAGS"] = "--sysroot={}".format(sdk_path) + build_env["PWD"] = self.build_dir + configure = sh.Command(join(self.build_dir, "configure")) + print "-->" + shprint(configure, _env=build_env) + sh.make("-C", self.build_dir, "-j4", "python.exe", "Parser/pgen") + print "<--" + + + + +recipe = HostpythonRecipe() diff --git a/recipes/hostpython/__init__.pyc b/recipes/hostpython/__init__.pyc new file mode 100644 index 0000000000000000000000000000000000000000..58d51ea39cf4f7ce8466b45d5e516e8f967e6755 GIT binary patch literal 1964 zcmb_cZEqVz5S~51G_S;Mpb{@1ija^$a6Zu@K*&^pBiauk3Jz6;znnIAYu_e!x5v#o zvD-vK3crdU!Jpv=z|5TM5DIO%uk zWcwd|`Tn*MrkHPZPcqznsVsz4#|BS9A@@<&6TIib@azAXV`mDXqIo zd#%tND65n|N<4d#PHEg&>vTIM&ZVTwcldB}KI_6&vylSje3L*NNq#Hslgy;}kg=hC zV?rMmdNB|??vgcKmbugE%JKpGdF^cy#`s5Wy?NH`_#N8$#ijGy;ED0`3iodfkyr+~ zOLUIgWREeaYPVQYVsVf3Lwg$CvGuw1ev6h&V_fL^+|-``r>iPo#sbdsB@$OH!cRB86NVaP!? zfYR4k(;X%VQSX|_vkNa?QYx=Ve2>q&QA)A@Hl%y+{Cki-g!B>Ibg0?)=?_Aw_X+-y zbWj*#dMZ(=&e5cyu4nVYlpddi)5PVj z4pXaVC1uzq=(&?dBjl`x`HFr*D_*@teoALrVMmTEhXI~+caMk^0VT8QLx+Ypg)y$OQHVnf)2NrmkQPTk| zl6qb?q^zh*a$6b{1c_hBFNKnr%wRz|b#p58Hb0br0 zETK1OlakA=k=;3iqKvr@h0^!KYq?Z|&_4V2YZ(Y1Q3z07diH}yYKxwI;`+y`qk8HS zB_rN5!Z header file. */ + /* #undef HAVE_BLUETOOTH_BLUETOOTH_H */ +@@ -218,7 +218,7 @@ + /* #undef HAVE_FDATASYNC */ + + /* Define to 1 if you have the `finite' function. */ +-#define HAVE_FINITE 1 ++/* #undef HAVE_FINITE */ + + /* Define to 1 if you have the `flock' function. */ + #define HAVE_FLOCK 1 +@@ -233,7 +233,7 @@ + #define HAVE_FPATHCONF 1 + + /* Define to 1 if you have the `fseek64' function. */ +-#define HAVE_FSEEK64 1 ++/* #undef HAVE_FSEEK64 */ + + /* Define to 1 if you have the `fseeko' function. */ + #define HAVE_FSEEKO 1 +@@ -245,7 +245,7 @@ + #define HAVE_FSYNC 1 + + /* Define to 1 if you have the `ftell64' function. */ +-#define HAVE_FTELL64 1 ++/* #undef HAVE_FTELL64 */ + + /* Define to 1 if you have the `ftello' function. */ + #define HAVE_FTELLO 1 +@@ -260,7 +260,7 @@ + #define HAVE_GAI_STRERROR 1 + + /* Define to 1 if you have the `gamma' function. */ +-#define HAVE_GAMMA 1 ++/* #undef HAVE_GAMMA */ + + /* Define if we can use gcc inline assembler to get and set x87 control word + */ +@@ -279,10 +279,10 @@ + #define HAVE_GETGROUPS 1 + + /* Define to 1 if you have the `gethostbyname' function. */ +-/* #undef HAVE_GETHOSTBYNAME */ ++#define HAVE_GETHOSTBYNAME 1 + + /* Define this if you have some version of gethostbyname_r() */ +-#define HAVE_GETHOSTBYNAME_R 1 ++/* #undef HAVE_GETHOSTBYNAME_R */ + + /* Define this if you have the 3-arg version of gethostbyname_r(). */ + /* #undef HAVE_GETHOSTBYNAME_R_3_ARG */ +@@ -291,7 +291,7 @@ + /* #undef HAVE_GETHOSTBYNAME_R_5_ARG */ + + /* Define this if you have the 6-arg version of gethostbyname_r(). */ +-#define HAVE_GETHOSTBYNAME_R_6_ARG 1 ++/* #undef HAVE_GETHOSTBYNAME_R_6_ARG */ + + /* Define to 1 if you have the `getitimer' function. */ + #define HAVE_GETITIMER 1 +@@ -327,19 +327,19 @@ + #define HAVE_GETPWENT 1 + + /* Define to 1 if you have the `getresgid' function. */ +-#define HAVE_GETRESGID 1 ++/* #undef HAVE_GETRESGID */ + + /* Define to 1 if you have the `getresuid' function. */ +-#define HAVE_GETRESUID 1 ++/* #undef HAVE_GETRESUID */ + + /* Define to 1 if you have the `getsid' function. */ + #define HAVE_GETSID 1 + + /* Define to 1 if you have the `getspent' function. */ +-#define HAVE_GETSPENT 1 ++/* #undef HAVE_GETSPENT */ + + /* Define to 1 if you have the `getspnam' function. */ +-#define HAVE_GETSPNAM 1 ++/* #undef HAVE_GETSPNAM */ + + /* Define to 1 if you have the `gettimeofday' function. */ + #define HAVE_GETTIMEOFDAY 1 +@@ -465,7 +465,7 @@ + #define HAVE_MKTIME 1 + + /* Define to 1 if you have the `mremap' function. */ +-#define HAVE_MREMAP 1 ++/* #undef HAVE_MREMAP */ + + /* Define to 1 if you have the header file. */ + /* #undef HAVE_NCURSES_H */ +@@ -492,7 +492,7 @@ + #define HAVE_PAUSE 1 + + /* Define to 1 if you have the `plock' function. */ +-#define HAVE_PLOCK 1 ++/* #undef HAVE_PLOCK */ + + /* Define to 1 if you have the `poll' function. */ + #define HAVE_POLL 1 +@@ -567,7 +567,7 @@ + #define HAVE_SEM_OPEN 1 + + /* Define to 1 if you have the `sem_timedwait' function. */ +-#define HAVE_SEM_TIMEDWAIT 1 ++/* #undef HAVE_SEM_TIMEDWAIT */ + + /* Define to 1 if you have the `sem_unlink' function. */ + #define HAVE_SEM_UNLINK 1 +@@ -600,10 +600,10 @@ + #define HAVE_SETREGID 1 + + /* Define to 1 if you have the `setresgid' function. */ +-#define HAVE_SETRESGID 1 ++/* #undef HAVE_SETRESGID */ + + /* Define to 1 if you have the `setresuid' function. */ +-#define HAVE_SETRESUID 1 ++/* #undef HAVE_SETRESUID */ + + /* Define to 1 if you have the `setreuid' function. */ + #define HAVE_SETREUID 1 +@@ -829,7 +829,7 @@ + #define HAVE_TMPNAM 1 + + /* Define to 1 if you have the `tmpnam_r' function. */ +-#define HAVE_TMPNAM_R 1 ++/* #undef HAVE_TMPNAM_R */ + + /* Define to 1 if your `struct tm' has `tm_zone'. Deprecated, use + `HAVE_STRUCT_TM_TM_ZONE' instead. */ +@@ -894,7 +894,7 @@ + #define HAVE_ZLIB_COPY 1 + + /* Define to 1 if you have the `_getpty' function. */ +-#define HAVE__GETPTY 1 ++/* #undef HAVE__GETPTY */ + + /* Define if you are using Mach cthreads directly under /include */ + /* #undef HURD_C_THREADS */ +@@ -1245,5 +1245,4 @@ + #define STRICT_SYSV_CURSES /* Don't use ncurses extensions */ + #endif + +-#endif /*Py_PYCONFIG_H*/ +- ++#endif /*Py_PYCONFIG_H*/ +\ No newline at end of file diff --git a/recipes/hostpython/setuppath.patch b/recipes/hostpython/setuppath.patch new file mode 100644 index 0000000..c4d9d19 --- /dev/null +++ b/recipes/hostpython/setuppath.patch @@ -0,0 +1,11 @@ +--- Python-2.7.1/setup.py.orig 2013-10-25 17:28:03.000000000 +0200 ++++ Python-2.7.1/setup.py 2013-10-25 17:27:56.000000000 +0200 +@@ -87,7 +87,7 @@ + f = os.path.join(sysroot, dir[1:], filename) + + if os.path.exists(f): +- return [dir] ++ return [os.path.dirname(f)] + + # Not found anywhere + return None diff --git a/recipes/hostpython/ssize-t-max.patch b/recipes/hostpython/ssize-t-max.patch new file mode 100644 index 0000000..3d63b49 --- /dev/null +++ b/recipes/hostpython/ssize-t-max.patch @@ -0,0 +1,17 @@ +diff -Naur Python-2.7.1.orig/Include/pyport.h Python-2.7.1/Include/pyport.h +--- Python-2.7.1.orig/Include/pyport.h 2010-09-14 18:10:22.000000000 +0200 ++++ Python-2.7.1/Include/pyport.h 2011-05-13 12:24:53.000000000 +0200 +@@ -186,9 +186,11 @@ + #endif + + /* Largest positive value of type Py_ssize_t. */ +-#define PY_SSIZE_T_MAX ((Py_ssize_t)(((size_t)-1)>>1)) ++//#define PY_SSIZE_T_MAX ((Py_ssize_t)(((size_t)-1)>>1)) + /* Smallest negative value of type Py_ssize_t. */ +-#define PY_SSIZE_T_MIN (-PY_SSIZE_T_MAX-1) ++//#define PY_SSIZE_T_MIN (-PY_SSIZE_T_MAX-1) ++#define PY_SSIZE_T_MAX TMP_MAX ++#define PY_SSIZE_T_MIN -TMP_MAX + + #if SIZEOF_PID_T > SIZEOF_LONG + # error "Python doesn't support sizeof(pid_t) > sizeof(long)" diff --git a/recipes/hostpython/static-_sqlite3.patch b/recipes/hostpython/static-_sqlite3.patch new file mode 100644 index 0000000..783c5ef --- /dev/null +++ b/recipes/hostpython/static-_sqlite3.patch @@ -0,0 +1,25 @@ +--- Python-2.7.1/Modules/_sqlite/module.c.orig 2012-10-28 02:30:58.000000000 +0200 ++++ Python-2.7.1/Modules/_sqlite/module.c 2012-10-28 02:28:12.000000000 +0200 +@@ -28,6 +28,9 @@ + #include "prepare_protocol.h" + #include "microprotocols.h" + #include "row.h" ++#ifndef MODULE_NAME ++#define MODULE_NAME "_sqlite3" ++#endif + + #if SQLITE_VERSION_NUMBER >= 3003003 + #define HAVE_SHARED_CACHE +--- Python-2.7.1/Modules/_sqlite/sqlitecompat.h.orig 2012-10-28 02:30:53.000000000 +0200 ++++ Python-2.7.1/Modules/_sqlite/sqlitecompat.h 2012-10-28 02:28:14.000000000 +0200 +@@ -26,6 +26,10 @@ + #ifndef PYSQLITE_COMPAT_H + #define PYSQLITE_COMPAT_H + ++#ifndef MODULE_NAME ++#define MODULE_NAME "_sqlite3" ++#endif ++ + /* define Py_ssize_t for pre-2.5 versions of Python */ + + #if PY_VERSION_HEX < 0x02050000 diff --git a/recipes/hostpython/xcompile.patch b/recipes/hostpython/xcompile.patch new file mode 100644 index 0000000..6f3a08e --- /dev/null +++ b/recipes/hostpython/xcompile.patch @@ -0,0 +1,138 @@ +diff -Naur Python-2.7-old/Makefile.pre.in Python-2.7-new/Makefile.pre.in +--- Python-2.7-old/Makefile.pre.in 2010-04-11 17:10:46.000000000 -0700 ++++ Python-2.7-new/Makefile.pre.in 2010-07-09 13:40:47.000000000 -0700 +@@ -179,6 +179,7 @@ + + PYTHON= python$(EXE) + BUILDPYTHON= python$(BUILDEXE) ++HOSTPYTHON= ./$(BUILDPYTHON) + + # The task to run while instrument when building the profile-opt target + PROFILE_TASK= $(srcdir)/Tools/pybench/pybench.py -n 2 --with-gc --with-syscheck +@@ -212,6 +213,8 @@ + # Parser + PGEN= Parser/pgen$(EXE) + ++HOSTPGEN= $(PGEN) ++ + POBJS= \ + Parser/acceler.o \ + Parser/grammar1.o \ +@@ -404,8 +407,8 @@ + # Build the shared modules + sharedmods: $(BUILDPYTHON) + @case $$MAKEFLAGS in \ +- *s*) $(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' ./$(BUILDPYTHON) -E $(srcdir)/setup.py -q build;; \ +- *) $(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' ./$(BUILDPYTHON) -E $(srcdir)/setup.py build;; \ ++ *s*) $(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' PYTHONXCPREFIX='$(DESTDIR)$(prefix)' $(HOSTPYTHON) -E $(srcdir)/setup.py -q build;; \ ++ *) $(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' PYTHONXCPREFIX='$(DESTDIR)$(prefix)' $(HOSTPYTHON) -E $(srcdir)/setup.py build;; \ + esac + + # Build static library +@@ -538,7 +541,7 @@ + + $(GRAMMAR_H) $(GRAMMAR_C): $(PGEN) $(GRAMMAR_INPUT) + -@$(INSTALL) -d Include +- -$(PGEN) $(GRAMMAR_INPUT) $(GRAMMAR_H) $(GRAMMAR_C) ++ -$(HOSTPGEN) $(GRAMMAR_INPUT) $(GRAMMAR_H) $(GRAMMAR_C) + + $(PGEN): $(PGENOBJS) + $(CC) $(OPT) $(LDFLAGS) $(PGENOBJS) $(LIBS) -o $(PGEN) +@@ -919,26 +922,26 @@ + done; \ + done + $(INSTALL_DATA) $(srcdir)/LICENSE $(DESTDIR)$(LIBDEST)/LICENSE.txt +- PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ +- ./$(BUILDPYTHON) -Wi -tt $(DESTDIR)$(LIBDEST)/compileall.py \ ++ -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ ++ $(HOSTPYTHON) -Wi -tt $(DESTDIR)$(LIBDEST)/compileall.py \ + -d $(LIBDEST) -f \ + -x 'bad_coding|badsyntax|site-packages|lib2to3/tests/data' \ + $(DESTDIR)$(LIBDEST) +- PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ +- ./$(BUILDPYTHON) -Wi -tt -O $(DESTDIR)$(LIBDEST)/compileall.py \ ++ -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ ++ $(HOSTPYTHON) -Wi -tt -O $(DESTDIR)$(LIBDEST)/compileall.py \ + -d $(LIBDEST) -f \ + -x 'bad_coding|badsyntax|site-packages|lib2to3/tests/data' \ + $(DESTDIR)$(LIBDEST) + -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ +- ./$(BUILDPYTHON) -Wi -t $(DESTDIR)$(LIBDEST)/compileall.py \ ++ $(HOSTPYTHON) -Wi -t $(DESTDIR)$(LIBDEST)/compileall.py \ + -d $(LIBDEST)/site-packages -f \ + -x badsyntax $(DESTDIR)$(LIBDEST)/site-packages + -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ +- ./$(BUILDPYTHON) -Wi -t -O $(DESTDIR)$(LIBDEST)/compileall.py \ ++ $(HOSTPYTHON) -Wi -t -O $(DESTDIR)$(LIBDEST)/compileall.py \ + -d $(LIBDEST)/site-packages -f \ + -x badsyntax $(DESTDIR)$(LIBDEST)/site-packages + -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ +- ./$(BUILDPYTHON) -Wi -t -c "import lib2to3.pygram, lib2to3.patcomp;lib2to3.patcomp.PatternCompiler()" ++ $(HOSTPYTHON) -Wi -t -c "import lib2to3.pygram, lib2to3.patcomp;lib2to3.patcomp.PatternCompiler()" + + # Create the PLATDIR source directory, if one wasn't distributed.. + $(srcdir)/Lib/$(PLATDIR): +@@ -1042,8 +1045,10 @@ + + # Install the dynamically loadable modules + # This goes into $(exec_prefix) +-sharedinstall: sharedmods +- $(RUNSHARED) ./$(BUILDPYTHON) -E $(srcdir)/setup.py install \ ++sharedinstall: sharedmods ++ CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' \ ++ $(RUNSHARED) $(HOSTPYTHON) -E $(srcdir)/setup.py install \ ++ --skip-build \ + --prefix=$(prefix) \ + --install-scripts=$(BINDIR) \ + --install-platlib=$(DESTSHARED) \ +diff -Naur Python-2.7-old/setup.py Python-2.7-new/setup.py +--- Python-2.7-old/setup.py 2010-06-27 05:36:16.000000000 -0700 ++++ Python-2.7-new/setup.py 2010-07-09 13:54:29.000000000 -0700 +@@ -23,6 +23,10 @@ + # This global variable is used to hold the list of modules to be disabled. + disabled_module_list = [] + ++# _ctypes fails to cross-compile due to the libffi configure script. ++if os.environ.has_key('PYTHONXCPREFIX'): ++ disabled_module_list.append('_ctypes') ++ + def add_dir_to_list(dirlist, dir): + """Add the directory 'dir' to the list 'dirlist' (at the front) if + 1) 'dir' is not already in 'dirlist' +@@ -278,6 +282,14 @@ + (ext.name, sys.exc_info()[1])) + self.failed.append(ext.name) + return ++ ++ # Inport check will not work when cross-compiling. ++ if os.environ.has_key('PYTHONXCPREFIX'): ++ self.announce( ++ 'WARNING: skipping inport check for cross-compiled: "%s"' % ++ ext.name) ++ return ++ + # Workaround for Mac OS X: The Carbon-based modules cannot be + # reliably imported into a command-line Python + if 'Carbon' in ext.extra_link_args: + +--- Python-2.7Orig/configure 2011-04-29 22:30:59.231331437 +1000 ++++ Python-2.7/configure 2010-05-29 01:28:47.000000000 +1000 +@@ -13517,7 +13517,7 @@ + $as_echo_n "(cached) " >&6 + else + if test "$cross_compiling" = yes; then : +- ac_cv_have_long_long_format=no ++ ac_cv_have_long_long_format="cross -- assuming yes" + else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext + /* end confdefs.h. */ +@@ -13569,7 +13569,7 @@ + $as_echo "$ac_cv_have_long_long_format" >&6; } + fi + +-if test "$ac_cv_have_long_long_format" = yes ++if test "$ac_cv_have_long_long_format" != no + then + + $as_echo "#define PY_FORMAT_LONG_LONG \"ll\"" >>confdefs.h + diff --git a/toolchain.py b/toolchain.py new file mode 100644 index 0000000..d43ac07 --- /dev/null +++ b/toolchain.py @@ -0,0 +1,307 @@ +""" +Tool for compiling iOS toolchain +================================ + +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 +import zipfile +import tarfile +import importlib +import sh +import shutil +try: + from urllib.request import FancyURLopener +except ImportError: + from urllib import FancyURLopener + + +def shprint(command, *args, **kwargs): + kwargs["_iter"] = True + kwargs["_out_bufsize"] = 1 + #kwargs["_err_to_out"] = True + for line in command(*args, **kwargs): + stdout.write(line) + + +class ChromeDownloader(FancyURLopener): + version = ( + 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 ' + '(KHTML, like Gecko) Chrome/28.0.1500.71 Safari/537.36') + +urlretrieve = ChromeDownloader().retrieve + + +class Context(object): + env = environ.copy() + root_dir = None + cache_dir = None + build_dir = None + dist_dir = None + install_dir = None + ccache = None + cython = None + sdkver = None + sdksimver = None + + def __init__(self): + super(Context, self).__init__() + ok = True + + sdks = sh.xcodebuild("-showsdks").splitlines() + + # get the latest iphoneos + iphoneos = [x for x in sdks if "iphoneos" in x] + if not iphoneos: + print("No iphone SDK installed") + ok = False + else: + iphoneos = iphoneos[0].split()[-1] + self.sdkver = iphoneos + + # get the latest iphonesimulator version + iphonesim = [x for x in sdks if "iphonesimulator" in x] + if not iphoneos: + ok = False + print("Error: No iphonesimulator SDK installed") + else: + iphonesim = iphonesim[0].split()[-1] + self.sdksimver = iphonesim + + # get the path for Developer + self.devroot = "{}/Platforms/iPhoneOS.platform/Developer".format( + sh.xcode_select("-print-path").strip()) + + # path to the iOS SDK + self.iossdkroot = "{}/SDKs.iPhoneOS{}.sdk".format( + self.devroot, self.sdkver) + + # root of the toolchain + self.root_dir = realpath(dirname(__file__)) + self.build_dir = "{}/build".format(self.root_dir) + self.cache_dir = "{}/.cache".format(self.root_dir) + self.dist_dir = "{}/dist".format(self.root_dir) + self.install_dir = "{}/dist/root".format(self.root_dir) + self.archs = ("i386", "armv7", "armv7s", "arm64") + + # path to some tools + self.ccache = sh.which("ccache") + if not self.ccache: + print("ccache is missing, the build will not be optimized in the future.") + for cython_fn in ("cython-2.7", "cython"): + cython = sh.which(cython_fn) + if cython: + self.cython = cython + break + if not self.cython: + ok = False + print("Missing requirement: cython is not installed") + + # check the basic tools + for tool in ("pkg-config", "autoconf", "automake", "libtool", "hg"): + if not sh.which(tool): + print("Missing requirement: {} is not installed".format( + tool)) + + if not ok: + sys.exit(1) + + ensure_dir(self.root_dir) + ensure_dir(self.build_dir) + ensure_dir(self.cache_dir) + ensure_dir(self.dist_dir) + ensure_dir(self.install_dir) + + +class Recipe(object): + version = None + url = None + + # API available for recipes + def download_file(self, url, filename, cwd=None): + """ + Download an `url` to `outfn` + """ + def report_hook(index, blksize, size): + if size <= 0: + progression = '{0} bytes'.format(index * blksize) + else: + progression = '{0:.2f}%'.format( + index * blksize * 100. / float(size)) + stdout.write('- Download {}\r'.format(progression)) + stdout.flush() + + if cwd: + filename = join(cwd, filename) + if exists(filename): + unlink(filename) + + print('Downloading {0}'.format(url)) + urlretrieve(url, filename, report_hook) + return filename + + def extract_file(self, filename, cwd): + """ + Extract the `filename` into the directory `cwd`. + """ + print("Extract {} into {}".format(filename, cwd)) + if filename.endswith(".tgz") or filename.endswith(".tar.gz"): + shprint(sh.tar, "-C", cwd, "-xvzf", filename) + + elif filename.endswith(".tbz2") or filename.endswith(".tar.bz2"): + shprint(sh.tar, "-C", cwd, "-xvjf", filename) + + elif filename.endswith(".zip"): + zf = zipfile.ZipFile(filename) + zf.extractall(path=cwd) + zf.close() + + else: + print("Error: cannot extract, unreconized extension for {}".format( + filename)) + raise Exception() + + def get_archive_rootdir(self, filename): + if filename.endswith(".tgz") or filename.endswith(".tar.gz") or \ + filename.endswith(".tbz2") or filename.endswith(".tar.bz2"): + archive = tarfile.open(filename) + root = archive.next().path.split("/") + return root[0] + else: + print("Error: cannot detect root direction") + print("Unrecognized extension for {}".format(filename)) + raise Exception() + + def apply_patch(self, filename): + """ + Apply a patch from the current recipe directory into the current + build directory. + """ + print("Apply patch {}".format(filename)) + filename = join(self.recipe_dir, filename) + sh.patch("-t", "-d", self.build_dir, "-p1", "-i", filename) + + def copy_file(self, filename, dest): + filename = join(self.recipe_dir, filename) + dest = join(self.build_dir, dest) + shutil.copy(filename, dest) + + def has_marker(self, marker): + """ + Return True if the current build directory has the marker set + """ + return exists(join(self.build_dir, ".{}".format(marker))) + + def set_marker(self, marker): + """ + Set a marker info the current build directory + """ + with open(join(self.build_dir, ".{}".format(marker)), "w") as fd: + fd.write("ok") + + def marker(self, marker): + """ + Return a context that will be executed only if the marker has been set + """ + + @property + def name(self): + modname = self.__class__.__module__ + return modname.split(".", 1)[-1] + + @property + def archive_fn(self): + if hasattr(self, "ext"): + ext = self.ext + else: + ext = basename(self.url).split(".", 1)[-1] + fn = "{}/{}.{}".format( + self.ctx.cache_dir, + self.name, ext) + return fn + + # Public Recipe API to be subclassed if needed + + def execute(self): + print("Download {}".format(self.name)) + self.download() + print("Extract {}".format(self.name)) + self.extract() + print("Build {}".format(self.name)) + self.build_all() + + def download(self): + fn = self.archive_fn + if not exists(fn): + self.download_file(self.url.format(version=self.version), 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)) + build_dir = join(self.ctx.build_dir, arch) + if exists(join(build_dir, archive_root)): + continue + ensure_dir(build_dir) + self.extract_file(self.archive_fn, build_dir) + + def build_all(self): + 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) + self.prebuild_arch(arch) + self.build_arch(arch) + self.postbuild_arch(arch) + + 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)() + + +def list_recipes(): + recipes_dir = join(dirname(__file__), "recipes") + for name in listdir(recipes_dir): + fn = join(recipes_dir, name) + if isdir(fn): + yield name + +def compile_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.execute() + + +def ensure_dir(filename): + if not exists(filename): + makedirs(filename) + + +if __name__ == "__main__": + import argparse + parser = argparse.ArgumentParser( + description='Compile Python and others extensions for iOS') + args = parser.parse_args() + ctx = Context() + print list(list_recipes()) + compile_recipe("hostpython", ctx)