diff --git a/pythonforandroid/recipes/libgeos/__init__.py b/pythonforandroid/recipes/libgeos/__init__.py index 30786f8ea4..cff9fe0f5e 100644 --- a/pythonforandroid/recipes/libgeos/__init__.py +++ b/pythonforandroid/recipes/libgeos/__init__.py @@ -1,44 +1,52 @@ -from pythonforandroid.toolchain import Recipe, shprint, shutil, current_directory -from os.path import exists, join -import sh +from pythonforandroid.util import current_directory, ensure_dir +from pythonforandroid.toolchain import shprint +from pythonforandroid.recipe import Recipe from multiprocessing import cpu_count +from os.path import join +import sh class LibgeosRecipe(Recipe): - version = '3.5' - # url = 'http://download.osgeo.org/geos/geos-{version}.tar.bz2' - url = 'https://github.com/libgeos/libgeos/archive/svn-{version}.zip' + version = '3.7.1' + url = 'https://github.com/libgeos/libgeos/archive/{version}.zip' depends = [] - - def should_build(self, arch): - super(LibgeosRecipe, self).should_build(arch) - return not exists(join(self.ctx.get_libs_dir(arch.arch), 'libgeos_c.so')) + built_libraries = { + 'libgeos.so': 'install_target/lib', + 'libgeos_c.so': 'install_target/lib' + } + need_stl_shared = True def build_arch(self, arch): - super(LibgeosRecipe, self).build_arch(arch) - env = self.get_recipe_env(arch) - - with current_directory(self.get_build_dir(arch.arch)): - dst_dir = join(self.get_build_dir(arch.arch), 'dist') - bash = sh.Command('bash') - print("If this fails make sure you have autoconf and libtool installed") - shprint(bash, 'autogen.sh') # Requires autoconf and libtool - shprint(bash, 'configure', '--host=arm-linux-androideabi', '--enable-shared', '--prefix={}'.format(dst_dir), _env=env) - shprint(sh.make, '-j', str(cpu_count()), _env=env) + source_dir = self.get_build_dir(arch.arch) + build_target = join(source_dir, 'build_target') + install_target = join(source_dir, 'install_target') + + ensure_dir(build_target) + with current_directory(build_target): + env = self.get_recipe_env(arch) + shprint(sh.cmake, source_dir, + '-DANDROID_ABI={}'.format(arch.arch), + '-DANDROID_NATIVE_API_LEVEL={}'.format(self.ctx.ndk_api), + '-DANDROID_STL=' + self.stl_lib_name, + + '-DCMAKE_TOOLCHAIN_FILE={}'.format( + join(self.ctx.ndk_dir, 'build', 'cmake', + 'android.toolchain.cmake')), + '-DCMAKE_INSTALL_PREFIX={}'.format(install_target), + '-DCMAKE_BUILD_TYPE=Release', + + '-DGEOS_ENABLE_TESTS=OFF', + + '-DBUILD_SHARED_LIBS=1', + + _env=env) + shprint(sh.make, '-j' + str(cpu_count()), _env=env) + + # We make the install because this way we will have all the + # includes in one place (mostly we are interested in `geos_c.h`, + # which is not in the include folder, so this way we make easier to + # link with this library...case of shapely's recipe) shprint(sh.make, 'install', _env=env) - shutil.copyfile('{}/lib/libgeos_c.so'.format(dst_dir), join(self.ctx.get_libs_dir(arch.arch), 'libgeos_c.so')) - - def get_recipe_env(self, arch): - env = super(LibgeosRecipe, self).get_recipe_env(arch) - env['CXXFLAGS'] += ' -I{}/sources/cxx-stl/gnu-libstdc++/4.8/include'.format(self.ctx.ndk_dir) - env['CXXFLAGS'] += ' -I{}/sources/cxx-stl/gnu-libstdc++/4.8/libs/{}/include'.format( - self.ctx.ndk_dir, arch) - env['CXXFLAGS'] += ' -L{}/sources/cxx-stl/gnu-libstdc++/4.8/libs/{}'.format( - self.ctx.ndk_dir, arch) - env['CXXFLAGS'] += ' -lgnustl_shared' - env['LDFLAGS'] += ' -L{}/sources/cxx-stl/gnu-libstdc++/4.8/libs/{}'.format( - self.ctx.ndk_dir, arch) - return env recipe = LibgeosRecipe() diff --git a/pythonforandroid/recipes/shapely/__init__.py b/pythonforandroid/recipes/shapely/__init__.py index e0b093766b..f70876132e 100644 --- a/pythonforandroid/recipes/shapely/__init__.py +++ b/pythonforandroid/recipes/shapely/__init__.py @@ -1,21 +1,38 @@ -from pythonforandroid.recipe import Recipe, CythonRecipe +from pythonforandroid.recipe import CythonRecipe +from os.path import join class ShapelyRecipe(CythonRecipe): - version = '1.5' - url = 'https://github.com/Toblerity/Shapely/archive/master.zip' + version = '1.7a1' + url = 'https://github.com/Toblerity/Shapely/archive/{version}.tar.gz' depends = ['setuptools', 'libgeos'] + + # Actually, this recipe seems to compile/install fine for python2, but it + # fails at runtime when importing module with: + # `[Errno 2] No such file or directory` + conflicts = ['python2'] + call_hostpython_via_targetpython = False - patches = ['setup.patch'] # Patch to force setup to fail when C extention fails to build + # Patch to avoid libgeos check (because it fails), insert environment + # variables for our libgeos build (includes, lib paths...) and force + # the cython's compilation to raise an error in case that it fails + patches = ['setup.patch'] + + # Don't Force Cython + # setup_extra_args = ['sdist'] + + def get_recipe_env(self, arch=None, with_flags_in_cc=True): + env = super(ShapelyRecipe, self).get_recipe_env(arch) - # setup_extra_args = ['sdist'] # DontForce Cython + libgeos_install = join(self.get_recipe( + 'libgeos', self.ctx).get_build_dir(arch.arch), 'install_target') + # All this `GEOS_X` variables should be string types, separated + # by commas in case that we need to pass more than one value + env['GEOS_INCLUDE_DIRS'] = join(libgeos_install, 'include') + env['GEOS_LIBRARY_DIRS'] = join(libgeos_install, 'lib') + env['GEOS_LIBRARIES'] = 'geos_c,geos' - def get_recipe_env(self, arch, with_flags_in_cc=True): - """ Add libgeos headers to path """ - env = super(ShapelyRecipe, self).get_recipe_env(arch, with_flags_in_cc) - libgeos_dir = Recipe.get_recipe('libgeos', self.ctx).get_build_dir(arch.arch) - env['CFLAGS'] += " -I{}/dist/include".format(libgeos_dir) return env diff --git a/pythonforandroid/recipes/shapely/setup.patch b/pythonforandroid/recipes/shapely/setup.patch index 9523f357bc..7fd1ca9149 100644 --- a/pythonforandroid/recipes/shapely/setup.patch +++ b/pythonforandroid/recipes/shapely/setup.patch @@ -1,12 +1,44 @@ -*** shapely/setup.py 2016-06-29 11:29:49.000000000 -0400 ---- b/setup.py 2016-07-09 01:51:37.759670990 -0400 -*************** -*** 359,364 **** ---- 359,365 ---- - construct_build_ext(existing_build_ext) - setup(ext_modules=ext_modules, **setup_args) - except BuildFailed as ex: -+ raise # Force python only build to fail - BUILD_EXT_WARNING = "The C extension could not be compiled, " \ - "speedups are not enabled." - log.warn(ex) +This patch does three things: + - disable the libgeos check, because, even setting the proper env variables, + it fails to load our libgeos library, so we skip that because it's not + mandatory for the cythonizing. + - sets some environment variables into the setup.py file, so we can pass + our libgeos information (includes, lib path and libraries) + - force to raise an error when cython file to compile (our current build + system relies on this failure to do the proper `cythonizing`, if we don't + raise the error, we will end up with the package installed without the + speed optimizations. +--- Shapely-1.7a1/setup.py.orig 2018-07-29 22:53:13.000000000 +0200 ++++ Shapely-1.7a1/setup.py 2019-02-24 14:26:19.178610660 +0100 +@@ -82,8 +82,8 @@ if not (py_version == (2, 7) or py_versi + + # Get geos_version from GEOS dynamic library, which depends on + # GEOS_LIBRARY_PATH and/or GEOS_CONFIG environment variables +-from shapely._buildcfg import geos_version_string, geos_version, \ +- geos_config, get_geos_config ++# from shapely._buildcfg import geos_version_string, geos_version, \ ++# geos_config, get_geos_config + + logging.basicConfig() + log = logging.getLogger(__file__) +@@ -248,9 +248,9 @@ if sys.platform == 'win32': + setup_args['package_data']['shapely'].append('shapely/DLLs/*.dll') + + # Prepare build opts and args for the speedups extension module. +-include_dirs = [] +-library_dirs = [] +-libraries = [] ++include_dirs = os.environ.get('GEOS_INCLUDE_DIRS', '').split(',') ++library_dirs = os.environ.get('GEOS_LIBRARY_DIRS', '').split(',') ++libraries = os.environ.get('GEOS_LIBRARIES', '').split(',') + extra_link_args = [] + + # If NO_GEOS_CONFIG is set in the environment, geos-config will not +@@ -375,6 +375,7 @@ try: + construct_build_ext(existing_build_ext) + setup(ext_modules=ext_modules, **setup_args) + except BuildFailed as ex: ++ raise # Force python only build to fail + BUILD_EXT_WARNING = "The C extension could not be compiled, " \ + "speedups are not enabled." + log.warn(ex)