diff --git a/ci/constants.py b/ci/constants.py index 804ceffa0d..e7f84aca02 100644 --- a/ci/constants.py +++ b/ci/constants.py @@ -44,6 +44,9 @@ class TargetPython(Enum): 'm2crypto', 'netifaces', 'Pillow', + # requires autoconf system dependency on host + # https://api.travis-ci.org/v3/job/450538715/log.txt + 'protobuf_cpp', # https://github.com/kivy/python-for-android/issues/1405 'psycopg2', 'pygame', diff --git a/pythonforandroid/recipes/protobuf_cpp/__init__.py b/pythonforandroid/recipes/protobuf_cpp/__init__.py index 1c01901a9c..6cfa674b57 100644 --- a/pythonforandroid/recipes/protobuf_cpp/__init__.py +++ b/pythonforandroid/recipes/protobuf_cpp/__init__.py @@ -1,21 +1,60 @@ from pythonforandroid.recipe import PythonRecipe -from pythonforandroid.logger import shprint +from pythonforandroid.logger import shprint, info_notify from pythonforandroid.util import current_directory, shutil from os.path import exists, join, dirname import sh from multiprocessing import cpu_count - - from pythonforandroid.toolchain import info +import sys +import os class ProtobufCppRecipe(PythonRecipe): name = 'protobuf_cpp' - version = '3.1.0' + version = '3.5.1' url = 'https://github.com/google/protobuf/releases/download/v{version}/protobuf-python-{version}.tar.gz' call_hostpython_via_targetpython = False depends = ['cffi', 'setuptools'] site_packages_name = 'google/protobuf/pyext' + protoc_dir = None + + def prebuild_arch(self, arch): + super(ProtobufCppRecipe, self).prebuild_arch(arch) + # During building, host needs to transpile .proto files to .py + # ideally with the same version as protobuf runtime, or with an older one. + # Because protoc is compiled for target (i.e. Android), we need an other binary + # which can be run by host. + # To make it easier, we download prebuild protoc binary adapted to the platform + + info_notify("Downloading protoc compiler for your platform") + url_prefix = "https://github.com/protocolbuffers/protobuf/releases/download/v{version}".format(version=self.version) + if sys.platform.startswith('linux'): + info_notify("GNU/Linux detected") + filename = "protoc-{version}-linux-x86_64.zip".format(version=self.version) + elif sys.platform.startswith('darwin'): + info_notify("Mac OS X detected") + filename = "protoc-{version}-osx-x86_64.zip".format(version=self.version) + else: + info_notify("Your platform is not supported, but recipe can still " + "be built if you have a valid protoc (<={version}) in " + "your path".format(version=self.version)) + return + + protoc_url = join(url_prefix, filename) + self.protoc_dir = join(self.ctx.build_dir, "tools", "protoc") + if os.path.exists(join(self.protoc_dir, "bin", "protoc")): + info_notify("protoc found, no download needed") + return + try: + os.makedirs(self.protoc_dir) + except OSError as e: + # if dir already exists (errno 17), we ignore the error + if e.errno != 17: + raise e + info_notify("Will download into {dest_dir}".format(dest_dir=self.protoc_dir)) + self.download_file(protoc_url, join(self.protoc_dir, filename)) + with current_directory(self.protoc_dir): + shprint(sh.unzip, join(self.protoc_dir, filename)) def build_arch(self, arch): env = self.get_recipe_env(arch) @@ -85,7 +124,9 @@ def install_python_package(self, arch): def get_recipe_env(self, arch): env = super(ProtobufCppRecipe, self).get_recipe_env(arch) - env['PROTOC'] = '/home/fipo/soft/protobuf-3.1.0/src/protoc' + if self.protoc_dir is not None: + # we need protoc with binary for host platform + env['PROTOC'] = join(self.protoc_dir, 'bin', 'protoc') env['PYTHON_ROOT'] = self.ctx.get_python_install_dir() env['TARGET_OS'] = 'OS_ANDROID_CROSSCOMPILE' env['CFLAGS'] += ( @@ -103,7 +144,7 @@ def get_recipe_env(self, arch): env['LDFLAGS'] += ( ' -L' + self.ctx.ndk_dir + '/sources/cxx-stl/gnu-libstdc++/' + self.ctx.toolchain_version + - '/libs/' + arch.arch + ' -lgnustl_shared -lpython2.7') + '/libs/' + arch.arch + ' -lgnustl_shared -lpython2.7 -landroid -llog') env['LDSHARED'] = env['CC'] + ' -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions' return env