Example #1
0
def _build_env(root, snap_name, confinement, arch_triplet,
               core_dynamic_linker=None):
    """Set the environment variables required for building.

    This is required for the current parts installdir due to stage-packages
    and also to setup the stagedir.
    """
    env = []

    paths = common.get_include_paths(root, arch_triplet)
    if paths:
        for envvar in ['CPPFLAGS', 'CFLAGS', 'CXXFLAGS']:
            env.append(formatting_utils.format_path_variable(
                envvar, paths, prepend='-I', separator=' '))

    if confinement == 'classic':
        if not core_dynamic_linker:
            raise EnvironmentError(
                'classic confinement requires the core snap to be installed. '
                'Install it by running `snap install core`.')

        core_path = common.get_core_path()
        core_rpaths = common.get_library_paths(core_path, arch_triplet,
                                               existing_only=False)
        snap_path = os.path.join('/snap', snap_name, 'current')
        snap_rpaths = common.get_library_paths(snap_path, arch_triplet,
                                               existing_only=False)

        # snap_rpaths before core_rpaths to prefer libraries from the snap.
        rpaths = formatting_utils.combine_paths(
            snap_rpaths + core_rpaths, prepend='', separator=':')
        env.append('LDFLAGS="$LDFLAGS '
                   # Building tools to continue the build becomes problematic
                   # with nodefaultlib.
                   # '-Wl,-z,nodefaultlib '
                   '-Wl,--dynamic-linker={0} '
                   '-Wl,-rpath,{1}"'.format(core_dynamic_linker, rpaths))

    paths = common.get_library_paths(root, arch_triplet)
    if paths:
        env.append(formatting_utils.format_path_variable(
            'LDFLAGS', paths, prepend='-L', separator=' '))

    paths = common.get_pkg_config_paths(root, arch_triplet)
    if paths:
        env.append(formatting_utils.format_path_variable(
            'PKG_CONFIG_PATH', paths, prepend='', separator=':'))

    return env
Example #2
0
def _runtime_env(root, arch_triplet):
    """Set the environment variables required for running binaries."""
    env = []

    env.append('PATH="' + ':'.join([
        '{0}/usr/sbin',
        '{0}/usr/bin',
        '{0}/sbin',
        '{0}/bin',
        '$PATH'
    ]).format(root) + '"')

    # Add the default LD_LIBRARY_PATH
    paths = common.get_library_paths(root, arch_triplet)
    if paths:
        env.append(formatting_utils.format_path_variable(
            'LD_LIBRARY_PATH', paths, prepend='', separator=':'))

    # Add more specific LD_LIBRARY_PATH from staged packages if necessary
    ld_library_paths = libraries.determine_ld_library_path(root)
    if ld_library_paths:
        env.append('LD_LIBRARY_PATH="' + ':'.join(ld_library_paths) +
                   ':$LD_LIBRARY_PATH"')

    return env
Example #3
0
def build_env(root: str, snap_name: str, arch_triplet: str) -> List[str]:
    """Set the environment variables required for building.

    This is required for the current parts installdir due to stage-packages
    and also to setup the stagedir.
    """
    env = []

    paths = common.get_include_paths(root, arch_triplet)
    if paths:
        for envvar in ["CPPFLAGS", "CFLAGS", "CXXFLAGS"]:
            env.append(
                formatting_utils.format_path_variable(
                    envvar, paths, prepend="-I", separator=" "
                )
            )

    paths = common.get_library_paths(root, arch_triplet)
    if paths:
        env.append(
            formatting_utils.format_path_variable(
                "LDFLAGS", paths, prepend="-L", separator=" "
            )
        )

    paths = common.get_pkg_config_paths(root, arch_triplet)
    if paths:
        env.append(
            formatting_utils.format_path_variable(
                "PKG_CONFIG_PATH", paths, prepend="", separator=":"
            )
        )

    return env
Example #4
0
def runtime_env(root: str, arch_triplet: str) -> List[str]:
    """Set the environment variables required for running binaries."""
    env = []

    env.append(
        'PATH="'
        + ":".join(
            ["{0}/usr/sbin", "{0}/usr/bin", "{0}/sbin", "{0}/bin", "$PATH"]
        ).format(root)
        + '"'
    )

    # Add the default LD_LIBRARY_PATH
    paths = common.get_library_paths(root, arch_triplet)
    # Add more specific LD_LIBRARY_PATH from staged packages if necessary
    paths += elf.determine_ld_library_path(root)

    if paths:
        env.append(
            formatting_utils.format_path_variable(
                "LD_LIBRARY_PATH", paths, prepend="", separator=":"
            )
        )

    return env
Example #5
0
def env_for_classic(base: str, arch_triplet: str) -> List[str]:
    """Set the required environment variables for a classic confined build."""
    env = []

    core_path = common.get_core_path(base)
    paths = common.get_library_paths(core_path, arch_triplet, existing_only=False)
    env.append(
        formatting_utils.format_path_variable(
            "LD_LIBRARY_PATH", paths, prepend="", separator=":"
        )
    )

    return env
Example #6
0
def _build_env(root, arch_triplet):
    """Set the environment variables required for building.

    This is required for the current parts installdir due to stage-packages
    and also to setup the stagedir.
    """
    env = []

    paths = common.get_include_paths(root, arch_triplet)
    if paths:
        for envvar in ['CPPFLAGS', 'CFLAGS', 'CXXFLAGS']:
            env.append(common.format_path_variable(
                envvar, paths, prepend='-I', separator=' '))
    paths = common.get_library_paths(root, arch_triplet)
    if paths:
        env.append(common.format_path_variable(
            'LDFLAGS', paths, prepend='-L', separator=' '))

    return env
Example #7
0
def _build_env(root,
               snap_name,
               confinement,
               arch_triplet,
               core_dynamic_linker=None):
    """Set the environment variables required for building.

    This is required for the current parts installdir due to stage-packages
    and also to setup the stagedir.
    """
    env = []

    paths = common.get_include_paths(root, arch_triplet)
    if paths:
        for envvar in ['CPPFLAGS', 'CFLAGS', 'CXXFLAGS']:
            env.append(
                formatting_utils.format_path_variable(envvar,
                                                      paths,
                                                      prepend='-I',
                                                      separator=' '))

    if confinement == 'classic':
        if not core_dynamic_linker:
            raise EnvironmentError(
                'classic confinement requires the core snap to be installed. '
                'Install it by running `snap install core`.')

        core_path = common.get_core_path()
        core_rpaths = common.get_library_paths(core_path,
                                               arch_triplet,
                                               existing_only=False)
        snap_path = os.path.join('/snap', snap_name, 'current')
        snap_rpaths = common.get_library_paths(snap_path,
                                               arch_triplet,
                                               existing_only=False)

        # snap_rpaths before core_rpaths to prefer libraries from the snap.
        rpaths = formatting_utils.combine_paths(snap_rpaths + core_rpaths,
                                                prepend='',
                                                separator=':')
        env.append(
            'LDFLAGS="$LDFLAGS '
            # Building tools to continue the build becomes problematic
            # with nodefaultlib.
            # '-Wl,-z,nodefaultlib '
            '-Wl,--dynamic-linker={0} '
            '-Wl,-rpath,{1}"'.format(core_dynamic_linker, rpaths))

    paths = common.get_library_paths(root, arch_triplet)
    if paths:
        env.append(
            formatting_utils.format_path_variable('LDFLAGS',
                                                  paths,
                                                  prepend='-L',
                                                  separator=' '))

    paths = common.get_pkg_config_paths(root, arch_triplet)
    if paths:
        env.append(
            formatting_utils.format_path_variable('PKG_CONFIG_PATH',
                                                  paths,
                                                  prepend='',
                                                  separator=':'))

    return env
Example #8
0
    def _run(self, arguments) -> str:
        with tempfile.NamedTemporaryFile(mode="w+") as f:
            lines = [
                'export PYTHONPATH="{}"'.format(
                    os.path.join(
                        self._rospack_install_path,
                        "usr",
                        "lib",
                        "python2.7",
                        "dist-packages",
                    )
                )
            ]

            ros_path = os.path.join(
                self._rospack_install_path, "opt", "ros", self._ros_distro
            )
            bin_paths = (
                os.path.join(ros_path, "bin"),
                os.path.join(self._rospack_install_path, "usr", "bin"),
            )
            lines.append(
                "export {}".format(
                    formatting_utils.format_path_variable(
                        "PATH", bin_paths, prepend="", separator=":"
                    )
                )
            )

            lib_paths = common.get_library_paths(
                self._rospack_install_path, self._project.arch_triplet
            )
            if lib_paths:
                lines.append(
                    "export {}".format(
                        formatting_utils.format_path_variable(
                            "LD_LIBRARY_PATH", lib_paths, prepend="", separator=":"
                        )
                    )
                )

            # Source our own workspace so we have all of rospack's dependencies
            lines.append(
                "_CATKIN_SETUP_DIR={} source {}".format(
                    ros_path, os.path.join(ros_path, "setup.sh")
                )
            )

            # By default, rospack saves its cache in $HOME/.ros, which we shouldn't
            # access here, so we'll redirect it with this environment variable.
            lines.append('export ROS_HOME="{}"'.format(self._rospack_cache_path))

            lines.append('export ROS_PACKAGE_PATH="{}"'.format(self._ros_package_path))

            lines.append('exec "$@"')
            f.write("\n".join(lines))
            f.flush()
            return (
                subprocess.check_output(
                    ["/bin/bash", f.name, "rospack"] + arguments,
                    stderr=subprocess.STDOUT,
                )
                .decode("utf8")
                .strip()
            )
Example #9
0
    def env(self, root):
        """Runtime environment for ROS binaries and services."""

        paths = common.get_library_paths(root, self.project.arch_triplet)
        ld_library_path = formatting_utils.combine_paths(paths,
                                                         prepend="",
                                                         separator=":")

        env = [
            # This environment variable tells ROS nodes where to find ROS
            # master. It does not affect ROS master, however-- this is just the
            # URI.
            "ROS_MASTER_URI={}".format(self.options.catkin_ros_master_uri),
            # Various ROS tools (e.g. roscore) keep a cache or a log,
            # and use $ROS_HOME to determine where to put them.
            "ROS_HOME=${SNAP_USER_DATA:-/tmp}/ros",
            # FIXME: LP: #1576411 breaks ROS snaps on the desktop, so we'll
            # temporarily work around that bug by forcing the locale to
            # C.UTF-8.
            "LC_ALL=C.UTF-8",
            # The Snapcraft Core will ensure that we get a good LD_LIBRARY_PATH
            # overall, but it defines it after this function runs. Some ROS
            # tools will cause binaries to be run when we source the setup.sh,
            # below, so we need to have a sensible LD_LIBRARY_PATH before then.
            "LD_LIBRARY_PATH=$LD_LIBRARY_PATH:{}".format(ld_library_path),
        ]

        # There's a chicken and egg problem here, everything run gets an
        # env built, even package installation, so the first runs for these
        # will likely fail.
        try:
            # The ROS packaging system tools (e.g. rospkg, etc.) don't go
            # into the ROS install path (/opt/ros/$distro), so we need the
            # PYTHONPATH to include the dist-packages in /usr/lib as well.
            #
            # Note: Empty segments in PYTHONPATH are interpreted as `.`, thus
            # adding the current working directory to the PYTHONPATH. That is
            # not desired in this situation, so take proper precautions when
            # expanding PYTHONPATH: only add it if it's not empty.
            env.append("PYTHONPATH={}${{PYTHONPATH:+:$PYTHONPATH}}".format(
                common.get_python2_path(root)))
        except errors.SnapcraftEnvironmentError as e:
            logger.debug(e)

        # The setup.sh we source below requires the in-snap python. Here we
        # make sure it's in the PATH before it's run.
        env.append("PATH=$PATH:{}/usr/bin".format(root))

        if self.options.underlay:
            script = textwrap.dedent("""
                if [ -f {snapcraft_setup} ]; then
                    . {snapcraft_setup}
                fi
            """).format(snapcraft_setup=os.path.join(self.rosdir,
                                                     "snapcraft-setup.sh"))
        else:
            script = self._source_setup_sh(root, None)

        # Each of these lines is prepended with an `export` when the
        # environment is actually generated. In order to inject real shell code
        # we have to hack it in by appending it on the end of an item already
        # in the environment. FIXME: There should be a better way to do this.
        # LP: #1792034
        env[-1] = env[-1] + "\n\n" + script

        return env