Пример #1
0
    def __init__(self, *, dynamic_linker: str, root_path: str) -> None:
        """Create a Patcher instance.

        :param str dynamic_linker: the path to the dynamic linker to set the
                                   elf file to.
        :param str root_path: the base path for the snap to determine
                              if use of $ORIGIN is possible.
        """
        self._dynamic_linker = dynamic_linker
        self._root_path = root_path

        # If we are running from the snap we want to use the patchelf
        # bundled there as it would have the capability of working
        # anywhere given the fixed ld it would have.
        # If not found, resort to whatever is on the system brought
        # in by packaging dependencies.
        # The docker conditional will work if the docker image has the
        # snaps unpacked in the corresponding locations.
        if common.is_snap():
            snap_dir = os.getenv('SNAP')
            self._patchelf_cmd = os.path.join(snap_dir, 'bin', 'patchelf')
        elif (common.is_docker_instance() and
              os.path.exists('/snap/snapcraft/current/bin/patchelf')):
            self._patchelf_cmd = '/snap/snapcraft/current/bin/patchelf'
        else:
            self._patchelf_cmd = 'patchelf'
Пример #2
0
    def __init__(self,
                 *,
                 dynamic_linker: str,
                 library_path_func=lambda x: x,
                 base_rpaths: List[str] = None) -> None:
        """Create a Patcher instance.

        :param str dynamic_linker: the path to the dynamic linker to set the
                                   elf file to.
        :param library_path_func: function to determine the library path to a
                                  given dependency of ElfFile.
        :param list base_rpaths: library paths for the used base snap.
        """
        self._dynamic_linker = dynamic_linker
        self._library_path_func = library_path_func
        if not base_rpaths:
            base_rpaths = []
        self._base_rpaths = base_rpaths

        # If we are running from the snap we want to use the patchelf
        # bundled there as it would have the capability of working
        # anywhere given the fixed ld it would have.
        # If not found, resort to whatever is on the system brought
        # in by packaging dependencies.
        # The docker conditional will work if the docker image has the
        # snaps unpacked in the corresponding locations.
        if common.is_snap():
            snap_dir = os.getenv('SNAP')
            self._patchelf_cmd = os.path.join(snap_dir, 'bin', 'patchelf')
        elif (common.is_docker_instance()
              and os.path.exists('/snap/snapcraft/current/bin/patchelf')):
            self._patchelf_cmd = '/snap/snapcraft/current/bin/patchelf'
        else:
            self._patchelf_cmd = 'patchelf'
Пример #3
0
    def __init__(self, *, force_provider: str = None) -> None:
        """Instantiate a BuildEnvironmentConfig.

        :param str force_provider: ignore the hints from the environment and use
                                   the specified provider.
        """
        if force_provider:
            build_provider = force_provider
        elif common.is_docker_instance():
            build_provider = "host"
        else:
            build_provider = os.environ.get("SNAPCRAFT_BUILD_ENVIRONMENT", "multipass")

        valid_providers = ["host", "multipass", "managed-host", "lxd"]
        if build_provider not in valid_providers:
            raise errors.SnapcraftEnvironmentError(
                "The snapcraft build environment must be one of: {}.".format(
                    humanize_list(items=valid_providers, conjunction="or")
                )
            )

        self.provider = build_provider
        self.is_host = build_provider == "host"
        self.is_multipass = build_provider == "multipass"
        self.is_multipass = build_provider == "lxd"
        self.is_managed_host = build_provider == "managed-host"
Пример #4
0
def get_tool_path(command_name: str) -> str:
    """Return the path to the given command

    Return a path to command_name, if Snapcraft is running out of the snap or out
    of Docker, it ensures it is using the one in the snap, not the host.
    If a path cannot be resolved, ToolMissingError is raised.

    : param str command_name: the name of the command to resolve a path for.
    :raises ToolMissingError: if command_name cannot be resolved to a path.
    :return: Path to command
    :rtype: str
    """
    if common.is_snap():
        command_path = _command_path_in_root(os.getenv("SNAP"), command_name)
    elif common.is_docker_instance():
        command_path = _command_path_in_root(
            os.path.join(os.sep, "snap", "snapcraft", "current"), command_name)
    else:
        command_path = shutil.which(command_name)

    # shutil.which will return None if it cannot find command_name
    if command_path is None:
        raise ToolMissingError(command_name=command_name)

    return command_path
Пример #5
0
def _should_get_core(confinement: str) -> bool:
    is_env_var_set = os.environ.get("SNAPCRAFT_SETUP_CORE", False) is not False
    # This is a quirk so that docker users not using the Dockerfile
    # we distribute and create can automatically build classic
    is_docker_instance = common.is_docker_instance()  # type: bool
    is_classic = confinement == "classic"  # type: bool

    return is_classic and (is_env_var_set or is_docker_instance)
Пример #6
0
def _should_get_core(confinement: str) -> bool:
    is_env_var_set = os.environ.get("SNAPCRAFT_SETUP_CORE", False) is not False
    # This is a quirk so that docker users not using the Dockerfile
    # we distribute and create can automatically build classic
    is_docker_instance = common.is_docker_instance()  # type: bool
    is_classic = confinement == "classic"  # type: bool

    return is_classic and (is_env_var_set or is_docker_instance)
Пример #7
0
    def __init__(self, project: project.Project) -> None:
        self.build_snaps = set()  # type: Set[str]
        self.project = project

        # raw_snapcraft_yaml is read only, create a new copy
        snapcraft_yaml = apply_extensions(project.info.get_raw_snapcraft())

        self.validator = Validator(snapcraft_yaml)
        self.validator.validate()

        snapcraft_yaml = self._expand_filesets(snapcraft_yaml)

        self.data = self._expand_env(snapcraft_yaml)
        self._ensure_no_duplicate_app_aliases()

        grammar_processor = grammar_processing.GlobalGrammarProcessor(
            properties=self.data, project=project)

        self.build_tools = grammar_processor.get_build_packages()
        self.build_tools |= set(project.additional_build_packages)

        # If version: git is used we want to add "git" to build-packages
        if self.data.get("version") == "git":
            self.build_tools.add("git")

        # Always add the base for building for non os and base snaps
        if project.info.base is not None and project.info.type not in ("base",
                                                                       "os"):
            # If the base is already installed by other means, skip its installation.
            # But, we should always add it when in a docker environment so
            # the creator of said docker image is aware that it is required.
            if common.is_docker_instance(
            ) or not repo.snaps.SnapPackage.is_snap_installed(
                    project.info.base):
                self.build_snaps.add(project.info.base)
        elif project.info.type not in ("base", "os"):
            # This exception is here to help with porting issues with bases. In normal
            # executions, when no base is set, the legacy snapcraft will be executed.
            raise RuntimeError("A base is required for {!r} snaps.".format(
                project.info.type))

        self.parts = PartsConfig(
            parts=self.data,
            project=project,
            validator=self.validator,
            build_snaps=self.build_snaps,
            build_tools=self.build_tools,
        )

        self.data["architectures"] = _process_architectures(
            self.data.get("architectures"), project.deb_arch)

        conduct_environment_sanity_check(self.project, self.data,
                                         self.validator.schema)
Пример #8
0
    def __init__(self,
                 *,
                 dynamic_linker: str,
                 root_path: str,
                 preferred_patchelf_path=None) -> None:
        """Create a Patcher instance.

        :param str dynamic_linker: the path to the dynamic linker to set the
                                   elf file to.
        :param str root_path: the base path for the snap to determine
                              if use of $ORIGIN is possible.
        :param str preferred_patchelf_path: patch the necessary elf_files with
                                        this patchelf.
        """
        self._dynamic_linker = dynamic_linker
        self._root_path = root_path

        # We will first fallback to the preferred_patchelf_path,
        # if that is not found we will look for the snap and finally,
        # if we are running from the snap we want to use the patchelf
        # bundled there as it would have the capability of working
        # anywhere given the fixed ld it would have.
        # If not found, resort to whatever is on the system brought
        # in by packaging dependencies.
        # The docker conditional will work if the docker image has the
        # snaps unpacked in the corresponding locations.
        if preferred_patchelf_path:
            self._patchelf_cmd = preferred_patchelf_path
        # We use the full path here as the path may not be set on
        # build systems where the path is recently created and added
        # to the environment
        elif os.path.exists('/snap/bin/patchelf'):
            self._patchelf_cmd = '/snap/bin/patchelf'
        elif common.is_snap():
            snap_dir = os.getenv('SNAP')
            self._patchelf_cmd = os.path.join(snap_dir, 'bin', 'patchelf')
        elif (common.is_docker_instance()
              and os.path.exists('/snap/snapcraft/current/bin/patchelf')):
            self._patchelf_cmd = '/snap/snapcraft/current/bin/patchelf'
        else:
            self._patchelf_cmd = 'patchelf'
Пример #9
0
def get_tool_path(command_name):
    """Return the path to the given command

    By default this utilizes the PATH, but if Snapcraft is running out of the
    snap or out of Docker, it ensures it's using the one in the snap, not the
    host.

    :return: Path to command
    :rtype: str
    """
    path = command_name

    if common.is_snap():
        path = _command_path_in_root(os.getenv("SNAP"), command_name)
    elif common.is_docker_instance():
        path = _command_path_in_root(
            os.path.join(os.sep, "snap", "snapcraft", "current"), command_name)

    if path:
        return path
    else:
        return command_name
Пример #10
0
def get_tool_path(command_name):
    """Return the path to the given command

    By default this utilizes the PATH, but if Snapcraft is running out of the
    snap or out of Docker, it ensures it's using the one in the snap, not the
    host.

    :return: Path to command
    :rtype: str
    """
    path = command_name

    if common.is_snap():
        path = _command_path_in_root(os.getenv("SNAP"), command_name)
    elif common.is_docker_instance():
        path = _command_path_in_root(
            os.path.join(os.sep, "snap", "snapcraft", "current"), command_name
        )

    if path:
        return path
    else:
        return command_name
Пример #11
0
def _requires_patchelf_snap(confinement: str) -> bool:
    is_snap = common.is_snap()
    is_docker_instance = common.is_docker_instance()
    is_classic = confinement == 'classic'

    return (is_classic and not is_snap and not is_docker_instance)