def get_pip_installed_recipe(cls, name, ctx): """Attempts to get the recipe installed via pip. Requires the use of the "p4a_recipe" entry point. This entry point must set a function that returns a tuple of (recipe, __file__) Example -------- #: In myrecipe.py from pythonforandroid.recipe import CythonRecipe class MyRecipe(CythonRecipe): version = "1.0" name = "my-recipe" # etc ... def get_recipe(): return (MyRecipe(), __file__) #: setup.py setup( #... entry_points = { 'p4a_recipe': ['my_recipe = myrecipe:get_recipe'], }, ) """ for ep in pkg_resources.iter_entry_points(group="p4a_recipe"): if ep.name.replace("-", "_") == name.replace("-", "_"): try: get_recipe = ep.load() return get_recipe() except Exception as e: #: Tell the user which one failed logger.warning("Failed to load {}: {}".format(ep.name, e)) raise
def get_recipe_env(self, arch=None, with_flags_in_cc=True): if self.from_crystax: return super(GuestPythonRecipe, self).get_recipe_env( arch=arch, with_flags_in_cc=with_flags_in_cc) env = environ.copy() android_host = env['HOSTARCH'] = arch.command_prefix toolchain = '{toolchain_prefix}-{toolchain_version}'.format( toolchain_prefix=self.ctx.toolchain_prefix, toolchain_version=self.ctx.toolchain_version) toolchain = join(self.ctx.ndk_dir, 'toolchains', toolchain, 'prebuilt', build_platform) env['CC'] = ( '{clang} -target {target} -gcc-toolchain {toolchain}').format( clang=join(self.ctx.ndk_dir, 'toolchains', 'llvm', 'prebuilt', build_platform, 'bin', 'clang'), target=arch.target, toolchain=toolchain) env['AR'] = join(toolchain, 'bin', android_host) + '-ar' env['LD'] = join(toolchain, 'bin', android_host) + '-ld' env['RANLIB'] = join(toolchain, 'bin', android_host) + '-ranlib' env['READELF'] = join(toolchain, 'bin', android_host) + '-readelf' env['STRIP'] = join(toolchain, 'bin', android_host) + '-strip' env['STRIP'] += ' --strip-debug --strip-unneeded' env['PATH'] = ('{hostpython_dir}:{old_path}').format( hostpython_dir=self.get_recipe('host' + self.name, self.ctx).get_path_to_python(), old_path=env['PATH']) ndk_flags = ( '-fPIC --sysroot={ndk_sysroot} -D__ANDROID_API__={android_api} ' '-isystem {ndk_android_host} -I{ndk_include}').format( ndk_sysroot=join(self.ctx.ndk_dir, 'sysroot'), android_api=self.ctx.ndk_api, ndk_android_host=join(self.ctx.ndk_dir, 'sysroot', 'usr', 'include', android_host), ndk_include=join(self.ctx.ndk_dir, 'sysroot', 'usr', 'include')) sysroot = self.ctx.ndk_platform env['CFLAGS'] = env.get('CFLAGS', '') + ' ' + ndk_flags env['CPPFLAGS'] = env.get('CPPFLAGS', '') + ' ' + ndk_flags env['LDFLAGS'] = env.get('LDFLAGS', '') + ' --sysroot={} -L{}'.format( sysroot, join(sysroot, 'usr', 'lib')) # Manually add the libs directory, and copy some object # files to the current directory otherwise they aren't # picked up. This seems necessary because the --sysroot # setting in LDFLAGS is overridden by the other flags. # TODO: Work out why this doesn't happen in the original # bpo-30386 Makefile system. logger.warning('Doing some hacky stuff to link properly') lib_dir = join(sysroot, 'usr', 'lib') if arch.arch == 'x86_64': lib_dir = join(sysroot, 'usr', 'lib64') env['LDFLAGS'] += ' -L{}'.format(lib_dir) shprint(sh.cp, join(lib_dir, 'crtbegin_so.o'), './') shprint(sh.cp, join(lib_dir, 'crtend_so.o'), './') env['SYSROOT'] = sysroot return env
def build_arch(self, arch): if self.ctx.ndk_api < self.MIN_NDK_API: error( 'Target ndk-api is {}, but the python3 recipe supports only {}+' .format(self.ctx.ndk_api, self.MIN_NDK_API)) exit(1) recipe_build_dir = self.get_build_dir(arch.arch) # Create a subdirectory to actually perform the build build_dir = join(recipe_build_dir, 'android-build') ensure_dir(build_dir) # TODO: Get these dynamically, like bpo-30386 does sys_prefix = '/usr/local' sys_exec_prefix = '/usr/local' # Skipping "Ensure that nl_langinfo is broken" from the original bpo-30386 platform_name = 'android-{}'.format(self.ctx.ndk_api) with current_directory(build_dir): env = environ.copy() # TODO: Get this information from p4a's arch system android_host = 'arm-linux-androideabi' android_build = sh.Command( join(recipe_build_dir, 'config.guess'))().stdout.strip().decode('utf-8') platform_dir = join(self.ctx.ndk_dir, 'platforms', platform_name, 'arch-arm') toolchain = '{android_host}-4.9'.format(android_host=android_host) toolchain = join(self.ctx.ndk_dir, 'toolchains', toolchain, 'prebuilt', 'linux-x86_64') CC = '{clang} -target {target} -gcc-toolchain {toolchain}'.format( clang=join(self.ctx.ndk_dir, 'toolchains', 'llvm', 'prebuilt', 'linux-x86_64', 'bin', 'clang'), target='armv7-none-linux-androideabi', toolchain=toolchain) AR = join(toolchain, 'bin', android_host) + '-ar' LD = join(toolchain, 'bin', android_host) + '-ld' RANLIB = join(toolchain, 'bin', android_host) + '-ranlib' READELF = join(toolchain, 'bin', android_host) + '-readelf' STRIP = join( toolchain, 'bin', android_host) + '-strip --strip-debug --strip-unneeded' env['CC'] = CC env['AR'] = AR env['LD'] = LD env['RANLIB'] = RANLIB env['READELF'] = READELF env['STRIP'] = STRIP env['PATH'] = '{hostpython_dir}:{old_path}'.format( hostpython_dir=self.get_recipe('hostpython3', self.ctx).get_path_to_python(), old_path=env['PATH']) ndk_flags = ( '--sysroot={ndk_sysroot} -D__ANDROID_API__={android_api} ' '-isystem {ndk_android_host}').format( ndk_sysroot=join(self.ctx.ndk_dir, 'sysroot'), android_api=self.ctx.ndk_api, ndk_android_host=join(self.ctx.ndk_dir, 'sysroot', 'usr', 'include', android_host)) sysroot = join(self.ctx.ndk_dir, 'platforms', platform_name, 'arch-arm') env['CFLAGS'] = env.get('CFLAGS', '') + ' ' + ndk_flags env['CPPFLAGS'] = env.get('CPPFLAGS', '') + ' ' + ndk_flags env['LDFLAGS'] = env.get('LDFLAGS', '') + ' --sysroot={} -L{}'.format( sysroot, join(sysroot, 'usr', 'lib')) # Manually add the libs directory, and copy some object # files to the current directory otherwise they aren't # picked up. This seems necessary because the --sysroot # setting in LDFLAGS is overridden by the other flags. # TODO: Work out why this doesn't happen in the original # bpo-30386 Makefile system. logger.warning('Doing some hacky stuff to link properly') lib_dir = join(sysroot, 'usr', 'lib') env['LDFLAGS'] += ' -L{}'.format(lib_dir) shprint(sh.cp, join(lib_dir, 'crtbegin_so.o'), './') shprint(sh.cp, join(lib_dir, 'crtend_so.o'), './') env['SYSROOT'] = sysroot env = self.set_libs_flags(env, arch) if not exists('config.status'): shprint(sh.Command(join(recipe_build_dir, 'configure')), *(' '.join( ('--host={android_host}', '--build={android_build}', '--enable-shared', '--disable-ipv6', 'ac_cv_file__dev_ptmx=yes', 'ac_cv_file__dev_ptc=no', '--without-ensurepip', 'ac_cv_little_endian_double=yes', '--prefix={prefix}', '--exec-prefix={exec_prefix}')).format( android_host=android_host, android_build=android_build, prefix=sys_prefix, exec_prefix=sys_exec_prefix)).split(' '), _env=env) if not exists('python'): shprint(sh.make, 'all', _env=env) # TODO: Look into passing the path to pyconfig.h in a # better way, although this is probably acceptable sh.cp('pyconfig.h', join(recipe_build_dir, 'Include'))
def build_arch(self, arch): if self.ctx.ndk_api < self.MIN_NDK_API: error('Target ndk-api is {}, but the python3 recipe supports only {}+'.format( self.ctx.ndk_api, self.MIN_NDK_API)) exit(1) recipe_build_dir = self.get_build_dir(arch.arch) # Create a subdirectory to actually perform the build build_dir = join(recipe_build_dir, 'android-build') ensure_dir(build_dir) # TODO: Get these dynamically, like bpo-30386 does sys_prefix = '/usr/local' sys_exec_prefix = '/usr/local' # Skipping "Ensure that nl_langinfo is broken" from the original bpo-30386 platform_name = 'android-{}'.format(self.ctx.ndk_api) with current_directory(build_dir): env = environ.copy() # TODO: Get this information from p4a's arch system android_host = arch.command_prefix android_build = sh.Command(join(recipe_build_dir, 'config.guess'))().stdout.strip().decode('utf-8') platform_dir = join(self.ctx.ndk_dir, 'platforms', platform_name, arch.platform_dir) toolchain = '{android_host}-4.9'.format(android_host=arch.toolchain_prefix) toolchain = join(self.ctx.ndk_dir, 'toolchains', toolchain, 'prebuilt', 'linux-x86_64') target_data = arch.command_prefix.split('-') if target_data[0] == 'arm': target_data[0] = 'armv7a' target = '-'.join([target_data[0], 'none', target_data[1], target_data[2]]) CC = '{clang} -target {target} -gcc-toolchain {toolchain}'.format( clang=join(self.ctx.ndk_dir, 'toolchains', 'llvm', 'prebuilt', 'linux-x86_64', 'bin', 'clang'), target=target, toolchain=toolchain) AR = join(toolchain, 'bin', android_host) + '-ar' LD = join(toolchain, 'bin', android_host) + '-ld' RANLIB = join(toolchain, 'bin', android_host) + '-ranlib' READELF = join(toolchain, 'bin', android_host) + '-readelf' STRIP = join(toolchain, 'bin', android_host) + '-strip --strip-debug --strip-unneeded' env['CC'] = CC env['AR'] = AR env['LD'] = LD env['RANLIB'] = RANLIB env['READELF'] = READELF env['STRIP'] = STRIP env['PATH'] = '{hostpython_dir}:{old_path}'.format( hostpython_dir=self.get_recipe('hostpython3', self.ctx).get_path_to_python(), old_path=env['PATH']) ndk_flags = ('-fPIC --sysroot={ndk_sysroot} -D__ANDROID_API__={android_api} ' '-isystem {ndk_android_host}').format( ndk_sysroot=join(self.ctx.ndk_dir, 'sysroot'), android_api=self.ctx.ndk_api, ndk_android_host=join( self.ctx.ndk_dir, 'sysroot', 'usr', 'include', android_host)) sysroot = join(self.ctx.ndk_dir, 'platforms', platform_name, arch.platform_dir) env['CFLAGS'] = env.get('CFLAGS', '') + ' ' + ndk_flags env['CPPFLAGS'] = env.get('CPPFLAGS', '') + ' ' + ndk_flags env['LDFLAGS'] = env.get('LDFLAGS', '') + ' --sysroot={} -L{}'.format(sysroot, join(sysroot, 'usr', 'lib')) # Manually add the libs directory, and copy some object # files to the current directory otherwise they aren't # picked up. This seems necessary because the --sysroot # setting in LDFLAGS is overridden by the other flags. # TODO: Work out why this doesn't happen in the original # bpo-30386 Makefile system. logger.warning('Doing some hacky stuff to link properly') lib_dir = join(sysroot, 'usr', 'lib') if arch.arch == 'x86_64': lib_dir = join(sysroot, 'usr', 'lib64') env['LDFLAGS'] += ' -L{}'.format(lib_dir) shprint(sh.cp, join(lib_dir, 'crtbegin_so.o'), './') shprint(sh.cp, join(lib_dir, 'crtend_so.o'), './') env['SYSROOT'] = sysroot env = self.set_libs_flags(env, arch) if not exists('config.status'): shprint(sh.Command(join(recipe_build_dir, 'configure')), *(' '.join(('--host={android_host}', '--build={android_build}', '--enable-shared', '--disable-ipv6', 'ac_cv_file__dev_ptmx=yes', 'ac_cv_file__dev_ptc=no', '--without-ensurepip', 'ac_cv_little_endian_double=yes', '--prefix={prefix}', '--exec-prefix={exec_prefix}')).format( android_host=android_host, android_build=android_build, prefix=sys_prefix, exec_prefix=sys_exec_prefix)).split(' '), _env=env) if not exists('python'): shprint(sh.make, 'all', _env=env) # TODO: Look into passing the path to pyconfig.h in a # better way, although this is probably acceptable sh.cp('pyconfig.h', join(recipe_build_dir, 'Include'))
def get_recipe_env(self, arch=None, with_flags_in_cc=True): if self.from_crystax: return super(GuestPythonRecipe, self).get_recipe_env( arch=arch, with_flags_in_cc=with_flags_in_cc) env = environ.copy() android_host = env['HOSTARCH'] = arch.command_prefix toolchain = '{toolchain_prefix}-{toolchain_version}'.format( toolchain_prefix=self.ctx.toolchain_prefix, toolchain_version=self.ctx.toolchain_version) toolchain = join(self.ctx.ndk_dir, 'toolchains', toolchain, 'prebuilt', build_platform) env['CC'] = ( '{clang} -target {target} -gcc-toolchain {toolchain}').format( clang=join(self.ctx.ndk_dir, 'toolchains', 'llvm', 'prebuilt', build_platform, 'bin', 'clang'), target=arch.target, toolchain=toolchain) env['AR'] = join(toolchain, 'bin', android_host) + '-ar' env['LD'] = join(toolchain, 'bin', android_host) + '-ld' env['RANLIB'] = join(toolchain, 'bin', android_host) + '-ranlib' env['READELF'] = join(toolchain, 'bin', android_host) + '-readelf' env['STRIP'] = join(toolchain, 'bin', android_host) + '-strip' env['STRIP'] += ' --strip-debug --strip-unneeded' env['PATH'] = ( '{hostpython_dir}:{old_path}').format( hostpython_dir=self.get_recipe( 'host' + self.name, self.ctx).get_path_to_python(), old_path=env['PATH']) ndk_flags = ( '-fPIC --sysroot={ndk_sysroot} -D__ANDROID_API__={android_api} ' '-isystem {ndk_android_host} -I{ndk_include}').format( ndk_sysroot=join(self.ctx.ndk_dir, 'sysroot'), android_api=self.ctx.ndk_api, ndk_android_host=join( self.ctx.ndk_dir, 'sysroot', 'usr', 'include', android_host), ndk_include=join(self.ctx.ndk_dir, 'sysroot', 'usr', 'include')) sysroot = self.ctx.ndk_platform env['CFLAGS'] = env.get('CFLAGS', '') + ' ' + ndk_flags env['CPPFLAGS'] = env.get('CPPFLAGS', '') + ' ' + ndk_flags env['LDFLAGS'] = env.get('LDFLAGS', '') + ' --sysroot={} -L{}'.format( sysroot, join(sysroot, 'usr', 'lib')) # Manually add the libs directory, and copy some object # files to the current directory otherwise they aren't # picked up. This seems necessary because the --sysroot # setting in LDFLAGS is overridden by the other flags. # TODO: Work out why this doesn't happen in the original # bpo-30386 Makefile system. logger.warning('Doing some hacky stuff to link properly') lib_dir = join(sysroot, 'usr', 'lib') if arch.arch == 'x86_64': lib_dir = join(sysroot, 'usr', 'lib64') env['LDFLAGS'] += ' -L{}'.format(lib_dir) shprint(sh.cp, join(lib_dir, 'crtbegin_so.o'), './') shprint(sh.cp, join(lib_dir, 'crtend_so.o'), './') env['SYSROOT'] = sysroot return env