Ejemplo n.º 1
0
class Python2Recipe(TargetPythonRecipe):
    version = "2.7.2"
    url = 'http://python.org/ftp/python/{version}/Python-{version}.tar.bz2'
    name = 'python2'

    depends = ['hostpython2']
    conflicts = ['python3crystax', 'python3']
    opt_depends = ['openssl']
    
    patches = ['patches/Python-{version}-xcompile.patch',
               'patches/Python-{version}-ctypes-disable-wchar.patch',
               'patches/disable-modules.patch',
               'patches/fix-locale.patch',
               'patches/fix-gethostbyaddr.patch',
               'patches/fix-setup-flags.patch',
               'patches/fix-filesystemdefaultencoding.patch',
               'patches/fix-platform.patch',
               'patches/fix-termios.patch',
               'patches/custom-loader.patch',
               'patches/verbose-compilation.patch',
               'patches/fix-remove-corefoundation.patch',
               'patches/fix-dynamic-lookup.patch',
               'patches/fix-dlfcn.patch',
               'patches/parsetuple.patch',
               'patches/ctypes-find-library-updated.patch',
               ('patches/fix-configure-darwin.patch', is_darwin),
               ('patches/fix-distutils-darwin.patch', is_darwin),
               ('patches/fix-ftime-removal.patch', is_api_gt(19)),
               ('patches/disable-openpty.patch', check_all(is_api_lt(21), is_ndk('crystax')))]

    from_crystax = False

    def build_arch(self, arch):

        if not exists(join(self.get_build_dir(arch.arch), 'libpython2.7.so')):
            self.do_python_build(arch)

        if not exists(self.ctx.get_python_install_dir()):
            shprint(sh.cp, '-a', join(self.get_build_dir(arch.arch), 'python-install'),
                    self.ctx.get_python_install_dir())

        # This should be safe to run every time
        info('Copying hostpython binary to targetpython folder')
        shprint(sh.cp, self.ctx.hostpython,
                join(self.ctx.get_python_install_dir(), 'bin', 'python.host'))
        self.ctx.hostpython = join(self.ctx.get_python_install_dir(), 'bin', 'python.host')

        if not exists(join(self.ctx.get_libs_dir(arch.arch), 'libpython2.7.so')):
            shprint(sh.cp, join(self.get_build_dir(arch.arch), 'libpython2.7.so'), self.ctx.get_libs_dir(arch.arch))


        # # if exists(join(self.get_build_dir(arch.arch), 'libpython2.7.so')):
        # if exists(join(self.ctx.libs_dir, 'libpython2.7.so')):
        #     info('libpython2.7.so already exists, skipping python build.')
        #     if not exists(join(self.ctx.get_python_install_dir(), 'libpython2.7.so')):
        #         info('Copying python-install to dist-dependent location')
        #         shprint(sh.cp, '-a', 'python-install', self.ctx.get_python_install_dir())
        #     self.ctx.hostpython = join(self.ctx.get_python_install_dir(), 'bin', 'python.host')

        #     return

    def do_python_build(self, arch):
        if 'sqlite' in self.ctx.recipe_build_order:
            print('sqlite support not yet enabled in python recipe')
            exit(1)

        hostpython_recipe = Recipe.get_recipe('hostpython2', self.ctx)
        shprint(sh.cp, self.ctx.hostpython, self.get_build_dir(arch.arch))
        shprint(sh.cp, self.ctx.hostpgen, self.get_build_dir(arch.arch))
        hostpython = join(self.get_build_dir(arch.arch), 'hostpython')
        hostpgen = join(self.get_build_dir(arch.arch), 'hostpython')

        with current_directory(self.get_build_dir(arch.arch)):


            hostpython_recipe = Recipe.get_recipe('hostpython2', self.ctx)
            shprint(sh.cp, join(hostpython_recipe.get_recipe_dir(), 'Setup'), 'Modules')

            env = arch.get_env()

            # AND: Should probably move these to get_recipe_env for
            # neatness, but the whole recipe needs tidying along these
            # lines
            env['HOSTARCH'] = 'arm-eabi'
            env['BUILDARCH'] = shprint(sh.gcc, '-dumpmachine').stdout.decode('utf-8').split('\n')[0]
            env['CFLAGS'] = ' '.join([env['CFLAGS'], '-DNO_MALLINFO'])

            # TODO need to add a should_build that checks if optional
            # dependencies have changed (possibly in a generic way)
            if 'openssl' in self.ctx.recipe_build_order:
                openssl_build_dir = Recipe.get_recipe('openssl', self.ctx).get_build_dir(arch.arch)
                setuplocal = join('Modules', 'Setup.local')
                shprint(sh.cp, join(self.get_recipe_dir(), 'Setup.local-ssl'), setuplocal)
                shprint(sh.sed, '-i', 's#^SSL=.*#SSL={}#'.format(openssl_build_dir), setuplocal)

            configure = sh.Command('./configure')
            # AND: OFLAG isn't actually set, should it be?
            shprint(configure,
                    '--host={}'.format(env['HOSTARCH']),
                    '--build={}'.format(env['BUILDARCH']),
                    # 'OPT={}'.format(env['OFLAG']),
                    '--prefix={}'.format(realpath('./python-install')),
                    '--enable-shared',
                    '--disable-toolbox-glue',
                    '--disable-framework',
                    _env=env)

            # AND: tito left this comment in the original source. It's still true!
            # FIXME, the first time, we got a error at:
            # python$EXE ../../Tools/scripts/h2py.py -i '(u_long)' /usr/include/netinet/in.h
        # /home/tito/code/python-for-android/build/python/Python-2.7.2/python: 1: Syntax error: word unexpected (expecting ")")
            # because at this time, python is arm, not x86. even that, why /usr/include/netinet/in.h is used ?
            # check if we can avoid this part.

            make = sh.Command(env['MAKE'].split(' ')[0])
            print('First install (expected to fail...')
            try:
                shprint(make, '-j5', 'install', 'HOSTPYTHON={}'.format(hostpython),
                        'HOSTPGEN={}'.format(hostpgen),
                        'CROSS_COMPILE_TARGET=yes',
                        'INSTSONAME=libpython2.7.so',
                        _env=env)
            except sh.ErrorReturnCode_2:
                print('First python2 make failed. This is expected, trying again.')


            print('Second install (expected to work)')
            shprint(sh.touch, 'python.exe', 'python')
            shprint(make, '-j5', 'install', 'HOSTPYTHON={}'.format(hostpython),
                    'HOSTPGEN={}'.format(hostpgen),
                    'CROSS_COMPILE_TARGET=yes',
                    'INSTSONAME=libpython2.7.so',
                    _env=env)

            if is_darwin():
                shprint(sh.cp, join(self.get_recipe_dir(), 'patches', '_scproxy.py'),
                        join('python-install', 'Lib'))
                shprint(sh.cp, join(self.get_recipe_dir(), 'patches', '_scproxy.py'),
                        join('python-install', 'lib', 'python2.7'))

            # reduce python
            for dir_name in ('test', join('json', 'tests'), 'lib-tk',
                             join('sqlite3', 'test'), join('unittest, test'),
                             join('lib2to3', 'tests'), join('bsddb', 'tests'),
                             join('distutils', 'tests'), join('email', 'test'),
                             'curses'):
                shprint(sh.rm, '-rf', join('python-install',
                                           'lib', 'python2.7', dir_name))
Ejemplo n.º 2
0
class Python2Recipe(TargetPythonRecipe):
    version = "2.7.2"
    url = 'https://python.org/ftp/python/{version}/Python-{version}.tar.bz2'
    name = 'python2'

    depends = ['hostpython2']
    conflicts = ['python3crystax', 'python3']
    opt_depends = ['openssl', 'sqlite3']

    patches = [
        'patches/Python-{version}-xcompile.patch',
        'patches/Python-{version}-ctypes-disable-wchar.patch',
        'patches/disable-modules.patch', 'patches/fix-locale.patch',
        'patches/fix-gethostbyaddr.patch', 'patches/fix-setup-flags.patch',
        'patches/fix-filesystemdefaultencoding.patch',
        'patches/fix-termios.patch', 'patches/custom-loader.patch',
        'patches/verbose-compilation.patch',
        'patches/fix-remove-corefoundation.patch',
        'patches/fix-dynamic-lookup.patch', 'patches/fix-dlfcn.patch',
        'patches/parsetuple.patch',
        'patches/ctypes-find-library-updated.patch',
        ('patches/fix-configure-darwin.patch', is_darwin),
        ('patches/fix-distutils-darwin.patch', is_darwin),
        ('patches/fix-ftime-removal.patch', is_api_gt(19)),
        ('patches/disable-openpty.patch',
         check_all(is_api_lt(21), is_ndk('crystax')))
    ]

    from_crystax = False

    def build_arch(self, arch):

        if not exists(join(self.get_build_dir(arch.arch), 'libpython2.7.so')):
            self.do_python_build(arch)

        if not exists(self.ctx.get_python_install_dir()):
            shprint(sh.cp, '-a',
                    join(self.get_build_dir(arch.arch), 'python-install'),
                    self.ctx.get_python_install_dir())

        # This should be safe to run every time
        info('Copying hostpython binary to targetpython folder')
        shprint(sh.cp, self.ctx.hostpython,
                join(self.ctx.get_python_install_dir(), 'bin', 'python.host'))
        self.ctx.hostpython = join(self.ctx.get_python_install_dir(), 'bin',
                                   'python.host')

        if not exists(join(self.ctx.get_libs_dir(arch.arch),
                           'libpython2.7.so')):
            shprint(sh.cp,
                    join(self.get_build_dir(arch.arch), 'libpython2.7.so'),
                    self.ctx.get_libs_dir(arch.arch))

        # # if exists(join(self.get_build_dir(arch.arch), 'libpython2.7.so')):
        # if exists(join(self.ctx.libs_dir, 'libpython2.7.so')):
        #     info('libpython2.7.so already exists, skipping python build.')
        #     if not exists(join(self.ctx.get_python_install_dir(), 'libpython2.7.so')):
        #         info('Copying python-install to dist-dependent location')
        #         shprint(sh.cp, '-a', 'python-install', self.ctx.get_python_install_dir())
        #     self.ctx.hostpython = join(self.ctx.get_python_install_dir(), 'bin', 'python.host')

        #     return

    def do_python_build(self, arch):

        hostpython_recipe = Recipe.get_recipe('hostpython2', self.ctx)
        shprint(sh.cp, self.ctx.hostpython, self.get_build_dir(arch.arch))
        shprint(sh.cp, self.ctx.hostpgen, self.get_build_dir(arch.arch))
        hostpython = join(self.get_build_dir(arch.arch), 'hostpython')
        hostpgen = join(self.get_build_dir(arch.arch), 'hostpython')

        with current_directory(self.get_build_dir(arch.arch)):

            hostpython_recipe = Recipe.get_recipe('hostpython2', self.ctx)
            shprint(sh.cp, join(hostpython_recipe.get_recipe_dir(), 'Setup'),
                    'Modules')

            env = arch.get_env()

            env['HOSTARCH'] = 'arm-eabi'
            env['BUILDARCH'] = shprint(
                sh.gcc, '-dumpmachine').stdout.decode('utf-8').split('\n')[0]
            env['CFLAGS'] = ' '.join([env['CFLAGS'], '-DNO_MALLINFO'])

            # TODO need to add a should_build that checks if optional
            # dependencies have changed (possibly in a generic way)
            if 'openssl' in self.ctx.recipe_build_order:
                recipe = Recipe.get_recipe('openssl', self.ctx)
                openssl_build_dir = recipe.get_build_dir(arch.arch)
                setuplocal = join('Modules', 'Setup.local')
                shprint(sh.cp, join(self.get_recipe_dir(), 'Setup.local-ssl'),
                        setuplocal)
                shprint(sh.sed, '-i.backup',
                        's#^SSL=.*#SSL={}#'.format(openssl_build_dir),
                        setuplocal)
                env['OPENSSL_VERSION'] = recipe.version

            if 'sqlite3' in self.ctx.recipe_build_order:
                # Include sqlite3 in python2 build
                recipe = Recipe.get_recipe('sqlite3', self.ctx)
                include = ' -I' + recipe.get_build_dir(arch.arch)
                lib = ' -L' + recipe.get_lib_dir(arch) + ' -lsqlite3'
                # Insert or append to env
                flag = 'CPPFLAGS'
                env[flag] = env[flag] + include if flag in env else include
                flag = 'LDFLAGS'
                env[flag] = env[flag] + lib if flag in env else lib

            # NDK has langinfo.h but doesn't define nl_langinfo()
            env['ac_cv_header_langinfo_h'] = 'no'
            configure = sh.Command('./configure')
            shprint(
                configure,
                '--host={}'.format(env['HOSTARCH']),
                '--build={}'.format(env['BUILDARCH']),
                # 'OPT={}'.format(env['OFLAG']),
                '--prefix={}'.format(realpath('./python-install')),
                '--enable-shared',
                '--disable-toolbox-glue',
                '--disable-framework',
                _env=env)

            # tito left this comment in the original source. It's still true!
            # FIXME, the first time, we got a error at:
            # python$EXE ../../Tools/scripts/h2py.py -i '(u_long)' /usr/include/netinet/in.h
            # /home/tito/code/python-for-android/build/python/Python-2.7.2/python: 1: Syntax error: word unexpected (expecting ")")
            # because at this time, python is arm, not x86. even that, why /usr/include/netinet/in.h is used ?
            # check if we can avoid this part.

            make = sh.Command(env['MAKE'].split(' ')[0])
            print('First install (expected to fail...')
            try:
                shprint(make,
                        '-j5',
                        'install',
                        'HOSTPYTHON={}'.format(hostpython),
                        'HOSTPGEN={}'.format(hostpgen),
                        'CROSS_COMPILE_TARGET=yes',
                        'INSTSONAME=libpython2.7.so',
                        _env=env)
            except sh.ErrorReturnCode_2:
                print(
                    'First python2 make failed. This is expected, trying again.'
                )

            print('Second install (expected to work)')
            shprint(sh.touch, 'python.exe', 'python')
            shprint(make,
                    '-j5',
                    'install',
                    'HOSTPYTHON={}'.format(hostpython),
                    'HOSTPGEN={}'.format(hostpgen),
                    'CROSS_COMPILE_TARGET=yes',
                    'INSTSONAME=libpython2.7.so',
                    _env=env)

            if is_darwin():
                shprint(sh.cp,
                        join(self.get_recipe_dir(), 'patches', '_scproxy.py'),
                        join('python-install', 'Lib'))
                shprint(sh.cp,
                        join(self.get_recipe_dir(), 'patches', '_scproxy.py'),
                        join('python-install', 'lib', 'python2.7'))

            # reduce python
            for dir_name in ('test', join('json', 'tests'), 'lib-tk',
                             join('sqlite3', 'test'), join('unittest, test'),
                             join('lib2to3', 'tests'), join('bsddb', 'tests'),
                             join('distutils',
                                  'tests'), join('email', 'test'), 'curses'):
                shprint(sh.rm, '-rf',
                        join('python-install', 'lib', 'python2.7', dir_name))

            # info('Copying python-install to dist-dependent location')
            # shprint(sh.cp, '-a', 'python-install', self.ctx.get_python_install_dir())

            # print('Copying hostpython binary to targetpython folder')
            # shprint(sh.cp, self.ctx.hostpython,
            #         join(self.ctx.get_python_install_dir(), 'bin', 'python.host'))
            # self.ctx.hostpython = join(self.ctx.get_python_install_dir(), 'bin', 'python.host')

        # print('python2 build done, exiting for debug')
        # exit(1)

    def create_python_bundle(self, dirn, arch):
        info("Filling private directory")
        if not exists(join(dirn, "lib")):
            info("lib dir does not exist, making")
            shprint(sh.cp, "-a", join("python-install", "lib"), dirn)
        shprint(sh.mkdir, "-p", join(dirn, "include", "python2.7"))

        libpymodules_fn = join("libs", arch.arch, "libpymodules.so")
        if exists(libpymodules_fn):
            shprint(sh.mv, libpymodules_fn, dirn)
        shprint(sh.cp,
                join('python-install', 'include', 'python2.7', 'pyconfig.h'),
                join(dirn, 'include', 'python2.7/'))

        info('Removing some unwanted files')
        shprint(sh.rm, '-f', join(dirn, 'lib', 'libpython2.7.so'))
        shprint(sh.rm, '-rf', join(dirn, 'lib', 'pkgconfig'))

        libdir = join(dirn, 'lib', 'python2.7')
        site_packages_dir = join(libdir, 'site-packages')
        with current_directory(libdir):
            removes = []
            for dirname, root, filenames in walk("."):
                for filename in filenames:
                    for suffix in EXCLUDE_EXTS:
                        if filename.endswith(suffix):
                            removes.append(filename)
            shprint(sh.rm, '-f', *removes)

            info('Deleting some other stuff not used on android')
            # To quote the original distribute.sh, 'well...'
            shprint(sh.rm, '-rf', 'lib2to3')
            shprint(sh.rm, '-rf', 'idlelib')
            shprint(sh.rm, '-f', *glob.glob('config/libpython*.a'))
            shprint(sh.rm, '-rf', 'config/python.o')

        return site_packages_dir

    def include_root(self, arch_name):
        return join(self.get_build_dir(arch_name), 'python-install', 'include',
                    'python2.7')

    def link_root(self, arch_name):
        return join(self.get_build_dir(arch_name), 'python-install', 'lib')