Example #1
0
    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
Example #2
0
    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
Example #3
0
    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'))
Example #5
0
    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