Пример #1
0
    def test_architecture_options(
        self,
        monkeypatch,
        machine,
        architecture,
        expected_arch_triplet,
        expected_deb_arch,
        expected_kernel_arch,
        expected_core_dynamic_linker,
    ):
        monkeypatch.setattr(platform, "architecture", lambda: architecture)
        monkeypatch.setattr(platform, "machine", lambda: machine)

        options = snapcraft.ProjectOptions()

        assert options.arch_triplet == expected_arch_triplet
        assert options.deb_arch == expected_deb_arch
        assert options.kernel_arch == expected_kernel_arch

        # The core dynamic linker is correct.  Guard against stray absolute
        # paths, as they cause os.path.join to discard the previous
        # argument.
        monkeypatch.setattr(os.path, "lexists", lambda x: True)
        monkeypatch.setattr(os.path, "islink", lambda x: False)
        expected_linker_path = os.path.join(
            common.get_installed_snap_path("core"), expected_core_dynamic_linker
        )
        assert options.get_core_dynamic_linker("core") == expected_linker_path
Пример #2
0
    def test_architecture_options(
        self, mock_platform_machine, mock_platform_architecture
    ):
        mock_platform_machine.return_value = self.machine
        mock_platform_architecture.return_value = self.architecture
        options = snapcraft.ProjectOptions()
        self.assertThat(options.arch_triplet, Equals(self.expected_arch_triplet))
        self.assertThat(options.deb_arch, Equals(self.expected_deb_arch))
        self.assertThat(options.kernel_arch, Equals(self.expected_kernel_arch))

        # The core dynamic linker is correct.  Guard against stray absolute
        # paths, as they cause os.path.join to discard the previous
        # argument.
        self.assertFalse(os.path.isabs(self.expected_core_dynamic_linker))
        with mock.patch("os.path.lexists") as mock_lexists:
            mock_lexists.return_value = True
            with mock.patch("os.path.islink") as mock_islink:
                mock_islink.return_value = False
                self.assertThat(
                    options.get_core_dynamic_linker("core"),
                    Equals(
                        os.path.join(
                            common.get_installed_snap_path("core"),
                            self.expected_core_dynamic_linker,
                        )
                    ),
                )
Пример #3
0
    def get_provider_content_directories(self) -> Set[str]:
        """Get provider content directories from installed snaps."""
        provider_dirs: Set[str] = set()

        for plug in self.get_content_plugs():
            # Get matching slot provider for plug.
            provider = plug.provider
            provider_path = common.get_installed_snap_path(provider)
            yaml_path = os.path.join(provider_path, "meta", "snap.yaml")

            snap = Snap.from_file(yaml_path)
            for slot in snap.get_content_slots():
                slot_installed_path = common.get_installed_snap_path(
                    plug.provider)
                provider_dirs |= slot.get_content_dirs(
                    installed_path=slot_installed_path)

        return provider_dirs
Пример #4
0
    def get_core_dynamic_linker(self, base: str, expand: bool = True) -> str:
        """Returns the dynamic linker used for the targeted core.

        :param str base: the base core snap to search for linker.
        :param bool expand: expand the linker to the actual linker if True,
                            else the main entry point to the linker for the
                            projects architecture.
        :return: the absolute path to the linker
        :rtype: str
        :raises snapcraft.internal.errors.SnapcraftMissingLinkerInBaseError:
            if the linker cannot be found in the base.
        :raises snapcraft.internal.errors.SnapcraftEnvironmentError:
            if a loop is found while resolving the real path to the linker.
        """
        core_path = common.get_installed_snap_path(base)
        dynamic_linker_path = os.path.join(
            core_path,
            self.__machine_info.get("core-dynamic-linker", "lib/ld-linux.so.2"),
        )

        # return immediately if we do not need to expand
        if not expand:
            return dynamic_linker_path

        # We can't use os.path.realpath because any absolute symlinks
        # have to be interpreted relative to core_path, not the real
        # root.
        seen_paths = set()  # type: Set[str]
        while True:
            if dynamic_linker_path in seen_paths:
                raise errors.SnapcraftEnvironmentError(
                    "found symlink loop resolving dynamic linker path"
                )

            seen_paths.add(dynamic_linker_path)
            if not os.path.lexists(dynamic_linker_path):
                raise errors.SnapcraftMissingLinkerInBaseError(
                    base=base, linker_path=dynamic_linker_path
                )
            if not os.path.islink(dynamic_linker_path):
                return dynamic_linker_path

            link_contents = os.readlink(dynamic_linker_path)
            if os.path.isabs(link_contents):
                dynamic_linker_path = os.path.join(core_path, link_contents.lstrip("/"))
            else:
                dynamic_linker_path = os.path.join(
                    os.path.dirname(dynamic_linker_path), link_contents
                )
Пример #5
0
    def build(self):
        super().build()
        self.run(
            ["shards", "build", "--without-development"] +
            self.options.crystal_build_options,
            self.builddir,
        )

        output_bin = os.path.join(self.builddir, "bin")
        if not os.path.exists(output_bin):
            raise errors.SnapcraftEnvironmentError(
                "No binaries were built. Ensure the shards.yaml contains valid targets."
            )

        install_bin_path = os.path.join(self.installdir, "bin")

        bin_paths = (os.path.join(output_bin, b)
                     for b in os.listdir(output_bin))
        elf_files = (elf.ElfFile(path=b) for b in bin_paths
                     if elf.ElfFile.is_elf(b))

        os.makedirs(install_bin_path, exist_ok=True)

        for elf_file in elf_files:
            shutil.copy2(
                elf_file.path,
                os.path.join(install_bin_path,
                             os.path.basename(elf_file.path)),
            )

            elf_dependencies_path = elf_file.load_dependencies(
                root_path=self.installdir,
                core_base_path=common.get_installed_snap_path(
                    self.project._get_build_base()),
                arch_triplet=self.project.arch_triplet,
                content_dirs=self.project._get_provider_content_dirs(),
            )
            for elf_dependency_path in elf_dependencies_path:
                lib_install_path = os.path.join(self.installdir,
                                                elf_dependency_path[1:])
                os.makedirs(os.path.dirname(lib_install_path), exist_ok=True)
                if not os.path.exists(lib_install_path):
                    file_utils.link_or_copy(elf_dependency_path,
                                            lib_install_path,
                                            follow_symlinks=True)