def get_bootstrap_from_recipes(cls, recipes, ctx):
     '''Returns a bootstrap whose recipe requirements do not conflict with
     the given recipes.'''
     info('Trying to find a bootstrap that matches the given recipes.')
     bootstraps = [
         cls.get_bootstrap(name, ctx) for name in cls.list_bootstraps()
     ]
     acceptable_bootstraps = []
     for bs in bootstraps:
         ok = True
         if not bs.can_be_chosen_automatically:
             ok = False
         for recipe in bs.recipe_depends:
             recipe = Recipe.get_recipe(recipe, ctx)
             if any([conflict in recipes for conflict in recipe.conflicts]):
                 ok = False
                 break
         for recipe in recipes:
             recipe = Recipe.get_recipe(recipe, ctx)
             if any([
                     conflict in bs.recipe_depends
                     for conflict in recipe.conflicts
             ]):
                 ok = False
                 break
         if ok:
             acceptable_bootstraps.append(bs)
     info('Found {} acceptable bootstraps: {}'.format(
         len(acceptable_bootstraps),
         [bs.name for bs in acceptable_bootstraps]))
     if acceptable_bootstraps:
         info('Using the first of these: {}'.format(
             acceptable_bootstraps[0].name))
         return acceptable_bootstraps[0]
     return None
    def set_libs_flags(self, env, arch):
        '''Takes care to properly link libraries with python depending on our
        requirements and the attribute :attr:`opt_depends`.
        '''
        def add_flags(include_flags, link_dirs, link_libs):
            env['CPPFLAGS'] = env.get('CPPFLAGS', '') + include_flags
            env['LDFLAGS'] = env.get('LDFLAGS', '') + link_dirs
            env['LIBS'] = env.get('LIBS', '') + link_libs

        if 'sqlite3' in self.ctx.recipe_build_order:
            info('Activating flags for sqlite3')
            recipe = Recipe.get_recipe('sqlite3', self.ctx)
            add_flags(' -I' + recipe.get_build_dir(arch.arch),
                      ' -L' + recipe.get_lib_dir(arch), ' -lsqlite3')

        if 'libffi' in self.ctx.recipe_build_order:
            info('Activating flags for libffi')
            recipe = Recipe.get_recipe('libffi', self.ctx)
            # In order to force the correct linkage for our libffi library, we
            # set the following variable to point where is our libffi.pc file,
            # because the python build system uses pkg-config to configure it.
            env['PKG_CONFIG_PATH'] = recipe.get_build_dir(arch.arch)
            add_flags(' -I' + ' -I'.join(recipe.get_include_dirs(arch)),
                      ' -L' + join(recipe.get_build_dir(arch.arch), '.libs'),
                      ' -lffi')

        if 'openssl' in self.ctx.recipe_build_order:
            info('Activating flags for openssl')
            recipe = Recipe.get_recipe('openssl', self.ctx)
            add_flags(recipe.include_flags(arch),
                      recipe.link_dirs_flags(arch), recipe.link_libs_flags())
        return env
    def set_libs_flags(self, env, arch):
        '''Takes care to properly link libraries with python depending on our
        requirements and the attribute :attr:`opt_depends`.
        '''
        def add_flags(include_flags, link_dirs, link_libs):
            env['CPPFLAGS'] = env.get('CPPFLAGS', '') + include_flags
            env['LDFLAGS'] = env.get('LDFLAGS', '') + link_dirs
            env['LIBS'] = env.get('LIBS', '') + link_libs

        if 'sqlite3' in self.ctx.recipe_build_order:
            info('Activating flags for sqlite3')
            recipe = Recipe.get_recipe('sqlite3', self.ctx)
            add_flags(' -I' + recipe.get_build_dir(arch.arch),
                      ' -L' + recipe.get_lib_dir(arch), ' -lsqlite3')

        if 'libffi' in self.ctx.recipe_build_order:
            info('Activating flags for libffi')
            recipe = Recipe.get_recipe('libffi', self.ctx)
            # In order to force the correct linkage for our libffi library, we
            # set the following variable to point where is our libffi.pc file,
            # because the python build system uses pkg-config to configure it.
            env['PKG_CONFIG_PATH'] = recipe.get_build_dir(arch.arch)
            add_flags(' -I' + ' -I'.join(recipe.get_include_dirs(arch)),
                      ' -L' + join(recipe.get_build_dir(arch.arch), '.libs'),
                      ' -lffi')

        if 'openssl' in self.ctx.recipe_build_order:
            info('Activating flags for openssl')
            recipe = Recipe.get_recipe('openssl', self.ctx)
            add_flags(recipe.include_flags(arch), recipe.link_dirs_flags(arch),
                      recipe.link_libs_flags())
        return env
Exemple #4
0
    def set_libs_flags(self, env, arch):
        '''Takes care to properly link libraries with python depending on our
        requirements and the attribute :attr:`opt_depends`.
        '''
        def add_flags(include_flags, link_dirs, link_libs):
            env['CPPFLAGS'] = env.get('CPPFLAGS', '') + include_flags
            env['LDFLAGS'] = env.get('LDFLAGS', '') + link_dirs
            env['LIBS'] = env.get('LIBS', '') + link_libs

        if 'sqlite3' in self.ctx.recipe_build_order:
            info('Activating flags for sqlite3')
            recipe = Recipe.get_recipe('sqlite3', self.ctx)
            add_flags(' -I' + recipe.get_build_dir(arch.arch),
                      ' -L' + recipe.get_lib_dir(arch), ' -lsqlite3')

        if 'libffi' in self.ctx.recipe_build_order:
            info('Activating flags for libffi')
            recipe = Recipe.get_recipe('libffi', self.ctx)
            add_flags(
                ' -I' + ' -I'.join(recipe.get_include_dirs(arch)),
                ' -L' + join(recipe.get_build_dir(arch.arch),
                             recipe.get_host(arch), '.libs'), ' -lffi')

        if 'openssl' in self.ctx.recipe_build_order:
            info('Activating flags for openssl')
            recipe = Recipe.get_recipe('openssl', self.ctx)
            add_flags(recipe.include_flags(arch), recipe.link_dirs_flags(arch),
                      recipe.link_libs_flags())
        return env
Exemple #5
0
    def set_libs_flags(self, env, arch):
        '''Takes care to properly link libraries with python depending on our
        requirements and the attribute :attr:`opt_depends`.
        '''
        if 'libffi' in self.ctx.recipe_build_order:
            info('Activating flags for libffi')
            recipe = Recipe.get_recipe('libffi', self.ctx)
            include = ' -I' + ' -I'.join(recipe.get_include_dirs(arch))
            ldflag = ' -L' + join(recipe.get_build_dir(arch.arch),
                                  recipe.get_host(arch), '.libs') + ' -lffi'
            env['CPPFLAGS'] = env.get('CPPFLAGS', '') + include
            env['LDFLAGS'] = env.get('LDFLAGS', '') + ldflag

        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
            
        return env
Exemple #6
0
def main():
    target_python = TargetPython.python3
    recipes = modified_recipes()
    logger.info('recipes modified: {}'.format(recipes))
    recipes -= CORE_RECIPES
    logger.info('recipes to build: {}'.format(recipes))
    context = Context()

    # removing the deleted recipes for the given target (if any)
    for recipe_name in recipes.copy():
        try:
            Recipe.get_recipe(recipe_name, context)
        except ValueError:
            # recipe doesn't exist, so probably we remove it
            recipes.remove(recipe_name)
            logger.warning(
                'removed {} from recipes because deleted'.format(recipe_name))

    # forces the default target
    recipes_and_target = recipes | set([target_python.name])
    try:
        build_order, python_modules, bs = get_recipe_order_and_bootstrap(
            context, recipes_and_target, None)
    except BuildInterruptingException:
        # fallback to python2 if default target is not compatible
        logger.info('incompatible with {}'.format(target_python.name))
        target_python = TargetPython.python2
        logger.info('falling back to {}'.format(target_python.name))
    # removing the known broken recipe for the given target
    broken_recipes = BROKEN_RECIPES[target_python]
    recipes -= broken_recipes
    logger.info('recipes to build (no broken): {}'.format(recipes))
    build(target_python, recipes)
Exemple #7
0
    def set_libs_flags(self, env, arch):
        '''Takes care to properly link libraries with python depending on our
        requirements and the attribute :attr:`opt_depends`.
        '''
        if 'libffi' in self.ctx.recipe_build_order:
            info('Activating flags for libffi')
            recipe = Recipe.get_recipe('libffi', self.ctx)
            include = ' -I' + ' -I'.join(recipe.get_include_dirs(arch))
            ldflag = ' -L' + join(recipe.get_build_dir(arch.arch),
                                  recipe.get_host(arch), '.libs') + ' -lffi'
            env['CPPFLAGS'] = env.get('CPPFLAGS', '') + include
            env['LDFLAGS'] = env.get('LDFLAGS', '') + ldflag

        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

        return env
 def get_bootstrap_from_recipes(cls, recipes, ctx):
     '''Returns a bootstrap whose recipe requirements do not conflict with
     the given recipes.'''
     info('Trying to find a bootstrap that matches the given recipes.')
     bootstraps = [cls.get_bootstrap(name, ctx)
                   for name in cls.list_bootstraps()]
     acceptable_bootstraps = []
     for bs in bootstraps:
         if not bs.can_be_chosen_automatically:
             continue
         possible_dependency_lists = expand_dependencies(bs.recipe_depends)
         for possible_dependencies in possible_dependency_lists:
             ok = True
             for recipe in possible_dependencies:
                 recipe = Recipe.get_recipe(recipe, ctx)
                 if any([conflict in recipes for conflict in recipe.conflicts]):
                     ok = False
                     break
             for recipe in recipes:
                 recipe = Recipe.get_recipe(recipe, ctx)
                 if any([conflict in possible_dependencies
                         for conflict in recipe.conflicts]):
                     ok = False
                     break
             if ok:
                 acceptable_bootstraps.append(bs)
     info('Found {} acceptable bootstraps: {}'.format(
         len(acceptable_bootstraps),
         [bs.name for bs in acceptable_bootstraps]))
     if acceptable_bootstraps:
         info('Using the first of these: {}'
              .format(acceptable_bootstraps[0].name))
         return acceptable_bootstraps[0]
     return None
Exemple #9
0
    def set_libs_flags(self, env, arch):
        '''Takes care to properly link libraries with python depending on our
        requirements and the attribute :attr:`opt_depends`.
        '''
        def add_flags(include_flags, link_dirs, link_libs):
            env['CPPFLAGS'] = env.get('CPPFLAGS', '') + include_flags
            env['LDFLAGS'] = env.get('LDFLAGS', '') + link_dirs
            env['LIBS'] = env.get('LIBS', '') + link_libs

        if 'sqlite3' in self.ctx.recipe_build_order:
            info('Activating flags for sqlite3')
            recipe = Recipe.get_recipe('sqlite3', self.ctx)
            add_flags(' -I' + recipe.get_build_dir(arch.arch),
                      ' -L' + recipe.get_lib_dir(arch), ' -lsqlite3')

        if 'libffi' in self.ctx.recipe_build_order:
            info('Activating flags for libffi')
            recipe = Recipe.get_recipe('libffi', self.ctx)
            # In order to force the correct linkage for our libffi library, we
            # set the following variable to point where is our libffi.pc file,
            # because the python build system uses pkg-config to configure it.
            env['PKG_CONFIG_PATH'] = recipe.get_build_dir(arch.arch)
            add_flags(' -I' + ' -I'.join(recipe.get_include_dirs(arch)),
                      ' -L' + join(recipe.get_build_dir(arch.arch), '.libs'),
                      ' -lffi')

        if 'openssl' in self.ctx.recipe_build_order:
            info('Activating flags for openssl')
            recipe = Recipe.get_recipe('openssl', self.ctx)
            add_flags(recipe.include_flags(arch),
                      recipe.link_dirs_flags(arch), recipe.link_libs_flags())

        # python build system contains hardcoded zlib version which prevents
        # the build of zlib module, here we search for android's zlib version
        # and sets the right flags, so python can be build with android's zlib
        info("Activating flags for android's zlib")
        zlib_lib_path = join(self.ctx.ndk_platform, 'usr', 'lib')
        zlib_includes = join(self.ctx.ndk_dir, 'sysroot', 'usr', 'include')
        zlib_h = join(zlib_includes, 'zlib.h')
        try:
            with open(zlib_h) as fileh:
                zlib_data = fileh.read()
        except IOError:
            raise BuildInterruptingException(
                "Could not determine android's zlib version, no zlib.h ({}) in"
                " the NDK dir includes".format(zlib_h)
            )
        for line in zlib_data.split('\n'):
            if line.startswith('#define ZLIB_VERSION '):
                break
        else:
            raise BuildInterruptingException(
                'Could not parse zlib.h...so we cannot find zlib version,'
                'required by python build,'
            )
        env['ZLIB_VERSION'] = line.replace('#define ZLIB_VERSION ', '')
        add_flags(' -I' + zlib_includes, ' -L' + zlib_lib_path, ' -lz')

        return env
Exemple #10
0
    def test_built_libraries(self):
        """The openssl recipe is a library recipe, so it should have set the
        attribute `built_libraries`, but not the case of `pyopenssl` recipe.
        """
        recipe = Recipe.get_recipe('openssl', self.ctx)
        self.assertTrue(recipe.built_libraries)

        recipe = Recipe.get_recipe('pyopenssl', self.ctx)
        self.assertFalse(recipe.built_libraries)
 def test_get_recipe(self):
     """
     Makes sure `get_recipe()` returns a `Recipe` object when possible.
     """
     ctx = Context()
     recipe_name = 'python3'
     recipe = Recipe.get_recipe(recipe_name, ctx)
     self.assertTrue(isinstance(recipe, Recipe))
     self.assertEqual(recipe.name, recipe_name)
     recipe_name = 'does_not_exist'
     with self.assertRaises(ValueError) as e:
         Recipe.get_recipe(recipe_name, ctx)
     self.assertEqual(
         e.exception.args[0], 'Recipe does not exist: {}'.format(recipe_name))
Exemple #12
0
 def test_get_recipe(self):
     """
     Makes sure `get_recipe()` returns a `Recipe` object when possible.
     """
     ctx = Context()
     recipe_name = 'python3'
     recipe = Recipe.get_recipe(recipe_name, ctx)
     self.assertTrue(isinstance(recipe, Recipe))
     self.assertEqual(recipe.name, recipe_name)
     recipe_name = 'does_not_exist'
     with self.assertRaises(ValueError) as e:
         Recipe.get_recipe(recipe_name, ctx)
     self.assertEqual(e.exception.args[0],
                      'Recipe does not exist: {}'.format(recipe_name))
Exemple #13
0
 def recipes(self, args):
     ctx = self.ctx
     if args.compact:
         print(" ".join(set(Recipe.list_recipes(ctx))))
     else:
         for name in sorted(Recipe.list_recipes(ctx)):
             try:
                 recipe = Recipe.get_recipe(name, ctx)
             except IOError:
                 warning('Recipe "{}" could not be loaded'.format(name))
             except SyntaxError:
                 import traceback
                 traceback.print_exc()
                 warning(('Recipe "{}" could not be loaded due to a '
                          'syntax error').format(name))
             version = str(recipe.version)
             print('{Fore.BLUE}{Style.BRIGHT}{recipe.name:<12} '
                   '{Style.RESET_ALL}{Fore.LIGHTBLUE_EX}'
                   '{version:<8}{Style.RESET_ALL}'.format(
                     recipe=recipe, Fore=Out_Fore, Style=Out_Style,
                     version=version))
             print('    {Fore.GREEN}depends: {recipe.depends}'
                   '{Fore.RESET}'.format(recipe=recipe, Fore=Out_Fore))
             if recipe.conflicts:
                 print('    {Fore.RED}conflicts: {recipe.conflicts}'
                       '{Fore.RESET}'
                       .format(recipe=recipe, Fore=Out_Fore))
             if recipe.opt_depends:
                 print('    {Fore.YELLOW}optional depends: '
                       '{recipe.opt_depends}{Fore.RESET}'
                       .format(recipe=recipe, Fore=Out_Fore))
Exemple #14
0
    def build_cython_components(self, arch):
        libzmq_recipe = Recipe.get_recipe('libzmq', self.ctx)
        libzmq_prefix = join(libzmq_recipe.get_build_dir(arch.arch), "install")
        self.setup_extra_args = ["--zmq={}".format(libzmq_prefix)]
        self.build_cmd = "configure"

        env = self.get_recipe_env(arch)
        setup_cfg = join(self.get_build_dir(arch.arch), "setup.cfg")
        with open(setup_cfg, "wb") as fd:
            fd.write("""
[global]
zmq_prefix = {}
skip_check_zmq = True
""".format(libzmq_prefix).encode())

        return super(PyZMQRecipe, self).build_cython_components(arch)

        with current_directory(self.get_build_dir(arch.arch)):
            hostpython = sh.Command(self.hostpython_location)
            shprint(hostpython, 'setup.py', 'configure', '-v', _env=env)
            shprint(hostpython, 'setup.py', 'build_ext', '-v', _env=env)
            build_dir = glob.glob('build/lib.*')[0]
            shprint(sh.find,
                    build_dir,
                    '-name',
                    '"*.o"',
                    '-exec',
                    env['STRIP'],
                    '{}',
                    ';',
                    _env=env)
def build_recipes(build_order, python_modules, ctx):
    # Put recipes in correct build order
    bs = ctx.bootstrap
    info_notify("Recipe build order is {}".format(build_order))
    if python_modules:
        python_modules = sorted(set(python_modules))
        info_notify(
            ('The requirements ({}) were not found as recipes, they will be '
             'installed with pip.').format(', '.join(python_modules)))

    recipes = [Recipe.get_recipe(name, ctx) for name in build_order]

    # download is arch independent
    info_main('# Downloading recipes ')
    for recipe in recipes:
        recipe.download_if_necessary()

    for arch in ctx.archs:
        info_main('# Building all recipes for arch {}'.format(arch.arch))

        info_main('# Unpacking recipes')
        for recipe in recipes:
            ensure_dir(recipe.get_build_container_dir(arch.arch))
            recipe.prepare_build_dir(arch.arch)

        info_main('# Prebuilding recipes')
        # 2) prebuild packages
        for recipe in recipes:
            info_main('Prebuilding {} for {}'.format(recipe.name, arch.arch))
            recipe.prebuild_arch(arch)
            recipe.apply_patches(arch)

        # 3) build packages
        info_main('# Building recipes')
        for recipe in recipes:
            info_main('Building {} for {}'.format(recipe.name, arch.arch))
            if recipe.should_build(arch):
                recipe.build_arch(arch)
            else:
                info('{} said it is already built, skipping'
                     .format(recipe.name))

        # 4) biglink everything
        # AND: Should make this optional
        info_main('# Biglinking object files')
        if not ctx.python_recipe or not ctx.python_recipe.from_crystax:
            biglink(ctx, arch)
        else:
            info('NDK is crystax, skipping biglink (will this work?)')

        # 5) postbuild packages
        info_main('# Postbuilding recipes')
        for recipe in recipes:
            info_main('Postbuilding {} for {}'.format(recipe.name, arch.arch))
            recipe.postbuild_arch(arch)

    info_main('# Installing pure Python modules')
    run_pymodules_install(ctx, python_modules)

    return
Exemple #16
0
    def has_package(self, name, arch=None):
        # If this is a file path, it'll need special handling:
        if (name.find("/") >= 0 or name.find("\\") >= 0) and \
                name.find("://") < 0:  # (:// would indicate an url)
            if not os.path.exists(name):
                # Non-existing dir, cannot look this up.
                return False
            try:
                name = get_package_name(os.path.abspath(name))
            except ValueError:
                # Failed to look up any meaningful name.
                return False

        # Try to look up recipe by name:
        try:
            recipe = Recipe.get_recipe(name, self)
        except ValueError:
            pass
        else:
            name = getattr(recipe, 'site_packages_name', None) or name
        name = name.replace('.', '/')
        site_packages_dir = self.get_site_packages_dir(arch)
        return (exists(join(site_packages_dir, name))
                or exists(join(site_packages_dir, name + '.py'))
                or exists(join(site_packages_dir, name + '.pyc'))
                or exists(join(site_packages_dir, name + '.pyo'))
                or exists(join(site_packages_dir, name + '.so'))
                or glob.glob(join(site_packages_dir, name + '-*.egg')))
Exemple #17
0
    def has_package(self, name, arch=None):
        # If this is a file path, it'll need special handling:
        if (name.find("/") >= 0 or name.find("\\") >= 0) and \
                name.find("://") < 0:  # (:// would indicate an url)
            if not os.path.exists(name):
                # Non-existing dir, cannot look this up.
                return False
            try:
                name = get_package_name(os.path.abspath(name))
            except ValueError:
                # Failed to look up any meaningful name.
                return False

        # Try to look up recipe by name:
        try:
            recipe = Recipe.get_recipe(name, self)
        except ValueError:
            pass
        else:
            name = getattr(recipe, 'site_packages_name', None) or name
        name = name.replace('.', '/')
        site_packages_dir = self.get_site_packages_dir(arch)
        return (exists(join(site_packages_dir, name)) or
                exists(join(site_packages_dir, name + '.py')) or
                exists(join(site_packages_dir, name + '.pyc')) or
                exists(join(site_packages_dir, name + '.pyo')) or
                exists(join(site_packages_dir, name + '.so')) or
                glob.glob(join(site_packages_dir, name + '-*.egg')))
Exemple #18
0
    def get_recipe_env(self, arch):
        env = super().get_recipe_env(arch)

        GCC_VER = '4.9'
        HOST = 'linux-x86_64'
        LIB = 'lib64' if '64' in arch.arch else 'lib'

        prefix = env['TOOLCHAIN_PREFIX']
        lapack_dir = join(
            Recipe.get_recipe('lapack', self.ctx).get_build_dir(arch.arch),
            'build', 'install')
        sysroot = f"{self.ctx.ndk_dir}/platforms/{env['NDK_API']}/{arch.platform_dir}"
        sysroot_include = f'{self.ctx.ndk_dir}/toolchains/llvm/prebuilt/{HOST}/sysroot/usr/include'
        libgfortran = f'{self.ctx.ndk_dir}/toolchains/{prefix}-{GCC_VER}/prebuilt/{HOST}/{prefix}/{LIB}'
        numpylib = self.ctx.get_python_install_dir() + '/numpy/core/lib'
        LDSHARED_opts = env['LDSHARED'].split('clang')[1]

        env['LAPACK'] = f'{lapack_dir}/lib'
        env['BLAS'] = env['LAPACK']
        env['F90'] = f'{prefix}-gfortran'
        env['CXX'] += f' -Wl,-l{self.stl_lib_name} -Wl,-L{self.get_stl_lib_dir(arch)}'
        env['CPPFLAGS'] += f' --sysroot={sysroot} -I{sysroot_include}/c++/v1 -I{sysroot_include}'
        env['LDSHARED'] = 'clang'
        env['LDFLAGS'] += f' {LDSHARED_opts} --sysroot={sysroot} -L{libgfortran} -L{numpylib}'
        env['LDFLAGS'] += f' -L{self.ctx.ndk_dir}/sources/cxx-stl/llvm-libc++/libs/{arch.arch}/'

        return env
Exemple #19
0
    def build_arch(self, arch):
        super(LibxsltRecipe, self).build_arch(arch)
        env = self.get_recipe_env(arch)
        build_dir = self.get_build_dir(arch.arch)
        with current_directory(build_dir):
            # If the build is done with /bin/sh things blow up,
            # try really hard to use bash
            libxml2_recipe = Recipe.get_recipe('libxml2', self.ctx)
            libxml2_build_dir = libxml2_recipe.get_build_dir(arch.arch)
            build_arch = shprint(sh.gcc, '-dumpmachine').stdout.decode(
                'utf-8').split('\n')[0]

            if not exists('configure'):
                shprint(sh.Command('./autogen.sh'), _env=env)
            shprint(sh.Command('autoreconf'), '-vif', _env=env)
            shprint(sh.Command('./configure'),
                    '--build=' + build_arch,
                    '--host=' + arch.command_prefix,
                    '--target=' + arch.command_prefix,
                    '--without-plugins',
                    '--without-debug',
                    '--without-python',
                    '--without-crypto',
                    '--with-libxml-src=' + libxml2_build_dir,
                    '--disable-shared',
                    _env=env)
            shprint(sh.make, "V=1", _env=env)

            shutil.copyfile('libxslt/.libs/libxslt.a',
                            join(self.ctx.libs_dir, 'libxslt.a'))
            shutil.copyfile('libexslt/.libs/libexslt.a',
                            join(self.ctx.libs_dir, 'libexslt.a'))
    def test_install_stl_lib(
        self, mock_ensure_dir, mock_isfile, mock_install_lib
    ):
        """
        Test that :meth:`~pythonforandroid.recipe.STLRecipe.install_stl_lib`,
        calls the method :meth:`~pythonforandroid.recipe.Recipe.install_libs`
        with the proper arguments: a subclass of
        :class:`~pythonforandroid.archs.Arch` and our stl lib
        (:attr:`~pythonforandroid.recipe.STLRecipe.stl_lib_name`)
        """
        mock_isfile.return_value = False

        arch = ArchAarch_64(self.ctx)
        recipe = Recipe.get_recipe('icu', self.ctx)
        recipe.ctx = self.ctx
        assert recipe.need_stl_shared, True
        recipe.install_stl_lib(arch)
        mock_install_lib.assert_called_once_with(
            arch,
            '{ndk_dir}/sources/cxx-stl/llvm-libc++/'
            'libs/{arch}/lib{stl_lib}.so'.format(
                ndk_dir=self.ctx.ndk_dir,
                arch=arch.arch,
                stl_lib=recipe.stl_lib_name,
            ),
        )
        mock_ensure_dir.assert_called()
Exemple #21
0
    def recipes(self, args):
        parser = argparse.ArgumentParser(
                description="List all the available recipes")
        parser.add_argument(
                "--compact", action="store_true", default=False,
                help="Produce a compact list suitable for scripting")

        args = parser.parse_args(args)

        ctx = self.ctx
        if args.compact:
            print(" ".join(set(Recipe.list_recipes(ctx))))
        else:
            for name in sorted(Recipe.list_recipes(ctx)):
                recipe = Recipe.get_recipe(name, ctx)
                version = str(recipe.version)
                print('{Fore.BLUE}{Style.BRIGHT}{recipe.name:<12} '
                      '{Style.RESET_ALL}{Fore.LIGHTBLUE_EX}'
                      '{version:<8}{Style.RESET_ALL}'.format(
                        recipe=recipe, Fore=Out_Fore, Style=Out_Style,
                        version=version))
                print('    {Fore.GREEN}depends: {recipe.depends}'
                      '{Fore.RESET}'.format(recipe=recipe, Fore=Out_Fore))
                if recipe.conflicts:
                    print('    {Fore.RED}conflicts: {recipe.conflicts}'
                          '{Fore.RESET}'
                          .format(recipe=recipe, Fore=Out_Fore))
                if recipe.opt_depends:
                    print('    {Fore.YELLOW}optional depends: '
                          '{recipe.opt_depends}{Fore.RESET}'
                          .format(recipe=recipe, Fore=Out_Fore))
Exemple #22
0
 def set_libs_flags(self, env, arch):
     env = super(Python3Recipe, self).set_libs_flags(env, arch)
     if 'openssl' in self.ctx.recipe_build_order:
         recipe = Recipe.get_recipe('openssl', self.ctx)
         self.configure_args += \
             ('--with-openssl=' + recipe.get_build_dir(arch.arch),)
     return env
Exemple #23
0
 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
    def test_bootstrap_strip(
        self,
        mock_find_executable,
        mock_ensure_dir,
        mock_sh_command,
        mock_sh_print,
    ):
        mock_find_executable.return_value = "arm-linux-androideabi-gcc"
        # prepare arch, bootstrap, distribution and PythonRecipe
        arch = ArchARMv7_a(self.ctx)
        bs = Bootstrap().get_bootstrap(self.bootstrap_name, self.ctx)
        self.setUp_distribution_with_bootstrap(bs)
        self.ctx.python_recipe = Recipe.get_recipe("python3", self.ctx)

        # test that strip_libraries runs with a fake distribution
        bs.strip_libraries(arch)

        mock_find_executable.assert_called_once()
        self.assertEqual(
            mock_find_executable.call_args[0][0],
            mock_find_executable.return_value,
        )
        mock_sh_command.assert_called_once_with("arm-linux-androideabi-strip")
        # check that the other mocks we made are actually called
        mock_ensure_dir.assert_called()
        mock_sh_print.assert_called()
Exemple #25
0
    def build_arch(self, arch):
        env = self.get_recipe_env(arch)
        build_dir = self.get_build_dir(arch.arch)
        with current_directory(build_dir):
            # If the build is done with /bin/sh things blow up,
            # try really hard to use bash
            libxml2_recipe = Recipe.get_recipe('libxml2', self.ctx)
            libxml2_build_dir = libxml2_recipe.get_build_dir(arch.arch)
            build_arch = shprint(sh.gcc, '-dumpmachine').stdout.decode(
                'utf-8').split('\n')[0]

            if not exists('configure'):
                shprint(sh.Command('./autogen.sh'), _env=env)
            shprint(sh.Command('autoreconf'), '-vif', _env=env)
            shprint(sh.Command('./configure'),
                    '--build=' + build_arch,
                    '--host=' + arch.command_prefix,
                    '--target=' + arch.command_prefix,
                    '--without-plugins',
                    '--without-debug',
                    '--without-python',
                    '--without-crypto',
                    '--with-libxml-src=' + libxml2_build_dir,
                    '--disable-shared',
                    _env=env)
            shprint(sh.make, "V=1", _env=env)
 def recipes(self, args):
     ctx = self.ctx
     if args.compact:
         print(" ".join(set(Recipe.list_recipes(ctx))))
     else:
         for name in sorted(Recipe.list_recipes(ctx)):
             try:
                 recipe = Recipe.get_recipe(name, ctx)
             except IOError:
                 warning('Recipe "{}" could not be loaded'.format(name))
             except SyntaxError:
                 import traceback
                 traceback.print_exc()
                 warning(('Recipe "{}" could not be loaded due to a '
                          'syntax error').format(name))
             version = str(recipe.version)
             print('{Fore.BLUE}{Style.BRIGHT}{recipe.name:<12} '
                   '{Style.RESET_ALL}{Fore.LIGHTBLUE_EX}'
                   '{version:<8}{Style.RESET_ALL}'.format(
                     recipe=recipe, Fore=Out_Fore, Style=Out_Style,
                     version=version))
             print('    {Fore.GREEN}depends: {recipe.depends}'
                   '{Fore.RESET}'.format(recipe=recipe, Fore=Out_Fore))
             if recipe.conflicts:
                 print('    {Fore.RED}conflicts: {recipe.conflicts}'
                       '{Fore.RESET}'
                       .format(recipe=recipe, Fore=Out_Fore))
             if recipe.opt_depends:
                 print('    {Fore.YELLOW}optional depends: '
                       '{recipe.opt_depends}{Fore.RESET}'
                       .format(recipe=recipe, Fore=Out_Fore))
Exemple #27
0
    def test_bootstrap_strip(
        self,
        mock_find_executable,
        mock_glob,
        mock_ensure_dir,
        mock_sh_command,
        mock_sh_print,
    ):
        mock_find_executable.return_value = os.path.join(
            self.ctx._ndk_dir,
            f"toolchains/llvm/prebuilt/{system().lower()}-x86_64/bin/clang",
        )
        mock_glob.return_value = [
            os.path.join(self.ctx._ndk_dir, "toolchains", "llvm")
        ]
        # prepare arch, bootstrap, distribution and PythonRecipe
        arch = ArchARMv7_a(self.ctx)
        bs = Bootstrap().get_bootstrap(self.bootstrap_name, self.ctx)
        self.setUp_distribution_with_bootstrap(bs)
        self.ctx.python_recipe = Recipe.get_recipe("python3", self.ctx)

        # test that strip_libraries runs with a fake distribution
        bs.strip_libraries(arch)

        mock_find_executable.assert_called_once()
        self.assertEqual(
            mock_find_executable.call_args[0][0],
            mock_find_executable.return_value,
        )
        mock_sh_command.assert_called_once_with("arm-linux-androideabi-strip")
        # check that the other mocks we made are actually called
        mock_ensure_dir.assert_called()
        mock_sh_print.assert_called()
def build_recipes(build_order, python_modules, ctx):
    # Put recipes in correct build order
    bs = ctx.bootstrap
    info_notify("Recipe build order is {}".format(build_order))
    if python_modules:
        python_modules = sorted(set(python_modules))
        info_notify(
            ('The requirements ({}) were not found as recipes, they will be '
             'installed with pip.').format(', '.join(python_modules)))

    recipes = [Recipe.get_recipe(name, ctx) for name in build_order]

    # download is arch independent
    info_main('# Downloading recipes ')
    for recipe in recipes:
        recipe.download_if_necessary()

    for arch in ctx.archs:
        info_main('# Building all recipes for arch {}'.format(arch.arch))

        info_main('# Unpacking recipes')
        for recipe in recipes:
            ensure_dir(recipe.get_build_container_dir(arch.arch))
            recipe.prepare_build_dir(arch.arch)

        info_main('# Prebuilding recipes')
        # 2) prebuild packages
        for recipe in recipes:
            info_main('Prebuilding {} for {}'.format(recipe.name, arch.arch))
            recipe.prebuild_arch(arch)
            recipe.apply_patches(arch)

        # 3) build packages
        info_main('# Building recipes')
        for recipe in recipes:
            info_main('Building {} for {}'.format(recipe.name, arch.arch))
            if recipe.should_build(arch):
                recipe.build_arch(arch)
            else:
                info('{} said it is already built, skipping'.format(
                    recipe.name))

        # 4) biglink everything
        # AND: Should make this optional
        info_main('# Biglinking object files')
        if not ctx.python_recipe or not ctx.python_recipe.from_crystax:
            biglink(ctx, arch)
        else:
            info('NDK is crystax, skipping biglink (will this work?)')

        # 5) postbuild packages
        info_main('# Postbuilding recipes')
        for recipe in recipes:
            info_main('Postbuilding {} for {}'.format(recipe.name, arch.arch))
            recipe.postbuild_arch(arch)

    info_main('# Installing pure Python modules')
    run_pymodules_install(ctx, python_modules)

    return
    def recipes(self, args):
        parser = argparse.ArgumentParser(
            description="List all the available recipes")
        parser.add_argument(
            "--compact",
            action="store_true",
            default=False,
            help="Produce a compact list suitable for scripting")

        args = parser.parse_args(args)

        ctx = self.ctx
        if args.compact:
            print(" ".join(set(Recipe.list_recipes(ctx))))
        else:
            for name in sorted(Recipe.list_recipes(ctx)):
                recipe = Recipe.get_recipe(name, ctx)
                version = str(recipe.version)
                print('{Fore.BLUE}{Style.BRIGHT}{recipe.name:<12} '
                      '{Style.RESET_ALL}{Fore.LIGHTBLUE_EX}'
                      '{version:<8}{Style.RESET_ALL}'.format(recipe=recipe,
                                                             Fore=Out_Fore,
                                                             Style=Out_Style,
                                                             version=version))
                print('    {Fore.GREEN}depends: {recipe.depends}'
                      '{Fore.RESET}'.format(recipe=recipe, Fore=Out_Fore))
                if recipe.conflicts:
                    print('    {Fore.RED}conflicts: {recipe.conflicts}'
                          '{Fore.RESET}'.format(recipe=recipe, Fore=Out_Fore))
                if recipe.opt_depends:
                    print('    {Fore.YELLOW}optional depends: '
                          '{recipe.opt_depends}{Fore.RESET}'.format(
                              recipe=recipe, Fore=Out_Fore))
    def get_usable_bootstraps_for_recipes(cls, recipes, ctx):
        '''Returns all bootstrap whose recipe requirements do not conflict
        with the given recipes, in no particular order.'''
        info('Trying to find a bootstrap that matches the given recipes.')
        bootstraps = [
            cls.get_bootstrap(name, ctx) for name in cls.all_bootstraps()
        ]
        acceptable_bootstraps = set()

        # Find out which bootstraps are acceptable:
        for bs in bootstraps:
            if not bs.can_be_chosen_automatically:
                continue
            possible_dependency_lists = expand_dependencies(
                bs.recipe_depends, ctx)
            for possible_dependencies in possible_dependency_lists:
                ok = True
                # Check if the bootstap's dependencies have an internal conflict:
                for recipe in possible_dependencies:
                    recipe = Recipe.get_recipe(recipe, ctx)
                    if any(
                        [conflict in recipes
                         for conflict in recipe.conflicts]):
                        ok = False
                        break
                # Check if bootstrap's dependencies conflict with chosen
                # packages:
                for recipe in recipes:
                    try:
                        recipe = Recipe.get_recipe(recipe, ctx)
                    except ValueError:
                        conflicts = []
                    else:
                        conflicts = recipe.conflicts
                    if any([
                            conflict in possible_dependencies
                            for conflict in conflicts
                    ]):
                        ok = False
                        break
                if ok and bs not in acceptable_bootstraps:
                    acceptable_bootstraps.add(bs)

        info('Found {} acceptable bootstraps: {}'.format(
            len(acceptable_bootstraps),
            [bs.name for bs in acceptable_bootstraps]))
        return acceptable_bootstraps
Exemple #31
0
 def set_libs_flags(self, env, arch):
     env = super(Python2Recipe, self).set_libs_flags(env, arch)
     if 'openssl' in self.ctx.recipe_build_order:
         recipe = Recipe.get_recipe('openssl', self.ctx)
         openssl_build = recipe.get_build_dir(arch.arch)
         env['OPENSSL_BUILD'] = openssl_build
         env['OPENSSL_VERSION'] = recipe.version
     return env
Exemple #32
0
    def test_should_build(self, mock_exists):
        arch = ArchAarch_64(self.ctx)
        recipe = Recipe.get_recipe('openssl', self.ctx)
        recipe.ctx = self.ctx
        self.assertFalse(recipe.should_build(arch))

        mock_exists.return_value = False
        self.assertTrue(recipe.should_build(arch))
Exemple #33
0
    def get_env(self):
        env = {}

        env["CFLAGS"] = " ".join([
            "-DANDROID", "-mandroid", "-fomit-frame-pointer",
            "--sysroot", self.ctx.ndk_platform])

        env["CXXFLAGS"] = env["CFLAGS"]

        env["LDFLAGS"] = " ".join(['-lm'])

        py_platform = sys.platform
        if py_platform in ['linux2', 'linux3']:
            py_platform = 'linux'

        toolchain_prefix = self.ctx.toolchain_prefix
        toolchain_version = self.ctx.toolchain_version
        command_prefix = self.command_prefix

        env['TOOLCHAIN_PREFIX'] = toolchain_prefix
        env['TOOLCHAIN_VERSION'] = toolchain_version

        print('path is', environ['PATH'])
        cc = find_executable('{command_prefix}-gcc'.format(
            command_prefix=command_prefix), path=environ['PATH'])
        if cc is None:
            warning('Couldn\'t find executable for CC. This indicates a '
                    'problem locating the {} executable in the Android '
                    'NDK, not that you don\'t have a normal compiler '
                    'installed. Exiting.')
            exit(1)

        env['CC'] = '{command_prefix}-gcc {cflags}'.format(
            command_prefix=command_prefix,
            cflags=env['CFLAGS'])
        env['CXX'] = '{command_prefix}-g++ {cxxflags}'.format(
            command_prefix=command_prefix,
            cxxflags=env['CXXFLAGS'])

        env['AR'] = '{}-ar'.format(command_prefix)
        env['RANLIB'] = '{}-ranlib'.format(command_prefix)
        env['LD'] = '{}-ld'.format(command_prefix)
        env['STRIP'] = '{}-strip --strip-unneeded'.format(command_prefix)
        env['MAKE'] = 'make -j5'
        env['READELF'] = '{}-readelf'.format(command_prefix)

        hostpython_recipe = Recipe.get_recipe('hostpython2', self.ctx)

        # AND: This hardcodes python version 2.7, needs fixing
        env['BUILDLIB_PATH'] = join(
            hostpython_recipe.get_build_dir(self.arch),
            'build', 'lib.linux-{}-2.7'.format(uname()[-1]))

        env['PATH'] = environ['PATH']

        env['ARCH'] = self.arch

        return env
Exemple #34
0
    def get_env(self):
        env = {}

        env["CFLAGS"] = " ".join([
            "-DANDROID", "-mandroid", "-fomit-frame-pointer", "--sysroot",
            self.ctx.ndk_platform
        ])

        env["CXXFLAGS"] = env["CFLAGS"]

        env["LDFLAGS"] = " ".join(['-lm'])

        py_platform = sys.platform
        if py_platform in ['linux2', 'linux3']:
            py_platform = 'linux'

        toolchain_prefix = self.ctx.toolchain_prefix
        toolchain_version = self.ctx.toolchain_version
        command_prefix = self.command_prefix

        env['TOOLCHAIN_PREFIX'] = toolchain_prefix
        env['TOOLCHAIN_VERSION'] = toolchain_version

        print('path is', environ['PATH'])
        cc = find_executable(
            '{command_prefix}-gcc'.format(command_prefix=command_prefix),
            path=environ['PATH'])
        if cc is None:
            warning('Couldn\'t find executable for CC. This indicates a '
                    'problem locating the {} executable in the Android '
                    'NDK, not that you don\'t have a normal compiler '
                    'installed. Exiting.')
            exit(1)

        env['CC'] = '{command_prefix}-gcc {cflags}'.format(
            command_prefix=command_prefix, cflags=env['CFLAGS'])
        env['CXX'] = '{command_prefix}-g++ {cxxflags}'.format(
            command_prefix=command_prefix, cxxflags=env['CXXFLAGS'])

        env['AR'] = '{}-ar'.format(command_prefix)
        env['RANLIB'] = '{}-ranlib'.format(command_prefix)
        env['LD'] = '{}-ld'.format(command_prefix)
        env['STRIP'] = '{}-strip --strip-unneeded'.format(command_prefix)
        env['MAKE'] = 'make -j5'
        env['READELF'] = '{}-readelf'.format(command_prefix)

        hostpython_recipe = Recipe.get_recipe('hostpython2', self.ctx)

        # AND: This hardcodes python version 2.7, needs fixing
        env['BUILDLIB_PATH'] = join(hostpython_recipe.get_build_dir(self.arch),
                                    'build',
                                    'lib.linux-{}-2.7'.format(uname()[-1]))

        env['PATH'] = environ['PATH']

        env['ARCH'] = self.arch

        return env
 def setUp(self):
     """
     Setups recipe and context.
     """
     self.context = Context()
     self.context.ndk_api = 21
     self.context.android_api = 27
     self.arch = ArchARMv7_a(self.context)
     self.recipe = Recipe.get_recipe('gevent', self.context)
Exemple #36
0
    def get_recipe_env(self, arch):
        env = super(CryptographyRecipe, self).get_recipe_env(arch)

        openssl_recipe = Recipe.get_recipe('openssl', self.ctx)
        env['CFLAGS'] += openssl_recipe.include_flags(arch)
        env['LDFLAGS'] += openssl_recipe.link_dirs_flags(arch)
        env['LIBS'] = openssl_recipe.link_libs_flags()

        return env
Exemple #37
0
    def get_recipe_env(self, arch):
        env = super().get_recipe_env(arch)

        openssl_recipe = Recipe.get_recipe('openssl', self.ctx)
        env['CFLAGS'] += openssl_recipe.include_flags(arch)
        env['LDFLAGS'] += openssl_recipe.link_dirs_flags(arch)
        env['LIBS'] = openssl_recipe.link_libs_flags()

        return env
Exemple #38
0
def recursively_collect_orders(name, ctx, all_inputs, orders=[]):
    '''For each possible recipe ordering, try to add the new recipe name
    to that order. Recursively do the same thing with all the
    dependencies of each recipe.

    '''
    try:
        recipe = Recipe.get_recipe(name, ctx)
        if recipe.depends is None:
            dependencies = []
        else:
            # make all dependencies into lists so that product will work
            dependencies = [
                ([dependency] if not isinstance(dependency,
                                                (list, tuple)) else dependency)
                for dependency in recipe.depends
            ]

        # handle opt_depends: these impose requirements on the build
        # order only if already present in the list of recipes to build
        dependencies.extend(
            [[d] for d in recipe.get_opt_depends_in_list(all_inputs)])

        if recipe.conflicts is None:
            conflicts = []
        else:
            conflicts = recipe.conflicts
    except IOError:
        # The recipe does not exist, so we assume it can be installed
        # via pip with no extra dependencies
        dependencies = []
        conflicts = []

    new_orders = []
    # for each existing recipe order, see if we can add the new recipe name
    for order in orders:
        if name in order:
            new_orders.append(deepcopy(order))
            continue
        if order.conflicts(name):
            continue
        if any([conflict in order for conflict in conflicts]):
            continue

        for dependency_set in product(*dependencies):
            new_order = deepcopy(order)
            new_order[name] = set(dependency_set)

            dependency_new_orders = [new_order]
            for dependency in dependency_set:
                dependency_new_orders = recursively_collect_orders(
                    dependency, ctx, all_inputs, dependency_new_orders)

            new_orders.extend(dependency_new_orders)

    return new_orders
 def setUp(self):
     """
     Initialize a Context with a Bootstrap and a Distribution to properly
     test a recipe which depends on android's STL library, to do so we reuse
     `BaseClassSetupBootstrap`
     """
     super().setUp()
     self.ctx.bootstrap = Bootstrap().get_bootstrap('sdl2', self.ctx)
     self.setUp_distribution_with_bootstrap(self.ctx.bootstrap)
     self.ctx.python_recipe = Recipe.get_recipe('python3', self.ctx)
Exemple #40
0
    def conflicts(self, name):
        for name in self.keys():
            try:
                recipe = Recipe.get_recipe(name, self.ctx)
                conflicts = recipe.conflicts
            except IOError:
                conflicts = []

            if any([c in self for c in conflicts]):
                return True
        return False
Exemple #41
0
    def conflicts(self):
        for name in self.keys():
            try:
                recipe = Recipe.get_recipe(name, self.ctx)
                conflicts = [dep.lower() for dep in recipe.conflicts]
            except ValueError:
                conflicts = []

            if any([c in self for c in conflicts]):
                return True
        return False
Exemple #42
0
    def conflicts(self):
        for name in self.keys():
            try:
                recipe = Recipe.get_recipe(name, self.ctx)
                conflicts = [dep.lower() for dep in recipe.conflicts]
            except ValueError:
                conflicts = []

            if any([c in self for c in conflicts]):
                return True
        return False
Exemple #43
0
    def conflicts(self, name):
        for name in self.keys():
            try:
                recipe = Recipe.get_recipe(name, self.ctx)
                conflicts = recipe.conflicts
            except IOError:
                conflicts = []

            if any([c in self for c in conflicts]):
                return True
        return False
 def get_recipe_env(self, arch=None):
     env = super(PyCryptoRecipe, self).get_recipe_env(arch)
     openssl_build_dir = Recipe.get_recipe('openssl', self.ctx).get_build_dir(arch.arch)
     env['CC'] = '%s -I%s' % (env['CC'], join(openssl_build_dir, 'include'))
     env['LDFLAGS'] = env['LDFLAGS'] + ' -L{}'.format(
         self.ctx.get_libs_dir(arch.arch) +
         '-L{}'.format(self.ctx.libs_dir)) + ' -L{}'.format(
         openssl_build_dir)
     env['EXTRA_CFLAGS'] = '--host linux-armv'
     env['ac_cv_func_malloc_0_nonnull'] = 'yes'
     return env
    def clean_recipe_build(self, args):
        '''Deletes the build files of the given recipe.

        This is intended for debug purposes, you may experience
        strange behaviour or problems with some recipes (if their
        build has done unexpected state changes). If this happens, run
        clean_builds, or attempt to clean other recipes until things
        work again.
        '''
        recipe = Recipe.get_recipe(args.recipe, self.ctx)
        info('Cleaning build for {} recipe.'.format(recipe.name))
        recipe.clean_build()
Exemple #46
0
def recursively_collect_orders(name, ctx, all_inputs, orders=[]):
    '''For each possible recipe ordering, try to add the new recipe name
    to that order. Recursively do the same thing with all the
    dependencies of each recipe.

    '''
    try:
        recipe = Recipe.get_recipe(name, ctx)
        if recipe.depends is None:
            dependencies = []
        else:
            # make all dependencies into lists so that product will work
            dependencies = [([dependency] if not isinstance(
                dependency, (list, tuple))
                            else dependency) for dependency in recipe.depends]

        # handle opt_depends: these impose requirements on the build
        # order only if already present in the list of recipes to build
        dependencies.extend([[d] for d in recipe.get_opt_depends_in_list(all_inputs)])

        if recipe.conflicts is None:
            conflicts = []
        else:
            conflicts = recipe.conflicts
    except IOError:
        # The recipe does not exist, so we assume it can be installed
        # via pip with no extra dependencies
        dependencies = []
        conflicts = []

    new_orders = []
    # for each existing recipe order, see if we can add the new recipe name
    for order in orders:
        if name in order:
            new_orders.append(deepcopy(order))
            continue
        if order.conflicts(name):
            continue
        if any([conflict in order for conflict in conflicts]):
            continue

        for dependency_set in product(*dependencies):
            new_order = deepcopy(order)
            new_order[name] = set(dependency_set)

            dependency_new_orders = [new_order]
            for dependency in dependency_set:
                dependency_new_orders = recursively_collect_orders(
                    dependency, ctx, all_inputs, dependency_new_orders)

            new_orders.extend(dependency_new_orders)

    return new_orders
Exemple #47
0
    def get_recipe_env(self, arch=None, clang=True):
        env = super(PyCryptoRecipe, self).get_recipe_env(arch)
        openssl_recipe = Recipe.get_recipe('openssl', self.ctx)
        env['CC'] = env['CC'] + openssl_recipe.include_flags(arch)

        env['LDFLAGS'] += ' -L{}'.format(self.ctx.get_libs_dir(arch.arch))
        env['LDFLAGS'] += ' -L{}'.format(self.ctx.libs_dir)
        env['LDFLAGS'] += openssl_recipe.link_dirs_flags(arch)
        env['LIBS'] = env.get('LIBS', '') + openssl_recipe.link_libs_flags()

        env['EXTRA_CFLAGS'] = '--host linux-armv'
        env['ac_cv_func_malloc_0_nonnull'] = 'yes'
        return env
Exemple #48
0
    def set_libs_flags(self, env, arch):
        env = super(Python2Recipe, self).set_libs_flags(env, arch)
        if 'libffi' in self.ctx.recipe_build_order:
            # For python2 we need to tell configure that we want to use our
            # compiled libffi, this step is not necessary for python3.
            self.configure_args += ('--with-system-ffi',)

        if 'openssl' in self.ctx.recipe_build_order:
            recipe = Recipe.get_recipe('openssl', self.ctx)
            openssl_build = recipe.get_build_dir(arch.arch)
            env['OPENSSL_BUILD'] = openssl_build
            env['OPENSSL_VERSION'] = recipe.version
        return env
 def set_libs_flags(self, env, arch):
     '''Takes care to properly link libraries with python depending on our
     requirements and the attribute :attr:`opt_depends`.
     '''
     if 'libffi' in self.ctx.recipe_build_order:
         info('Activating flags for libffi')
         recipe = Recipe.get_recipe('libffi', self.ctx)
         include = ' -I' + ' -I'.join(recipe.get_include_dirs(arch))
         ldflag = ' -L' + join(recipe.get_build_dir(arch.arch),
                               recipe.get_host(arch), '.libs') + ' -lffi'
         env['CPPFLAGS'] = env.get('CPPFLAGS', '') + include
         env['LDFLAGS'] = env.get('LDFLAGS', '') + ldflag
     return env
Exemple #50
0
 def has_package(self, name, arch=None):
     try:
         recipe = Recipe.get_recipe(name, self)
     except IOError:
         pass
     else:
         name = getattr(recipe, 'site_packages_name', None) or name
     name = name.replace('.', '/')
     site_packages_dir = self.get_site_packages_dir(arch)
     return (exists(join(site_packages_dir, name)) or
             exists(join(site_packages_dir, name + '.py')) or
             exists(join(site_packages_dir, name + '.pyc')) or
             exists(join(site_packages_dir, name + '.pyo')) or
             exists(join(site_packages_dir, name + '.so')))
 def remove_remaining_conflicts(self, ctx):
     # It's unpleasant to have to pass ctx as an argument...
     '''Checks all possible graphs for conflicts that have arisen during
     the additon of alternative repice branches, as these are not checked
     for conflicts at the time.'''
     new_graphs = []
     for i, graph in enumerate(self.graphs):
         for name in graph.keys():
             recipe = Recipe.get_recipe(name, ctx)
             if any([c in graph for c in recipe.conflicts]):
                 break
         else:
             new_graphs.append(graph)
     self.graphs = new_graphs
    def clean_recipe_build(self, args):
        '''Deletes the build files of the given recipe.

        This is intended for debug purposes, you may experience
        strange behaviour or problems with some recipes (if their
        build has done unexpected state changes). If this happens, run
        clean_builds, or attempt to clean other recipes until things
        work again.
        '''
        parser = argparse.ArgumentParser(
            description="Delete all build files for the given recipe name.")
        parser.add_argument('recipe', help='The recipe name')
        args = parser.parse_args(args)

        recipe = Recipe.get_recipe(args.recipe, self.ctx)
        info('Cleaning build for {} recipe.'.format(recipe.name))
        recipe.clean_build()
 def setUp(self):
     """
     Setups recipe and context.
     """
     self.context = Context()
     self.arch = ArchARMv7_a(self.context)
     self.recipe = Recipe.get_recipe('reportlab', self.context)
     self.recipe.ctx = self.context
     self.bootstrap = None
     recipe_build_order, python_modules, bootstrap = \
         get_recipe_order_and_bootstrap(
             self.context, [self.recipe.name], self.bootstrap)
     self.context.recipe_build_order = recipe_build_order
     self.context.python_modules = python_modules
     self.context.setup_dirs(tempfile.gettempdir())
     self.bootstrap = bootstrap
     self.recipe_dir = self.recipe.get_build_dir(self.arch.arch)
     ensure_dir(self.recipe_dir)
Exemple #54
0
def biglink(ctx, arch):
    # First, collate object files from each recipe
    info('Collating object files from each recipe')
    obj_dir = join(ctx.bootstrap.build_dir, 'collated_objects')
    ensure_dir(obj_dir)
    recipes = [Recipe.get_recipe(name, ctx) for name in ctx.recipe_build_order]
    for recipe in recipes:
        recipe_obj_dir = join(recipe.get_build_container_dir(arch.arch),
                              'objects_{}'.format(recipe.name))
        if not exists(recipe_obj_dir):
            info('{} recipe has no biglinkable files dir, skipping'
                 .format(recipe.name))
            continue
        files = glob.glob(join(recipe_obj_dir, '*'))
        if not len(files):
            info('{} recipe has no biglinkable files, skipping'
                 .format(recipe.name))
            continue
        info('{} recipe has object files, copying'.format(recipe.name))
        files.append(obj_dir)
        shprint(sh.cp, '-r', *files)

    env = arch.get_env()
    env['LDFLAGS'] = env['LDFLAGS'] + ' -L{}'.format(
        join(ctx.bootstrap.build_dir, 'obj', 'local', arch.arch))

    if not len(glob.glob(join(obj_dir, '*'))):
        info('There seem to be no libraries to biglink, skipping.')
        return
    info('Biglinking')
    info('target {}'.format(join(ctx.get_libs_dir(arch.arch),
                                 'libpymodules.so')))
    do_biglink = copylibs_function if ctx.copy_libs else biglink_function

    # Move to the directory containing crtstart_so.o and crtend_so.o
    # This is necessary with newer NDKs? A gcc bug?
    with current_directory(join(ctx.ndk_platform, 'usr', 'lib')):
        do_biglink(
            join(ctx.get_libs_dir(arch.arch), 'libpymodules.so'),
            obj_dir.split(' '),
            extra_link_dirs=[join(ctx.bootstrap.build_dir,
                                  'obj', 'local', arch.arch),
                             os.path.abspath('.')],
            env=env)
Exemple #55
0
    def get_recipe_env(self, arch):
        env = super(LibxsltRecipe, self).get_recipe_env(arch)
        env['CONFIG_SHELL'] = '/bin/bash'
        env['SHELL'] = '/bin/bash'

        libxml2_recipe = Recipe.get_recipe('libxml2', self.ctx)
        libxml2_build_dir = libxml2_recipe.get_build_dir(arch.arch)
        libxml2_libs_dir = join(libxml2_build_dir, '.libs')

        env['CFLAGS'] = ' '.join([
            env['CFLAGS'],
            '-I' + libxml2_build_dir,
            '-I' + join(libxml2_build_dir, 'include', 'libxml'),
            '-I' + self.get_build_dir(arch.arch),
        ])
        env['LDFLAGS'] += ' -L' + libxml2_libs_dir
        env['LIBS'] = '-lxml2 -lz -lm'

        return env
Exemple #56
0
    def has_package(self, name, arch=None):
        # If this is a file path, it'll need special handling:
        if (name.find("/") >= 0 or name.find("\\") >= 0) and \
                name.find("://") < 0:  # (:// would indicate an url)
            if not os.path.exists(name):
                # Non-existing dir, cannot look this up.
                return False
            if os.path.exists(os.path.join(name, "setup.py")):
                # Get name from setup.py:
                name = subprocess.check_output([
                    sys.executable, "setup.py", "--name"],
                    cwd=name)
                try:
                    name = name.decode('utf-8', 'replace')
                except AttributeError:
                    pass
                name = name.strip()
                if len(name) == 0:
                    # Failed to look up any meaningful name.
                    return False
            else:
                # A folder with whatever, cannot look this up.
                return False

        # Try to look up recipe by name:
        try:
            recipe = Recipe.get_recipe(name, self)
        except IOError:
            pass
        else:
            name = getattr(recipe, 'site_packages_name', None) or name
        name = name.replace('.', '/')
        site_packages_dir = self.get_site_packages_dir(arch)
        return (exists(join(site_packages_dir, name)) or
                exists(join(site_packages_dir, name + '.py')) or
                exists(join(site_packages_dir, name + '.pyc')) or
                exists(join(site_packages_dir, name + '.pyo')) or
                exists(join(site_packages_dir, name + '.so')) or
                glob.glob(join(site_packages_dir, name + '-*.egg')))
 def recipes(self, args):
     ctx = self.ctx
     if args.compact:
         print(" ".join(set(Recipe.list_recipes(ctx))))
     else:
         for name in sorted(Recipe.list_recipes(ctx)):
             recipe = Recipe.get_recipe(name, ctx)
             version = str(recipe.version)
             print('{Fore.BLUE}{Style.BRIGHT}{recipe.name:<12} '
                   '{Style.RESET_ALL}{Fore.LIGHTBLUE_EX}'
                   '{version:<8}{Style.RESET_ALL}'.format(
                     recipe=recipe, Fore=Out_Fore, Style=Out_Style,
                     version=version))
             print('    {Fore.GREEN}depends: {recipe.depends}'
                   '{Fore.RESET}'.format(recipe=recipe, Fore=Out_Fore))
             if recipe.conflicts:
                 print('    {Fore.RED}conflicts: {recipe.conflicts}'
                       '{Fore.RESET}'
                       .format(recipe=recipe, Fore=Out_Fore))
             if recipe.opt_depends:
                 print('    {Fore.YELLOW}optional depends: '
                       '{recipe.opt_depends}{Fore.RESET}'
                       .format(recipe=recipe, Fore=Out_Fore))
Exemple #58
0
def biglink(ctx, arch):
    # First, collate object files from each recipe
    info('Collating object files from each recipe')
    obj_dir = join(ctx.bootstrap.build_dir, 'collated_objects')
    ensure_dir(obj_dir)
    recipes = [Recipe.get_recipe(name, ctx) for name in ctx.recipe_build_order]
    for recipe in recipes:
        recipe_obj_dir = join(recipe.get_build_container_dir(arch.arch),
                              'objects_{}'.format(recipe.name))
        if not exists(recipe_obj_dir):
            info('{} recipe has no biglinkable files dir, skipping'
                 .format(recipe.name))
            continue
        files = glob.glob(join(recipe_obj_dir, '*'))
        if not len(files):
            info('{} recipe has no biglinkable files, skipping'
                 .format(recipe.name))
        info('{} recipe has object files, copying'.format(recipe.name))
        files.append(obj_dir)
        shprint(sh.cp, '-r', *files)

    env = arch.get_env()
    env['LDFLAGS'] = env['LDFLAGS'] + ' -L{}'.format(
        join(ctx.bootstrap.build_dir, 'obj', 'local', arch.arch))

    if not len(glob.glob(join(obj_dir, '*'))):
        info('There seem to be no libraries to biglink, skipping.')
        return
    info('Biglinking')
    info('target {}'.format(join(ctx.get_libs_dir(arch.arch),
                                 'libpymodules.so')))
    biglink_function(
        join(ctx.get_libs_dir(arch.arch), 'libpymodules.so'),
        obj_dir.split(' '),
        extra_link_dirs=[join(ctx.bootstrap.build_dir,
                              'obj', 'local', arch.arch)],
        env=env)