Example #1
0
    def __init__(self):
        super(Context, self).__init__()
        self.include_dirs = []

        self._build_env_prepared = False

        self._sdk_dir = None
        self._ndk_dir = None
        self._android_api = None
        self._ndk_api = None
        self.ndk = None

        self.toolchain_prefix = None
        self.toolchain_version = None

        self.local_recipes = None
        self.copy_libs = False

        # this list should contain all Archs, it is pruned later
        self.archs = (
            ArchARM(self),
            ArchARMv7_a(self),
            Archx86(self),
            Archx86_64(self),
            ArchAarch_64(self),
        )

        self.root_dir = realpath(dirname(__file__))

        # remove the most obvious flags that can break the compilation
        self.env.pop("LDFLAGS", None)
        self.env.pop("ARCHFLAGS", None)
        self.env.pop("CFLAGS", None)

        self.python_recipe = None  # Set by TargetPythonRecipe
    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()
Example #3
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()
Example #4
0
    def __init__(self):
        super(Context, self).__init__()
        self.include_dirs = []

        self._build_env_prepared = False

        self._sdk_dir = None
        self._ndk_dir = None
        self._android_api = None
        self._ndk_ver = None

        self.toolchain_prefix = None
        self.toolchain_version = None

        self.local_recipes = None

        # root of the toolchain
        self.setup_dirs()

        # this list should contain all Archs, it is pruned later
        self.archs = (ArchARM(self), ArchARMv7_a(self), Archx86(self))

        ensure_dir(join(self.build_dir, 'bootstrap_builds'))
        ensure_dir(join(self.build_dir, 'other_builds'))
        # other_builds: where everything else is built

        # remove the most obvious flags that can break the compilation
        self.env.pop("LDFLAGS", None)
        self.env.pop("ARCHFLAGS", None)
        self.env.pop("CFLAGS", None)
Example #5
0
    def test_arch_armv7a(self, mock_ensure_dir, mock_find_executable,
                         mock_glob):
        """
        Test that class :class:`~pythonforandroid.archs.ArchARMv7_a` returns
        some expected attributes and environment variables.

        .. note::
            Here we mock the same functions than
            :meth:`TestArchARM.test_arch_arm` plus `glob`, so we make sure that
            the glob result is the expected even if the folder doesn't exist,
            which is probably the case. This has to be done because here we
            tests the `get_env` with clang

        """
        mock_find_executable.return_value = self.expected_compiler
        mock_ensure_dir.return_value = True
        mock_glob.return_value = ["llvm"]

        arch = ArchARMv7_a(self.ctx)
        self.assertEqual(arch.arch, "armeabi-v7a")
        self.assertEqual(arch.__str__(), "armeabi-v7a")
        self.assertEqual(arch.toolchain_prefix, "arm-linux-androideabi")
        self.assertEqual(arch.command_prefix, "arm-linux-androideabi")
        self.assertEqual(arch.target, "armv7a-linux-androideabi21")
        self.assertEqual(arch.platform_dir, "arch-arm")

        env = arch.get_env()
        # check glob and find_executable calls
        self.assertEqual(mock_glob.call_count, 4)
        for glob_call, kw in mock_glob.call_args_list:
            self.assertEqual(
                glob_call[0],
                "{ndk_dir}/toolchains/llvm*".format(ndk_dir=self.ctx._ndk_dir),
            )
        mock_find_executable.assert_called_once_with(self.expected_compiler,
                                                     path=environ["PATH"])

        # check clang
        build_platform = "{system}-{machine}".format(
            system=os.uname()[0], machine=os.uname()[-1]).lower()
        self.assertEqual(
            env["CC"].split()[0],
            "{ndk_dir}/toolchains/llvm/prebuilt/"
            "{build_platform}/bin/clang".format(ndk_dir=self.ctx._ndk_dir,
                                                build_platform=build_platform),
        )
        self.assertEqual(
            env["CXX"].split()[0],
            "{ndk_dir}/toolchains/llvm/prebuilt/"
            "{build_platform}/bin/clang++".format(
                ndk_dir=self.ctx._ndk_dir, build_platform=build_platform),
        )

        # For armeabi-v7a we expect some extra cflags
        self.assertIn(
            " -march=armv7-a -mfloat-abi=softfp -mfpu=vfp -mthumb",
            env["CFLAGS"],
        )
Example #6
0
 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)
 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)
    def test_distribute_methods(self, mock_build_dir, mock_bs_dir, mock_glob,
                                mock_shprint):
        # prepare arch, bootstrap and distribution
        arch = ArchARMv7_a(self.ctx)
        bs = Bootstrap().get_bootstrap(self.bootstrap_name, self.ctx)
        self.setUp_distribution_with_bootstrap(bs)

        # a convenient method to reset mocks in one shot
        def reset_mocks():
            mock_glob.reset_mock()
            mock_shprint.reset_mock()
            mock_build_dir.reset_mock()
            mock_bs_dir.reset_mock()

        # test distribute_libs
        mock_glob.return_value = [
            "/fake_dir/libsqlite3.so",
            "/fake_dir/libpng16.so",
        ]
        bs.distribute_libs(arch, [self.ctx.get_libs_dir(arch.arch)])
        libs_dir = os.path.join("libs", arch.arch)
        # we expect two calls to glob/copy command via shprint
        self.assertEqual(len(mock_glob.call_args_list), 2)
        self.assertEqual(len(mock_shprint.call_args_list), 2)
        for i, lib in enumerate(mock_glob.return_value):
            self.assertEqual(
                mock_shprint.call_args_list[i],
                mock.call(sh.cp, "-a", lib, libs_dir),
            )
        mock_build_dir.assert_called()
        mock_bs_dir.assert_called_once_with(libs_dir)
        reset_mocks()

        # test distribute_javaclasses
        mock_glob.return_value = ["/fakedir/java_file.java"]
        bs.distribute_javaclasses(self.ctx.javaclass_dir)
        mock_glob.assert_called_once_with(self.ctx.javaclass_dir)
        mock_build_dir.assert_called_with(self.ctx.javaclass_dir)
        mock_bs_dir.assert_called_once_with("src")
        self.assertEqual(
            mock_shprint.call_args,
            mock.call(sh.cp, "-a", "/fakedir/java_file.java", "src"),
        )
        reset_mocks()

        # test distribute_aars
        mock_glob.return_value = ["/fakedir/file.aar"]
        bs.distribute_aars(arch)
        mock_build_dir.assert_called_with(self.ctx.aars_dir)
        # We expect three calls to shprint: unzip, cp, cp
        zip_call, kw = mock_shprint.call_args_list[0]
        self.assertEqual(zip_call[0], sh.unzip)
        self.assertEqual(zip_call[2], "/fakedir/file.aar")
        cp_java_call, kw = mock_shprint.call_args_list[1]
        self.assertEqual(cp_java_call[0], sh.cp)
        self.assertTrue(cp_java_call[2].endswith("classes.jar"))
        self.assertEqual(cp_java_call[3], "libs/file.jar")
        cp_libs_call, kw = mock_shprint.call_args_list[2]
        self.assertEqual(cp_libs_call[0], sh.cp)
        self.assertEqual(cp_libs_call[2], "/fakedir/file.aar")
        self.assertEqual(cp_libs_call[3], libs_dir)
        mock_bs_dir.assert_has_calls([mock.call("libs"), mock.call(libs_dir)])
        mock_glob.assert_called()
    def test_run_distribute(
        self,
        mock_sh_cp,
        mock_sh_rm,
        mock_listdir,
        mock_chdir,
        mock_ensure_dir,
        mock_strip_libraries,
        mock_create_python_bundle,
        mock_open_dist_files,
        mock_open_sdl2_files,
        mock_open_webview_files,
        mock_open_service_only_files,
    ):
        """
        A test for any overwritten method of
        `~pythonforandroid.bootstrap.Bootstrap.run_distribute`. Here we mock
        any file/dir operation that it could slow down our tests, and there is
        a lot to mock, because the `run_distribute` method it should take care
        of prepare all compiled files to generate the final `apk`. The targets
        of this test will be:

            - :meth:`~pythonforandroid.bootstraps.sdl2.BootstrapSdl2
              .run_distribute`
            - :meth:`~pythonforandroid.bootstraps.service_only
              .ServiceOnlyBootstrap.run_distribute`
            - :meth:`~pythonforandroid.bootstraps.webview.WebViewBootstrap
               .run_distribute`
            - :meth:`~pythonforandroid.bootstraps.empty.EmptyBootstrap.
              run_distribute`

        Here we will tests all those methods that are specific for each class.
        """
        # prepare bootstrap and distribution
        bs = Bootstrap().get_bootstrap(self.bootstrap_name, self.ctx)
        bs.build_dir = bs.get_build_dir()
        self.setUp_distribution_with_bootstrap(bs)

        self.ctx.hostpython = "/some/fake/hostpython3"
        self.ctx.python_recipe = Recipe.get_recipe("python3", self.ctx)
        self.ctx.python_modules = ["requests"]
        self.ctx.archs = [ArchARMv7_a(self.ctx)]

        bs.run_distribute()

        mock_open_dist_files.assert_called_once_with("dist_info.json", "w")
        mock_open_bootstraps = {
            "sdl2": mock_open_sdl2_files,
            "webview": mock_open_webview_files,
            "service_only": mock_open_service_only_files,
        }
        expected_open_calls = {
            "sdl2": [
                mock.call("local.properties", "w"),
                mock.call("blacklist.txt", "a"),
            ],
            "webview": [mock.call("local.properties", "w")],
            "service_only": [mock.call("local.properties", "w")],
        }
        mock_open_bs = mock_open_bootstraps[self.bootstrap_name]
        # test that the expected calls has been called
        for expected_call in expected_open_calls[self.bootstrap_name]:
            self.assertIn(expected_call, mock_open_bs.call_args_list)
        # test that the write function has been called with the expected args
        self.assertIn(
            mock.call().__enter__().write("sdk.dir=/opt/android/android-sdk"),
            mock_open_bs.mock_calls,
        )
        if self.bootstrap_name == "sdl2":
            self.assertIn(
                mock.call().__enter__().write(
                    "\nsqlite3/*\nlib-dynload/_sqlite3.so\n"),
                mock_open_bs.mock_calls,
            )

        # check that the other mocks we made are actually called
        mock_sh_rm.assert_called()
        mock_sh_cp.assert_called()
        mock_chdir.assert_called()
        mock_listdir.assert_called()
        mock_strip_libraries.assert_called()
        mock_create_python_bundle.assert_called()