Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Pillow Recipe #1339

Merged
merged 2 commits into from
Aug 26, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions pythonforandroid/recipes/Pillow/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
from pythonforandroid.recipe import CompiledComponentsPythonRecipe
from pythonforandroid.toolchain import shprint
from os.path import join, dirname
import sh


class PillowRecipe(CompiledComponentsPythonRecipe):

version = '5.2.0'
url = 'https://github.com/python-pillow/Pillow/archive/{version}.tar.gz'
site_packages_name = 'Pillow'
depends = [
('python2', 'python3crystax'),
'png',
'jpeg',
'freetype',
'setuptools'
]
patches = [
join('patches', 'fix-docstring.patch'),
join('patches', 'fix-setup.patch')
]

call_hostpython_via_targetpython = False

def get_recipe_env(self, arch=None):
env = super(PillowRecipe, self).get_recipe_env(arch)
py_ver = self.ctx.python_recipe.version[0:3]

ndk_dir = self.ctx.ndk_platform
ndk_lib_dir = join(ndk_dir, 'usr', 'lib')
ndk_include_dir = (join(self.ctx.ndk_dir, 'sysroot', 'usr', 'include')
if py_ver == '2.7' else join(ndk_dir, 'usr', 'include'))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was the zlib.h include actually deployed here on your Python 2.7 installation? Because on mine it's seems that join(ndk_dir, 'usr', 'include')) doesn't exist, while the former does (join(self.ctx.ndk_dir, 'sysroot', 'usr', 'include').
So basically when running recipe on Python2, the ZLIB_ROOT would contain the following:

/home/andre/.buildozer/android/platform/android-ndk-r9c/platforms/android-19/arch-arm/usr/lib|/home/andre/.buildozer/android/platform/android-ndk-r9c/sysroot/usr/include

The lib directory seems fine:

ls /home/andre/.buildozer/android/platform/android-ndk-r9c/platforms/android-19/arch-arm/usr/lib/
crtbegin_dynamic.o  crtbegin_so.o  crtbegin_static.o  crtend_android.o  crtend_so.o  libandroid.so  libc.a  libc.so  libdl.so  libEGL.so  libGLESv1_CM.so  libGLESv2.so  libGLESv3.so  libjnigraphics.so  liblog.so  libm.a  libm_hard.a  libm.so  libOpenMAXAL.so  libOpenSLES.so  libstdc++.a  libstdc++.so  libthread_db.so  libz.so  rs

However the include is not:

ls /home/andre/.buildozer/android/platform/android-ndk-r9c/sysroot/usr/include
ls: cannot access '/home/andre/.buildozer/android/platform/android-ndk-r9c/sysroot/usr/include': No such file or directory

But if I skip line 33 and set the include as ndk_include_dir = (join(self.ctx.ndk_dir, 'sysroot', 'usr', 'include') then it contains the includes:

ls /home/andre/.buildozer/android/platform/android-ndk-r9c/platforms/android-19/arch-arm/usr/include/
alloca.h  asm          byteswap.h  dlfcn.h  endian.h  fcntl.h     fnmatch.h  GLES   grp.h       KHR        limits.h  locale.h  math.h    mtd      netinet     OMXAL       poll.h     regex.h   sched.h      sgtty.h   SLES      stdlib.h   sys       termios.h    time.h    utime.h  wctype.h
android   asm-generic  ctype.h     EGL      err.h     features.h  fts.h      GLES2  inttypes.h  lastlog.h  link.h    machine   memory.h  net      netpacket   pathconf.h  pthread.h  resolv.h  semaphore.h  sha1.h    stdint.h  string.h   syslog.h  thread_db.h  unistd.h  utmp.h   zconf.h
arpa      assert.h     dirent.h    elf.h    errno.h   fenv.h      getopt.h   GLES3  jni.h       libgen.h   linux     malloc.h  mntent.h  netdb.h  nsswitch.h  paths.h     pwd.h      rs        setjmp.h     signal.h  stdio.h   strings.h  termio.h  time64.h     util.h    wchar.h  zlib.h


png = self.get_recipe('png', self.ctx)
png_lib_dir = png.get_lib_dir(arch)
png_jni_dir = png.get_jni_dir(arch)

jpeg = self.get_recipe('jpeg', self.ctx)
jpeg_lib_dir = jpeg.get_lib_dir(arch)
jpeg_jni_dir = jpeg.get_jni_dir(arch)

env['JPEG_ROOT'] = '{}|{}'.format(jpeg_lib_dir, jpeg_jni_dir)
env['ZLIB_ROOT'] = '{}|{}'.format(ndk_lib_dir, ndk_include_dir)

cflags = ' -nostdinc'
cflags += ' -I{} -L{}'.format(png_jni_dir, png_lib_dir)
cflags += ' -I{} -L{}'.format(jpeg_jni_dir, jpeg_lib_dir)
cflags += ' -I{} -L{}'.format(ndk_include_dir, ndk_lib_dir)

gcc_lib = (shprint(sh.gcc, '-print-libgcc-file-name')
.stdout.decode('utf-8').split('\n')[0])
gcc_include = join(dirname(gcc_lib), 'include')
cflags += ' -I{}'.format(gcc_include)

if self.ctx.ndk == 'crystax':
py_inc_dir = join(self.ctx.ndk_dir, 'sources', 'python', py_ver,
'include', 'python')
py_lib_dir = join(self.ctx.ndk_dir, 'sources', 'python', py_ver,
'libs', arch.arch)
cflags += ' -I{}'.format(py_inc_dir)
env['LDFLAGS'] += ' -L{} -lpython{}m'.format(py_lib_dir, py_ver)

env['LDFLAGS'] += ' {} -L{}'.format(env['CFLAGS'], self.ctx.libs_dir)
if cflags not in env['CFLAGS']:
env['CFLAGS'] += cflags
env['LDSHARED'] = '{} {}'.format(env['CC'],
'-pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions')
return env


recipe = PillowRecipe()
13 changes: 13 additions & 0 deletions pythonforandroid/recipes/Pillow/patches/fix-docstring.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
diff --git a/src/PIL/__init__.py b/src/PIL/__init__.py
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor, FWIW I would reference the upstream bug python-pillow/Pillow#3231

index a07280e..6b9fe99 100644
--- a/src/PIL/__init__.py
+++ b/src/PIL/__init__.py
@@ -24,7 +24,7 @@ PILLOW_VERSION = __version__ = _version.__version__

del _version

-__doc__ = __doc__.format(__version__) # include version in docstring
+__doc__ = ''


_plugins = ['BlpImagePlugin',
148 changes: 148 additions & 0 deletions pythonforandroid/recipes/Pillow/patches/fix-setup.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
diff --git a/setup.py b/setup.py
index 761d552..4ddc598 100755
--- a/setup.py
+++ b/setup.py
@@ -136,12 +136,12 @@ except (ImportError, OSError):

NAME = 'Pillow'
PILLOW_VERSION = get_version()
-JPEG_ROOT = None
+JPEG_ROOT = tuple(os.environ['JPEG_ROOT'].split('|')) if 'JPEG_ROOT' in os.environ else None
JPEG2K_ROOT = None
-ZLIB_ROOT = None
+ZLIB_ROOT = tuple(os.environ['ZLIB_ROOT'].split('|')) if 'ZLIB_ROOT' in os.environ else None
IMAGEQUANT_ROOT = None
TIFF_ROOT = None
-FREETYPE_ROOT = None
+FREETYPE_ROOT = tuple(os.environ['FREETYPE_ROOT'].split('|')) if 'FREETYPE_ROOT' in os.environ else None
LCMS_ROOT = None


@@ -194,7 +194,7 @@ class pil_build_ext(build_ext):
]

def initialize_options(self):
- self.disable_platform_guessing = None
+ self.disable_platform_guessing = True
build_ext.initialize_options(self)
for x in self.feature:
setattr(self, 'disable_%s' % x, None)
@@ -466,61 +466,6 @@ class pil_build_ext(build_ext):
feature.jpeg = "libjpeg" # alternative name

feature.openjpeg_version = None
- if feature.want('jpeg2000'):
- _dbg('Looking for jpeg2000')
- best_version = None
- best_path = None
-
- # Find the best version
- for directory in self.compiler.include_dirs:
- _dbg('Checking for openjpeg-#.# in %s', directory)
- try:
- listdir = os.listdir(directory)
- except Exception:
- # WindowsError, FileNotFoundError
- continue
- for name in listdir:
- if name.startswith('openjpeg-') and \
- os.path.isfile(os.path.join(directory, name,
- 'openjpeg.h')):
- _dbg('Found openjpeg.h in %s/%s', (directory, name))
- version = tuple(int(x) for x in name[9:].split('.'))
- if best_version is None or version > best_version:
- best_version = version
- best_path = os.path.join(directory, name)
- _dbg('Best openjpeg version %s so far in %s',
- (best_version, best_path))
-
- if best_version and _find_library_file(self, 'openjp2'):
- # Add the directory to the include path so we can include
- # <openjpeg.h> rather than having to cope with the versioned
- # include path
- # FIXME (melvyn-sopacua):
- # At this point it's possible that best_path is already in
- # self.compiler.include_dirs. Should investigate how that is
- # possible.
- _add_directory(self.compiler.include_dirs, best_path, 0)
- feature.jpeg2000 = 'openjp2'
- feature.openjpeg_version = '.'.join(str(x) for x in best_version)
-
- if feature.want('imagequant'):
- _dbg('Looking for imagequant')
- if _find_include_file(self, 'libimagequant.h'):
- if _find_library_file(self, "imagequant"):
- feature.imagequant = "imagequant"
- elif _find_library_file(self, "libimagequant"):
- feature.imagequant = "libimagequant"
-
- if feature.want('tiff'):
- _dbg('Looking for tiff')
- if _find_include_file(self, 'tiff.h'):
- if _find_library_file(self, "tiff"):
- feature.tiff = "tiff"
- if sys.platform == "win32" and _find_library_file(self, "libtiff"):
- feature.tiff = "libtiff"
- if (sys.platform == "darwin" and
- _find_library_file(self, "libtiff")):
- feature.tiff = "libtiff"

if feature.want('freetype'):
_dbg('Looking for freetype')
@@ -546,36 +491,6 @@ class pil_build_ext(build_ext):
if subdir:
_add_directory(self.compiler.include_dirs, subdir, 0)

- if feature.want('lcms'):
- _dbg('Looking for lcms')
- if _find_include_file(self, "lcms2.h"):
- if _find_library_file(self, "lcms2"):
- feature.lcms = "lcms2"
- elif _find_library_file(self, "lcms2_static"):
- # alternate Windows name.
- feature.lcms = "lcms2_static"
-
- if feature.want('webp'):
- _dbg('Looking for webp')
- if (_find_include_file(self, "webp/encode.h") and
- _find_include_file(self, "webp/decode.h")):
- # In Google's precompiled zip it is call "libwebp":
- if _find_library_file(self, "webp"):
- feature.webp = "webp"
- elif _find_library_file(self, "libwebp"):
- feature.webp = "libwebp"
-
- if feature.want('webpmux'):
- _dbg('Looking for webpmux')
- if (_find_include_file(self, "webp/mux.h") and
- _find_include_file(self, "webp/demux.h")):
- if (_find_library_file(self, "webpmux") and
- _find_library_file(self, "webpdemux")):
- feature.webpmux = "webpmux"
- if (_find_library_file(self, "libwebpmux") and
- _find_library_file(self, "libwebpdemux")):
- feature.webpmux = "libwebpmux"
-
for f in feature:
if not getattr(feature, f) and feature.require(f):
if f in ('jpeg', 'zlib'):
@@ -612,8 +527,6 @@ class pil_build_ext(build_ext):
defs.append(("HAVE_LIBTIFF", None))
if sys.platform == "win32":
libs.extend(["kernel32", "user32", "gdi32"])
- if struct.unpack("h", "\0\1".encode('ascii'))[0] == 1:
- defs.append(("WORDS_BIGENDIAN", None))

if sys.platform == "win32" and not (PLATFORM_PYPY or PLATFORM_MINGW):
defs.append(("PILLOW_VERSION", '"\\"%s\\""' % PILLOW_VERSION))
@@ -658,10 +571,6 @@ class pil_build_ext(build_ext):
define_macros=defs))

tk_libs = ['psapi'] if sys.platform == 'win32' else []
- exts.append(Extension("PIL._imagingtk",
- ["src/_imagingtk.c", "src/Tk/tkImaging.c"],
- include_dirs=['src/Tk'],
- libraries=tk_libs))

exts.append(Extension("PIL._imagingmath", ["src/_imagingmath.c"]))
exts.append(Extension("PIL._imagingmorph", ["src/_imagingmorph.c"]))
2 changes: 1 addition & 1 deletion pythonforandroid/recipes/setuptools/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@


class SetuptoolsRecipe(PythonRecipe):
version = '18.3.1'
version = '40.0.0'
url = 'https://pypi.python.org/packages/source/s/setuptools/setuptools-{version}.zip'

depends = [('python2', 'python3crystax')]
Expand Down