From 2c4564303b3ec57bef0e6bc42da3f4bad9e570be Mon Sep 17 00:00:00 2001 From: artivis Date: Mon, 20 Mar 2023 10:05:23 +0100 Subject: [PATCH 01/84] ros: rationalize ws sourcing Signed-off-by: artivis --- snapcraft_legacy/plugins/v2/_ros.py | 18 ++++++ snapcraft_legacy/plugins/v2/catkin.py | 43 ++++++------ snapcraft_legacy/plugins/v2/colcon.py | 50 ++++++++------ tests/legacy/unit/plugins/v2/test_catkin.py | 72 ++++++++++++++++++--- tests/legacy/unit/plugins/v2/test_colcon.py | 50 ++++++++++++-- 5 files changed, 181 insertions(+), 52 deletions(-) diff --git a/snapcraft_legacy/plugins/v2/_ros.py b/snapcraft_legacy/plugins/v2/_ros.py index 393196a458..6a6f5c80be 100644 --- a/snapcraft_legacy/plugins/v2/_ros.py +++ b/snapcraft_legacy/plugins/v2/_ros.py @@ -169,9 +169,27 @@ def get_build_commands(self) -> List[str]: # https://github.com/ros-infrastructure/rosdep/issues/271 "sudo --preserve-env=http_proxy,https_proxy rosdep init; fi", 'rosdep update --include-eol-distros --rosdistro "${ROS_DISTRO}"', + ] + # There are a number of unbound vars, disable flag + # after saving current state to restore after. + + [ + 'state="$(set +o); set -$-"', + "set +u", + "", + ] + + self._get_workspace_activation_commands() + # Restore saved state + + ['eval "${state}"'] + + [ 'rosdep install --default-yes --ignore-packages-from-source --from-paths "${SNAPCRAFT_PART_SRC_WORK}"', ] + + [ + 'state="$(set +o); set -$-"', + "set +u", + "", + ] + self._get_workspace_activation_commands() + + ['eval "${state}"'] + self._get_build_commands() + self._get_stage_runtime_dependencies_commands() ) diff --git a/snapcraft_legacy/plugins/v2/catkin.py b/snapcraft_legacy/plugins/v2/catkin.py index 876f07b0f8..af855f7300 100644 --- a/snapcraft_legacy/plugins/v2/catkin.py +++ b/snapcraft_legacy/plugins/v2/catkin.py @@ -74,6 +74,17 @@ def get_schema(cls) -> Dict[str, Any]: def get_build_packages(self) -> Set[str]: return super().get_build_packages() | {"ros-noetic-catkin"} + def _get_source_command(self, path: str) -> List[str]: + return [ + f'if [ -f "{path}/opt/ros/${{ROS_DISTRO}}/setup.sh" ]; then', + 'set -- --local "${_EXTEND_WS}"', + '_CATKIN_SETUP_DIR="{fpath}" . "{fpath}/setup.sh"'.format( + fpath=f"{path}/opt/ros/${{ROS_DISTRO}}" + ), + 'if [ -z ${_EXTEND_WS} ]; then _EXTEND_WS="--extend"; fi', + "fi", + ] + def _get_workspace_activation_commands(self) -> List[str]: """Return a list of commands to source a ROS workspace. @@ -86,23 +97,19 @@ def _get_workspace_activation_commands(self) -> List[str]: specific functionality. """ - # There are a number of unbound vars, disable flag - # after saving current state to restore after. - return [ - 'state="$(set +o); set -$-"', - "set +u", - 'if [ -f "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/setup.sh" ]; then', - "set -- --local", - '_CATKIN_SETUP_DIR="{path}" . "{path}/setup.sh"'.format( - path="${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}" - ), - "set -- --local --extend", - "else", - "set -- --local", - "fi", - '. /opt/ros/"${ROS_DISTRO}"/setup.sh', - 'eval "${state}"', - ] + activation_commands = list() + + # Source ROS ws in stage-snaps + activation_commands.append("## Sourcing ROS ws in stage snaps") + activation_commands.extend(self._get_source_command("${SNAPCRAFT_PART_INSTALL}")) + activation_commands.append("") + + # Finally source system's ROS ws + activation_commands.append("## Sourcing ROS ws in system") + activation_commands.extend(self._get_source_command("")) + activation_commands.append("") + + return activation_commands def _get_build_commands(self) -> List[str]: cmd = [ @@ -128,4 +135,4 @@ def _get_build_commands(self) -> List[str]: if self.options.catkin_cmake_args: cmd.extend(["--cmake-args", *self.options.catkin_cmake_args]) - return [" ".join(cmd)] + return ["## Build command", " ".join(cmd)] diff --git a/snapcraft_legacy/plugins/v2/colcon.py b/snapcraft_legacy/plugins/v2/colcon.py index 89516cdd15..33b2027dc6 100644 --- a/snapcraft_legacy/plugins/v2/colcon.py +++ b/snapcraft_legacy/plugins/v2/colcon.py @@ -119,6 +119,20 @@ def get_build_environment(self) -> Dict[str, str]: return env + def _get_source_command(self, path: str) -> List[str]: + return [ + f'if [ -f "{path}/opt/ros/${{ROS_DISTRO}}/local_setup.sh" ]; then', + 'AMENT_CURRENT_PREFIX="{wspath}" . "{wspath}/local_setup.sh"'.format( + wspath=f"{path}/opt/ros/${{ROS_DISTRO}}" + ), + "fi", + f'if [ -f "{path}/opt/ros/snap/local_setup.sh" ]; then', + 'COLCON_CURRENT_PREFIX="{wspath}" . "{wspath}/local_setup.sh"'.format( + wspath=f"{path}/opt/ros/snap" + ), + "fi", + ] + def _get_workspace_activation_commands(self) -> List[str]: """Return a list of commands source a ROS 2 workspace. @@ -131,25 +145,21 @@ def _get_workspace_activation_commands(self) -> List[str]: specific functionality. """ - # There are a number of unbound vars, disable flag - # after saving current state to restore after. - return [ - 'state="$(set +o); set -$-"', - "set +u", - # If it exists, source the stage-snap underlay - 'if [ -f "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/local_setup.sh" ]; then', - 'AMENT_CURRENT_PREFIX="{path}" . "{path}/local_setup.sh"'.format( - path='${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}' - ), - "fi", - 'if [ -f "${SNAPCRAFT_PART_INSTALL}"/opt/ros/snap/local_setup.sh ]; then', - "COLCON_CURRENT_PREFIX={path} . {path}/local_setup.sh".format( - path='"${SNAPCRAFT_PART_INSTALL}"/opt/ros/snap' - ), - "fi", - '. /opt/ros/"${ROS_DISTRO}"/local_setup.sh', - 'eval "${state}"', - ] + activation_commands = list() + + # Source ROS ws in stage-snaps + activation_commands.append("## Sourcing ROS ws in stage snaps") + activation_commands.extend( + self._get_source_command("${SNAPCRAFT_PART_INSTALL}") + ) + activation_commands.append("") + + # Finally source system's ROS ws + activation_commands.append("## Sourcing ROS ws in system") + activation_commands.extend(self._get_source_command("")) + activation_commands.append("") + + return activation_commands def _get_build_commands(self) -> List[str]: cmd = [ @@ -182,7 +192,7 @@ def _get_build_commands(self) -> List[str]: # Specify the number of workers cmd.extend(["--parallel-workers", '"${SNAPCRAFT_PARALLEL_BUILD_COUNT}"']) - return [" ".join(cmd)] + [ + return ["## Build command", " ".join(cmd)] + [ # Remove the COLCON_IGNORE marker so that, at staging, # catkin can crawl the entire folder to look up for packages. 'if [ -f "${SNAPCRAFT_PART_INSTALL}"/opt/ros/snap/COLCON_IGNORE ]; then', diff --git a/tests/legacy/unit/plugins/v2/test_catkin.py b/tests/legacy/unit/plugins/v2/test_catkin.py index df99d97d77..233f90940a 100644 --- a/tests/legacy/unit/plugins/v2/test_catkin.py +++ b/tests/legacy/unit/plugins/v2/test_catkin.py @@ -98,18 +98,44 @@ class Options: "if [ ! -f /etc/ros/rosdep/sources.list.d/20-default.list ]; then", "sudo --preserve-env=http_proxy,https_proxy rosdep init; fi", 'rosdep update --include-eol-distros --rosdistro "${ROS_DISTRO}"', + 'state="$(set +o); set -$-"', + "set +u", + "", + "## Sourcing ROS ws in stage snaps", + 'if [ -f "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/setup.sh" ]; then', + 'set -- --local "${_EXTEND_WS}"', + '_CATKIN_SETUP_DIR="${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}" . "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/setup.sh"', + 'if [ -z ${_EXTEND_WS} ]; then _EXTEND_WS="--extend"; fi', + "fi", + "", + "## Sourcing ROS ws in system", + 'if [ -f "/opt/ros/${ROS_DISTRO}/setup.sh" ]; then', + 'set -- --local "${_EXTEND_WS}"', + '_CATKIN_SETUP_DIR="/opt/ros/${ROS_DISTRO}" . "/opt/ros/${ROS_DISTRO}/setup.sh"', + 'if [ -z ${_EXTEND_WS} ]; then _EXTEND_WS="--extend"; fi', + "fi", + "", + 'eval "${state}"', 'rosdep install --default-yes --ignore-packages-from-source --from-paths "${SNAPCRAFT_PART_SRC_WORK}"', 'state="$(set +o); set -$-"', "set +u", + "", + "## Sourcing ROS ws in stage snaps", 'if [ -f "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/setup.sh" ]; then', - "set -- --local", + 'set -- --local "${_EXTEND_WS}"', '_CATKIN_SETUP_DIR="${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}" . "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/setup.sh"', - "set -- --local --extend", - "else", - "set -- --local", + 'if [ -z ${_EXTEND_WS} ]; then _EXTEND_WS="--extend"; fi', "fi", - '. /opt/ros/"${ROS_DISTRO}"/setup.sh', + "", + "## Sourcing ROS ws in system", + 'if [ -f "/opt/ros/${ROS_DISTRO}/setup.sh" ]; then', + 'set -- --local "${_EXTEND_WS}"', + '_CATKIN_SETUP_DIR="/opt/ros/${ROS_DISTRO}" . "/opt/ros/${ROS_DISTRO}/setup.sh"', + 'if [ -z ${_EXTEND_WS} ]; then _EXTEND_WS="--extend"; fi', + "fi", + "", 'eval "${state}"', + "## Build command", "catkin_make_isolated --install --merge " '--source-space "${SNAPCRAFT_PART_SRC_WORK}" --build-space "${SNAPCRAFT_PART_BUILD}" ' '--install-space "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}" ' @@ -162,18 +188,44 @@ class Options: "if [ ! -f /etc/ros/rosdep/sources.list.d/20-default.list ]; then", "sudo --preserve-env=http_proxy,https_proxy rosdep init; fi", 'rosdep update --include-eol-distros --rosdistro "${ROS_DISTRO}"', + 'state="$(set +o); set -$-"', + "set +u", + "", + "## Sourcing ROS ws in stage snaps", + 'if [ -f "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/setup.sh" ]; then', + 'set -- --local "${_EXTEND_WS}"', + '_CATKIN_SETUP_DIR="${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}" . "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/setup.sh"', + 'if [ -z ${_EXTEND_WS} ]; then _EXTEND_WS="--extend"; fi', + "fi", + "", + "## Sourcing ROS ws in system", + 'if [ -f "/opt/ros/${ROS_DISTRO}/setup.sh" ]; then', + 'set -- --local "${_EXTEND_WS}"', + '_CATKIN_SETUP_DIR="/opt/ros/${ROS_DISTRO}" . "/opt/ros/${ROS_DISTRO}/setup.sh"', + 'if [ -z ${_EXTEND_WS} ]; then _EXTEND_WS="--extend"; fi', + "fi", + "", + 'eval "${state}"', 'rosdep install --default-yes --ignore-packages-from-source --from-paths "${SNAPCRAFT_PART_SRC_WORK}"', 'state="$(set +o); set -$-"', "set +u", + "", + "## Sourcing ROS ws in stage snaps", 'if [ -f "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/setup.sh" ]; then', - "set -- --local", + 'set -- --local "${_EXTEND_WS}"', '_CATKIN_SETUP_DIR="${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}" . "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/setup.sh"', - "set -- --local --extend", - "else", - "set -- --local", + 'if [ -z ${_EXTEND_WS} ]; then _EXTEND_WS="--extend"; fi', "fi", - '. /opt/ros/"${ROS_DISTRO}"/setup.sh', + "", + "## Sourcing ROS ws in system", + 'if [ -f "/opt/ros/${ROS_DISTRO}/setup.sh" ]; then', + 'set -- --local "${_EXTEND_WS}"', + '_CATKIN_SETUP_DIR="/opt/ros/${ROS_DISTRO}" . "/opt/ros/${ROS_DISTRO}/setup.sh"', + 'if [ -z ${_EXTEND_WS} ]; then _EXTEND_WS="--extend"; fi', + "fi", + "", 'eval "${state}"', + "## Build command", "catkin_make_isolated --install --merge " '--source-space "${SNAPCRAFT_PART_SRC_WORK}" --build-space "${SNAPCRAFT_PART_BUILD}" ' '--install-space "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}" ' diff --git a/tests/legacy/unit/plugins/v2/test_colcon.py b/tests/legacy/unit/plugins/v2/test_colcon.py index 9821d9817e..fcf65e6b43 100644 --- a/tests/legacy/unit/plugins/v2/test_colcon.py +++ b/tests/legacy/unit/plugins/v2/test_colcon.py @@ -118,17 +118,38 @@ class Options: "if [ ! -f /etc/ros/rosdep/sources.list.d/20-default.list ]; then", "sudo --preserve-env=http_proxy,https_proxy rosdep init; fi", 'rosdep update --include-eol-distros --rosdistro "${ROS_DISTRO}"', + 'state="$(set +o); set -$-"', + "set +u", + "", + "## Sourcing ROS ws in stage snaps", + 'if [ -f "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/local_setup.sh" ]; then', + 'AMENT_CURRENT_PREFIX="${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}" . "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/local_setup.sh"', + "fi", + 'if [ -f "${SNAPCRAFT_PART_INSTALL}/opt/ros/snap/local_setup.sh" ]; then', + 'COLCON_CURRENT_PREFIX="${SNAPCRAFT_PART_INSTALL}/opt/ros/snap" . "${SNAPCRAFT_PART_INSTALL}/opt/ros/snap/local_setup.sh"', + "fi", + "", + "## Sourcing ROS ws in system", + '. /opt/ros/"${ROS_DISTRO}"/local_setup.sh', + "", + 'eval "${state}"', 'rosdep install --default-yes --ignore-packages-from-source --from-paths "${SNAPCRAFT_PART_SRC_WORK}"', 'state="$(set +o); set -$-"', "set +u", + "", + "## Sourcing ROS ws in stage snaps", 'if [ -f "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/local_setup.sh" ]; then', 'AMENT_CURRENT_PREFIX="${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}" . "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/local_setup.sh"', "fi", - 'if [ -f "${SNAPCRAFT_PART_INSTALL}"/opt/ros/snap/local_setup.sh ]; then', - 'COLCON_CURRENT_PREFIX="${SNAPCRAFT_PART_INSTALL}"/opt/ros/snap . "${SNAPCRAFT_PART_INSTALL}"/opt/ros/snap/local_setup.sh', + 'if [ -f "${SNAPCRAFT_PART_INSTALL}/opt/ros/snap/local_setup.sh" ]; then', + 'COLCON_CURRENT_PREFIX="${SNAPCRAFT_PART_INSTALL}/opt/ros/snap" . "${SNAPCRAFT_PART_INSTALL}/opt/ros/snap/local_setup.sh"', "fi", + "", + "## Sourcing ROS ws in system", '. /opt/ros/"${ROS_DISTRO}"/local_setup.sh', + "", 'eval "${state}"', + "## Build command", "colcon build " '--base-paths "${SNAPCRAFT_PART_SRC_WORK}" --build-base "${SNAPCRAFT_PART_BUILD}" ' '--merge-install --install-base "${SNAPCRAFT_PART_INSTALL}"/opt/ros/snap ' @@ -185,17 +206,38 @@ class Options: "if [ ! -f /etc/ros/rosdep/sources.list.d/20-default.list ]; then", "sudo --preserve-env=http_proxy,https_proxy rosdep init; fi", 'rosdep update --include-eol-distros --rosdistro "${ROS_DISTRO}"', + 'state="$(set +o); set -$-"', + "set +u", + "", + "## Sourcing ROS ws in stage snaps", + 'if [ -f "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/local_setup.sh" ]; then', + 'AMENT_CURRENT_PREFIX="${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}" . "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/local_setup.sh"', + "fi", + 'if [ -f "${SNAPCRAFT_PART_INSTALL}/opt/ros/snap/local_setup.sh" ]; then', + 'COLCON_CURRENT_PREFIX="${SNAPCRAFT_PART_INSTALL}/opt/ros/snap" . "${SNAPCRAFT_PART_INSTALL}/opt/ros/snap/local_setup.sh"', + "fi", + "", + "## Sourcing ROS ws in system", + '. /opt/ros/"${ROS_DISTRO}"/local_setup.sh', + "", + 'eval "${state}"', 'rosdep install --default-yes --ignore-packages-from-source --from-paths "${SNAPCRAFT_PART_SRC_WORK}"', 'state="$(set +o); set -$-"', "set +u", + "", + "## Sourcing ROS ws in stage snaps", 'if [ -f "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/local_setup.sh" ]; then', 'AMENT_CURRENT_PREFIX="${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}" . "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/local_setup.sh"', "fi", - 'if [ -f "${SNAPCRAFT_PART_INSTALL}"/opt/ros/snap/local_setup.sh ]; then', - 'COLCON_CURRENT_PREFIX="${SNAPCRAFT_PART_INSTALL}"/opt/ros/snap . "${SNAPCRAFT_PART_INSTALL}"/opt/ros/snap/local_setup.sh', + 'if [ -f "${SNAPCRAFT_PART_INSTALL}/opt/ros/snap/local_setup.sh" ]; then', + 'COLCON_CURRENT_PREFIX="${SNAPCRAFT_PART_INSTALL}/opt/ros/snap" . "${SNAPCRAFT_PART_INSTALL}/opt/ros/snap/local_setup.sh"', "fi", + "", + "## Sourcing ROS ws in system", '. /opt/ros/"${ROS_DISTRO}"/local_setup.sh', + "", 'eval "${state}"', + "## Build command", "colcon build " '--base-paths "${SNAPCRAFT_PART_SRC_WORK}" --build-base "${SNAPCRAFT_PART_BUILD}" ' '--merge-install --install-base "${SNAPCRAFT_PART_INSTALL}"/opt/ros/snap ' From 4434e9748f522280b14a8276fb825645b6babbae Mon Sep 17 00:00:00 2001 From: artivis Date: Mon, 20 Mar 2023 10:57:11 +0100 Subject: [PATCH 02/84] ros: source build-snap ws Signed-off-by: artivis --- snapcraft_legacy/plugins/v2/catkin.py | 11 ++++++++++- snapcraft_legacy/plugins/v2/colcon.py | 13 ++++++++++++- tests/legacy/unit/plugins/v2/test_catkin.py | 18 ++++++++++++++++++ tests/legacy/unit/plugins/v2/test_colcon.py | 20 ++++++++++++++++++++ 4 files changed, 60 insertions(+), 2 deletions(-) diff --git a/snapcraft_legacy/plugins/v2/catkin.py b/snapcraft_legacy/plugins/v2/catkin.py index af855f7300..d0249779d9 100644 --- a/snapcraft_legacy/plugins/v2/catkin.py +++ b/snapcraft_legacy/plugins/v2/catkin.py @@ -38,6 +38,7 @@ from typing import Any, Dict, List, Set +from snapcraft_legacy.internal.repo.snaps import _get_parsed_snap from snapcraft_legacy.plugins.v2 import _ros @@ -99,7 +100,15 @@ def _get_workspace_activation_commands(self) -> List[str]: activation_commands = list() - # Source ROS ws in stage-snaps + # Source ROS ws in all build-snaps first + activation_commands.append("## Sourcing ROS ws in build snaps") + if self.options.build_snaps: + for build_snap in self.options.build_snaps: + snap_name = _get_parsed_snap(build_snap)[0] + activation_commands.extend(self._get_source_command('/snap/{build_snap}/current'.format(build_snap=snap_name))) + activation_commands.append("") + + # Source ROS ws in stage-snaps next activation_commands.append("## Sourcing ROS ws in stage snaps") activation_commands.extend(self._get_source_command("${SNAPCRAFT_PART_INSTALL}")) activation_commands.append("") diff --git a/snapcraft_legacy/plugins/v2/colcon.py b/snapcraft_legacy/plugins/v2/colcon.py index 33b2027dc6..d560a5dd48 100644 --- a/snapcraft_legacy/plugins/v2/colcon.py +++ b/snapcraft_legacy/plugins/v2/colcon.py @@ -56,6 +56,7 @@ from typing import Any, Dict, List, Set +from snapcraft_legacy.internal.repo.snaps import _get_parsed_snap from snapcraft_legacy.plugins.v2 import _ros @@ -147,7 +148,17 @@ def _get_workspace_activation_commands(self) -> List[str]: activation_commands = list() - # Source ROS ws in stage-snaps + # Source ROS ws in all build-snaps first + activation_commands.append("## Sourcing ROS ws in build snaps") + if self.options.build_snaps: + for build_snap in self.options.build_snaps: + snap_name = _get_parsed_snap(build_snap)[0] + activation_commands.extend( + self._get_source_command(f"/snap/{snap_name}/current") + ) + activation_commands.append("") + + # Source ROS ws in stage-snaps next activation_commands.append("## Sourcing ROS ws in stage snaps") activation_commands.extend( self._get_source_command("${SNAPCRAFT_PART_INSTALL}") diff --git a/tests/legacy/unit/plugins/v2/test_catkin.py b/tests/legacy/unit/plugins/v2/test_catkin.py index 233f90940a..7e2508b026 100644 --- a/tests/legacy/unit/plugins/v2/test_catkin.py +++ b/tests/legacy/unit/plugins/v2/test_catkin.py @@ -75,6 +75,7 @@ class Options: catkin_cmake_args = list() catkin_packages = list() catkin_packages_ignore = list() + build_snaps = list() plugin = catkin.CatkinPlugin(part_name="my-part", options=Options()) @@ -101,6 +102,7 @@ class Options: 'state="$(set +o); set -$-"', "set +u", "", + "## Sourcing ROS ws in build snaps", "## Sourcing ROS ws in stage snaps", 'if [ -f "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/setup.sh" ]; then', 'set -- --local "${_EXTEND_WS}"', @@ -120,6 +122,7 @@ class Options: 'state="$(set +o); set -$-"', "set +u", "", + "## Sourcing ROS ws in build snaps", "## Sourcing ROS ws in stage snaps", 'if [ -f "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/setup.sh" ]; then', 'set -- --local "${_EXTEND_WS}"', @@ -152,6 +155,7 @@ class Options: catkin_cmake_args = ["cmake", "args..."] catkin_packages = ["package1", "package2..."] catkin_packages_ignore = ["ipackage1", "ipackage2..."] + build_snaps = ["foo"] plugin = catkin.CatkinPlugin(part_name="my-part", options=Options()) @@ -191,6 +195,13 @@ class Options: 'state="$(set +o); set -$-"', "set +u", "", + "## Sourcing ROS ws in build snaps", + 'if [ -f "/snap/foo/current/opt/ros/${ROS_DISTRO}/setup.sh" ]; then', + 'set -- --local "${_EXTEND_WS}"', + '_CATKIN_SETUP_DIR="/snap/foo/current/opt/ros/${ROS_DISTRO}" . "/snap/foo/current/opt/ros/${ROS_DISTRO}/setup.sh"', + 'if [ -z ${_EXTEND_WS} ]; then _EXTEND_WS="--extend"; fi', + "fi", + "", "## Sourcing ROS ws in stage snaps", 'if [ -f "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/setup.sh" ]; then', 'set -- --local "${_EXTEND_WS}"', @@ -210,6 +221,13 @@ class Options: 'state="$(set +o); set -$-"', "set +u", "", + "## Sourcing ROS ws in build snaps", + 'if [ -f "/snap/foo/current/opt/ros/${ROS_DISTRO}/setup.sh" ]; then', + 'set -- --local "${_EXTEND_WS}"', + '_CATKIN_SETUP_DIR="/snap/foo/current/opt/ros/${ROS_DISTRO}" . "/snap/foo/current/opt/ros/${ROS_DISTRO}/setup.sh"', + 'if [ -z ${_EXTEND_WS} ]; then _EXTEND_WS="--extend"; fi', + "fi", + "", "## Sourcing ROS ws in stage snaps", 'if [ -f "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/setup.sh" ]; then', 'set -- --local "${_EXTEND_WS}"', diff --git a/tests/legacy/unit/plugins/v2/test_colcon.py b/tests/legacy/unit/plugins/v2/test_colcon.py index fcf65e6b43..88db9bde07 100644 --- a/tests/legacy/unit/plugins/v2/test_colcon.py +++ b/tests/legacy/unit/plugins/v2/test_colcon.py @@ -96,6 +96,7 @@ class Options: colcon_cmake_args = list() colcon_packages = list() colcon_packages_ignore = list() + build_snaps = list() plugin = colcon.ColconPlugin(part_name="my-part", options=Options()) @@ -121,6 +122,7 @@ class Options: 'state="$(set +o); set -$-"', "set +u", "", + "## Sourcing ROS ws in build snaps", "## Sourcing ROS ws in stage snaps", 'if [ -f "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/local_setup.sh" ]; then', 'AMENT_CURRENT_PREFIX="${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}" . "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/local_setup.sh"', @@ -137,6 +139,7 @@ class Options: 'state="$(set +o); set -$-"', "set +u", "", + "## Sourcing ROS ws in build snaps", "## Sourcing ROS ws in stage snaps", 'if [ -f "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/local_setup.sh" ]; then', 'AMENT_CURRENT_PREFIX="${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}" . "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/local_setup.sh"', @@ -171,6 +174,7 @@ class Options: colcon_cmake_args = ["cmake", "args..."] colcon_packages = ["package1", "package2..."] colcon_packages_ignore = ["ipackage1", "ipackage2..."] + build_snaps = ["foo"] plugin = colcon.ColconPlugin(part_name="my-part", options=Options()) @@ -209,6 +213,14 @@ class Options: 'state="$(set +o); set -$-"', "set +u", "", + "## Sourcing ROS ws in build snaps", + 'if [ -f "/snap/foo/current/opt/ros/${ROS_DISTRO}/local_setup.sh" ]; then', + 'AMENT_CURRENT_PREFIX="/snap/foo/current/opt/ros/${ROS_DISTRO}" . "/snap/foo/current/opt/ros/${ROS_DISTRO}/local_setup.sh"', + "fi", + 'if [ -f "/snap/foo/current/opt/ros/snap/local_setup.sh" ]; then', + 'COLCON_CURRENT_PREFIX="/snap/foo/current/opt/ros/snap" . "/snap/foo/current/opt/ros/snap/local_setup.sh"', + "fi", + "", "## Sourcing ROS ws in stage snaps", 'if [ -f "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/local_setup.sh" ]; then', 'AMENT_CURRENT_PREFIX="${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}" . "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/local_setup.sh"', @@ -225,6 +237,14 @@ class Options: 'state="$(set +o); set -$-"', "set +u", "", + "## Sourcing ROS ws in build snaps", + 'if [ -f "/snap/foo/current/opt/ros/${ROS_DISTRO}/local_setup.sh" ]; then', + 'AMENT_CURRENT_PREFIX="/snap/foo/current/opt/ros/${ROS_DISTRO}" . "/snap/foo/current/opt/ros/${ROS_DISTRO}/local_setup.sh"', + "fi", + 'if [ -f "/snap/foo/current/opt/ros/snap/local_setup.sh" ]; then', + 'COLCON_CURRENT_PREFIX="/snap/foo/current/opt/ros/snap" . "/snap/foo/current/opt/ros/snap/local_setup.sh"', + "fi", + "", "## Sourcing ROS ws in stage snaps", 'if [ -f "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/local_setup.sh" ]; then', 'AMENT_CURRENT_PREFIX="${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}" . "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/local_setup.sh"', From 4ff7f8f3005e1c1a1caff888970061e2d8bb9380 Mon Sep 17 00:00:00 2001 From: artivis Date: Tue, 21 Mar 2023 11:35:37 +0100 Subject: [PATCH 03/84] ros: unmark build snap packages Signed-off-by: artivis --- snapcraft_legacy/plugins/v2/_ros.py | 51 +++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/snapcraft_legacy/plugins/v2/_ros.py b/snapcraft_legacy/plugins/v2/_ros.py index 6a6f5c80be..019797b56d 100644 --- a/snapcraft_legacy/plugins/v2/_ros.py +++ b/snapcraft_legacy/plugins/v2/_ros.py @@ -27,6 +27,7 @@ from snapcraft_legacy.internal import errors from snapcraft_legacy.internal.repo import Repo +from snapcraft_legacy.internal.repo.snaps import _get_parsed_snap from snapcraft_legacy.plugins.v2 import PluginV2 @@ -81,6 +82,7 @@ def get_build_snaps(self) -> Set[str]: def get_build_packages(self) -> Set[str]: return { "python3-rosdep", + "rospack-tools", } def get_build_environment(self) -> Dict[str, str]: @@ -119,6 +121,41 @@ def _get_build_commands(self) -> List[str]: specific functionality. """ + def _get_list_packages_commands(self) -> List[str]: + + cmd = list() + + # Clean up previously established list of packages in build snaps + cmd.append('rm -f "${SNAPCRAFT_PART_INSTALL}/.installed_packages.txt"') + cmd.append('rm -f "${SNAPCRAFT_PART_INSTALL}/.build_snaps.txt"') + + if self.options.build_snaps: + for build_snap in self.options.build_snaps: + snap_name = _get_parsed_snap(build_snap)[0] + path = f"/snap/{snap_name}/current/opt/ros" + cmd.extend([ + # Retrieve the list of all ROS packages available in the build snap + f"if [ -d {path} ]; then", + f"ROS_PACKAGE_PATH={path} " + 'rospack list-names | (xargs rosdep resolve --rosdistro "${ROS_DISTRO}" || echo "") | ' + 'awk "/#apt/{getline;print;}" >> "${SNAPCRAFT_PART_INSTALL}/.installed_packages.txt"', + "fi", + + # Retrieve the list of all non-ROS packages available in the build snap + f'if [ -d "{path}/${{ROS_DISTRO}}/" ]; then', + f'rosdep keys --rosdistro "${{ROS_DISTRO}}" --from-paths "{path}/${{ROS_DISTRO}}" --ignore-packages-from-source ' + '| (xargs rosdep resolve --rosdistro "${ROS_DISTRO}" || echo "") | grep -v "#" >> "${SNAPCRAFT_PART_INSTALL}"/.installed_packages.txt', + "fi", + + f'if [ -d "{path}/snap/" ]; then', + f'rosdep keys --rosdistro "${{ROS_DISTRO}}" --from-paths "{path}/snap" --ignore-packages-from-source ' + '| (xargs rosdep resolve --rosdistro "${ROS_DISTRO}" || echo "") | grep -v "#" >> "${SNAPCRAFT_PART_INSTALL}"/.installed_packages.txt', + "fi", + ]) + cmd.append("") + + return cmd + def _get_stage_runtime_dependencies_commands(self) -> List[str]: env = dict(LANG="C.UTF-8", LC_ALL="C.UTF-8") @@ -180,6 +217,7 @@ def get_build_commands(self) -> List[str]: + self._get_workspace_activation_commands() # Restore saved state + ['eval "${state}"'] + + self._get_list_packages_commands() + [ 'rosdep install --default-yes --ignore-packages-from-source --from-paths "${SNAPCRAFT_PART_SRC_WORK}"', ] @@ -256,20 +294,29 @@ def stage_runtime_dependencies( if parsed: click.echo(f"unhandled dependencies: {parsed!r}") + build_snap_packages: Set[str] = set() + try: + with open(part_install + "/.installed_packages.txt", "r") as f: + build_snap_packages = set(f.read().split()) + click.echo(f"Will not fetch staged packages: {build_snap_packages!r}") + except IOError: + pass + if apt_packages: package_names = sorted(apt_packages) install_path = pathlib.Path(part_install) stage_packages_path = install_path.parent / "stage_packages" click.echo(f"Fetching stage packages: {package_names!r}") - Repo.fetch_stage_packages( + fetched_stage_packages = Repo.fetch_stage_packages( package_names=package_names, base="core20", stage_packages_path=stage_packages_path, target_arch=target_arch, + packages_filters=build_snap_packages, ) - click.echo(f"Unpacking stage packages: {package_names!r}") + click.echo(f"Unpacking stage packages: {fetched_stage_packages!r}") Repo.unpack_stage_packages( stage_packages_path=stage_packages_path, install_path=install_path ) From b621c61782a911730df4d5f2104bec449051a141 Mon Sep 17 00:00:00 2001 From: artivis Date: Tue, 21 Mar 2023 16:43:31 +0100 Subject: [PATCH 04/84] ros: prepare build-snap ws Signed-off-by: artivis --- snapcraft_legacy/plugins/v2/catkin.py | 50 +++++++++++++++++++++++---- 1 file changed, 43 insertions(+), 7 deletions(-) diff --git a/snapcraft_legacy/plugins/v2/catkin.py b/snapcraft_legacy/plugins/v2/catkin.py index d0249779d9..910d911d4c 100644 --- a/snapcraft_legacy/plugins/v2/catkin.py +++ b/snapcraft_legacy/plugins/v2/catkin.py @@ -105,7 +105,7 @@ def _get_workspace_activation_commands(self) -> List[str]: if self.options.build_snaps: for build_snap in self.options.build_snaps: snap_name = _get_parsed_snap(build_snap)[0] - activation_commands.extend(self._get_source_command('/snap/{build_snap}/current'.format(build_snap=snap_name))) + activation_commands.extend(self._get_source_command(f"/snap/{snap_name}/current")) activation_commands.append("") # Source ROS ws in stage-snaps next @@ -121,7 +121,38 @@ def _get_workspace_activation_commands(self) -> List[str]: return activation_commands def _get_build_commands(self) -> List[str]: - cmd = [ + + prepare_build_command = list() + export_command = list() + + if self.options.build_snaps: + for build_snap in self.options.build_snaps: + build_snap = _get_parsed_snap(build_snap)[0] + # ROS workspaces present in buid-snaps have their '*.cmake' files pointing to hard-coded internal paths. + # We need to fix those paths so that they can be properly sourced. + # Since snaps are immutable, we copy the said '*.cmake' files to the current SNAPCRAFT_PART_BUILD path + # and edit these copies accordingly. + + pkg_path=f"/snap/{build_snap}/current/opt/ros/${{ROS_DISTRO}}/share" + + prepare_build_command.extend([ + f'if [ -d "{pkg_path}" ]; then ', + f'mkdir -p "${{SNAPCRAFT_PART_BUILD}}"/build_snaps/{build_snap}', + f'cp -r "{pkg_path}" "${{SNAPCRAFT_PART_BUILD}}/build_snaps/{build_snap}/."', + ( + 'find "${{SNAPCRAFT_PART_BUILD}}/build_snaps/{build_snap}" \( -name "*Config.cmake" -o -name "*extras.cmake" \) -exec ' # noqa: W605 + 'sed -i -e "s|/opt|/snap/{build_snap}/current&|g" -e "s|/usr|/snap/{build_snap}/current&|g" ' + '-e "s|\${{.*_DIR}}/../../..|/snap/{build_snap}/current/opt/ros/${{ROS_DISTRO}}|g" {{}} \;' # noqa: W605 + ).format(build_snap=build_snap), + "fi", + ]) + export_command.extend([ + 'if [ -d "${{SNAPCRAFT_PART_BUILD}}"/build_snaps/{build_snap} ]; then ' + 'export CMAKE_PREFIX_PATH="${{SNAPCRAFT_PART_BUILD}}/build_snaps/{build_snap}:${{CMAKE_PREFIX_PATH}}"; ' + 'fi'.format(build_snap=build_snap) + ]) + + build_command = [ "catkin_make_isolated", "--install", "--merge", @@ -136,12 +167,17 @@ def _get_build_commands(self) -> List[str]: ] if self.options.catkin_packages: - cmd.extend(["--pkg", *self.options.catkin_packages]) + build_command.extend(["--pkg", *self.options.catkin_packages]) if self.options.catkin_packages_ignore: - cmd.extend(["--ignore-pkg", *self.options.catkin_packages_ignore]) + build_command.extend(["--ignore-pkg", *self.options.catkin_packages_ignore]) if self.options.catkin_cmake_args: - cmd.extend(["--cmake-args", *self.options.catkin_cmake_args]) - - return ["## Build command", " ".join(cmd)] + build_command.extend(["--cmake-args", *self.options.catkin_cmake_args]) + + return ( + ["## Prepare build"] + + prepare_build_command + + export_command + + ["## Build command", " ".join(build_command)] + ) From b32527a381139bd3627baee982e8627af0811022 Mon Sep 17 00:00:00 2001 From: artivis Date: Tue, 21 Mar 2023 16:45:42 +0100 Subject: [PATCH 05/84] ros: command-chain source content-shared ws ros1 Signed-off-by: artivis --- extensions/ros1/launch | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/extensions/ros1/launch b/extensions/ros1/launch index 5a0158370f..5b4f85ef98 100755 --- a/extensions/ros1/launch +++ b/extensions/ros1/launch @@ -2,19 +2,25 @@ function activate_workspace() { rosdir="$1" - setup_sh="$rosdir/setup.bash" + setup_sh="$rosdir/setup.sh" if [ ! -f "$setup_sh" ]; then echo "error: $setup_sh not found" exit 1 fi # shellcheck disable=SC1090 - _CATKIN_SETUP_DIR="$rosdir" source "$setup_sh" + _CATKIN_SETUP_DIR="$rosdir" source "$setup_sh" "${@:2}" } # Save off parameters, the sourced setup scripts may manipulate them. original_args=("$@") -activate_workspace "$SNAP/opt/ros/$ROS_DISTRO" +# activate_workspace in content shared snaps +if [ -d "$SNAP/opt/ros/underlay_ws/opt/ros/$ROS_DISTRO" ]; then + activate_workspace "$SNAP/opt/ros/underlay_ws/opt/ros/$ROS_DISTRO" --local + export LD_LIBRARY_PATH="$SNAP/opt/ros/underlay_ws/usr/lib/x86_64-linux-gnu:${LD_LIBRARY_PATH}" +fi + +activate_workspace "$SNAP/opt/ros/$ROS_DISTRO" --local --extend exec "${original_args[@]}" From 37871b0fc4b60c103d4cf45cad690759e53d3a14 Mon Sep 17 00:00:00 2001 From: artivis Date: Mon, 27 Mar 2023 17:08:26 +0200 Subject: [PATCH 06/84] ros: add noetic meta extensions Signed-off-by: artivis --- schema/snapcraft.json | 5 + .../_extensions/_ros1_noetic_meta.py | 46 +++++++ .../_extensions/ros1_noetic_desktop.py | 28 ++++ .../_extensions/ros1_noetic_perception.py | 28 ++++ .../_extensions/ros1_noetic_robot.py | 28 ++++ .../_extensions/ros1_noetic_ros_base.py | 28 ++++ .../_extensions/ros1_noetic_ros_core.py | 28 ++++ .../extensions/test_ros1_noetic_meta.py | 125 ++++++++++++++++++ 8 files changed, 316 insertions(+) create mode 100644 snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py create mode 100644 snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_desktop.py create mode 100644 snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_perception.py create mode 100644 snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_robot.py create mode 100644 snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_ros_base.py create mode 100644 snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_ros_core.py create mode 100644 tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py diff --git a/schema/snapcraft.json b/schema/snapcraft.json index c9c61369e4..f73d4d4bac 100644 --- a/schema/snapcraft.json +++ b/schema/snapcraft.json @@ -915,6 +915,11 @@ "gnome-3-38", "kde-neon", "ros1-noetic", + "ros1-noetic-desktop", + "ros1-noetic-perception", + "ros1-noetic-robot", + "ros1-noetic-ros-base", + "ros1-noetic-ros-core", "ros2-foxy" ] } diff --git a/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py b/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py new file mode 100644 index 0000000000..7dfd824c3c --- /dev/null +++ b/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py @@ -0,0 +1,46 @@ +# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*- +# +# Copyright (C) 2023 Canonical Ltd +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 3 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Import types and tell flake8 to ignore the "unused" List. + +from typing import Any, Dict + +from .ros1_noetic import ExtensionImpl as RosNoeticExtension + + +class RosNoeticMetaBase(RosNoeticExtension): + """Setup a ROS 1 build and runtime environment suitable for a snap.""" + + def __init__(self, *, extension_name: str, yaml_data: Dict[str, Any]) -> None: + super().__init__(extension_name=extension_name, yaml_data=yaml_data) + + # python_paths = [ + # f"$SNAP/opt/ros/{self.ROS_DISTRO}/lib/python3.8/site-packages", + # "$SNAP/usr/lib/python3/dist-packages", + # "${PYTHONPATH}", + # ] + + self.root_snippet["plugs"] = { + "ros-meta": + { + "interface": "content", + "content": "ros-meta", + "target": "$SNAP/opt/ros/underlay_ws", + "default-provider": self.ROS_META, + } + } + + self.part_snippet["build-snaps"] = [self.ROS_META_DEV] diff --git a/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_desktop.py b/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_desktop.py new file mode 100644 index 0000000000..49222a1d8a --- /dev/null +++ b/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_desktop.py @@ -0,0 +1,28 @@ +# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*- +# +# Copyright (C) 2023 Canonical Ltd +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 3 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Import types and tell flake8 to ignore the "unused" List. + +from typing_extensions import Final + +from ._ros1_noetic_meta import RosNoeticMetaBase + + +class ExtensionImpl(RosNoeticMetaBase): + """Setup a ROS 1 build and runtime environment suitable for a snap.""" + + ROS_META: Final[str] = "ros-meta-desktop" + ROS_META_DEV: Final[str] = "ros-meta-desktop" diff --git a/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_perception.py b/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_perception.py new file mode 100644 index 0000000000..dca661e75f --- /dev/null +++ b/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_perception.py @@ -0,0 +1,28 @@ +# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*- +# +# Copyright (C) 2023 Canonical Ltd +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 3 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Import types and tell flake8 to ignore the "unused" List. + +from typing_extensions import Final + +from ._ros1_noetic_meta import RosNoeticMetaBase + + +class ExtensionImpl(RosNoeticMetaBase): + """Setup a ROS 1 build and runtime environment suitable for a snap.""" + + ROS_META: Final[str] = "ros-meta-perception" + ROS_META_DEV: Final[str] = "ros-meta-perception" diff --git a/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_robot.py b/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_robot.py new file mode 100644 index 0000000000..4c2bd448b3 --- /dev/null +++ b/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_robot.py @@ -0,0 +1,28 @@ +# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*- +# +# Copyright (C) 2023 Canonical Ltd +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 3 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Import types and tell flake8 to ignore the "unused" List. + +from typing_extensions import Final + +from ._ros1_noetic_meta import RosNoeticMetaBase + + +class ExtensionImpl(RosNoeticMetaBase): + """Setup a ROS 1 build and runtime environment suitable for a snap.""" + + ROS_META: Final[str] = "ros-meta-robot" + ROS_META_DEV: Final[str] = "ros-meta-robot" diff --git a/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_ros_base.py b/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_ros_base.py new file mode 100644 index 0000000000..11ed5ff228 --- /dev/null +++ b/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_ros_base.py @@ -0,0 +1,28 @@ +# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*- +# +# Copyright (C) 2023 Canonical Ltd +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 3 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Import types and tell flake8 to ignore the "unused" List. + +from typing_extensions import Final + +from ._ros1_noetic_meta import RosNoeticMetaBase + + +class ExtensionImpl(RosNoeticMetaBase): + """Setup a ROS 1 build and runtime environment suitable for a snap.""" + + ROS_META: Final[str] = "ros-meta-ros-base" + ROS_META_DEV: Final[str] = "ros-meta-ros-base" diff --git a/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_ros_core.py b/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_ros_core.py new file mode 100644 index 0000000000..1c020661d5 --- /dev/null +++ b/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_ros_core.py @@ -0,0 +1,28 @@ +# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*- +# +# Copyright (C) 2023 Canonical Ltd +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 3 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Import types and tell flake8 to ignore the "unused" List. + +from typing_extensions import Final + +from ._ros1_noetic_meta import RosNoeticMetaBase + + +class ExtensionImpl(RosNoeticMetaBase): + """Setup a ROS 1 build and runtime environment suitable for a snap.""" + + ROS_META: Final[str] = "ros-meta-ros-core" + ROS_META_DEV: Final[str] = "ros-meta-ros-core" diff --git a/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py b/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py new file mode 100644 index 0000000000..b86e37a8ec --- /dev/null +++ b/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py @@ -0,0 +1,125 @@ +# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*- +# +# Copyright (C) 2023 Canonical Ltd +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 3 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from snapcraft_legacy.internal.project_loader._extensions.ros1_noetic_desktop import ( + ExtensionImpl as Ros1NoeticDesktopExtension, +) +from snapcraft_legacy.internal.project_loader._extensions.ros1_noetic_perception import ( + ExtensionImpl as Ros1NoeticPerceptionExtension, +) +from snapcraft_legacy.internal.project_loader._extensions.ros1_noetic_robot import ( + ExtensionImpl as Ros1NoeticRobotExtension, +) +from snapcraft_legacy.internal.project_loader._extensions.ros1_noetic_ros_base import ( + ExtensionImpl as Ros1NoeticRosBaseExtension, +) +from snapcraft_legacy.internal.project_loader._extensions.ros1_noetic_ros_core import ( + ExtensionImpl as Ros1NoeticRosCoreExtension, +) + + +class TestClass: + scenarios = [ + ( + "desktop", + { + "extension_class": Ros1NoeticDesktopExtension, + "meta": "ros-meta-desktop", + "meta_dev": "ros-meta-desktop", + }, + "perception", + { + "extension_class": Ros1NoeticPerceptionExtension, + "meta": "ros-meta-perception", + "meta_dev": "ros-meta-perception", + }, + "robot", + { + "extension_class": Ros1NoeticRobotExtension, + "meta": "ros-meta-robot", + "meta_dev": "ros-meta-robot", + }, + "ros-base", + { + "extension_class": Ros1NoeticRosBaseExtension, + "meta": "ros-meta-ros-base", + "meta_dev": "ros-meta-ros-base", + }, + "ros-core", + { + "extension_class": Ros1NoeticRosCoreExtension, + "meta": "ros-meta-ros-core", + "meta_dev": "ros-meta-ros-core", + }, + ), + ] + + def test_extension(self, extension_class, meta, meta_dev): + ros1_extension = extension_class( + extension_name="ros1-noetic", yaml_data=dict(base="core20") + ) + + assert ros1_extension.root_snippet == { + "package-repositories": [ + { + "components": ["main"], + "formats": ["deb"], + "key-id": "C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654", + "key-server": "keyserver.ubuntu.com", + "suites": ["focal"], + "type": "apt", + "url": "http://packages.ros.org/ros/ubuntu", + } + ], + "plugs": { + "ros-meta": { + "interface": "content", + "content": "ros-meta", + "target": "$SNAP/opt/ros/underlay_ws", + "default-provider": meta, + } + }, + } + + assert ros1_extension.app_snippet == { + "command-chain": ["snap/command-chain/ros1-launch"], + "environment": { + "PYTHONPATH": "$SNAP/opt/ros/noetic/lib/python3.8/site-packages:$SNAP/usr/lib/python3/dist-packages:${PYTHONPATH}", + "ROS_VERSION": "1", + "ROS_DISTRO": "noetic", + }, + } + + assert ros1_extension.part_snippet == { + "build-environment": [{"ROS_VERSION": "1"}, {"ROS_DISTRO": "noetic"}], + "build-snaps": [meta_dev], + } + + assert ros1_extension.parts == { + "ros1-noetic-extension": { + "build-packages": ["ros-noetic-catkin"], + "override-build": "install -D -m 0755 launch " + "${SNAPCRAFT_PART_INSTALL}/snap/command-chain/ros1-launch", + "plugin": "nil", + "source": "$SNAPCRAFT_EXTENSIONS_DIR/ros1", + } + } + + def test_supported_bases(self, extension_class, meta, meta_dev): + assert extension_class.get_supported_bases() == ("core20",) + + def test_supported_confinement(self, extension_class, meta, meta_dev): + extension_class.get_supported_confinement() == ("strict", "devmode") From f7cd12bc1546d42e5e5dfaa7af9e06d1a4500d64 Mon Sep 17 00:00:00 2001 From: artivis Date: Mon, 27 Mar 2023 17:26:49 +0200 Subject: [PATCH 07/84] ros: fix unit tests Signed-off-by: artivis --- tests/legacy/unit/plugins/v2/test_catkin.py | 43 ++++++++++++++++++++- tests/legacy/unit/plugins/v2/test_colcon.py | 24 ++++++++++++ 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/tests/legacy/unit/plugins/v2/test_catkin.py b/tests/legacy/unit/plugins/v2/test_catkin.py index 7e2508b026..0bfa1ed7c2 100644 --- a/tests/legacy/unit/plugins/v2/test_catkin.py +++ b/tests/legacy/unit/plugins/v2/test_catkin.py @@ -53,7 +53,11 @@ def test_schema(): def test_get_build_packages(): plugin = catkin.CatkinPlugin(part_name="my-part", options=lambda: None) - assert plugin.get_build_packages() == {"python3-rosdep", "ros-noetic-catkin"} + assert plugin.get_build_packages() == { + "python3-rosdep", + "ros-noetic-catkin", + "rospack-tools", + } def test_get_build_environment(): @@ -118,6 +122,8 @@ class Options: "fi", "", 'eval "${state}"', + 'rm -f "${SNAPCRAFT_PART_INSTALL}/.installed_packages.txt"', + 'rm -f "${SNAPCRAFT_PART_INSTALL}/.build_snaps.txt"', 'rosdep install --default-yes --ignore-packages-from-source --from-paths "${SNAPCRAFT_PART_SRC_WORK}"', 'state="$(set +o); set -$-"', "set +u", @@ -138,6 +144,7 @@ class Options: "fi", "", 'eval "${state}"', + "## Prepare build", "## Build command", "catkin_make_isolated --install --merge " '--source-space "${SNAPCRAFT_PART_SRC_WORK}" --build-space "${SNAPCRAFT_PART_BUILD}" ' @@ -217,6 +224,27 @@ class Options: "fi", "", 'eval "${state}"', + 'rm -f "${SNAPCRAFT_PART_INSTALL}/.installed_packages.txt"', + 'rm -f "${SNAPCRAFT_PART_INSTALL}/.build_snaps.txt"', + "if [ -d /snap/foo/current/opt/ros ]; then", + "ROS_PACKAGE_PATH=/snap/foo/current/opt/ros rospack list-names | (xargs " + 'rosdep resolve --rosdistro "${ROS_DISTRO}" || echo "") | awk ' + '"/#apt/{getline;print;}" >> ' + '"${SNAPCRAFT_PART_INSTALL}/.installed_packages.txt"', + "fi", + 'if [ -d "/snap/foo/current/opt/ros/${ROS_DISTRO}/" ]; then', + 'rosdep keys --rosdistro "${ROS_DISTRO}" --from-paths ' + '"/snap/foo/current/opt/ros/${ROS_DISTRO}" --ignore-packages-from-source | ' + '(xargs rosdep resolve --rosdistro "${ROS_DISTRO}" || echo "") | grep -v "#" ' + '>> "${SNAPCRAFT_PART_INSTALL}"/.installed_packages.txt', + "fi", + 'if [ -d "/snap/foo/current/opt/ros/snap/" ]; then', + 'rosdep keys --rosdistro "${ROS_DISTRO}" --from-paths ' + '"/snap/foo/current/opt/ros/snap" --ignore-packages-from-source | (xargs ' + 'rosdep resolve --rosdistro "${ROS_DISTRO}" || echo "") | grep -v "#" >> ' + '"${SNAPCRAFT_PART_INSTALL}"/.installed_packages.txt', + "fi", + "", 'rosdep install --default-yes --ignore-packages-from-source --from-paths "${SNAPCRAFT_PART_SRC_WORK}"', 'state="$(set +o); set -$-"', "set +u", @@ -243,6 +271,19 @@ class Options: "fi", "", 'eval "${state}"', + "## Prepare build", + 'if [ -d "/snap/foo/current/opt/ros/${ROS_DISTRO}/share" ]; then ', + 'mkdir -p "${SNAPCRAFT_PART_BUILD}"/build_snaps/foo', + 'cp -r "/snap/foo/current/opt/ros/${ROS_DISTRO}/share" ' + '"${SNAPCRAFT_PART_BUILD}/build_snaps/foo/."', + 'find "${SNAPCRAFT_PART_BUILD}/build_snaps/foo" \\( -name "*Config.cmake" -o ' + '-name "*extras.cmake" \\) -exec sed -i -e "s|/opt|/snap/foo/current&|g" -e ' + '"s|/usr|/snap/foo/current&|g" -e ' + '"s|\\${.*_DIR}/../../..|/snap/foo/current/opt/ros/${ROS_DISTRO}|g" {} \\;', + "fi", + 'if [ -d "${SNAPCRAFT_PART_BUILD}"/build_snaps/foo ]; then export ' + 'CMAKE_PREFIX_PATH="${SNAPCRAFT_PART_BUILD}/build_snaps/foo:${CMAKE_PREFIX_PATH}"; ' + "fi", "## Build command", "catkin_make_isolated --install --merge " '--source-space "${SNAPCRAFT_PART_SRC_WORK}" --build-space "${SNAPCRAFT_PART_BUILD}" ' diff --git a/tests/legacy/unit/plugins/v2/test_colcon.py b/tests/legacy/unit/plugins/v2/test_colcon.py index 88db9bde07..b4519fe1c4 100644 --- a/tests/legacy/unit/plugins/v2/test_colcon.py +++ b/tests/legacy/unit/plugins/v2/test_colcon.py @@ -70,6 +70,7 @@ def test_get_build_packages(): "python3-rosdep", "python3-rosinstall", "python3-wstool", + "rospack-tools", } @@ -135,6 +136,8 @@ class Options: '. /opt/ros/"${ROS_DISTRO}"/local_setup.sh', "", 'eval "${state}"', + 'rm -f "${SNAPCRAFT_PART_INSTALL}/.installed_packages.txt"', + 'rm -f "${SNAPCRAFT_PART_INSTALL}/.build_snaps.txt"', 'rosdep install --default-yes --ignore-packages-from-source --from-paths "${SNAPCRAFT_PART_SRC_WORK}"', 'state="$(set +o); set -$-"', "set +u", @@ -233,6 +236,27 @@ class Options: '. /opt/ros/"${ROS_DISTRO}"/local_setup.sh', "", 'eval "${state}"', + 'rm -f "${SNAPCRAFT_PART_INSTALL}/.installed_packages.txt"', + 'rm -f "${SNAPCRAFT_PART_INSTALL}/.build_snaps.txt"', + "if [ -d /snap/foo/current/opt/ros ]; then", + "ROS_PACKAGE_PATH=/snap/foo/current/opt/ros rospack list-names | (xargs " + 'rosdep resolve --rosdistro "${ROS_DISTRO}" || echo "") | awk ' + '"/#apt/{getline;print;}" >> ' + '"${SNAPCRAFT_PART_INSTALL}/.installed_packages.txt"', + "fi", + 'if [ -d "/snap/foo/current/opt/ros/${ROS_DISTRO}/" ]; then', + 'rosdep keys --rosdistro "${ROS_DISTRO}" --from-paths ' + '"/snap/foo/current/opt/ros/${ROS_DISTRO}" --ignore-packages-from-source | ' + '(xargs rosdep resolve --rosdistro "${ROS_DISTRO}" || echo "") | grep -v "#" ' + '>> "${SNAPCRAFT_PART_INSTALL}"/.installed_packages.txt', + "fi", + 'if [ -d "/snap/foo/current/opt/ros/snap/" ]; then', + 'rosdep keys --rosdistro "${ROS_DISTRO}" --from-paths ' + '"/snap/foo/current/opt/ros/snap" --ignore-packages-from-source | (xargs ' + 'rosdep resolve --rosdistro "${ROS_DISTRO}" || echo "") | grep -v "#" >> ' + '"${SNAPCRAFT_PART_INSTALL}"/.installed_packages.txt', + "fi", + "", 'rosdep install --default-yes --ignore-packages-from-source --from-paths "${SNAPCRAFT_PART_SRC_WORK}"', 'state="$(set +o); set -$-"', "set +u", From a84df0a4b34c5ea27ebfc075fc4485a007e5dcdf Mon Sep 17 00:00:00 2001 From: artivis Date: Thu, 30 Mar 2023 09:42:48 +0200 Subject: [PATCH 08/84] ros: add noetic meta spread test Signed-off-by: artivis --- tests/spread/extensions/ros-meta/task.yaml | 77 +++++++++++++++++++ .../catkin-noetic-robot/snap/snapcraft.yaml | 21 +++++ .../src/snapcraft_hello/CMakeLists.txt | 22 ++++++ .../src/snapcraft_hello/package.xml | 13 ++++ .../src/snapcraft_hello/src/hello.cpp | 24 ++++++ .../snap/snapcraft.yaml | 21 +++++ .../src/snapcraft_hello/CMakeLists.txt | 22 ++++++ .../src/snapcraft_hello/package.xml | 13 ++++ .../src/snapcraft_hello/src/hello.cpp | 24 ++++++ 9 files changed, 237 insertions(+) create mode 100644 tests/spread/extensions/ros-meta/task.yaml create mode 100644 tests/spread/extensions/snaps/catkin-noetic-robot/snap/snapcraft.yaml create mode 100644 tests/spread/extensions/snaps/catkin-noetic-robot/src/snapcraft_hello/CMakeLists.txt create mode 100644 tests/spread/extensions/snaps/catkin-noetic-robot/src/snapcraft_hello/package.xml create mode 100644 tests/spread/extensions/snaps/catkin-noetic-robot/src/snapcraft_hello/src/hello.cpp create mode 100644 tests/spread/extensions/snaps/catkin-noetic-ros-core/snap/snapcraft.yaml create mode 100644 tests/spread/extensions/snaps/catkin-noetic-ros-core/src/snapcraft_hello/CMakeLists.txt create mode 100644 tests/spread/extensions/snaps/catkin-noetic-ros-core/src/snapcraft_hello/package.xml create mode 100644 tests/spread/extensions/snaps/catkin-noetic-ros-core/src/snapcraft_hello/src/hello.cpp diff --git a/tests/spread/extensions/ros-meta/task.yaml b/tests/spread/extensions/ros-meta/task.yaml new file mode 100644 index 0000000000..b7d35480d9 --- /dev/null +++ b/tests/spread/extensions/ros-meta/task.yaml @@ -0,0 +1,77 @@ +summary: Build and run a basic ROS snap using meta-ros extension + +kill-timeout: 180m + +environment: + SNAP/catkin_noetic_ros_core: catkin-noetic-ros-core + META_SNAP/catkin_noetic_ros_core: ros-meta-ros-core + # SNAP/catkin_noetic_ros_base: catkin-noetic-ros-base + # META_SNAP/catkin_noetic_ros_base: ros-meta-ros-base + SNAP/catkin_noetic_robot: catkin-noetic-robot + META_SNAP/catkin_noetic_robot: ros-meta-robot + # SNAP/catkin_noetic_desktop: catkin-noetic-desktop + # META_SNAP/catkin_noetic_desktop: ros-meta-desktop + SNAP_DIR: "../snaps/$SNAP" + +# The content snap required for the test to succeed is only +# available on a subset of all the architectures this testbed +# can run on. +systems: + - ubuntu-20.04 + - ubuntu-20.04-64 + - ubuntu-20.04-amd64 + - ubuntu-20.04-arm64 + +prepare: | + #shellcheck source=tests/spread/tools/snapcraft-yaml.sh + . "$TOOLS_DIR/snapcraft-yaml.sh" + set_base "$SNAP_DIR/snap/snapcraft.yaml" + +restore: | + cd "$SNAP_DIR" + snapcraft clean + rm -f ./*.snap + + [ -f src/snapcraft_hello/src/hello.cpp ] && git checkout src/snapcraft_hello/src/hello.cpp + + #shellcheck source=tests/spread/tools/snapcraft-yaml.sh + . "$TOOLS_DIR/snapcraft-yaml.sh" + restore_yaml "snap/snapcraft.yaml" + +execute: | + cd "$SNAP_DIR" + + # Build what we have and verify the snap runs as expected. + snapcraft + snap install "${SNAP}"_1.0_*.snap --dangerous + + # Check that the snap size is fairly small + # The non-content sharing snap is ~90M + SNAP_SIZE=$(ls -s "${SNAP}"_1.0_*.snap | cut -d " " -f1) + [ "100" -gt "$SNAP_SIZE" ] + + snap connect ${SNAP}:ros-meta ${META_SNAP} + [ "$($SNAP)" = "hello world" ] + + # Clean the hello part, then build and run again. + snapcraft clean hello + snapcraft + snap install "${SNAP}"_1.0_*.snap --dangerous + + snap connect ${SNAP}:ros-meta ${META_SNAP} + [ "$($SNAP)" = "hello world" ] + + # Make sure that what we built runs with the changes applied. + if [ -f src/snapcraft_hello/src/hello.cpp ]; then + modified_file=src/snapcraft_hello/src/hello.cpp + else + FATAL "Cannot setup ${SNAP} for rebuilding" + fi + + sed -i "${modified_file}" -e 's/hello world/hello rebuilt world/' + + snapcraft + snap install "${SNAP}"_1.0_*.snap --dangerous + + snap connect ${SNAP}:ros-meta ${META_SNAP} + [ "$($SNAP)" = "hello rebuilt world" ] diff --git a/tests/spread/extensions/snaps/catkin-noetic-robot/snap/snapcraft.yaml b/tests/spread/extensions/snaps/catkin-noetic-robot/snap/snapcraft.yaml new file mode 100644 index 0000000000..4f70aae3e6 --- /dev/null +++ b/tests/spread/extensions/snaps/catkin-noetic-robot/snap/snapcraft.yaml @@ -0,0 +1,21 @@ +name: catkin-noetic-robot +version: "1.0" +summary: hello world +description: | + A ROS 1 roscpp-based workspace. + +grade: stable +confinement: strict +base: core20 + +apps: + catkin-noetic-robot: + command: opt/ros/noetic/lib/snapcraft_hello/snapcraft_hello + plugs: [network, network-bind] + extensions: [ros1-noetic-robot] + +parts: + hello: + plugin: catkin + source: . + build-packages: [g++, make] diff --git a/tests/spread/extensions/snaps/catkin-noetic-robot/src/snapcraft_hello/CMakeLists.txt b/tests/spread/extensions/snaps/catkin-noetic-robot/src/snapcraft_hello/CMakeLists.txt new file mode 100644 index 0000000000..af5cba06c3 --- /dev/null +++ b/tests/spread/extensions/snaps/catkin-noetic-robot/src/snapcraft_hello/CMakeLists.txt @@ -0,0 +1,22 @@ +cmake_minimum_required(VERSION 3.0.2) +project(snapcraft_hello) + +find_package(catkin REQUIRED COMPONENTS + roscpp +) + +catkin_package() + +include_directories( + ${catkin_INCLUDE_DIRS} +) + +add_executable(${PROJECT_NAME} src/hello.cpp) + +target_link_libraries(${PROJECT_NAME} + ${catkin_LIBRARIES} +) + +install(TARGETS ${PROJECT_NAME} + RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} +) diff --git a/tests/spread/extensions/snaps/catkin-noetic-robot/src/snapcraft_hello/package.xml b/tests/spread/extensions/snaps/catkin-noetic-robot/src/snapcraft_hello/package.xml new file mode 100644 index 0000000000..3e92ea7b10 --- /dev/null +++ b/tests/spread/extensions/snaps/catkin-noetic-robot/src/snapcraft_hello/package.xml @@ -0,0 +1,13 @@ + + + snapcraft_hello + 0.0.1 + snapcraft test for roscpp + me + GPLv3 + catkin + roscpp + fake_package_that_does_not_exists + roscpp + roscpp + diff --git a/tests/spread/extensions/snaps/catkin-noetic-robot/src/snapcraft_hello/src/hello.cpp b/tests/spread/extensions/snaps/catkin-noetic-robot/src/snapcraft_hello/src/hello.cpp new file mode 100644 index 0000000000..46e30f4564 --- /dev/null +++ b/tests/spread/extensions/snaps/catkin-noetic-robot/src/snapcraft_hello/src/hello.cpp @@ -0,0 +1,24 @@ +// Copyright (C) 2020 Canonical Ltd +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 3 as +// published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include +#include + +int main(int argc, char * argv[]) +{ + ros::init(argc, argv, "snapcraft_hello"); + std::cout << "hello world" << std::endl; + ros::shutdown(); + return 0; +} diff --git a/tests/spread/extensions/snaps/catkin-noetic-ros-core/snap/snapcraft.yaml b/tests/spread/extensions/snaps/catkin-noetic-ros-core/snap/snapcraft.yaml new file mode 100644 index 0000000000..f234a9c930 --- /dev/null +++ b/tests/spread/extensions/snaps/catkin-noetic-ros-core/snap/snapcraft.yaml @@ -0,0 +1,21 @@ +name: catkin-noetic-ros-core +version: "1.0" +summary: hello world +description: | + A ROS 1 roscpp-based workspace. + +grade: stable +confinement: strict +base: core20 + +apps: + catkin-noetic-ros-core: + command: opt/ros/noetic/lib/snapcraft_hello/snapcraft_hello + plugs: [network, network-bind] + extensions: [ros1-noetic-ros-core] + +parts: + hello: + plugin: catkin + source: . + build-packages: [g++, make] diff --git a/tests/spread/extensions/snaps/catkin-noetic-ros-core/src/snapcraft_hello/CMakeLists.txt b/tests/spread/extensions/snaps/catkin-noetic-ros-core/src/snapcraft_hello/CMakeLists.txt new file mode 100644 index 0000000000..af5cba06c3 --- /dev/null +++ b/tests/spread/extensions/snaps/catkin-noetic-ros-core/src/snapcraft_hello/CMakeLists.txt @@ -0,0 +1,22 @@ +cmake_minimum_required(VERSION 3.0.2) +project(snapcraft_hello) + +find_package(catkin REQUIRED COMPONENTS + roscpp +) + +catkin_package() + +include_directories( + ${catkin_INCLUDE_DIRS} +) + +add_executable(${PROJECT_NAME} src/hello.cpp) + +target_link_libraries(${PROJECT_NAME} + ${catkin_LIBRARIES} +) + +install(TARGETS ${PROJECT_NAME} + RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} +) diff --git a/tests/spread/extensions/snaps/catkin-noetic-ros-core/src/snapcraft_hello/package.xml b/tests/spread/extensions/snaps/catkin-noetic-ros-core/src/snapcraft_hello/package.xml new file mode 100644 index 0000000000..3e92ea7b10 --- /dev/null +++ b/tests/spread/extensions/snaps/catkin-noetic-ros-core/src/snapcraft_hello/package.xml @@ -0,0 +1,13 @@ + + + snapcraft_hello + 0.0.1 + snapcraft test for roscpp + me + GPLv3 + catkin + roscpp + fake_package_that_does_not_exists + roscpp + roscpp + diff --git a/tests/spread/extensions/snaps/catkin-noetic-ros-core/src/snapcraft_hello/src/hello.cpp b/tests/spread/extensions/snaps/catkin-noetic-ros-core/src/snapcraft_hello/src/hello.cpp new file mode 100644 index 0000000000..46e30f4564 --- /dev/null +++ b/tests/spread/extensions/snaps/catkin-noetic-ros-core/src/snapcraft_hello/src/hello.cpp @@ -0,0 +1,24 @@ +// Copyright (C) 2020 Canonical Ltd +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 3 as +// published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include +#include + +int main(int argc, char * argv[]) +{ + ros::init(argc, argv, "snapcraft_hello"); + std::cout << "hello world" << std::endl; + ros::shutdown(); + return 0; +} From 7b1a63df0551f68cead5d4a66b16726bf3b9ae0a Mon Sep 17 00:00:00 2001 From: artivis Date: Wed, 5 Apr 2023 14:43:10 +0200 Subject: [PATCH 09/84] ros: add foxy meta extensions Signed-off-by: artivis --- schema/snapcraft.json | 5 +- .../_extensions/_ros2_foxy_meta.py | 56 +++++++++++++++++++ .../_extensions/ros2_foxy_desktop.py | 28 ++++++++++ .../_extensions/ros2_foxy_ros_base.py | 28 ++++++++++ .../_extensions/ros2_foxy_ros_core.py | 28 ++++++++++ 5 files changed, 144 insertions(+), 1 deletion(-) create mode 100644 snapcraft_legacy/internal/project_loader/_extensions/_ros2_foxy_meta.py create mode 100644 snapcraft_legacy/internal/project_loader/_extensions/ros2_foxy_desktop.py create mode 100644 snapcraft_legacy/internal/project_loader/_extensions/ros2_foxy_ros_base.py create mode 100644 snapcraft_legacy/internal/project_loader/_extensions/ros2_foxy_ros_core.py diff --git a/schema/snapcraft.json b/schema/snapcraft.json index f73d4d4bac..3cc20cbaf3 100644 --- a/schema/snapcraft.json +++ b/schema/snapcraft.json @@ -920,7 +920,10 @@ "ros1-noetic-robot", "ros1-noetic-ros-base", "ros1-noetic-ros-core", - "ros2-foxy" + "ros2-foxy", + "ros2-foxy-ros-base", + "ros2-foxy-ros-core", + "ros2-foxy-desktop" ] } } diff --git a/snapcraft_legacy/internal/project_loader/_extensions/_ros2_foxy_meta.py b/snapcraft_legacy/internal/project_loader/_extensions/_ros2_foxy_meta.py new file mode 100644 index 0000000000..d5380d5413 --- /dev/null +++ b/snapcraft_legacy/internal/project_loader/_extensions/_ros2_foxy_meta.py @@ -0,0 +1,56 @@ +# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*- +# +# Copyright (C) 2023 Canonical Ltd +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 3 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Import types and tell flake8 to ignore the "unused" List. + +from typing import Any, Dict + +from .ros2_foxy import ExtensionImpl as RosFoxyExtension + + +class RosFoxyMetaBase(RosFoxyExtension): + """Setup a ROS 2 build and runtime environment suitable for a snap.""" + + def __init__(self, *, extension_name: str, yaml_data: Dict[str, Any]) -> None: + super().__init__(extension_name=extension_name, yaml_data=yaml_data) + + # python_paths = [ + # f"$SNAP/opt/ros/{self.ROS_DISTRO}/lib/python3.8/site-packages", + # "$SNAP/usr/lib/python3/dist-packages", + # "${PYTHONPATH}", + # ] + + # Very unlikely but it may happen that the snapped application doesn't + # even pull those deps. In that case, there is no valid ROS 2 ws to source. + # We make sure here that they are staged no matter what. + self.parts[f"ros2-{self.ROS_DISTRO}-extension"]["stage-packages"] = [ + f"ros-{self.ROS_DISTRO}-ros-environment", + f"ros-{self.ROS_DISTRO}-ros-workspace", + f"ros-{self.ROS_DISTRO}-ament-index-cpp", + f"ros-{self.ROS_DISTRO}-ament-index-python", + ] + + self.root_snippet["plugs"] = { + "ros-meta": + { + "interface": "content", + "content": "ros2-meta", + "target": "$SNAP/opt/ros/underlay_ws", + "default-provider": self.ROS_META, + } + } + + self.part_snippet["build-snaps"] = [self.ROS_META_DEV] diff --git a/snapcraft_legacy/internal/project_loader/_extensions/ros2_foxy_desktop.py b/snapcraft_legacy/internal/project_loader/_extensions/ros2_foxy_desktop.py new file mode 100644 index 0000000000..b369ebb473 --- /dev/null +++ b/snapcraft_legacy/internal/project_loader/_extensions/ros2_foxy_desktop.py @@ -0,0 +1,28 @@ +# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*- +# +# Copyright (C) 2023 Canonical Ltd +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 3 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Import types and tell flake8 to ignore the "unused" List. + +from typing_extensions import Final + +from ._ros2_foxy_meta import RosFoxyMetaBase + + +class ExtensionImpl(RosFoxyMetaBase): + """Setup a ROS 2 build and runtime environment suitable for a snap.""" + + ROS_META: Final[str] = "ros2-meta-desktop" + ROS_META_DEV: Final[str] = "ros2-meta-desktop" diff --git a/snapcraft_legacy/internal/project_loader/_extensions/ros2_foxy_ros_base.py b/snapcraft_legacy/internal/project_loader/_extensions/ros2_foxy_ros_base.py new file mode 100644 index 0000000000..2f8bf80b56 --- /dev/null +++ b/snapcraft_legacy/internal/project_loader/_extensions/ros2_foxy_ros_base.py @@ -0,0 +1,28 @@ +# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*- +# +# Copyright (C) 2023 Canonical Ltd +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 3 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Import types and tell flake8 to ignore the "unused" List. + +from typing_extensions import Final + +from ._ros2_foxy_meta import RosFoxyMetaBase + + +class ExtensionImpl(RosFoxyMetaBase): + """Setup a ROS 2 build and runtime environment suitable for a snap.""" + + ROS_META: Final[str] = "ros2-meta-ros-base" + ROS_META_DEV: Final[str] = "ros2-meta-ros-base" diff --git a/snapcraft_legacy/internal/project_loader/_extensions/ros2_foxy_ros_core.py b/snapcraft_legacy/internal/project_loader/_extensions/ros2_foxy_ros_core.py new file mode 100644 index 0000000000..b4f8f854ab --- /dev/null +++ b/snapcraft_legacy/internal/project_loader/_extensions/ros2_foxy_ros_core.py @@ -0,0 +1,28 @@ +# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*- +# +# Copyright (C) 2023 Canonical Ltd +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 3 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Import types and tell flake8 to ignore the "unused" List. + +from typing_extensions import Final + +from ._ros2_foxy_meta import RosFoxyMetaBase + + +class ExtensionImpl(RosFoxyMetaBase): + """Setup a ROS 2 build and runtime environment suitable for a snap.""" + + ROS_META: Final[str] = "ros2-meta-ros-core" + ROS_META_DEV: Final[str] = "ros2-meta-ros-core" From 7e2415dfe8b453ba218c2686f4405ce9de8f9634 Mon Sep 17 00:00:00 2001 From: artivis Date: Wed, 5 Apr 2023 14:49:32 +0200 Subject: [PATCH 10/84] ros: add foxy meta spread test Signed-off-by: artivis --- tests/spread/extensions/ros2-meta/task.yaml | 75 +++++++++++++++++++ .../snaps/colcon-foxy-ros-core/CMakeLists.txt | 34 +++++++++ .../snaps/colcon-foxy-ros-core/package.xml | 25 +++++++ .../colcon-foxy-ros-core/snap/snapcraft.yaml | 21 ++++++ .../snaps/colcon-foxy-ros-core/src/hello.cpp | 28 +++++++ 5 files changed, 183 insertions(+) create mode 100644 tests/spread/extensions/ros2-meta/task.yaml create mode 100644 tests/spread/extensions/snaps/colcon-foxy-ros-core/CMakeLists.txt create mode 100644 tests/spread/extensions/snaps/colcon-foxy-ros-core/package.xml create mode 100644 tests/spread/extensions/snaps/colcon-foxy-ros-core/snap/snapcraft.yaml create mode 100644 tests/spread/extensions/snaps/colcon-foxy-ros-core/src/hello.cpp diff --git a/tests/spread/extensions/ros2-meta/task.yaml b/tests/spread/extensions/ros2-meta/task.yaml new file mode 100644 index 0000000000..0bc5e4a79b --- /dev/null +++ b/tests/spread/extensions/ros2-meta/task.yaml @@ -0,0 +1,75 @@ +summary: Build and run a basic ROS 2 snap using meta-ros extension + +kill-timeout: 180m + +environment: + SNAP/colcon_foxy_ros_core: colcon-foxy-ros-core + META_SNAP/colcon_foxy_ros_core: ros2-meta-ros-core + SNAP/colcon_foxy_ros_base: colcon-foxy-ros-core + META_SNAP/colcon_foxy_ros_base: ros2-meta-ros-base + # SNAP/colcon_foxy_desktop: colcon-foxy-desktop + # META_SNAP/colcon_foxy_desktop: ros-meta-desktop + SNAP_DIR: "../snaps/$SNAP" + +# The content snap required for the test to succeed is only +# available on a subset of all the architectures this testbed +# can run on. +systems: + - ubuntu-20.04 + - ubuntu-20.04-64 + - ubuntu-20.04-amd64 + - ubuntu-20.04-arm64 + +prepare: | + #shellcheck source=tests/spread/tools/snapcraft-yaml.sh + . "$TOOLS_DIR/snapcraft-yaml.sh" + set_base "$SNAP_DIR/snap/snapcraft.yaml" + +restore: | + cd "$SNAP_DIR" + snapcraft clean + rm -f ./*.snap + + [ -f src/colcon-foxy-ros-core/src/hello.cpp ] && git checkout src/colcon-foxy-ros-core/src/hello.cpp + + #shellcheck source=tests/spread/tools/snapcraft-yaml.sh + . "$TOOLS_DIR/snapcraft-yaml.sh" + restore_yaml "snap/snapcraft.yaml" + +execute: | + cd "$SNAP_DIR" + + # Build what we have and verify the snap runs as expected. + snapcraft + snap install "${SNAP}"_1.0_*.snap --dangerous + + # Check that the snap size is fairly small + # The non-content sharing snap is ~90M + SNAP_SIZE=$(ls -s "${SNAP}"_1.0_*.snap | cut -d " " -f1) + [ "200" -gt "$SNAP_SIZE" ] + + snap connect ${SNAP}:ros-meta ${META_SNAP} + [ "$($SNAP)" = "hello world" ] + + # Clean the hello part, then build and run again. + snapcraft clean hello + snapcraft + snap install "${SNAP}"_1.0_*.snap --dangerous + + snap connect ${SNAP}:ros-meta ${META_SNAP} + [ "$($SNAP)" = "hello world" ] + + # Make sure that what we built runs with the changes applied. + if [ -f src/hello.cpp ]; then + modified_file=src/hello.cpp + else + FATAL "Cannot setup ${SNAP} for rebuilding" + fi + + sed -i "${modified_file}" -e 's/hello world/hello rebuilt world/' + + snapcraft + snap install "${SNAP}"_1.0_*.snap --dangerous + + snap connect ${SNAP}:ros-meta ${META_SNAP} + [ "$($SNAP)" = "hello rebuilt world" ] diff --git a/tests/spread/extensions/snaps/colcon-foxy-ros-core/CMakeLists.txt b/tests/spread/extensions/snaps/colcon-foxy-ros-core/CMakeLists.txt new file mode 100644 index 0000000000..c014f3f36d --- /dev/null +++ b/tests/spread/extensions/snaps/colcon-foxy-ros-core/CMakeLists.txt @@ -0,0 +1,34 @@ +cmake_minimum_required(VERSION 3.5) +project(colcon_ros2_rlcpp_hello) + +# Default to C++14 +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 14) +endif() + +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() + +find_package(ament_cmake REQUIRED) +find_package(rclcpp REQUIRED) +find_package(rclcpp_components REQUIRED) +find_package(std_msgs REQUIRED) + +# This package installs libraries without exporting them. +# Export the library path to ensure that the installed libraries are available. +if(NOT WIN32) + ament_environment_hooks( + "${ament_cmake_package_templates_ENVIRONMENT_HOOK_LIBRARY_PATH}" + ) +endif() + +add_executable(colcon_ros2_rlcpp_hello src/hello.cpp) +target_link_libraries(colcon_ros2_rlcpp_hello) +ament_target_dependencies(colcon_ros2_rlcpp_hello rclcpp class_loader) + +install(TARGETS + colcon_ros2_rlcpp_hello + DESTINATION lib/${PROJECT_NAME}) + +ament_package() diff --git a/tests/spread/extensions/snaps/colcon-foxy-ros-core/package.xml b/tests/spread/extensions/snaps/colcon-foxy-ros-core/package.xml new file mode 100644 index 0000000000..133e482823 --- /dev/null +++ b/tests/spread/extensions/snaps/colcon-foxy-ros-core/package.xml @@ -0,0 +1,25 @@ + + + + colcon_ros2_rlcpp_hello + 0.0.1 + snapcraft test for rlcpp + me + Apache License 2.0 + + ament_cmake + + rclcpp + rclcpp_components + std_msgs + fake_package_that_does_not_exists + + rclcpp + rclcpp_components + ros2run + std_msgs + + + ament_cmake + + diff --git a/tests/spread/extensions/snaps/colcon-foxy-ros-core/snap/snapcraft.yaml b/tests/spread/extensions/snaps/colcon-foxy-ros-core/snap/snapcraft.yaml new file mode 100644 index 0000000000..80e185c970 --- /dev/null +++ b/tests/spread/extensions/snaps/colcon-foxy-ros-core/snap/snapcraft.yaml @@ -0,0 +1,21 @@ +name: colcon-foxy-ros-core +version: "1.0" +summary: hello world +description: | + A ROS2 rlcpp-based workspace. + +grade: stable +confinement: strict +base: core20 + +apps: + colcon-foxy-ros-core: + command: ros2 run colcon_ros2_rlcpp_hello colcon_ros2_rlcpp_hello + plugs: [network, network-bind] + extensions: [ros2-foxy-ros-core] + +parts: + hello: + plugin: colcon + source: . + build-packages: [g++, make] diff --git a/tests/spread/extensions/snaps/colcon-foxy-ros-core/src/hello.cpp b/tests/spread/extensions/snaps/colcon-foxy-ros-core/src/hello.cpp new file mode 100644 index 0000000000..770203acec --- /dev/null +++ b/tests/spread/extensions/snaps/colcon-foxy-ros-core/src/hello.cpp @@ -0,0 +1,28 @@ +// Copyright 2016 Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include "rclcpp/rclcpp.hpp" + +int main(int argc, char * argv[]) +{ + rclcpp::init(argc, argv); + rclcpp::executors::SingleThreadedExecutor exec; + rclcpp::NodeOptions options; + + printf("hello world"); + + rclcpp::shutdown(); + return 0; +} From fea4d039f15205199c31ffafc6b56080e0707de2 Mon Sep 17 00:00:00 2001 From: artivis Date: Wed, 12 Apr 2023 11:15:13 +0200 Subject: [PATCH 11/84] ros: command-chain source content-sharing ws ros2 Signed-off-by: artivis --- extensions/ros2/launch | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/extensions/ros2/launch b/extensions/ros2/launch index fc6dab06a8..1cf3fd7016 100755 --- a/extensions/ros2/launch +++ b/extensions/ros2/launch @@ -13,6 +13,14 @@ function source_with_prefix() { # Save off parameters, the sourced setup scripts may manipulate them. original_args=("$@") +if [ -d "$SNAP/opt/ros/underlay_ws/opt/ros/$ROS_DISTRO" ]; then + source_with_prefix "$SNAP/opt/ros/underlay_ws/opt/ros/$ROS_DISTRO" +fi +if [ -d "$SNAP/opt/ros/underlay_ws/opt/ros/snap" ]; then + source_with_prefix "$SNAP/opt/ros/underlay_ws/opt/ros/snap" + export LD_LIBRARY_PATH="$SNAP/opt/ros/underlay_ws/usr/lib/x86_64-linux-gnu:${LD_LIBRARY_PATH}" +fi + source_with_prefix "$SNAP/opt/ros/$ROS_DISTRO" source_with_prefix "$SNAP/opt/ros/snap" From 556161ab8e8cd87c6f3f0123a7f8bd8aefaf52eb Mon Sep 17 00:00:00 2001 From: artivis Date: Wed, 12 Apr 2023 11:21:09 +0200 Subject: [PATCH 12/84] ros: colcon export CMAKE_PREFIX_PATH pointing to build snap Signed-off-by: artivis --- snapcraft_legacy/plugins/v2/colcon.py | 49 +++++++++++++++++++-------- 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/snapcraft_legacy/plugins/v2/colcon.py b/snapcraft_legacy/plugins/v2/colcon.py index d560a5dd48..551fe9f245 100644 --- a/snapcraft_legacy/plugins/v2/colcon.py +++ b/snapcraft_legacy/plugins/v2/colcon.py @@ -173,7 +173,20 @@ def _get_workspace_activation_commands(self) -> List[str]: return activation_commands def _get_build_commands(self) -> List[str]: - cmd = [ + + export_command = list() + + if self.options.build_snaps: + for build_snap in self.options.build_snaps: + build_snap = _get_parsed_snap(build_snap)[0] + + export_command.extend([ + 'if [ -d "/snap/{build_snap}/current" ]; then ' + 'export CMAKE_PREFIX_PATH="/snap/{build_snap}/current:/snap/{build_snap}/current/usr:${{CMAKE_PREFIX_PATH}}"; ' + 'fi'.format(build_snap=build_snap) + ]) + + build_command = [ "colcon", "build", "--base-paths", @@ -186,27 +199,33 @@ def _get_build_commands(self) -> List[str]: ] if self.options.colcon_packages_ignore: - cmd.extend(["--packages-ignore", *self.options.colcon_packages_ignore]) + build_command.extend(["--packages-ignore", *self.options.colcon_packages_ignore]) if self.options.colcon_packages: - cmd.extend(["--packages-select", *self.options.colcon_packages]) + build_command.extend(["--packages-select", *self.options.colcon_packages]) if self.options.colcon_cmake_args: - cmd.extend(["--cmake-args", *self.options.colcon_cmake_args]) + build_command.extend(["--cmake-args", *self.options.colcon_cmake_args]) if self.options.colcon_ament_cmake_args: - cmd.extend(["--ament-cmake-args", *self.options.colcon_ament_cmake_args]) + build_command.extend(["--ament-cmake-args", *self.options.colcon_ament_cmake_args]) if self.options.colcon_catkin_cmake_args: - cmd.extend(["--catkin-cmake-args", *self.options.colcon_catkin_cmake_args]) + build_command.extend(["--catkin-cmake-args", *self.options.colcon_catkin_cmake_args]) # Specify the number of workers - cmd.extend(["--parallel-workers", '"${SNAPCRAFT_PARALLEL_BUILD_COUNT}"']) - - return ["## Build command", " ".join(cmd)] + [ - # Remove the COLCON_IGNORE marker so that, at staging, - # catkin can crawl the entire folder to look up for packages. - 'if [ -f "${SNAPCRAFT_PART_INSTALL}"/opt/ros/snap/COLCON_IGNORE ]; then', - 'rm "${SNAPCRAFT_PART_INSTALL}"/opt/ros/snap/COLCON_IGNORE', - "fi", - ] + build_command.extend(["--parallel-workers", '"${SNAPCRAFT_PARALLEL_BUILD_COUNT}"']) + + return ( + ["## Prepare build"] + + export_command + + ["## Build command", " ".join(build_command)] + + [ + "## Post build command", + # Remove the COLCON_IGNORE marker so that, at staging, + # catkin can crawl the entire folder to look up for packages. + 'if [ -f "${SNAPCRAFT_PART_INSTALL}"/opt/ros/snap/COLCON_IGNORE ]; then', + 'rm "${SNAPCRAFT_PART_INSTALL}"/opt/ros/snap/COLCON_IGNORE', + "fi", + ] + ) From f6f3a857fee10d02b12c771b66f463604b338945 Mon Sep 17 00:00:00 2001 From: gbeuzeboc Date: Thu, 20 Apr 2023 13:43:34 +0200 Subject: [PATCH 13/84] feat(ros-content-sharing): recursively unmark the dependencies --- snapcraft_legacy/plugins/v2/_ros.py | 51 +++++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 7 deletions(-) diff --git a/snapcraft_legacy/plugins/v2/_ros.py b/snapcraft_legacy/plugins/v2/_ros.py index 019797b56d..71347d97cb 100644 --- a/snapcraft_legacy/plugins/v2/_ros.py +++ b/snapcraft_legacy/plugins/v2/_ros.py @@ -238,6 +238,47 @@ def plugin_cli(): pass +def get_installed_dependencies(installed_packages_path: str) -> Set[str]: + try: + with open(installed_packages_path, "r") as f: + build_snap_packages = set(f.read().split()) + package_dependencies = set() + for package in build_snap_packages: + try: + cmd = [ + "apt", + "depends", + "--recurse", + "--no-recommends", + "--no-suggests", + "--no-conflicts", + "--no-breaks", + "--no-replaces", + "--no-enhances", + f"{package}", + ] + click.echo(f"Running {cmd!r}") + proc = subprocess.run( + cmd, + check=True, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + env=dict(PATH=os.environ["PATH"]), + ) + except subprocess.CalledProcessError as error: + click.echo(f"failed to run {cmd!r}: {error.output}") + apt_dependency_regex = re.compile("^\w.*$") + for line in proc.stdout.decode().strip().split("\n"): + if apt_dependency_regex.match(line): + package_dependencies.add(line) + + build_snap_packages.update(package_dependencies) + click.echo(f"Will not fetch staged packages: {build_snap_packages!r}") + return build_snap_packages + except IOError: + return Set(str) + + @plugin_cli.command() @click.option("--part-src", envvar="SNAPCRAFT_PART_SRC_WORK", required=True) @click.option("--part-install", envvar="SNAPCRAFT_PART_INSTALL", required=True) @@ -294,13 +335,9 @@ def stage_runtime_dependencies( if parsed: click.echo(f"unhandled dependencies: {parsed!r}") - build_snap_packages: Set[str] = set() - try: - with open(part_install + "/.installed_packages.txt", "r") as f: - build_snap_packages = set(f.read().split()) - click.echo(f"Will not fetch staged packages: {build_snap_packages!r}") - except IOError: - pass + build_snap_packages = get_installed_dependencies( + part_install + "/.installed_packages.txt" + ) if apt_packages: package_names = sorted(apt_packages) From bb9dd386d0dfe9d7aefed3b0637f0a30922f272e Mon Sep 17 00:00:00 2001 From: gbeuzeboc Date: Thu, 20 Apr 2023 13:45:32 +0200 Subject: [PATCH 14/84] test(spread): catkin noetic content sharing --- tests/spread/plugins/v2/ros1-hello/task.yaml | 19 +++++++++++++ .../snap/snapcraft.yaml | 21 ++++++++++++++ .../src/snapcraft_hello/CMakeLists.txt | 28 +++++++++++++++++++ .../src/snapcraft_hello/package.xml | 15 ++++++++++ .../src/snapcraft_hello/src/hello.cpp | 28 +++++++++++++++++++ 5 files changed, 111 insertions(+) create mode 100644 tests/spread/plugins/v2/snaps/catkin-noetic-content-sharing/snap/snapcraft.yaml create mode 100644 tests/spread/plugins/v2/snaps/catkin-noetic-content-sharing/src/snapcraft_hello/CMakeLists.txt create mode 100644 tests/spread/plugins/v2/snaps/catkin-noetic-content-sharing/src/snapcraft_hello/package.xml create mode 100644 tests/spread/plugins/v2/snaps/catkin-noetic-content-sharing/src/snapcraft_hello/src/hello.cpp diff --git a/tests/spread/plugins/v2/ros1-hello/task.yaml b/tests/spread/plugins/v2/ros1-hello/task.yaml index 0150d966a1..e3cf196bab 100644 --- a/tests/spread/plugins/v2/ros1-hello/task.yaml +++ b/tests/spread/plugins/v2/ros1-hello/task.yaml @@ -10,6 +10,7 @@ environment: SNAP/catkin_tools_noetic_hello: catkin-tools-noetic-hello SNAP/catkin_tools_noetic_subdir: catkin-tools-noetic-subdir SNAP/catkin_rosrun_wrapper: catkin-rosrun-wrapper + SNAP/catkin_noetic_content_sharing: catkin-noetic-content-sharing systems: - ubuntu-20.04 @@ -40,6 +41,24 @@ execute: | # Build what we have and verify the snap runs as expected. snapcraft snap install "${SNAP}"_1.0_*.snap --dangerous + + # Check specific to content sharing SNAP + if [ "$SNAP" = "catkin-noetic-content-sharing" ]; then + # Make sure final snap doesn't contain roscpp or roslaunch pkg + for to_check in \ + "/snap/$SNAP/current/opt/ros/noetic/share/roscpp" \ + "/snap/$SNAP/current/opt/ros/noetic/share/roslaunch" \ + "/snap/$SNAP/current/usr/lib/x86_64-linux-gnu/libboost_filesystem.so.1.71.0" + do + if [ -e "$to_check" ]; then + FATAL "The $SNAP is containing $to_check from the content-sharing snap" + fi + done + + # Connect the content sharing snap + snap connect $SNAP:ros-meta ros-meta-ros-core:ros-core + fi + [ "$($SNAP)" = "hello world" ] # Clean the hello part, then build and run again. diff --git a/tests/spread/plugins/v2/snaps/catkin-noetic-content-sharing/snap/snapcraft.yaml b/tests/spread/plugins/v2/snaps/catkin-noetic-content-sharing/snap/snapcraft.yaml new file mode 100644 index 0000000000..c35dab0fca --- /dev/null +++ b/tests/spread/plugins/v2/snaps/catkin-noetic-content-sharing/snap/snapcraft.yaml @@ -0,0 +1,21 @@ +name: catkin-noetic-content-sharing +version: "1.0" +summary: hello world +description: | + A ROS 1 roscpp-based workspace. + +grade: stable +confinement: strict +base: core20 + +apps: + catkin-noetic-content-sharing: + command: opt/ros/noetic/lib/snapcraft_hello/snapcraft_hello + plugs: [network, network-bind] + extensions: [ros1-noetic-ros-core] + +parts: + hello: + plugin: catkin + source: . + build-packages: [g++, make] diff --git a/tests/spread/plugins/v2/snaps/catkin-noetic-content-sharing/src/snapcraft_hello/CMakeLists.txt b/tests/spread/plugins/v2/snaps/catkin-noetic-content-sharing/src/snapcraft_hello/CMakeLists.txt new file mode 100644 index 0000000000..5102c8946f --- /dev/null +++ b/tests/spread/plugins/v2/snaps/catkin-noetic-content-sharing/src/snapcraft_hello/CMakeLists.txt @@ -0,0 +1,28 @@ +cmake_minimum_required(VERSION 3.0.2) +project(snapcraft_hello) + +find_package(catkin REQUIRED COMPONENTS + roscpp +) + +find_package( Boost REQUIRED COMPONENTS + filesystem +) + +catkin_package() + +include_directories( + ${catkin_INCLUDE_DIRS} + ${Boost_INCLUDE_DIRS} +) + +add_executable(${PROJECT_NAME} src/hello.cpp) + +target_link_libraries(${PROJECT_NAME} + ${catkin_LIBRARIES} + ${Boost_LIBRARIES} +) + +install(TARGETS ${PROJECT_NAME} + RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} +) diff --git a/tests/spread/plugins/v2/snaps/catkin-noetic-content-sharing/src/snapcraft_hello/package.xml b/tests/spread/plugins/v2/snaps/catkin-noetic-content-sharing/src/snapcraft_hello/package.xml new file mode 100644 index 0000000000..c4e3788aa9 --- /dev/null +++ b/tests/spread/plugins/v2/snaps/catkin-noetic-content-sharing/src/snapcraft_hello/package.xml @@ -0,0 +1,15 @@ + + + snapcraft_hello + 0.0.1 + snapcraft test for roscpp + me + GPLv3 + catkin + roscpp + fake_package_that_does_not_exists + libboost-filesystem-dev + roscpp + roscpp + libboost-filesystem + diff --git a/tests/spread/plugins/v2/snaps/catkin-noetic-content-sharing/src/snapcraft_hello/src/hello.cpp b/tests/spread/plugins/v2/snaps/catkin-noetic-content-sharing/src/snapcraft_hello/src/hello.cpp new file mode 100644 index 0000000000..dae269b001 --- /dev/null +++ b/tests/spread/plugins/v2/snaps/catkin-noetic-content-sharing/src/snapcraft_hello/src/hello.cpp @@ -0,0 +1,28 @@ +// Copyright (C) 2020 Canonical Ltd +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 3 as +// published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include + +#include + +#include + +int main(int argc, char * argv[]) +{ + ros::init(argc, argv, "snapcraft_hello"); + if(! boost::filesystem::exists("FileDoesntExist")) + std::cout << "hello world" << std::endl; + ros::shutdown(); + return 0; +} From 0ba59f4fc20e8672e894fa8edbf83777e3c02817 Mon Sep 17 00:00:00 2001 From: gbeuzeboc Date: Fri, 21 Apr 2023 10:38:21 +0200 Subject: [PATCH 15/84] test(spread): fix linter ros1-hello --- tests/spread/plugins/v2/ros1-hello/task.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/spread/plugins/v2/ros1-hello/task.yaml b/tests/spread/plugins/v2/ros1-hello/task.yaml index e3cf196bab..bf965c8870 100644 --- a/tests/spread/plugins/v2/ros1-hello/task.yaml +++ b/tests/spread/plugins/v2/ros1-hello/task.yaml @@ -56,7 +56,7 @@ execute: | done # Connect the content sharing snap - snap connect $SNAP:ros-meta ros-meta-ros-core:ros-core + snap connect "${SNAP}":ros-meta ros-meta-ros-core:ros-core fi [ "$($SNAP)" = "hello world" ] From 7a4b865d561a43ab0fa349a58da0a4e9bc06316b Mon Sep 17 00:00:00 2001 From: artivis Date: Thu, 20 Apr 2023 09:10:20 +0200 Subject: [PATCH 16/84] ros: check if file exists before opening --- snapcraft_legacy/plugins/v2/_ros.py | 77 +++++++++++++++-------------- 1 file changed, 39 insertions(+), 38 deletions(-) diff --git a/snapcraft_legacy/plugins/v2/_ros.py b/snapcraft_legacy/plugins/v2/_ros.py index 71347d97cb..67163b4321 100644 --- a/snapcraft_legacy/plugins/v2/_ros.py +++ b/snapcraft_legacy/plugins/v2/_ros.py @@ -239,44 +239,45 @@ def plugin_cli(): def get_installed_dependencies(installed_packages_path: str) -> Set[str]: - try: - with open(installed_packages_path, "r") as f: - build_snap_packages = set(f.read().split()) - package_dependencies = set() - for package in build_snap_packages: - try: - cmd = [ - "apt", - "depends", - "--recurse", - "--no-recommends", - "--no-suggests", - "--no-conflicts", - "--no-breaks", - "--no-replaces", - "--no-enhances", - f"{package}", - ] - click.echo(f"Running {cmd!r}") - proc = subprocess.run( - cmd, - check=True, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - env=dict(PATH=os.environ["PATH"]), - ) - except subprocess.CalledProcessError as error: - click.echo(f"failed to run {cmd!r}: {error.output}") - apt_dependency_regex = re.compile("^\w.*$") - for line in proc.stdout.decode().strip().split("\n"): - if apt_dependency_regex.match(line): - package_dependencies.add(line) - - build_snap_packages.update(package_dependencies) - click.echo(f"Will not fetch staged packages: {build_snap_packages!r}") - return build_snap_packages - except IOError: - return Set(str) + if os.path.isfile(installed_packages_path): + try: + with open(installed_packages_path, "r") as f: + build_snap_packages = set(f.read().split()) + package_dependencies = set() + for package in build_snap_packages: + try: + cmd = [ + "apt", + "depends", + "--recurse", + "--no-recommends", + "--no-suggests", + "--no-conflicts", + "--no-breaks", + "--no-replaces", + "--no-enhances", + f"{package}", + ] + click.echo(f"Running {cmd!r}") + proc = subprocess.run( + cmd, + check=True, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + env=dict(PATH=os.environ["PATH"]), + ) + except subprocess.CalledProcessError as error: + click.echo(f"failed to run {cmd!r}: {error.output}") + apt_dependency_regex = re.compile("^\w.*$") + for line in proc.stdout.decode().strip().split("\n"): + if apt_dependency_regex.match(line): + package_dependencies.add(line) + + build_snap_packages.update(package_dependencies) + click.echo(f"Will not fetch staged packages: {build_snap_packages!r}") + return build_snap_packages + except IOError: + return Set(str) @plugin_cli.command() From cb22a72f620eb044900f5fd9b79d74c3fee13fd7 Mon Sep 17 00:00:00 2001 From: artivis Date: Thu, 20 Apr 2023 09:10:46 +0200 Subject: [PATCH 17/84] ros: typo Signed-off-by: artivis --- snapcraft_legacy/plugins/v2/colcon.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snapcraft_legacy/plugins/v2/colcon.py b/snapcraft_legacy/plugins/v2/colcon.py index 551fe9f245..6a3693ebbd 100644 --- a/snapcraft_legacy/plugins/v2/colcon.py +++ b/snapcraft_legacy/plugins/v2/colcon.py @@ -14,7 +14,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -"""The colcon plugin for ROS2 parts. +"""The colcon plugin for ROS 2 parts. - colcon-packages: (list of strings) From b85f171b8bc401691c0eebb97233f60e06d66eb3 Mon Sep 17 00:00:00 2001 From: artivis Date: Thu, 20 Apr 2023 09:11:20 +0200 Subject: [PATCH 18/84] ros: fix colcon unit test Signed-off-by: artivis --- tests/legacy/unit/plugins/v2/test_colcon.py | 35 ++++++++++++++++++--- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/tests/legacy/unit/plugins/v2/test_colcon.py b/tests/legacy/unit/plugins/v2/test_colcon.py index b4519fe1c4..1e4fa4513b 100644 --- a/tests/legacy/unit/plugins/v2/test_colcon.py +++ b/tests/legacy/unit/plugins/v2/test_colcon.py @@ -133,7 +133,12 @@ class Options: "fi", "", "## Sourcing ROS ws in system", - '. /opt/ros/"${ROS_DISTRO}"/local_setup.sh', + 'if [ -f "/opt/ros/${ROS_DISTRO}/local_setup.sh" ]; then', + 'AMENT_CURRENT_PREFIX="/opt/ros/${ROS_DISTRO}" . "/opt/ros/${ROS_DISTRO}/local_setup.sh"', + "fi", + 'if [ -f "/opt/ros/snap/local_setup.sh" ]; then', + 'COLCON_CURRENT_PREFIX="/opt/ros/snap" . "/opt/ros/snap/local_setup.sh"', + "fi", "", 'eval "${state}"', 'rm -f "${SNAPCRAFT_PART_INSTALL}/.installed_packages.txt"', @@ -152,14 +157,21 @@ class Options: "fi", "", "## Sourcing ROS ws in system", - '. /opt/ros/"${ROS_DISTRO}"/local_setup.sh', + 'if [ -f "/opt/ros/${ROS_DISTRO}/local_setup.sh" ]; then', + 'AMENT_CURRENT_PREFIX="/opt/ros/${ROS_DISTRO}" . "/opt/ros/${ROS_DISTRO}/local_setup.sh"', + "fi", + 'if [ -f "/opt/ros/snap/local_setup.sh" ]; then', + 'COLCON_CURRENT_PREFIX="/opt/ros/snap" . "/opt/ros/snap/local_setup.sh"', + "fi", "", 'eval "${state}"', + '## Prepare build', "## Build command", "colcon build " '--base-paths "${SNAPCRAFT_PART_SRC_WORK}" --build-base "${SNAPCRAFT_PART_BUILD}" ' '--merge-install --install-base "${SNAPCRAFT_PART_INSTALL}"/opt/ros/snap ' '--parallel-workers "${SNAPCRAFT_PARALLEL_BUILD_COUNT}"', + '## Post build command', 'if [ -f "${SNAPCRAFT_PART_INSTALL}"/opt/ros/snap/COLCON_IGNORE ]; then', 'rm "${SNAPCRAFT_PART_INSTALL}"/opt/ros/snap/COLCON_IGNORE', "fi", @@ -233,7 +245,12 @@ class Options: "fi", "", "## Sourcing ROS ws in system", - '. /opt/ros/"${ROS_DISTRO}"/local_setup.sh', + 'if [ -f "/opt/ros/${ROS_DISTRO}/local_setup.sh" ]; then', + 'AMENT_CURRENT_PREFIX="/opt/ros/${ROS_DISTRO}" . "/opt/ros/${ROS_DISTRO}/local_setup.sh"', + "fi", + 'if [ -f "/opt/ros/snap/local_setup.sh" ]; then', + 'COLCON_CURRENT_PREFIX="/opt/ros/snap" . "/opt/ros/snap/local_setup.sh"', + "fi", "", 'eval "${state}"', 'rm -f "${SNAPCRAFT_PART_INSTALL}/.installed_packages.txt"', @@ -278,9 +295,18 @@ class Options: "fi", "", "## Sourcing ROS ws in system", - '. /opt/ros/"${ROS_DISTRO}"/local_setup.sh', + 'if [ -f "/opt/ros/${ROS_DISTRO}/local_setup.sh" ]; then', + 'AMENT_CURRENT_PREFIX="/opt/ros/${ROS_DISTRO}" . "/opt/ros/${ROS_DISTRO}/local_setup.sh"', + "fi", + 'if [ -f "/opt/ros/snap/local_setup.sh" ]; then', + 'COLCON_CURRENT_PREFIX="/opt/ros/snap" . "/opt/ros/snap/local_setup.sh"', + "fi", "", 'eval "${state}"', + '## Prepare build', + 'if [ -d "/snap/foo/current" ]; then export ' + 'CMAKE_PREFIX_PATH="/snap/foo/current:/snap/foo/current/usr:${CMAKE_PREFIX_PATH}"; ' + "fi", "## Build command", "colcon build " '--base-paths "${SNAPCRAFT_PART_SRC_WORK}" --build-base "${SNAPCRAFT_PART_BUILD}" ' @@ -289,6 +315,7 @@ class Options: "package2... --cmake-args cmake args... " "--ament-cmake-args ament args... --catkin-cmake-args catkin " 'args... --parallel-workers "${SNAPCRAFT_PARALLEL_BUILD_COUNT}"', + '## Post build command', 'if [ -f "${SNAPCRAFT_PART_INSTALL}"/opt/ros/snap/COLCON_IGNORE ]; then', 'rm "${SNAPCRAFT_PART_INSTALL}"/opt/ros/snap/COLCON_IGNORE', "fi", From 4260d62ca20e188feb2db60e029faa39cdfcd5d3 Mon Sep 17 00:00:00 2001 From: artivis Date: Thu, 20 Apr 2023 12:01:49 +0200 Subject: [PATCH 19/84] ros: test noetic meta fix name Signed-off-by: artivis --- .../extensions/test_ros1_noetic_meta.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py b/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py index b86e37a8ec..3748f3e2bb 100644 --- a/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py +++ b/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py @@ -36,30 +36,35 @@ class TestClass: ( "desktop", { + "extension_name": "ros1-noetic-desktop", "extension_class": Ros1NoeticDesktopExtension, "meta": "ros-meta-desktop", "meta_dev": "ros-meta-desktop", }, "perception", { + "extension_name": "ros1-noetic-perception", "extension_class": Ros1NoeticPerceptionExtension, "meta": "ros-meta-perception", "meta_dev": "ros-meta-perception", }, "robot", { + "extension_name": "ros1-noetic-robot", "extension_class": Ros1NoeticRobotExtension, "meta": "ros-meta-robot", "meta_dev": "ros-meta-robot", }, "ros-base", { + "extension_name": "ros1-noetic-ros-base", "extension_class": Ros1NoeticRosBaseExtension, "meta": "ros-meta-ros-base", "meta_dev": "ros-meta-ros-base", }, "ros-core", { + "extension_name": "ros1-noetic-ros-core", "extension_class": Ros1NoeticRosCoreExtension, "meta": "ros-meta-ros-core", "meta_dev": "ros-meta-ros-core", @@ -67,9 +72,9 @@ class TestClass: ), ] - def test_extension(self, extension_class, meta, meta_dev): + def test_extension(self, extension_name, extension_class, meta, meta_dev): ros1_extension = extension_class( - extension_name="ros1-noetic", yaml_data=dict(base="core20") + extension_name=extension_name, yaml_data=dict(base="core20") ) assert ros1_extension.root_snippet == { @@ -111,15 +116,13 @@ def test_extension(self, extension_class, meta, meta_dev): assert ros1_extension.parts == { "ros1-noetic-extension": { "build-packages": ["ros-noetic-catkin"], - "override-build": "install -D -m 0755 launch " - "${SNAPCRAFT_PART_INSTALL}/snap/command-chain/ros1-launch", - "plugin": "nil", + "plugin": "make", "source": "$SNAPCRAFT_EXTENSIONS_DIR/ros1", } } - def test_supported_bases(self, extension_class, meta, meta_dev): + def test_supported_bases(self, extension_name, extension_class, meta, meta_dev): assert extension_class.get_supported_bases() == ("core20",) - def test_supported_confinement(self, extension_class, meta, meta_dev): + def test_supported_confinement(self, extension_name, extension_class, meta, meta_dev): extension_class.get_supported_confinement() == ("strict", "devmode") From 5eba53fd7c1fa29c751c8355b5eb998cbf00bd4f Mon Sep 17 00:00:00 2001 From: artivis Date: Thu, 20 Apr 2023 12:02:49 +0200 Subject: [PATCH 20/84] ros: test ros2 foxy meta extentions Signed-off-by: artivis --- .../extensions/test_ros2_foxy_meta.py | 119 ++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 tests/legacy/unit/project_loader/extensions/test_ros2_foxy_meta.py diff --git a/tests/legacy/unit/project_loader/extensions/test_ros2_foxy_meta.py b/tests/legacy/unit/project_loader/extensions/test_ros2_foxy_meta.py new file mode 100644 index 0000000000..f56422e9d8 --- /dev/null +++ b/tests/legacy/unit/project_loader/extensions/test_ros2_foxy_meta.py @@ -0,0 +1,119 @@ +# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*- +# +# Copyright (C) 2023 Canonical Ltd +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 3 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from snapcraft_legacy.internal.project_loader._extensions.ros2_foxy_desktop import ( + ExtensionImpl as Ros2FoxyDesktopExtension, +) +from snapcraft_legacy.internal.project_loader._extensions.ros2_foxy_ros_base import ( + ExtensionImpl as Ros2FoxyRosBaseExtension, +) +from snapcraft_legacy.internal.project_loader._extensions.ros2_foxy_ros_core import ( + ExtensionImpl as Ros2FoxyRosCoreExtension, +) + + +class TestClass: + scenarios = [ + ( + "desktop", + { + "extension_name": "ros2-foxy-desktop", + "extension_class": Ros2FoxyDesktopExtension, + "meta": "ros2-meta-desktop", + "meta_dev": "ros2-meta-desktop", + }, + "ros-base", + { + "extension_name": "ros2-foxy-ros-base", + "extension_class": Ros2FoxyRosBaseExtension, + "meta": "ros2-meta-ros-base", + "meta_dev": "ros2-meta-ros-base", + }, + "ros-core", + { + "extension_name": "ros2-foxy-ros-core", + "extension_class": Ros2FoxyRosCoreExtension, + "meta": "ros2-meta-ros-core", + "meta_dev": "ros2-meta-ros-core", + }, + ), + ] + + def test_extension(self, extension_name, extension_class, meta, meta_dev): + ros_extension = extension_class( + extension_name=extension_name, yaml_data=dict(base="core20") + ) + + assert ros_extension.root_snippet == { + "package-repositories": [ + { + "components": ["main"], + "formats": ["deb"], + "key-id": "C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654", + "key-server": "keyserver.ubuntu.com", + "suites": ["focal"], + "type": "apt", + "url": "http://repo.ros2.org/ubuntu/main", + } + ], + "plugs": { + "ros-meta": { + "interface": "content", + "content": "ros2-meta", + "target": "$SNAP/opt/ros/underlay_ws", + "default-provider": meta, + } + }, + } + + assert ros_extension.app_snippet == { + "command-chain": ["snap/command-chain/ros2-launch"], + "environment": { + "PYTHONPATH": "$SNAP/opt/ros/foxy/lib/python3.8/site-packages:$SNAP/usr/lib/python3/dist-packages:${PYTHONPATH}", + "ROS_VERSION": "2", + "ROS_DISTRO": "foxy", + }, + } + + assert ros_extension.part_snippet == { + "build-environment": [{"ROS_VERSION": "2"}, {"ROS_DISTRO": "foxy"}], + "build-snaps": [meta_dev], + } + + assert ros_extension.parts == { + "ros2-foxy-extension": { + "build-packages": [ + "ros-foxy-ros-environment", + "ros-foxy-ros-workspace", + "ros-foxy-ament-index-cpp", + "ros-foxy-ament-index-python", + ], + "stage-packages": [ + "ros-foxy-ros-environment", + "ros-foxy-ros-workspace", + "ros-foxy-ament-index-cpp", + "ros-foxy-ament-index-python", + ], + "plugin": "make", + "source": "$SNAPCRAFT_EXTENSIONS_DIR/ros2", + } + } + + def test_supported_bases(self, extension_name, extension_class, meta, meta_dev): + assert extension_class.get_supported_bases() == ("core20",) + + def test_supported_confinement(self, extension_name, extension_class, meta, meta_dev): + extension_class.get_supported_confinement() == ("strict", "devmode") From 16c2d3d6c0264500a2b4e3d85ae577e5fb8c570d Mon Sep 17 00:00:00 2001 From: artivis Date: Thu, 20 Apr 2023 09:12:47 +0200 Subject: [PATCH 21/84] ros: humble support content-sharing Signed-off-by: artivis --- snapcraft/parts/plugins/_ros.py | 81 +++++++++++++++- snapcraft/parts/plugins/colcon_plugin.py | 113 +++++++++++++++-------- 2 files changed, 155 insertions(+), 39 deletions(-) diff --git a/snapcraft/parts/plugins/_ros.py b/snapcraft/parts/plugins/_ros.py index c4891128ef..c202687c51 100644 --- a/snapcraft/parts/plugins/_ros.py +++ b/snapcraft/parts/plugins/_ros.py @@ -30,6 +30,7 @@ from catkin_pkg import packages as catkin_packages from craft_parts import plugins from craft_parts.packages import Repository as Repo +from craft_parts.packages.snaps import _get_parsed_snap from overrides import overrides from snapcraft.errors import SnapcraftError @@ -89,7 +90,7 @@ def get_build_snaps(self) -> Set[str]: @overrides def get_build_packages(self) -> Set[str]: - return {"python3-rosdep"} + return {"python3-rosdep", "rospack-tools"} @overrides def get_build_environment(self) -> Dict[str, str]: @@ -127,6 +128,50 @@ def _get_build_commands(self) -> List[str]: specific functionality. """ + def _get_list_packages_commands(self) -> List[str]: + """Generate a list of ROS 2 packages available in build snaps. + + The ROS 2 workspaces contained in build snaps are crawled with `rospack` + to establish the list of all available ROS 2 packages. + The package names are then resolved with `rosdep` to map their names to debs. + The list is finally saved in the part's install directory. + """ + + cmd = list() + + # Clean up previously established list of packages in build snaps + cmd.append('rm -f "${CRAFT_PART_INSTALL}/.installed_packages.txt"') + cmd.append('rm -f "${CRAFT_PART_INSTALL}/.build_snaps.txt"') + + # self.get_build_properties + + if self._options.build_snaps: + for build_snap in self._options.build_snaps: + snap_name = _get_parsed_snap(build_snap)[0] + path = f"/snap/{snap_name}/current/opt/ros" + cmd.extend([ + # Retrieve the list of all ROS packages available in the build snap + f"if [ -d {path} ]; then", + f"ROS_PACKAGE_PATH={path} " + 'rospack list-names | (xargs rosdep resolve --rosdistro "${ROS_DISTRO}" || echo "") | ' + 'awk "/#apt/{getline;print;}" >> "${CRAFT_PART_INSTALL}/.installed_packages.txt"', + "fi", + + # Retrieve the list of all non-ROS packages available in the build snap + f'if [ -d "{path}/${{ROS_DISTRO}}/" ]; then', + f'rosdep keys --rosdistro "${{ROS_DISTRO}}" --from-paths "{path}/${{ROS_DISTRO}}" --ignore-packages-from-source ' + '| (xargs rosdep resolve --rosdistro "${ROS_DISTRO}" || echo "") | grep -v "#" >> "${CRAFT_PART_INSTALL}"/.installed_packages.txt', + "fi", + + f'if [ -d "{path}/snap/" ]; then', + f'rosdep keys --rosdistro "${{ROS_DISTRO}}" --from-paths "{path}/snap" --ignore-packages-from-source ' + '| (xargs rosdep resolve --rosdistro "${ROS_DISTRO}" || echo "") | grep -v "#" >> "${CRAFT_PART_INSTALL}"/.installed_packages.txt', + "fi", + ]) + cmd.append("") + + return cmd + def _get_stage_runtime_dependencies_commands(self) -> List[str]: env = {"LANG": "C.UTF-8", "LC_ALL": "C.UTF-8"} @@ -183,10 +228,28 @@ def get_build_commands(self) -> List[str]: # https://github.com/ros-infrastructure/rosdep/issues/271 "sudo --preserve-env=http_proxy,https_proxy rosdep init; fi", 'rosdep update --include-eol-distros --rosdistro "${ROS_DISTRO}"', - "rosdep install --default-yes --ignore-packages-from-source " - '--from-paths "${CRAFT_PART_SRC_WORK}"', + ] + # There are a number of unbound vars, disable flag + # after saving current state to restore after. + + [ + 'state="$(set +o); set -$-"', + "set +u", + "", ] + self._get_workspace_activation_commands() + # Restore saved state + + ['eval "${state}"'] + + self._get_list_packages_commands() + + [ + 'rosdep install --default-yes --ignore-packages-from-source --from-paths "${CRAFT_PART_SRC_WORK}"', + ] + + [ + 'state="$(set +o); set -$-"', + "set +u", + "", + ] + + self._get_workspace_activation_commands() + + ['eval "${state}"'] + self._get_build_commands() + self._get_stage_runtime_dependencies_commands() ) @@ -263,6 +326,17 @@ def stage_runtime_dependencies( if parsed: click.echo(f"unhandled dependencies: {parsed!r}") + build_snap_packages: Set[str] = set() + installed_packages_file = part_install + "/.installed_packages.txt" + if os.path.isfile(installed_packages_file): + try: + with open(installed_packages_file, "r") as f: + build_snap_packages = set(f.read().split()) + click.echo(f"Will not fetch staged packages: {build_snap_packages!r}") + except IOError: + click.echo(f"failed to open file {installed_packages_file}") + pass + if apt_packages: package_names = sorted(apt_packages) install_path = pathlib.Path(part_install) @@ -277,6 +351,7 @@ def stage_runtime_dependencies( arch=target_arch, base=base, stage_packages_path=stage_packages_path, + packages_filters=build_snap_packages, ) click.echo(f"Unpacking stage packages: {fetched_stage_packages!r}") diff --git a/snapcraft/parts/plugins/colcon_plugin.py b/snapcraft/parts/plugins/colcon_plugin.py index 45cac24029..ab62797148 100644 --- a/snapcraft/parts/plugins/colcon_plugin.py +++ b/snapcraft/parts/plugins/colcon_plugin.py @@ -14,7 +14,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -"""The colcon plugin for ROS2 parts. +"""The colcon plugin for ROS 2 parts. - colcon-packages: (list of strings) @@ -58,6 +58,7 @@ from typing import Any, Dict, List, Set, cast from craft_parts import plugins +from craft_parts.packages.snaps import _get_parsed_snap from overrides import overrides from . import _ros @@ -71,11 +72,13 @@ class ColconPluginProperties(plugins.PluginProperties, plugins.PluginModel): colcon_cmake_args: List[str] = [] colcon_packages: List[str] = [] colcon_packages_ignore: List[str] = [] + build_snaps: List[str] = [] # part properties required by the plugin source: str @classmethod + @overrides def unmarshal(cls, data: Dict[str, Any]) -> "ColconPluginProperties": """Populate make properties from the part specification. @@ -86,7 +89,7 @@ def unmarshal(cls, data: Dict[str, Any]) -> "ColconPluginProperties": :raise pydantic.ValidationError: If validation fails. """ plugin_data = plugins.extract_plugin_properties( - data, plugin_name="colcon", required=["source"] + data, plugin_name="colcon", required=["source", "build-snaps"] ) return cls(**plugin_data) @@ -116,6 +119,20 @@ def get_build_environment(self) -> Dict[str, str]: return env + def _get_source_command(self, path: str) -> List[str]: + return [ + f'if [ -f "{path}/opt/ros/${{ROS_DISTRO}}/local_setup.sh" ]; then', + 'AMENT_CURRENT_PREFIX="{wspath}" . "{wspath}/local_setup.sh"'.format( + wspath=f"{path}/opt/ros/${{ROS_DISTRO}}" + ), + "fi", + f'if [ -f "{path}/opt/ros/snap/local_setup.sh" ]; then', + 'COLCON_CURRENT_PREFIX="{wspath}" . "{wspath}/local_setup.sh"'.format( + wspath=f"{path}/opt/ros/snap" + ), + "fi", + ] + @overrides def _get_workspace_activation_commands(self) -> List[str]: """Return a list of commands source a ROS 2 workspace. @@ -129,31 +146,49 @@ def _get_workspace_activation_commands(self) -> List[str]: specific functionality. """ - # There are a number of unbound vars, disable flag - # after saving current state to restore after. - return [ - 'state="$(set +o); set -$-"', - "set +u", - # If it exists, source the stage-snap underlay - 'if [ -f "${CRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/local_setup.sh" ]; then', - 'COLCON_CURRENT_PREFIX="{path}" . "{path}/local_setup.sh"'.format( - path="${CRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}" - ), - "fi", - 'if [ -f "${CRAFT_PART_INSTALL}/opt/ros/snap/local_setup.sh" ]; then', - 'COLCON_CURRENT_PREFIX="{path}" . "{path}/local_setup.sh"'.format( - path="${CRAFT_PART_INSTALL}/opt/ros/snap" - ), - "fi", - '. "/opt/ros/${ROS_DISTRO}/local_setup.sh"', - 'eval "${state}"', - ] + activation_commands = list() + + # Source ROS ws in all build-snaps first + activation_commands.append("## Sourcing ROS ws in build snaps") + if self._options.build_snaps: + for build_snap in self._options.build_snaps: + snap_name = _get_parsed_snap(build_snap)[0] + activation_commands.extend( + self._get_source_command(f"/snap/{snap_name}/current") + ) + activation_commands.append("") + + # Source ROS ws in stage-snaps next + activation_commands.append("## Sourcing ROS ws in stage snaps") + activation_commands.extend( + self._get_source_command("${CRAFT_PART_INSTALL}") + ) + activation_commands.append("") + + # Finally source system's ROS ws + activation_commands.append("## Sourcing ROS ws in system") + activation_commands.extend(self._get_source_command("")) + activation_commands.append("") + + return activation_commands @overrides def _get_build_commands(self) -> List[str]: options = cast(ColconPluginProperties, self._options) - cmd = [ + export_command = list() + + if self._options.build_snaps: + for build_snap in self._options.build_snaps: + build_snap = _get_parsed_snap(build_snap)[0] + + export_command.extend([ + 'if [ -d "/snap/{build_snap}/current" ]; then ' + 'export CMAKE_PREFIX_PATH="/snap/{build_snap}/current:/snap/{build_snap}/current/usr:${{CMAKE_PREFIX_PATH}}"; ' + 'fi'.format(build_snap=build_snap) + ]) + + build_command = [ "colcon", "build", "--base-paths", @@ -166,27 +201,33 @@ def _get_build_commands(self) -> List[str]: ] if options.colcon_packages_ignore: - cmd.extend(["--packages-ignore", *options.colcon_packages_ignore]) + build_command.extend(["--packages-ignore", *options.colcon_packages_ignore]) if options.colcon_packages: - cmd.extend(["--packages-select", *options.colcon_packages]) + build_command.extend(["--packages-select", *options.colcon_packages]) if options.colcon_cmake_args: - cmd.extend(["--cmake-args", *options.colcon_cmake_args]) + build_command.extend(["--cmake-args", *options.colcon_cmake_args]) if options.colcon_ament_cmake_args: - cmd.extend(["--ament-cmake-args", *options.colcon_ament_cmake_args]) + build_command.extend(["--ament-cmake-args", *options.colcon_ament_cmake_args]) if options.colcon_catkin_cmake_args: - cmd.extend(["--catkin-cmake-args", *options.colcon_catkin_cmake_args]) + build_command.extend(["--catkin-cmake-args", *options.colcon_catkin_cmake_args]) # Specify the number of workers - cmd.extend(["--parallel-workers", '"${CRAFT_PARALLEL_BUILD_COUNT}"']) - - return [" ".join(cmd)] + [ - # Remove the COLCON_IGNORE marker so that, at staging, - # catkin can crawl the entire folder to look up for packages. - 'if [ -f "${CRAFT_PART_INSTALL}/opt/ros/snap/COLCON_IGNORE" ]; then', - 'rm "${CRAFT_PART_INSTALL}/opt/ros/snap/COLCON_IGNORE"', - "fi", - ] + build_command.extend(["--parallel-workers", '"${CRAFT_PARALLEL_BUILD_COUNT}"']) + + return ( + ["## Prepare build"] + + export_command + + ["## Build command", " ".join(build_command)] + + [ + "## Post build command", + # Remove the COLCON_IGNORE marker so that, at staging, + # catkin can crawl the entire folder to look up for packages. + 'if [ -f "${CRAFT_PART_INSTALL}"/opt/ros/snap/COLCON_IGNORE ]; then', + 'rm "${CRAFT_PART_INSTALL}"/opt/ros/snap/COLCON_IGNORE', + "fi", + ] + ) From a46cae75f75921a8dcbf9291e3123d4756293e6d Mon Sep 17 00:00:00 2001 From: artivis Date: Thu, 20 Apr 2023 09:13:35 +0200 Subject: [PATCH 22/84] ros: test humble support content-sharing Signed-off-by: artivis --- tests/unit/parts/plugins/test_colcon.py | 155 +++++++++++++++++++++--- 1 file changed, 136 insertions(+), 19 deletions(-) diff --git a/tests/unit/parts/plugins/test_colcon.py b/tests/unit/parts/plugins/test_colcon.py index a37c025dc4..58d411871c 100644 --- a/tests/unit/parts/plugins/test_colcon.py +++ b/tests/unit/parts/plugins/test_colcon.py @@ -74,6 +74,15 @@ def test_property_default(self): except ValidationError as e: raise AssertionError(f"{e}") from e + def test_property_unexpected(self): + try: + properties = colcon.ColconPlugin.properties_class(source=".") + except ValidationError as e: + raise AssertionError(f"{e}") from e + + with pytest.raises(ValidationError): + properties = colcon.ColconPlugin.properties_class(source=".", foo="bar") + def test_property_all(self): try: properties = colcon.ColconPlugin.properties_class.unmarshal( @@ -84,6 +93,7 @@ def test_property_all(self): "colcon-cmake-args": ["cmake", "args..."], "colcon-packages": ["package1", "package2..."], "colcon-packages-ignore": ["ipackage1", "ipackage2..."], + "build-snaps": ["ros-core"], } ) except ValidationError as e: @@ -95,6 +105,7 @@ def test_property_all(self): assert properties.colcon_cmake_args == ["cmake", "args..."] # type: ignore assert properties.colcon_packages == ["package1", "package2..."] # type: ignore assert properties.colcon_packages_ignore == ["ipackage1", "ipackage2..."] # type: ignore + assert properties.build_snaps == ["ros-core"] # type: ignore def test_get_build_packages(self, setup_method_fixture, new_dir): plugin = setup_method_fixture(new_dir) @@ -104,6 +115,7 @@ def test_get_build_packages(self, setup_method_fixture, new_dir): "python3-rosdep", "python3-rosinstall", "python3-wstool", + "rospack-tools", } def test_get_build_environment(self, setup_method_fixture, new_dir): @@ -142,26 +154,60 @@ def test_get_build_commands(self, setup_method_fixture, new_dir, monkeypatch): "if [ ! -f /etc/ros/rosdep/sources.list.d/20-default.list ]; then", "sudo --preserve-env=http_proxy,https_proxy rosdep init; fi", 'rosdep update --include-eol-distros --rosdistro "${ROS_DISTRO}"', - "rosdep install --default-yes --ignore-packages-from-source " - '--from-paths "${CRAFT_PART_SRC_WORK}"', 'state="$(set +o); set -$-"', "set +u", + "", + "## Sourcing ROS ws in build snaps", + "## Sourcing ROS ws in stage snaps", 'if [ -f "${CRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/local_setup.sh" ]; then', - 'COLCON_CURRENT_PREFIX="${CRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}" . ' - '"${CRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/local_setup.sh"', + 'AMENT_CURRENT_PREFIX="${CRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}" . "${CRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/local_setup.sh"', "fi", 'if [ -f "${CRAFT_PART_INSTALL}/opt/ros/snap/local_setup.sh" ]; then', - 'COLCON_CURRENT_PREFIX="${CRAFT_PART_INSTALL}/opt/ros/snap" . ' - '"${CRAFT_PART_INSTALL}/opt/ros/snap/local_setup.sh"', + 'COLCON_CURRENT_PREFIX="${CRAFT_PART_INSTALL}/opt/ros/snap" . "${CRAFT_PART_INSTALL}/opt/ros/snap/local_setup.sh"', "fi", - '. "/opt/ros/${ROS_DISTRO}/local_setup.sh"', + "", + "## Sourcing ROS ws in system", + 'if [ -f "/opt/ros/${ROS_DISTRO}/local_setup.sh" ]; then', + 'AMENT_CURRENT_PREFIX="/opt/ros/${ROS_DISTRO}" . "/opt/ros/${ROS_DISTRO}/local_setup.sh"', + "fi", + 'if [ -f "/opt/ros/snap/local_setup.sh" ]; then', + 'COLCON_CURRENT_PREFIX="/opt/ros/snap" . "/opt/ros/snap/local_setup.sh"', + "fi", + "", 'eval "${state}"', - "colcon build " + 'rm -f "${CRAFT_PART_INSTALL}/.installed_packages.txt"', + 'rm -f "${CRAFT_PART_INSTALL}/.build_snaps.txt"', + 'rosdep install --default-yes --ignore-packages-from-source --from-paths "${CRAFT_PART_SRC_WORK}"', + 'state="$(set +o); set -$-"', + "set +u", + "", + "## Sourcing ROS ws in build snaps", + "## Sourcing ROS ws in stage snaps", + 'if [ -f "${CRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/local_setup.sh" ]; then', + 'AMENT_CURRENT_PREFIX="${CRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}" . "${CRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/local_setup.sh"', + "fi", + 'if [ -f "${CRAFT_PART_INSTALL}/opt/ros/snap/local_setup.sh" ]; then', + 'COLCON_CURRENT_PREFIX="${CRAFT_PART_INSTALL}/opt/ros/snap" . "${CRAFT_PART_INSTALL}/opt/ros/snap/local_setup.sh"', + "fi", + "", + "## Sourcing ROS ws in system", + 'if [ -f "/opt/ros/${ROS_DISTRO}/local_setup.sh" ]; then', + 'AMENT_CURRENT_PREFIX="/opt/ros/${ROS_DISTRO}" . "/opt/ros/${ROS_DISTRO}/local_setup.sh"', + "fi", + 'if [ -f "/opt/ros/snap/local_setup.sh" ]; then', + 'COLCON_CURRENT_PREFIX="/opt/ros/snap" . "/opt/ros/snap/local_setup.sh"', + "fi", + "", + 'eval "${state}"', + '## Prepare build', + "## Build command", + 'colcon build ' '--base-paths "${CRAFT_PART_SRC_WORK}" --build-base "${CRAFT_PART_BUILD}" ' '--merge-install --install-base "${CRAFT_PART_INSTALL}/opt/ros/snap" ' '--parallel-workers "${CRAFT_PARALLEL_BUILD_COUNT}"', - 'if [ -f "${CRAFT_PART_INSTALL}/opt/ros/snap/COLCON_IGNORE" ]; then', - 'rm "${CRAFT_PART_INSTALL}/opt/ros/snap/COLCON_IGNORE"', + '## Post build command', + 'if [ -f "${CRAFT_PART_INSTALL}"/opt/ros/snap/COLCON_IGNORE ]; then', + 'rm "${CRAFT_PART_INSTALL}"/opt/ros/snap/COLCON_IGNORE', "fi", "env -i LANG=C.UTF-8 LC_ALL=C.UTF-8 /test/python3 -I " "/test/_ros.py " @@ -184,6 +230,7 @@ def test_get_build_commands_with_all_properties( "colcon-cmake-args": ["cmake", "args..."], "colcon-packages": ["package1", "package2..."], "colcon-packages-ignore": ["ipackage1", "ipackage2..."], + "build-snaps": ["foo"], }, ) @@ -221,20 +268,89 @@ def test_get_build_commands_with_all_properties( "if [ ! -f /etc/ros/rosdep/sources.list.d/20-default.list ]; then", "sudo --preserve-env=http_proxy,https_proxy rosdep init; fi", 'rosdep update --include-eol-distros --rosdistro "${ROS_DISTRO}"', - "rosdep install --default-yes --ignore-packages-from-source " - '--from-paths "${CRAFT_PART_SRC_WORK}"', 'state="$(set +o); set -$-"', "set +u", + "", + "## Sourcing ROS ws in build snaps", + 'if [ -f "/snap/foo/current/opt/ros/${ROS_DISTRO}/local_setup.sh" ]; then', + 'AMENT_CURRENT_PREFIX="/snap/foo/current/opt/ros/${ROS_DISTRO}" . "/snap/foo/current/opt/ros/${ROS_DISTRO}/local_setup.sh"', + "fi", + 'if [ -f "/snap/foo/current/opt/ros/snap/local_setup.sh" ]; then', + 'COLCON_CURRENT_PREFIX="/snap/foo/current/opt/ros/snap" . "/snap/foo/current/opt/ros/snap/local_setup.sh"', + "fi", + "", + "## Sourcing ROS ws in stage snaps", 'if [ -f "${CRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/local_setup.sh" ]; then', - 'COLCON_CURRENT_PREFIX="${CRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}" . ' - '"${CRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/local_setup.sh"', + 'AMENT_CURRENT_PREFIX="${CRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}" . "${CRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/local_setup.sh"', "fi", 'if [ -f "${CRAFT_PART_INSTALL}/opt/ros/snap/local_setup.sh" ]; then', - 'COLCON_CURRENT_PREFIX="${CRAFT_PART_INSTALL}/opt/ros/snap" . ' - '"${CRAFT_PART_INSTALL}/opt/ros/snap/local_setup.sh"', + 'COLCON_CURRENT_PREFIX="${CRAFT_PART_INSTALL}/opt/ros/snap" . "${CRAFT_PART_INSTALL}/opt/ros/snap/local_setup.sh"', "fi", - '. "/opt/ros/${ROS_DISTRO}/local_setup.sh"', + "", + "## Sourcing ROS ws in system", + 'if [ -f "/opt/ros/${ROS_DISTRO}/local_setup.sh" ]; then', + 'AMENT_CURRENT_PREFIX="/opt/ros/${ROS_DISTRO}" . "/opt/ros/${ROS_DISTRO}/local_setup.sh"', + "fi", + 'if [ -f "/opt/ros/snap/local_setup.sh" ]; then', + 'COLCON_CURRENT_PREFIX="/opt/ros/snap" . "/opt/ros/snap/local_setup.sh"', + "fi", + "", 'eval "${state}"', + 'rm -f "${CRAFT_PART_INSTALL}/.installed_packages.txt"', + 'rm -f "${CRAFT_PART_INSTALL}/.build_snaps.txt"', + "if [ -d /snap/foo/current/opt/ros ]; then", + "ROS_PACKAGE_PATH=/snap/foo/current/opt/ros rospack list-names | (xargs " + 'rosdep resolve --rosdistro "${ROS_DISTRO}" || echo "") | awk ' + '"/#apt/{getline;print;}" >> ' + '"${CRAFT_PART_INSTALL}/.installed_packages.txt"', + "fi", + 'if [ -d "/snap/foo/current/opt/ros/${ROS_DISTRO}/" ]; then', + 'rosdep keys --rosdistro "${ROS_DISTRO}" --from-paths ' + '"/snap/foo/current/opt/ros/${ROS_DISTRO}" --ignore-packages-from-source | ' + '(xargs rosdep resolve --rosdistro "${ROS_DISTRO}" || echo "") | grep -v "#" ' + '>> "${CRAFT_PART_INSTALL}"/.installed_packages.txt', + "fi", + 'if [ -d "/snap/foo/current/opt/ros/snap/" ]; then', + 'rosdep keys --rosdistro "${ROS_DISTRO}" --from-paths ' + '"/snap/foo/current/opt/ros/snap" --ignore-packages-from-source | (xargs ' + 'rosdep resolve --rosdistro "${ROS_DISTRO}" || echo "") | grep -v "#" >> ' + '"${CRAFT_PART_INSTALL}"/.installed_packages.txt', + "fi", + "", + 'rosdep install --default-yes --ignore-packages-from-source --from-paths "${CRAFT_PART_SRC_WORK}"', + 'state="$(set +o); set -$-"', + "set +u", + "", + "## Sourcing ROS ws in build snaps", + 'if [ -f "/snap/foo/current/opt/ros/${ROS_DISTRO}/local_setup.sh" ]; then', + 'AMENT_CURRENT_PREFIX="/snap/foo/current/opt/ros/${ROS_DISTRO}" . "/snap/foo/current/opt/ros/${ROS_DISTRO}/local_setup.sh"', + "fi", + 'if [ -f "/snap/foo/current/opt/ros/snap/local_setup.sh" ]; then', + 'COLCON_CURRENT_PREFIX="/snap/foo/current/opt/ros/snap" . "/snap/foo/current/opt/ros/snap/local_setup.sh"', + "fi", + "", + "## Sourcing ROS ws in stage snaps", + 'if [ -f "${CRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/local_setup.sh" ]; then', + 'AMENT_CURRENT_PREFIX="${CRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}" . "${CRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/local_setup.sh"', + "fi", + 'if [ -f "${CRAFT_PART_INSTALL}/opt/ros/snap/local_setup.sh" ]; then', + 'COLCON_CURRENT_PREFIX="${CRAFT_PART_INSTALL}/opt/ros/snap" . "${CRAFT_PART_INSTALL}/opt/ros/snap/local_setup.sh"', + "fi", + "", + "## Sourcing ROS ws in system", + 'if [ -f "/opt/ros/${ROS_DISTRO}/local_setup.sh" ]; then', + 'AMENT_CURRENT_PREFIX="/opt/ros/${ROS_DISTRO}" . "/opt/ros/${ROS_DISTRO}/local_setup.sh"', + "fi", + 'if [ -f "/opt/ros/snap/local_setup.sh" ]; then', + 'COLCON_CURRENT_PREFIX="/opt/ros/snap" . "/opt/ros/snap/local_setup.sh"', + "fi", + "", + 'eval "${state}"', + "## Prepare build", + 'if [ -d "/snap/foo/current" ]; then export ' + 'CMAKE_PREFIX_PATH="/snap/foo/current:/snap/foo/current/usr:${CMAKE_PREFIX_PATH}"; ' + "fi", + "## Build command", "colcon build " '--base-paths "${CRAFT_PART_SRC_WORK}" --build-base "${CRAFT_PART_BUILD}" ' '--merge-install --install-base "${CRAFT_PART_INSTALL}/opt/ros/snap" ' @@ -242,8 +358,9 @@ def test_get_build_commands_with_all_properties( "package2... --cmake-args cmake args... " "--ament-cmake-args ament args... --catkin-cmake-args catkin " 'args... --parallel-workers "${CRAFT_PARALLEL_BUILD_COUNT}"', - 'if [ -f "${CRAFT_PART_INSTALL}/opt/ros/snap/COLCON_IGNORE" ]; then', - 'rm "${CRAFT_PART_INSTALL}/opt/ros/snap/COLCON_IGNORE"', + "## Post build command", + 'if [ -f "${CRAFT_PART_INSTALL}"/opt/ros/snap/COLCON_IGNORE ]; then', + 'rm "${CRAFT_PART_INSTALL}"/opt/ros/snap/COLCON_IGNORE', "fi", "env -i LANG=C.UTF-8 LC_ALL=C.UTF-8 PATH=/bin:/test SNAP=TESTSNAP " "SNAP_ARCH=TESTARCH SNAP_NAME=TESTSNAPNAME SNAP_VERSION=TESTV1 " From bb6b45bd1d68de58ca184cbf371f5a39d9c2fad9 Mon Sep 17 00:00:00 2001 From: artivis Date: Thu, 20 Apr 2023 11:41:25 +0200 Subject: [PATCH 23/84] ros: add humble meta extensions --- snapcraft/extensions/_ros2_humble_meta.py | 64 ++++++ snapcraft/extensions/registry.py | 6 + snapcraft/extensions/ros2_humble_desktop.py | 38 ++++ snapcraft/extensions/ros2_humble_ros_base.py | 38 ++++ snapcraft/extensions/ros2_humble_ros_core.py | 38 ++++ .../parts/extensions/test_ros2_humble_meta.py | 183 ++++++++++++++++++ 6 files changed, 367 insertions(+) create mode 100644 snapcraft/extensions/_ros2_humble_meta.py create mode 100644 snapcraft/extensions/ros2_humble_desktop.py create mode 100644 snapcraft/extensions/ros2_humble_ros_base.py create mode 100644 snapcraft/extensions/ros2_humble_ros_core.py create mode 100644 tests/unit/parts/extensions/test_ros2_humble_meta.py diff --git a/snapcraft/extensions/_ros2_humble_meta.py b/snapcraft/extensions/_ros2_humble_meta.py new file mode 100644 index 0000000000..8fe76e7ab2 --- /dev/null +++ b/snapcraft/extensions/_ros2_humble_meta.py @@ -0,0 +1,64 @@ +# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*- +# +# Copyright 2023 Canonical Ltd. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 3 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Import types and tell flake8 to ignore the "unused" List. + +"""Base for ROS 2 Humble extensions to the Colcon plugin using content-sharing.""" + +from typing import Any, Dict, Optional + +from overrides import overrides + +from .ros2_humble import ROS2HumbleExtension + + +class ROS2HumbleMetaBase(ROS2HumbleExtension): + """Drives ROS 2 build and runtime environment for snap using content-sharing.""" + + @overrides + def get_root_snippet(self) -> Dict[str, Any]: + root_snippet = super().get_root_snippet() + root_snippet["plugs"] = { + "ros-meta": + { + "interface": "content", + "content": "ros2-meta", + "target": "$SNAP/opt/ros/underlay_ws", + "default-provider": self.ROS_META, + } + } + return root_snippet + + @overrides + def get_part_snippet(self) -> Dict[str, Any]: + part_snippet = super().get_part_snippet() + part_snippet["build-snaps"] = [self.ROS_META_DEV] + return part_snippet + + @overrides + def get_parts_snippet(self) -> Dict[str, Any]: + parts_snippet = super().get_parts_snippet() + # Very unlikely but it may happen that the snapped application doesn't + # even pull those deps. In that case, there is no valid ROS 2 ws to source. + # We make sure here that they are staged no matter what. + print("parts_snippet ", parts_snippet) + parts_snippet[f"ros2-{self.ROS_DISTRO}/ros2-launch"]["stage-packages"] = [ + f"ros-{self.ROS_DISTRO}-ros-environment", + f"ros-{self.ROS_DISTRO}-ros-workspace", + f"ros-{self.ROS_DISTRO}-ament-index-cpp", + f"ros-{self.ROS_DISTRO}-ament-index-python", + ] + return parts_snippet diff --git a/snapcraft/extensions/registry.py b/snapcraft/extensions/registry.py index 77ddb6ebe4..ae5d69f463 100644 --- a/snapcraft/extensions/registry.py +++ b/snapcraft/extensions/registry.py @@ -23,6 +23,9 @@ from .gnome import GNOME from .kde_neon import KDENeon from .ros2_humble import ROS2HumbleExtension +from .ros2_humble_desktop import ROS2HumbleDesktopExtension +from .ros2_humble_ros_base import ROS2HumbleRosBaseExtension +from .ros2_humble_ros_core import ROS2HumbleRosCoreExtension if TYPE_CHECKING: from .extension import Extension @@ -32,6 +35,9 @@ _EXTENSIONS: Dict[str, "ExtensionType"] = { "gnome": GNOME, "ros2-humble": ROS2HumbleExtension, + "ros2-humble-ros-core": ROS2HumbleRosCoreExtension, + "ros2-humble-ros-base": ROS2HumbleRosBaseExtension, + "ros2-humble-desktop": ROS2HumbleDesktopExtension, "kde-neon": KDENeon, } diff --git a/snapcraft/extensions/ros2_humble_desktop.py b/snapcraft/extensions/ros2_humble_desktop.py new file mode 100644 index 0000000000..069db72e87 --- /dev/null +++ b/snapcraft/extensions/ros2_humble_desktop.py @@ -0,0 +1,38 @@ +# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*- +# +# Copyright 2023 Canonical Ltd. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 3 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Import types and tell flake8 to ignore the "unused" List. + +"""Extension to the Colcon plugin for ROS 2 Humble using content sharing.""" + +from typing import Optional + +from overrides import overrides +from typing_extensions import Final + +from ._ros2_humble_meta import ROS2HumbleMetaBase + + +class ROS2HumbleDesktopExtension(ROS2HumbleMetaBase): + """Drives ROS 2 build and runtime environment for snap using content-sharing.""" + + @staticmethod + @overrides + def is_experimental(base: Optional[str]) -> bool: + return True + + ROS_META: Final[str] = "ros-humble-desktop" + ROS_META_DEV: Final[str] = "ros-humble-desktop" \ No newline at end of file diff --git a/snapcraft/extensions/ros2_humble_ros_base.py b/snapcraft/extensions/ros2_humble_ros_base.py new file mode 100644 index 0000000000..529cd3be9b --- /dev/null +++ b/snapcraft/extensions/ros2_humble_ros_base.py @@ -0,0 +1,38 @@ +# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*- +# +# Copyright 2023 Canonical Ltd. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 3 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Import types and tell flake8 to ignore the "unused" List. + +"""Extension to the Colcon plugin for ROS 2 Humble using content sharing.""" + +from typing import Optional + +from overrides import overrides +from typing_extensions import Final + +from ._ros2_humble_meta import ROS2HumbleMetaBase + + +class ROS2HumbleRosBaseExtension(ROS2HumbleMetaBase): + """Drives ROS 2 build and runtime environment for snap using content-sharing.""" + + @staticmethod + @overrides + def is_experimental(base: Optional[str]) -> bool: + return True + + ROS_META: Final[str] = "ros-humble-ros-base" + ROS_META_DEV: Final[str] = "ros-humble-ros-base" \ No newline at end of file diff --git a/snapcraft/extensions/ros2_humble_ros_core.py b/snapcraft/extensions/ros2_humble_ros_core.py new file mode 100644 index 0000000000..039ac7fbd7 --- /dev/null +++ b/snapcraft/extensions/ros2_humble_ros_core.py @@ -0,0 +1,38 @@ +# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*- +# +# Copyright 2023 Canonical Ltd. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 3 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Import types and tell flake8 to ignore the "unused" List. + +"""Extension to the Colcon plugin for ROS 2 Humble using content sharing.""" + +from typing import Optional + +from overrides import overrides +from typing_extensions import Final + +from ._ros2_humble_meta import ROS2HumbleMetaBase + + +class ROS2HumbleRosCoreExtension(ROS2HumbleMetaBase): + """Drives ROS 2 build and runtime environment for snap using content-sharing.""" + + @staticmethod + @overrides + def is_experimental(base: Optional[str]) -> bool: + return True + + ROS_META: Final[str] = "ros-humble-ros-core" + ROS_META_DEV: Final[str] = "ros-humble-ros-core" \ No newline at end of file diff --git a/tests/unit/parts/extensions/test_ros2_humble_meta.py b/tests/unit/parts/extensions/test_ros2_humble_meta.py new file mode 100644 index 0000000000..4c4cadfaa6 --- /dev/null +++ b/tests/unit/parts/extensions/test_ros2_humble_meta.py @@ -0,0 +1,183 @@ +# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*- +# +# Copyright (C) 2020 Canonical Ltd +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 3 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import pytest + +import snapcraft.extensions.registry as reg +from snapcraft import errors +from snapcraft.extensions.extension import get_extensions_data_dir +from snapcraft.extensions.ros2_humble_desktop import ROS2HumbleDesktopExtension +from snapcraft.extensions.ros2_humble_ros_base import ROS2HumbleRosBaseExtension +from snapcraft.extensions.ros2_humble_ros_core import ROS2HumbleRosCoreExtension + + +def setup_method_fixture(extension, yaml_data=None, arch=None, target_arch=None): + if yaml_data is None: + yaml_data = {} + if arch is None: + arch = "amd64" + if target_arch is None: + target_arch = "amd64" + + return extension( + yaml_data=yaml_data, arch=arch, target_arch=target_arch + ) + + +class TestExtensionROS2HumbleMetaExtensions: + """ROS 2 Humble meta extensions tests.""" + + fixture_variables = "extension_name,extension_class,meta,meta_dev" + fixture_values = [ + ( + "ros2-humble-desktop", + ROS2HumbleDesktopExtension, + "ros-humble-desktop", + "ros-humble-desktop" + ), + ( + "ros2-humble-ros-base", + ROS2HumbleRosBaseExtension, + "ros-humble-ros-base", + "ros-humble-ros-base" + ), + ( + "ros2-humble-ros-core", + ROS2HumbleRosCoreExtension, + "ros-humble-ros-core", + "ros-humble-ros-core" + ), + ] + + @pytest.mark.parametrize(fixture_variables, fixture_values) + def test_is_registered(self, extension_name, extension_class, meta, meta_dev): + assert extension_name in reg.get_extension_names() + + try: + reg.get_extension_class(extension_name) + except errors.ExtensionError as exc: + raise AssertionError(f"Couldn't get extension '{extension_name}': {exc}") + + @pytest.mark.parametrize(fixture_variables, fixture_values) + def test_ros_version(self, extension_name, extension_class, meta, meta_dev): + extension = setup_method_fixture(extension_class) + assert extension.ROS_VERSION == "2" + + @pytest.mark.parametrize(fixture_variables, fixture_values) + def test_get_supported_bases(self, extension_name, extension_class, meta, meta_dev): + extension = setup_method_fixture(extension_class) + assert extension.get_supported_bases() == ("core22",) + + @pytest.mark.parametrize(fixture_variables, fixture_values) + def test_get_supported_confinement(self, extension_name, extension_class, meta, meta_dev): + extension = setup_method_fixture(extension_class) + assert extension.get_supported_confinement() == ("strict", "devmode") + + @pytest.mark.parametrize(fixture_variables, fixture_values) + def test_get_root_snippet(self, extension_name, extension_class, meta, meta_dev): + extension = setup_method_fixture(extension_class) + assert extension.get_root_snippet() == { + "package-repositories": [ + { + "type": "apt", + "url": "http://repo.ros2.org/ubuntu/main", + "components": ["main"], + "formats": ["deb"], + "key-id": "C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654", + "key-server": "keyserver.ubuntu.com", + "suites": ["jammy"], + } + ], + "lint": { + "ignore": [ + { + "unused-library": [ + "opt/ros/*", + "lib/*/libcrypt.so*", + "lib/*/libexpat.so*", + "lib/*/libtirpc.so*", + "lib/*/libz.so*", + "usr/lib/*libatomic.so*", + "usr/lib/*libconsole_bridge.so*", + "usr/lib/*libfmt.so*", + "usr/lib/*libicui18n.so*", + "usr/lib/*libicuio.so*", + "usr/lib/*libicutest.so*", + "usr/lib/*libicutu.so*", + "usr/lib/*libpython3.10.so*", + "usr/lib/*libspdlog.so*", + "usr/lib/*libtinyxml2.so*", + ] + } + ] + }, + 'plugs': { + 'ros-meta': { + 'content': 'ros2-meta', + 'default-provider': meta, + 'interface': 'content', + 'target': '$SNAP/opt/ros/underlay_ws' + } + }, + } + + @pytest.mark.parametrize(fixture_variables, fixture_values) + def test_get_app_snippet(self, extension_name, extension_class, meta, meta_dev): + python_paths = [ + "$SNAP/opt/ros/humble/lib/python3.10/site-packages", + "$SNAP/usr/lib/python3/dist-packages", + "${PYTHONPATH}", + ] + extension = setup_method_fixture(extension_class) + assert extension.get_app_snippet() == { + "command-chain": ["snap/command-chain/ros2-launch"], + "environment": { + "ROS_VERSION": "2", + "ROS_DISTRO": "humble", + "PYTHONPATH": ":".join(python_paths), + "ROS_HOME": "$SNAP_USER_DATA/ros", + }, + } + + @pytest.mark.parametrize(fixture_variables, fixture_values) + def test_get_part_snippet(self, extension_name, extension_class, meta, meta_dev): + extension = setup_method_fixture(extension_class) + assert extension.get_part_snippet() == { + "build-environment": [{"ROS_VERSION": "2"}, {"ROS_DISTRO": "humble"}], + 'build-snaps': [meta_dev] + } + + @pytest.mark.parametrize(fixture_variables, fixture_values) + def test_get_parts_snippet(self, extension_name, extension_class, meta, meta_dev): + extension = setup_method_fixture(extension_class) + assert extension.get_parts_snippet() == { + "ros2-humble/ros2-launch": { + "source": f"{get_extensions_data_dir()}/ros2", + "plugin": "make", + "build-packages": [ + "ros-humble-ros-environment", + "ros-humble-ros-workspace", + "ros-humble-ament-index-cpp", + "ros-humble-ament-index-python", + ], + "stage-packages": [ + "ros-humble-ros-environment", + "ros-humble-ros-workspace", + "ros-humble-ament-index-cpp", + "ros-humble-ament-index-python", + ], + } + } From 874702cc0e8891a54baade3d49dbe8abd2cf8eb5 Mon Sep 17 00:00:00 2001 From: artivis Date: Thu, 20 Apr 2023 15:31:18 +0200 Subject: [PATCH 24/84] ros: rename meta snap and plugs Signed-off-by: artivis --- snapcraft/extensions/_ros2_humble_meta.py | 4 ++-- .../_extensions/_ros1_noetic_meta.py | 4 ++-- .../_extensions/_ros2_foxy_meta.py | 4 ++-- .../_extensions/ros1_noetic_desktop.py | 4 ++-- .../_extensions/ros1_noetic_perception.py | 4 ++-- .../_extensions/ros1_noetic_robot.py | 4 ++-- .../_extensions/ros1_noetic_ros_base.py | 4 ++-- .../_extensions/ros1_noetic_ros_core.py | 4 ++-- .../_extensions/ros2_foxy_desktop.py | 4 ++-- .../_extensions/ros2_foxy_ros_base.py | 4 ++-- .../_extensions/ros2_foxy_ros_core.py | 4 ++-- .../extensions/test_ros1_noetic_meta.py | 20 +++++++++---------- .../extensions/test_ros2_foxy_meta.py | 16 +++++++-------- .../parts/extensions/test_ros2_humble_meta.py | 4 ++-- 14 files changed, 42 insertions(+), 42 deletions(-) diff --git a/snapcraft/extensions/_ros2_humble_meta.py b/snapcraft/extensions/_ros2_humble_meta.py index 8fe76e7ab2..db65964a2e 100644 --- a/snapcraft/extensions/_ros2_humble_meta.py +++ b/snapcraft/extensions/_ros2_humble_meta.py @@ -32,10 +32,10 @@ class ROS2HumbleMetaBase(ROS2HumbleExtension): def get_root_snippet(self) -> Dict[str, Any]: root_snippet = super().get_root_snippet() root_snippet["plugs"] = { - "ros-meta": + "ros2": { "interface": "content", - "content": "ros2-meta", + "content": "ros-humble", "target": "$SNAP/opt/ros/underlay_ws", "default-provider": self.ROS_META, } diff --git a/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py b/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py index 7dfd824c3c..cfd8bfd3b3 100644 --- a/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py +++ b/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py @@ -34,10 +34,10 @@ def __init__(self, *, extension_name: str, yaml_data: Dict[str, Any]) -> None: # ] self.root_snippet["plugs"] = { - "ros-meta": + "ros": { "interface": "content", - "content": "ros-meta", + "content": "ros-noetic", "target": "$SNAP/opt/ros/underlay_ws", "default-provider": self.ROS_META, } diff --git a/snapcraft_legacy/internal/project_loader/_extensions/_ros2_foxy_meta.py b/snapcraft_legacy/internal/project_loader/_extensions/_ros2_foxy_meta.py index d5380d5413..28048288dc 100644 --- a/snapcraft_legacy/internal/project_loader/_extensions/_ros2_foxy_meta.py +++ b/snapcraft_legacy/internal/project_loader/_extensions/_ros2_foxy_meta.py @@ -44,10 +44,10 @@ def __init__(self, *, extension_name: str, yaml_data: Dict[str, Any]) -> None: ] self.root_snippet["plugs"] = { - "ros-meta": + "ros2": { "interface": "content", - "content": "ros2-meta", + "content": "ros-foxy", "target": "$SNAP/opt/ros/underlay_ws", "default-provider": self.ROS_META, } diff --git a/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_desktop.py b/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_desktop.py index 49222a1d8a..c0eb16987e 100644 --- a/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_desktop.py +++ b/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_desktop.py @@ -24,5 +24,5 @@ class ExtensionImpl(RosNoeticMetaBase): """Setup a ROS 1 build and runtime environment suitable for a snap.""" - ROS_META: Final[str] = "ros-meta-desktop" - ROS_META_DEV: Final[str] = "ros-meta-desktop" + ROS_META: Final[str] = "ros-noetic-desktop" + ROS_META_DEV: Final[str] = "ros-noetic-desktop" diff --git a/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_perception.py b/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_perception.py index dca661e75f..57681585fd 100644 --- a/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_perception.py +++ b/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_perception.py @@ -24,5 +24,5 @@ class ExtensionImpl(RosNoeticMetaBase): """Setup a ROS 1 build and runtime environment suitable for a snap.""" - ROS_META: Final[str] = "ros-meta-perception" - ROS_META_DEV: Final[str] = "ros-meta-perception" + ROS_META: Final[str] = "ros-noetic-perception" + ROS_META_DEV: Final[str] = "ros-noetic-perception" diff --git a/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_robot.py b/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_robot.py index 4c2bd448b3..bf08f99a0f 100644 --- a/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_robot.py +++ b/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_robot.py @@ -24,5 +24,5 @@ class ExtensionImpl(RosNoeticMetaBase): """Setup a ROS 1 build and runtime environment suitable for a snap.""" - ROS_META: Final[str] = "ros-meta-robot" - ROS_META_DEV: Final[str] = "ros-meta-robot" + ROS_META: Final[str] = "ros-noetic-robot" + ROS_META_DEV: Final[str] = "ros-noetic-robot" diff --git a/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_ros_base.py b/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_ros_base.py index 11ed5ff228..9250ce7a24 100644 --- a/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_ros_base.py +++ b/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_ros_base.py @@ -24,5 +24,5 @@ class ExtensionImpl(RosNoeticMetaBase): """Setup a ROS 1 build and runtime environment suitable for a snap.""" - ROS_META: Final[str] = "ros-meta-ros-base" - ROS_META_DEV: Final[str] = "ros-meta-ros-base" + ROS_META: Final[str] = "ros-noetic-ros-base" + ROS_META_DEV: Final[str] = "ros-noetic-ros-base" diff --git a/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_ros_core.py b/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_ros_core.py index 1c020661d5..e61b082f5a 100644 --- a/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_ros_core.py +++ b/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_ros_core.py @@ -24,5 +24,5 @@ class ExtensionImpl(RosNoeticMetaBase): """Setup a ROS 1 build and runtime environment suitable for a snap.""" - ROS_META: Final[str] = "ros-meta-ros-core" - ROS_META_DEV: Final[str] = "ros-meta-ros-core" + ROS_META: Final[str] = "ros-noetic-ros-core" + ROS_META_DEV: Final[str] = "ros-noetic-ros-core" diff --git a/snapcraft_legacy/internal/project_loader/_extensions/ros2_foxy_desktop.py b/snapcraft_legacy/internal/project_loader/_extensions/ros2_foxy_desktop.py index b369ebb473..936502aada 100644 --- a/snapcraft_legacy/internal/project_loader/_extensions/ros2_foxy_desktop.py +++ b/snapcraft_legacy/internal/project_loader/_extensions/ros2_foxy_desktop.py @@ -24,5 +24,5 @@ class ExtensionImpl(RosFoxyMetaBase): """Setup a ROS 2 build and runtime environment suitable for a snap.""" - ROS_META: Final[str] = "ros2-meta-desktop" - ROS_META_DEV: Final[str] = "ros2-meta-desktop" + ROS_META: Final[str] = "ros-foxy-desktop" + ROS_META_DEV: Final[str] = "ros-foxy-desktop" diff --git a/snapcraft_legacy/internal/project_loader/_extensions/ros2_foxy_ros_base.py b/snapcraft_legacy/internal/project_loader/_extensions/ros2_foxy_ros_base.py index 2f8bf80b56..79bd8b022c 100644 --- a/snapcraft_legacy/internal/project_loader/_extensions/ros2_foxy_ros_base.py +++ b/snapcraft_legacy/internal/project_loader/_extensions/ros2_foxy_ros_base.py @@ -24,5 +24,5 @@ class ExtensionImpl(RosFoxyMetaBase): """Setup a ROS 2 build and runtime environment suitable for a snap.""" - ROS_META: Final[str] = "ros2-meta-ros-base" - ROS_META_DEV: Final[str] = "ros2-meta-ros-base" + ROS_META: Final[str] = "ros-foxy-ros-base" + ROS_META_DEV: Final[str] = "ros-foxy-ros-base" diff --git a/snapcraft_legacy/internal/project_loader/_extensions/ros2_foxy_ros_core.py b/snapcraft_legacy/internal/project_loader/_extensions/ros2_foxy_ros_core.py index b4f8f854ab..42d2d087fc 100644 --- a/snapcraft_legacy/internal/project_loader/_extensions/ros2_foxy_ros_core.py +++ b/snapcraft_legacy/internal/project_loader/_extensions/ros2_foxy_ros_core.py @@ -24,5 +24,5 @@ class ExtensionImpl(RosFoxyMetaBase): """Setup a ROS 2 build and runtime environment suitable for a snap.""" - ROS_META: Final[str] = "ros2-meta-ros-core" - ROS_META_DEV: Final[str] = "ros2-meta-ros-core" + ROS_META: Final[str] = "ros-foxy-ros-core" + ROS_META_DEV: Final[str] = "ros-foxy-ros-core" diff --git a/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py b/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py index 3748f3e2bb..fc8a60da8f 100644 --- a/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py +++ b/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py @@ -38,29 +38,29 @@ class TestClass: { "extension_name": "ros1-noetic-desktop", "extension_class": Ros1NoeticDesktopExtension, - "meta": "ros-meta-desktop", - "meta_dev": "ros-meta-desktop", + "meta": "ros-noetic-desktop", + "meta_dev": "ros-noetic-desktop", }, "perception", { "extension_name": "ros1-noetic-perception", "extension_class": Ros1NoeticPerceptionExtension, - "meta": "ros-meta-perception", - "meta_dev": "ros-meta-perception", + "meta": "ros-noetic-perception", + "meta_dev": "ros-noetic-perception", }, "robot", { "extension_name": "ros1-noetic-robot", "extension_class": Ros1NoeticRobotExtension, - "meta": "ros-meta-robot", - "meta_dev": "ros-meta-robot", + "meta": "ros-noetic-robot", + "meta_dev": "ros-noetic-robot", }, "ros-base", { "extension_name": "ros1-noetic-ros-base", "extension_class": Ros1NoeticRosBaseExtension, - "meta": "ros-meta-ros-base", - "meta_dev": "ros-meta-ros-base", + "meta": "ros-noetic-ros-base", + "meta_dev": "ros-noetic-ros-base", }, "ros-core", { @@ -90,9 +90,9 @@ def test_extension(self, extension_name, extension_class, meta, meta_dev): } ], "plugs": { - "ros-meta": { + "ros": { "interface": "content", - "content": "ros-meta", + "content": "ros-noetic", "target": "$SNAP/opt/ros/underlay_ws", "default-provider": meta, } diff --git a/tests/legacy/unit/project_loader/extensions/test_ros2_foxy_meta.py b/tests/legacy/unit/project_loader/extensions/test_ros2_foxy_meta.py index f56422e9d8..a96723fb54 100644 --- a/tests/legacy/unit/project_loader/extensions/test_ros2_foxy_meta.py +++ b/tests/legacy/unit/project_loader/extensions/test_ros2_foxy_meta.py @@ -32,22 +32,22 @@ class TestClass: { "extension_name": "ros2-foxy-desktop", "extension_class": Ros2FoxyDesktopExtension, - "meta": "ros2-meta-desktop", - "meta_dev": "ros2-meta-desktop", + "meta": "ros-foxy-desktop", + "meta_dev": "ros-foxy-desktop", }, "ros-base", { "extension_name": "ros2-foxy-ros-base", "extension_class": Ros2FoxyRosBaseExtension, - "meta": "ros2-meta-ros-base", - "meta_dev": "ros2-meta-ros-base", + "meta": "ros-foxy-ros-base", + "meta_dev": "ros-foxy-ros-base", }, "ros-core", { "extension_name": "ros2-foxy-ros-core", "extension_class": Ros2FoxyRosCoreExtension, - "meta": "ros2-meta-ros-core", - "meta_dev": "ros2-meta-ros-core", + "meta": "ros-foxy-ros-core", + "meta_dev": "ros-foxy-ros-core", }, ), ] @@ -70,9 +70,9 @@ def test_extension(self, extension_name, extension_class, meta, meta_dev): } ], "plugs": { - "ros-meta": { + "ros2": { "interface": "content", - "content": "ros2-meta", + "content": "ros-foxy", "target": "$SNAP/opt/ros/underlay_ws", "default-provider": meta, } diff --git a/tests/unit/parts/extensions/test_ros2_humble_meta.py b/tests/unit/parts/extensions/test_ros2_humble_meta.py index 4c4cadfaa6..14f90e6e5e 100644 --- a/tests/unit/parts/extensions/test_ros2_humble_meta.py +++ b/tests/unit/parts/extensions/test_ros2_humble_meta.py @@ -125,8 +125,8 @@ def test_get_root_snippet(self, extension_name, extension_class, meta, meta_dev) ] }, 'plugs': { - 'ros-meta': { - 'content': 'ros2-meta', + 'ros2': { + 'content': 'ros-humble', 'default-provider': meta, 'interface': 'content', 'target': '$SNAP/opt/ros/underlay_ws' From f18694b5604c98308851e4bf27fe3ed870228514 Mon Sep 17 00:00:00 2001 From: artivis Date: Thu, 20 Apr 2023 18:49:10 +0200 Subject: [PATCH 25/84] ros: rename plugs Signed-off-by: artivis --- snapcraft/extensions/_ros2_humble_meta.py | 2 +- .../internal/project_loader/_extensions/_ros1_noetic_meta.py | 2 +- .../internal/project_loader/_extensions/_ros2_foxy_meta.py | 2 +- .../unit/project_loader/extensions/test_ros1_noetic_meta.py | 2 +- .../unit/project_loader/extensions/test_ros2_foxy_meta.py | 2 +- tests/unit/parts/extensions/test_ros2_humble_meta.py | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/snapcraft/extensions/_ros2_humble_meta.py b/snapcraft/extensions/_ros2_humble_meta.py index db65964a2e..8df3469c51 100644 --- a/snapcraft/extensions/_ros2_humble_meta.py +++ b/snapcraft/extensions/_ros2_humble_meta.py @@ -32,7 +32,7 @@ class ROS2HumbleMetaBase(ROS2HumbleExtension): def get_root_snippet(self) -> Dict[str, Any]: root_snippet = super().get_root_snippet() root_snippet["plugs"] = { - "ros2": + "ros-humble": { "interface": "content", "content": "ros-humble", diff --git a/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py b/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py index cfd8bfd3b3..bad3e33d8b 100644 --- a/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py +++ b/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py @@ -34,7 +34,7 @@ def __init__(self, *, extension_name: str, yaml_data: Dict[str, Any]) -> None: # ] self.root_snippet["plugs"] = { - "ros": + "ros-noetic": { "interface": "content", "content": "ros-noetic", diff --git a/snapcraft_legacy/internal/project_loader/_extensions/_ros2_foxy_meta.py b/snapcraft_legacy/internal/project_loader/_extensions/_ros2_foxy_meta.py index 28048288dc..5cd04f8d8d 100644 --- a/snapcraft_legacy/internal/project_loader/_extensions/_ros2_foxy_meta.py +++ b/snapcraft_legacy/internal/project_loader/_extensions/_ros2_foxy_meta.py @@ -44,7 +44,7 @@ def __init__(self, *, extension_name: str, yaml_data: Dict[str, Any]) -> None: ] self.root_snippet["plugs"] = { - "ros2": + "ros-foxy": { "interface": "content", "content": "ros-foxy", diff --git a/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py b/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py index fc8a60da8f..5ef1752d77 100644 --- a/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py +++ b/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py @@ -90,7 +90,7 @@ def test_extension(self, extension_name, extension_class, meta, meta_dev): } ], "plugs": { - "ros": { + "ros-noetic": { "interface": "content", "content": "ros-noetic", "target": "$SNAP/opt/ros/underlay_ws", diff --git a/tests/legacy/unit/project_loader/extensions/test_ros2_foxy_meta.py b/tests/legacy/unit/project_loader/extensions/test_ros2_foxy_meta.py index a96723fb54..b7aaafd2c2 100644 --- a/tests/legacy/unit/project_loader/extensions/test_ros2_foxy_meta.py +++ b/tests/legacy/unit/project_loader/extensions/test_ros2_foxy_meta.py @@ -70,7 +70,7 @@ def test_extension(self, extension_name, extension_class, meta, meta_dev): } ], "plugs": { - "ros2": { + "ros-foxy": { "interface": "content", "content": "ros-foxy", "target": "$SNAP/opt/ros/underlay_ws", diff --git a/tests/unit/parts/extensions/test_ros2_humble_meta.py b/tests/unit/parts/extensions/test_ros2_humble_meta.py index 14f90e6e5e..de83f3489e 100644 --- a/tests/unit/parts/extensions/test_ros2_humble_meta.py +++ b/tests/unit/parts/extensions/test_ros2_humble_meta.py @@ -125,7 +125,7 @@ def test_get_root_snippet(self, extension_name, extension_class, meta, meta_dev) ] }, 'plugs': { - 'ros2': { + 'ros-humble': { 'content': 'ros-humble', 'default-provider': meta, 'interface': 'content', From 9222180d119867741e1dcc5081e81256ad3d7b38 Mon Sep 17 00:00:00 2001 From: artivis Date: Sun, 23 Apr 2023 14:14:33 +0200 Subject: [PATCH 26/84] ros: use dev build snaps Signed-off-by: artivis --- .../project_loader/_extensions/ros1_noetic_desktop.py | 2 +- .../project_loader/_extensions/ros1_noetic_robot.py | 2 +- .../project_loader/_extensions/ros1_noetic_ros_base.py | 2 +- .../project_loader/_extensions/ros1_noetic_ros_core.py | 2 +- .../project_loader/_extensions/ros2_foxy_desktop.py | 2 +- .../project_loader/_extensions/ros2_foxy_ros_base.py | 2 +- .../project_loader/_extensions/ros2_foxy_ros_core.py | 2 +- .../project_loader/extensions/test_ros1_noetic_meta.py | 10 +++++----- .../project_loader/extensions/test_ros2_foxy_meta.py | 6 +++--- tests/spread/extensions/ros-meta/task.yaml | 4 ++-- 10 files changed, 17 insertions(+), 17 deletions(-) diff --git a/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_desktop.py b/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_desktop.py index c0eb16987e..ff2b924629 100644 --- a/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_desktop.py +++ b/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_desktop.py @@ -25,4 +25,4 @@ class ExtensionImpl(RosNoeticMetaBase): """Setup a ROS 1 build and runtime environment suitable for a snap.""" ROS_META: Final[str] = "ros-noetic-desktop" - ROS_META_DEV: Final[str] = "ros-noetic-desktop" + ROS_META_DEV: Final[str] = "ros-noetic-desktop-dev" diff --git a/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_robot.py b/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_robot.py index bf08f99a0f..16aabb7d19 100644 --- a/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_robot.py +++ b/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_robot.py @@ -25,4 +25,4 @@ class ExtensionImpl(RosNoeticMetaBase): """Setup a ROS 1 build and runtime environment suitable for a snap.""" ROS_META: Final[str] = "ros-noetic-robot" - ROS_META_DEV: Final[str] = "ros-noetic-robot" + ROS_META_DEV: Final[str] = "ros-noetic-robot-dev" diff --git a/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_ros_base.py b/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_ros_base.py index 9250ce7a24..edc821146b 100644 --- a/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_ros_base.py +++ b/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_ros_base.py @@ -25,4 +25,4 @@ class ExtensionImpl(RosNoeticMetaBase): """Setup a ROS 1 build and runtime environment suitable for a snap.""" ROS_META: Final[str] = "ros-noetic-ros-base" - ROS_META_DEV: Final[str] = "ros-noetic-ros-base" + ROS_META_DEV: Final[str] = "ros-noetic-ros-base-dev" diff --git a/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_ros_core.py b/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_ros_core.py index e61b082f5a..a0849fb0a9 100644 --- a/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_ros_core.py +++ b/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_ros_core.py @@ -25,4 +25,4 @@ class ExtensionImpl(RosNoeticMetaBase): """Setup a ROS 1 build and runtime environment suitable for a snap.""" ROS_META: Final[str] = "ros-noetic-ros-core" - ROS_META_DEV: Final[str] = "ros-noetic-ros-core" + ROS_META_DEV: Final[str] = "ros-noetic-ros-core-dev" diff --git a/snapcraft_legacy/internal/project_loader/_extensions/ros2_foxy_desktop.py b/snapcraft_legacy/internal/project_loader/_extensions/ros2_foxy_desktop.py index 936502aada..63cba51047 100644 --- a/snapcraft_legacy/internal/project_loader/_extensions/ros2_foxy_desktop.py +++ b/snapcraft_legacy/internal/project_loader/_extensions/ros2_foxy_desktop.py @@ -25,4 +25,4 @@ class ExtensionImpl(RosFoxyMetaBase): """Setup a ROS 2 build and runtime environment suitable for a snap.""" ROS_META: Final[str] = "ros-foxy-desktop" - ROS_META_DEV: Final[str] = "ros-foxy-desktop" + ROS_META_DEV: Final[str] = "ros-foxy-desktop-dev" diff --git a/snapcraft_legacy/internal/project_loader/_extensions/ros2_foxy_ros_base.py b/snapcraft_legacy/internal/project_loader/_extensions/ros2_foxy_ros_base.py index 79bd8b022c..5b91cdcdc3 100644 --- a/snapcraft_legacy/internal/project_loader/_extensions/ros2_foxy_ros_base.py +++ b/snapcraft_legacy/internal/project_loader/_extensions/ros2_foxy_ros_base.py @@ -25,4 +25,4 @@ class ExtensionImpl(RosFoxyMetaBase): """Setup a ROS 2 build and runtime environment suitable for a snap.""" ROS_META: Final[str] = "ros-foxy-ros-base" - ROS_META_DEV: Final[str] = "ros-foxy-ros-base" + ROS_META_DEV: Final[str] = "ros-foxy-ros-base-dev" diff --git a/snapcraft_legacy/internal/project_loader/_extensions/ros2_foxy_ros_core.py b/snapcraft_legacy/internal/project_loader/_extensions/ros2_foxy_ros_core.py index 42d2d087fc..cfa95a7478 100644 --- a/snapcraft_legacy/internal/project_loader/_extensions/ros2_foxy_ros_core.py +++ b/snapcraft_legacy/internal/project_loader/_extensions/ros2_foxy_ros_core.py @@ -25,4 +25,4 @@ class ExtensionImpl(RosFoxyMetaBase): """Setup a ROS 2 build and runtime environment suitable for a snap.""" ROS_META: Final[str] = "ros-foxy-ros-core" - ROS_META_DEV: Final[str] = "ros-foxy-ros-core" + ROS_META_DEV: Final[str] = "ros-foxy-ros-core-dev" diff --git a/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py b/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py index 5ef1752d77..fb0e3f2991 100644 --- a/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py +++ b/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py @@ -39,35 +39,35 @@ class TestClass: "extension_name": "ros1-noetic-desktop", "extension_class": Ros1NoeticDesktopExtension, "meta": "ros-noetic-desktop", - "meta_dev": "ros-noetic-desktop", + "meta_dev": "ros-noetic-desktop-dev", }, "perception", { "extension_name": "ros1-noetic-perception", "extension_class": Ros1NoeticPerceptionExtension, "meta": "ros-noetic-perception", - "meta_dev": "ros-noetic-perception", + "meta_dev": "ros-noetic-perception-dev", }, "robot", { "extension_name": "ros1-noetic-robot", "extension_class": Ros1NoeticRobotExtension, "meta": "ros-noetic-robot", - "meta_dev": "ros-noetic-robot", + "meta_dev": "ros-noetic-robot-dev", }, "ros-base", { "extension_name": "ros1-noetic-ros-base", "extension_class": Ros1NoeticRosBaseExtension, "meta": "ros-noetic-ros-base", - "meta_dev": "ros-noetic-ros-base", + "meta_dev": "ros-noetic-ros-base-dev", }, "ros-core", { "extension_name": "ros1-noetic-ros-core", "extension_class": Ros1NoeticRosCoreExtension, "meta": "ros-meta-ros-core", - "meta_dev": "ros-meta-ros-core", + "meta_dev": "ros-meta-ros-core-dev", }, ), ] diff --git a/tests/legacy/unit/project_loader/extensions/test_ros2_foxy_meta.py b/tests/legacy/unit/project_loader/extensions/test_ros2_foxy_meta.py index b7aaafd2c2..31bc74bea7 100644 --- a/tests/legacy/unit/project_loader/extensions/test_ros2_foxy_meta.py +++ b/tests/legacy/unit/project_loader/extensions/test_ros2_foxy_meta.py @@ -33,21 +33,21 @@ class TestClass: "extension_name": "ros2-foxy-desktop", "extension_class": Ros2FoxyDesktopExtension, "meta": "ros-foxy-desktop", - "meta_dev": "ros-foxy-desktop", + "meta_dev": "ros-foxy-desktop-dev", }, "ros-base", { "extension_name": "ros2-foxy-ros-base", "extension_class": Ros2FoxyRosBaseExtension, "meta": "ros-foxy-ros-base", - "meta_dev": "ros-foxy-ros-base", + "meta_dev": "ros-foxy-ros-base-dev", }, "ros-core", { "extension_name": "ros2-foxy-ros-core", "extension_class": Ros2FoxyRosCoreExtension, "meta": "ros-foxy-ros-core", - "meta_dev": "ros-foxy-ros-core", + "meta_dev": "ros-foxy-ros-core-dev", }, ), ] diff --git a/tests/spread/extensions/ros-meta/task.yaml b/tests/spread/extensions/ros-meta/task.yaml index b7d35480d9..0f6af4187e 100644 --- a/tests/spread/extensions/ros-meta/task.yaml +++ b/tests/spread/extensions/ros-meta/task.yaml @@ -50,7 +50,7 @@ execute: | SNAP_SIZE=$(ls -s "${SNAP}"_1.0_*.snap | cut -d " " -f1) [ "100" -gt "$SNAP_SIZE" ] - snap connect ${SNAP}:ros-meta ${META_SNAP} + snap connect ${SNAP}:ros-noetic ${META_SNAP} [ "$($SNAP)" = "hello world" ] # Clean the hello part, then build and run again. @@ -58,7 +58,7 @@ execute: | snapcraft snap install "${SNAP}"_1.0_*.snap --dangerous - snap connect ${SNAP}:ros-meta ${META_SNAP} + snap connect ${SNAP}:ros-noetic ${META_SNAP} [ "$($SNAP)" = "hello world" ] # Make sure that what we built runs with the changes applied. From e8415e37df2b69d7133089668658435550f237ce Mon Sep 17 00:00:00 2001 From: artivis Date: Sun, 23 Apr 2023 14:15:04 +0200 Subject: [PATCH 27/84] ros: use humble dev build snaps Signed-off-by: artivis --- snapcraft/extensions/ros2_humble_desktop.py | 2 +- snapcraft/extensions/ros2_humble_ros_base.py | 2 +- snapcraft/extensions/ros2_humble_ros_core.py | 2 +- tests/unit/parts/extensions/test_ros2_humble_meta.py | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/snapcraft/extensions/ros2_humble_desktop.py b/snapcraft/extensions/ros2_humble_desktop.py index 069db72e87..5b404a20f2 100644 --- a/snapcraft/extensions/ros2_humble_desktop.py +++ b/snapcraft/extensions/ros2_humble_desktop.py @@ -35,4 +35,4 @@ def is_experimental(base: Optional[str]) -> bool: return True ROS_META: Final[str] = "ros-humble-desktop" - ROS_META_DEV: Final[str] = "ros-humble-desktop" \ No newline at end of file + ROS_META_DEV: Final[str] = "ros-humble-desktop-dev" diff --git a/snapcraft/extensions/ros2_humble_ros_base.py b/snapcraft/extensions/ros2_humble_ros_base.py index 529cd3be9b..a773e6ab3d 100644 --- a/snapcraft/extensions/ros2_humble_ros_base.py +++ b/snapcraft/extensions/ros2_humble_ros_base.py @@ -35,4 +35,4 @@ def is_experimental(base: Optional[str]) -> bool: return True ROS_META: Final[str] = "ros-humble-ros-base" - ROS_META_DEV: Final[str] = "ros-humble-ros-base" \ No newline at end of file + ROS_META_DEV: Final[str] = "ros-humble-ros-base-dev" diff --git a/snapcraft/extensions/ros2_humble_ros_core.py b/snapcraft/extensions/ros2_humble_ros_core.py index 039ac7fbd7..efc1ee4b97 100644 --- a/snapcraft/extensions/ros2_humble_ros_core.py +++ b/snapcraft/extensions/ros2_humble_ros_core.py @@ -35,4 +35,4 @@ def is_experimental(base: Optional[str]) -> bool: return True ROS_META: Final[str] = "ros-humble-ros-core" - ROS_META_DEV: Final[str] = "ros-humble-ros-core" \ No newline at end of file + ROS_META_DEV: Final[str] = "ros-humble-ros-core-dev" diff --git a/tests/unit/parts/extensions/test_ros2_humble_meta.py b/tests/unit/parts/extensions/test_ros2_humble_meta.py index de83f3489e..f36d645db6 100644 --- a/tests/unit/parts/extensions/test_ros2_humble_meta.py +++ b/tests/unit/parts/extensions/test_ros2_humble_meta.py @@ -46,19 +46,19 @@ class TestExtensionROS2HumbleMetaExtensions: "ros2-humble-desktop", ROS2HumbleDesktopExtension, "ros-humble-desktop", - "ros-humble-desktop" + "ros-humble-desktop-dev" ), ( "ros2-humble-ros-base", ROS2HumbleRosBaseExtension, "ros-humble-ros-base", - "ros-humble-ros-base" + "ros-humble-ros-base-dev" ), ( "ros2-humble-ros-core", ROS2HumbleRosCoreExtension, "ros-humble-ros-core", - "ros-humble-ros-core" + "ros-humble-ros-core-dev" ), ] From 5db3e2845cca3872adf33324148ef5907333ff53 Mon Sep 17 00:00:00 2001 From: artivis Date: Fri, 21 Apr 2023 18:09:06 +0200 Subject: [PATCH 28/84] ros: fix spread test Signed-off-by: artivis --- tests/spread/extensions/ros-meta/task.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/spread/extensions/ros-meta/task.yaml b/tests/spread/extensions/ros-meta/task.yaml index 0f6af4187e..c9a89f9da7 100644 --- a/tests/spread/extensions/ros-meta/task.yaml +++ b/tests/spread/extensions/ros-meta/task.yaml @@ -50,7 +50,7 @@ execute: | SNAP_SIZE=$(ls -s "${SNAP}"_1.0_*.snap | cut -d " " -f1) [ "100" -gt "$SNAP_SIZE" ] - snap connect ${SNAP}:ros-noetic ${META_SNAP} + snap connect ${SNAP}:ros-noetic ${META_SNAP}:ros-noetic [ "$($SNAP)" = "hello world" ] # Clean the hello part, then build and run again. @@ -58,7 +58,7 @@ execute: | snapcraft snap install "${SNAP}"_1.0_*.snap --dangerous - snap connect ${SNAP}:ros-noetic ${META_SNAP} + snap connect ${SNAP}:ros-noetic ${META_SNAP}:ros-noetic [ "$($SNAP)" = "hello world" ] # Make sure that what we built runs with the changes applied. @@ -73,5 +73,5 @@ execute: | snapcraft snap install "${SNAP}"_1.0_*.snap --dangerous - snap connect ${SNAP}:ros-meta ${META_SNAP} + snap connect ${SNAP}:ros-noetic ${META_SNAP}:ros-noetic [ "$($SNAP)" = "hello rebuilt world" ] From bbb1ccd6d24796568254462b9ef497b7114d591a Mon Sep 17 00:00:00 2001 From: artivis Date: Sun, 23 Apr 2023 14:11:03 +0200 Subject: [PATCH 29/84] ros: fix legacy static tests Signed-off-by: artivis --- snapcraft_legacy/plugins/v2/_ros.py | 2 +- tests/legacy/unit/plugins/v2/test_colcon.py | 8 ++++---- .../project_loader/extensions/test_ros1_noetic_meta.py | 4 +++- .../unit/project_loader/extensions/test_ros2_foxy_meta.py | 4 +++- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/snapcraft_legacy/plugins/v2/_ros.py b/snapcraft_legacy/plugins/v2/_ros.py index 67163b4321..3484e5faf0 100644 --- a/snapcraft_legacy/plugins/v2/_ros.py +++ b/snapcraft_legacy/plugins/v2/_ros.py @@ -268,7 +268,7 @@ def get_installed_dependencies(installed_packages_path: str) -> Set[str]: ) except subprocess.CalledProcessError as error: click.echo(f"failed to run {cmd!r}: {error.output}") - apt_dependency_regex = re.compile("^\w.*$") + apt_dependency_regex = re.compile("^\w.*$") # noqa: W605 for line in proc.stdout.decode().strip().split("\n"): if apt_dependency_regex.match(line): package_dependencies.add(line) diff --git a/tests/legacy/unit/plugins/v2/test_colcon.py b/tests/legacy/unit/plugins/v2/test_colcon.py index 1e4fa4513b..0d1389d666 100644 --- a/tests/legacy/unit/plugins/v2/test_colcon.py +++ b/tests/legacy/unit/plugins/v2/test_colcon.py @@ -165,13 +165,13 @@ class Options: "fi", "", 'eval "${state}"', - '## Prepare build', + "## Prepare build", "## Build command", "colcon build " '--base-paths "${SNAPCRAFT_PART_SRC_WORK}" --build-base "${SNAPCRAFT_PART_BUILD}" ' '--merge-install --install-base "${SNAPCRAFT_PART_INSTALL}"/opt/ros/snap ' '--parallel-workers "${SNAPCRAFT_PARALLEL_BUILD_COUNT}"', - '## Post build command', + "## Post build command", 'if [ -f "${SNAPCRAFT_PART_INSTALL}"/opt/ros/snap/COLCON_IGNORE ]; then', 'rm "${SNAPCRAFT_PART_INSTALL}"/opt/ros/snap/COLCON_IGNORE', "fi", @@ -303,7 +303,7 @@ class Options: "fi", "", 'eval "${state}"', - '## Prepare build', + "## Prepare build", 'if [ -d "/snap/foo/current" ]; then export ' 'CMAKE_PREFIX_PATH="/snap/foo/current:/snap/foo/current/usr:${CMAKE_PREFIX_PATH}"; ' "fi", @@ -315,7 +315,7 @@ class Options: "package2... --cmake-args cmake args... " "--ament-cmake-args ament args... --catkin-cmake-args catkin " 'args... --parallel-workers "${SNAPCRAFT_PARALLEL_BUILD_COUNT}"', - '## Post build command', + "## Post build command", 'if [ -f "${SNAPCRAFT_PART_INSTALL}"/opt/ros/snap/COLCON_IGNORE ]; then', 'rm "${SNAPCRAFT_PART_INSTALL}"/opt/ros/snap/COLCON_IGNORE', "fi", diff --git a/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py b/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py index fb0e3f2991..1c75ef753c 100644 --- a/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py +++ b/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py @@ -124,5 +124,7 @@ def test_extension(self, extension_name, extension_class, meta, meta_dev): def test_supported_bases(self, extension_name, extension_class, meta, meta_dev): assert extension_class.get_supported_bases() == ("core20",) - def test_supported_confinement(self, extension_name, extension_class, meta, meta_dev): + def test_supported_confinement( + self, extension_name, extension_class, meta, meta_dev + ): extension_class.get_supported_confinement() == ("strict", "devmode") diff --git a/tests/legacy/unit/project_loader/extensions/test_ros2_foxy_meta.py b/tests/legacy/unit/project_loader/extensions/test_ros2_foxy_meta.py index 31bc74bea7..0cefe27645 100644 --- a/tests/legacy/unit/project_loader/extensions/test_ros2_foxy_meta.py +++ b/tests/legacy/unit/project_loader/extensions/test_ros2_foxy_meta.py @@ -115,5 +115,7 @@ def test_extension(self, extension_name, extension_class, meta, meta_dev): def test_supported_bases(self, extension_name, extension_class, meta, meta_dev): assert extension_class.get_supported_bases() == ("core20",) - def test_supported_confinement(self, extension_name, extension_class, meta, meta_dev): + def test_supported_confinement( + self, extension_name, extension_class, meta, meta_dev + ): extension_class.get_supported_confinement() == ("strict", "devmode") From 4bce041d1d6bf6fd9ee779e00b9bc66d36bde86b Mon Sep 17 00:00:00 2001 From: artivis Date: Sun, 23 Apr 2023 14:11:33 +0200 Subject: [PATCH 30/84] ros: fix parts static tests Signed-off-by: artivis --- snapcraft/extensions/_ros2_humble_meta.py | 28 ++++++++---- snapcraft/parts/plugins/_ros.py | 45 +++++++++---------- snapcraft/parts/plugins/colcon_plugin.py | 25 ++++++----- .../parts/extensions/test_ros2_humble_meta.py | 28 ++++++------ tests/unit/parts/plugins/test_colcon.py | 12 ++--- 5 files changed, 77 insertions(+), 61 deletions(-) diff --git a/snapcraft/extensions/_ros2_humble_meta.py b/snapcraft/extensions/_ros2_humble_meta.py index 8df3469c51..d8db989328 100644 --- a/snapcraft/extensions/_ros2_humble_meta.py +++ b/snapcraft/extensions/_ros2_humble_meta.py @@ -18,7 +18,8 @@ """Base for ROS 2 Humble extensions to the Colcon plugin using content-sharing.""" -from typing import Any, Dict, Optional +from abc import abstractmethod +from typing import Any, Dict from overrides import overrides @@ -28,17 +29,28 @@ class ROS2HumbleMetaBase(ROS2HumbleExtension): """Drives ROS 2 build and runtime environment for snap using content-sharing.""" + @property + @abstractmethod + def ROS_META(cls): + """Abstract property to define the extension's content-sharing snap.""" + raise NotImplementedError + + @property + @abstractmethod + def ROS_META_DEV(cls): + """Abstract property to define the extension's build snap.""" + raise NotImplementedError + @overrides def get_root_snippet(self) -> Dict[str, Any]: root_snippet = super().get_root_snippet() root_snippet["plugs"] = { - "ros-humble": - { - "interface": "content", - "content": "ros-humble", - "target": "$SNAP/opt/ros/underlay_ws", - "default-provider": self.ROS_META, - } + "ros-humble": { + "interface": "content", + "content": "ros-humble", + "target": "$SNAP/opt/ros/underlay_ws", + "default-provider": self.ROS_META, + } } return root_snippet diff --git a/snapcraft/parts/plugins/_ros.py b/snapcraft/parts/plugins/_ros.py index c202687c51..017f72aba4 100644 --- a/snapcraft/parts/plugins/_ros.py +++ b/snapcraft/parts/plugins/_ros.py @@ -130,7 +130,6 @@ def _get_build_commands(self) -> List[str]: def _get_list_packages_commands(self) -> List[str]: """Generate a list of ROS 2 packages available in build snaps. - The ROS 2 workspaces contained in build snaps are crawled with `rospack` to establish the list of all available ROS 2 packages. The package names are then resolved with `rosdep` to map their names to debs. @@ -143,31 +142,29 @@ def _get_list_packages_commands(self) -> List[str]: cmd.append('rm -f "${CRAFT_PART_INSTALL}/.installed_packages.txt"') cmd.append('rm -f "${CRAFT_PART_INSTALL}/.build_snaps.txt"') - # self.get_build_properties - - if self._options.build_snaps: - for build_snap in self._options.build_snaps: + if self._options.build_snaps: # type: ignore + for build_snap in self._options.build_snaps: # type: ignore snap_name = _get_parsed_snap(build_snap)[0] path = f"/snap/{snap_name}/current/opt/ros" - cmd.extend([ - # Retrieve the list of all ROS packages available in the build snap - f"if [ -d {path} ]; then", - f"ROS_PACKAGE_PATH={path} " - 'rospack list-names | (xargs rosdep resolve --rosdistro "${ROS_DISTRO}" || echo "") | ' - 'awk "/#apt/{getline;print;}" >> "${CRAFT_PART_INSTALL}/.installed_packages.txt"', - "fi", - - # Retrieve the list of all non-ROS packages available in the build snap - f'if [ -d "{path}/${{ROS_DISTRO}}/" ]; then', - f'rosdep keys --rosdistro "${{ROS_DISTRO}}" --from-paths "{path}/${{ROS_DISTRO}}" --ignore-packages-from-source ' - '| (xargs rosdep resolve --rosdistro "${ROS_DISTRO}" || echo "") | grep -v "#" >> "${CRAFT_PART_INSTALL}"/.installed_packages.txt', - "fi", - - f'if [ -d "{path}/snap/" ]; then', - f'rosdep keys --rosdistro "${{ROS_DISTRO}}" --from-paths "{path}/snap" --ignore-packages-from-source ' - '| (xargs rosdep resolve --rosdistro "${ROS_DISTRO}" || echo "") | grep -v "#" >> "${CRAFT_PART_INSTALL}"/.installed_packages.txt', - "fi", - ]) + cmd.extend( + [ + # Retrieve the list of all ROS packages available in the build snap + f"if [ -d {path} ]; then", + f"ROS_PACKAGE_PATH={path} " + 'rospack list-names | (xargs rosdep resolve --rosdistro "${ROS_DISTRO}" || echo "") | ' + 'awk "/#apt/{getline;print;}" >> "${CRAFT_PART_INSTALL}/.installed_packages.txt"', + "fi", + # Retrieve the list of all non-ROS packages available in the build snap + f'if [ -d "{path}/${{ROS_DISTRO}}/" ]; then', + f'rosdep keys --rosdistro "${{ROS_DISTRO}}" --from-paths "{path}/${{ROS_DISTRO}}" --ignore-packages-from-source ' + '| (xargs rosdep resolve --rosdistro "${ROS_DISTRO}" || echo "") | grep -v "#" >> "${CRAFT_PART_INSTALL}"/.installed_packages.txt', + "fi", + f'if [ -d "{path}/snap/" ]; then', + f'rosdep keys --rosdistro "${{ROS_DISTRO}}" --from-paths "{path}/snap" --ignore-packages-from-source ' + '| (xargs rosdep resolve --rosdistro "${ROS_DISTRO}" || echo "") | grep -v "#" >> "${CRAFT_PART_INSTALL}"/.installed_packages.txt', + "fi", + ] + ) cmd.append("") return cmd diff --git a/snapcraft/parts/plugins/colcon_plugin.py b/snapcraft/parts/plugins/colcon_plugin.py index ab62797148..baa65877d9 100644 --- a/snapcraft/parts/plugins/colcon_plugin.py +++ b/snapcraft/parts/plugins/colcon_plugin.py @@ -150,6 +150,7 @@ def _get_workspace_activation_commands(self) -> List[str]: # Source ROS ws in all build-snaps first activation_commands.append("## Sourcing ROS ws in build snaps") + self._options: ColconPluginProperties if self._options.build_snaps: for build_snap in self._options.build_snaps: snap_name = _get_parsed_snap(build_snap)[0] @@ -160,9 +161,7 @@ def _get_workspace_activation_commands(self) -> List[str]: # Source ROS ws in stage-snaps next activation_commands.append("## Sourcing ROS ws in stage snaps") - activation_commands.extend( - self._get_source_command("${CRAFT_PART_INSTALL}") - ) + activation_commands.extend(self._get_source_command("${CRAFT_PART_INSTALL}")) activation_commands.append("") # Finally source system's ROS ws @@ -182,11 +181,13 @@ def _get_build_commands(self) -> List[str]: for build_snap in self._options.build_snaps: build_snap = _get_parsed_snap(build_snap)[0] - export_command.extend([ - 'if [ -d "/snap/{build_snap}/current" ]; then ' - 'export CMAKE_PREFIX_PATH="/snap/{build_snap}/current:/snap/{build_snap}/current/usr:${{CMAKE_PREFIX_PATH}}"; ' - 'fi'.format(build_snap=build_snap) - ]) + export_command.extend( + [ + 'if [ -d "/snap/{build_snap}/current" ]; then ' + 'export CMAKE_PREFIX_PATH="/snap/{build_snap}/current:/snap/{build_snap}/current/usr:${{CMAKE_PREFIX_PATH}}"; ' + "fi".format(build_snap=build_snap) + ] + ) build_command = [ "colcon", @@ -210,10 +211,14 @@ def _get_build_commands(self) -> List[str]: build_command.extend(["--cmake-args", *options.colcon_cmake_args]) if options.colcon_ament_cmake_args: - build_command.extend(["--ament-cmake-args", *options.colcon_ament_cmake_args]) + build_command.extend( + ["--ament-cmake-args", *options.colcon_ament_cmake_args] + ) if options.colcon_catkin_cmake_args: - build_command.extend(["--catkin-cmake-args", *options.colcon_catkin_cmake_args]) + build_command.extend( + ["--catkin-cmake-args", *options.colcon_catkin_cmake_args] + ) # Specify the number of workers build_command.extend(["--parallel-workers", '"${CRAFT_PARALLEL_BUILD_COUNT}"']) diff --git a/tests/unit/parts/extensions/test_ros2_humble_meta.py b/tests/unit/parts/extensions/test_ros2_humble_meta.py index f36d645db6..ebd3e8f9b6 100644 --- a/tests/unit/parts/extensions/test_ros2_humble_meta.py +++ b/tests/unit/parts/extensions/test_ros2_humble_meta.py @@ -32,9 +32,7 @@ def setup_method_fixture(extension, yaml_data=None, arch=None, target_arch=None) if target_arch is None: target_arch = "amd64" - return extension( - yaml_data=yaml_data, arch=arch, target_arch=target_arch - ) + return extension(yaml_data=yaml_data, arch=arch, target_arch=target_arch) class TestExtensionROS2HumbleMetaExtensions: @@ -46,19 +44,19 @@ class TestExtensionROS2HumbleMetaExtensions: "ros2-humble-desktop", ROS2HumbleDesktopExtension, "ros-humble-desktop", - "ros-humble-desktop-dev" + "ros-humble-desktop-dev", ), ( "ros2-humble-ros-base", ROS2HumbleRosBaseExtension, "ros-humble-ros-base", - "ros-humble-ros-base-dev" + "ros-humble-ros-base-dev", ), ( "ros2-humble-ros-core", ROS2HumbleRosCoreExtension, "ros-humble-ros-core", - "ros-humble-ros-core-dev" + "ros-humble-ros-core-dev", ), ] @@ -82,7 +80,9 @@ def test_get_supported_bases(self, extension_name, extension_class, meta, meta_d assert extension.get_supported_bases() == ("core22",) @pytest.mark.parametrize(fixture_variables, fixture_values) - def test_get_supported_confinement(self, extension_name, extension_class, meta, meta_dev): + def test_get_supported_confinement( + self, extension_name, extension_class, meta, meta_dev + ): extension = setup_method_fixture(extension_class) assert extension.get_supported_confinement() == ("strict", "devmode") @@ -124,12 +124,12 @@ def test_get_root_snippet(self, extension_name, extension_class, meta, meta_dev) } ] }, - 'plugs': { - 'ros-humble': { - 'content': 'ros-humble', - 'default-provider': meta, - 'interface': 'content', - 'target': '$SNAP/opt/ros/underlay_ws' + "plugs": { + "ros-humble": { + "content": "ros-humble", + "default-provider": meta, + "interface": "content", + "target": "$SNAP/opt/ros/underlay_ws", } }, } @@ -157,7 +157,7 @@ def test_get_part_snippet(self, extension_name, extension_class, meta, meta_dev) extension = setup_method_fixture(extension_class) assert extension.get_part_snippet() == { "build-environment": [{"ROS_VERSION": "2"}, {"ROS_DISTRO": "humble"}], - 'build-snaps': [meta_dev] + "build-snaps": [meta_dev], } @pytest.mark.parametrize(fixture_variables, fixture_values) diff --git a/tests/unit/parts/plugins/test_colcon.py b/tests/unit/parts/plugins/test_colcon.py index 58d411871c..00104c76e8 100644 --- a/tests/unit/parts/plugins/test_colcon.py +++ b/tests/unit/parts/plugins/test_colcon.py @@ -76,12 +76,14 @@ def test_property_default(self): def test_property_unexpected(self): try: - properties = colcon.ColconPlugin.properties_class(source=".") + properties = colcon.ColconPlugin.properties_class(source=".") # noqa F841 except ValidationError as e: raise AssertionError(f"{e}") from e with pytest.raises(ValidationError): - properties = colcon.ColconPlugin.properties_class(source=".", foo="bar") + properties = colcon.ColconPlugin.properties_class( # noqa F841 + source=".", foo="bar" + ) def test_property_all(self): try: @@ -199,13 +201,13 @@ def test_get_build_commands(self, setup_method_fixture, new_dir, monkeypatch): "fi", "", 'eval "${state}"', - '## Prepare build', + "## Prepare build", "## Build command", - 'colcon build ' + "colcon build " '--base-paths "${CRAFT_PART_SRC_WORK}" --build-base "${CRAFT_PART_BUILD}" ' '--merge-install --install-base "${CRAFT_PART_INSTALL}/opt/ros/snap" ' '--parallel-workers "${CRAFT_PARALLEL_BUILD_COUNT}"', - '## Post build command', + "## Post build command", 'if [ -f "${CRAFT_PART_INSTALL}"/opt/ros/snap/COLCON_IGNORE ]; then', 'rm "${CRAFT_PART_INSTALL}"/opt/ros/snap/COLCON_IGNORE', "fi", From 2007bae5f9f32de943cded236b47bcfef03db4d3 Mon Sep 17 00:00:00 2001 From: artivis Date: Fri, 21 Apr 2023 20:13:26 +0200 Subject: [PATCH 31/84] ros: handle possibly undefined env var Signed-off-by: artivis --- snapcraft/parts/plugins/colcon_plugin.py | 2 +- snapcraft_legacy/plugins/v2/catkin.py | 2 +- snapcraft_legacy/plugins/v2/colcon.py | 2 +- tests/legacy/unit/plugins/v2/test_catkin.py | 2 +- tests/legacy/unit/plugins/v2/test_colcon.py | 2 +- tests/unit/parts/plugins/test_colcon.py | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/snapcraft/parts/plugins/colcon_plugin.py b/snapcraft/parts/plugins/colcon_plugin.py index baa65877d9..abf6d6b255 100644 --- a/snapcraft/parts/plugins/colcon_plugin.py +++ b/snapcraft/parts/plugins/colcon_plugin.py @@ -184,7 +184,7 @@ def _get_build_commands(self) -> List[str]: export_command.extend( [ 'if [ -d "/snap/{build_snap}/current" ]; then ' - 'export CMAKE_PREFIX_PATH="/snap/{build_snap}/current:/snap/{build_snap}/current/usr:${{CMAKE_PREFIX_PATH}}"; ' + 'export CMAKE_PREFIX_PATH="/snap/{build_snap}/current:/snap/{build_snap}/current/usr:${{CMAKE_PREFIX_PATH-}}"; ' "fi".format(build_snap=build_snap) ] ) diff --git a/snapcraft_legacy/plugins/v2/catkin.py b/snapcraft_legacy/plugins/v2/catkin.py index 910d911d4c..94a919bfe8 100644 --- a/snapcraft_legacy/plugins/v2/catkin.py +++ b/snapcraft_legacy/plugins/v2/catkin.py @@ -148,7 +148,7 @@ def _get_build_commands(self) -> List[str]: ]) export_command.extend([ 'if [ -d "${{SNAPCRAFT_PART_BUILD}}"/build_snaps/{build_snap} ]; then ' - 'export CMAKE_PREFIX_PATH="${{SNAPCRAFT_PART_BUILD}}/build_snaps/{build_snap}:${{CMAKE_PREFIX_PATH}}"; ' + 'export CMAKE_PREFIX_PATH="${{SNAPCRAFT_PART_BUILD}}/build_snaps/{build_snap}:${{CMAKE_PREFIX_PATH-}}"; ' 'fi'.format(build_snap=build_snap) ]) diff --git a/snapcraft_legacy/plugins/v2/colcon.py b/snapcraft_legacy/plugins/v2/colcon.py index 6a3693ebbd..60e6d0f954 100644 --- a/snapcraft_legacy/plugins/v2/colcon.py +++ b/snapcraft_legacy/plugins/v2/colcon.py @@ -182,7 +182,7 @@ def _get_build_commands(self) -> List[str]: export_command.extend([ 'if [ -d "/snap/{build_snap}/current" ]; then ' - 'export CMAKE_PREFIX_PATH="/snap/{build_snap}/current:/snap/{build_snap}/current/usr:${{CMAKE_PREFIX_PATH}}"; ' + 'export CMAKE_PREFIX_PATH="/snap/{build_snap}/current:/snap/{build_snap}/current/usr:${{CMAKE_PREFIX_PATH-}}"; ' 'fi'.format(build_snap=build_snap) ]) diff --git a/tests/legacy/unit/plugins/v2/test_catkin.py b/tests/legacy/unit/plugins/v2/test_catkin.py index 0bfa1ed7c2..d3b73858c7 100644 --- a/tests/legacy/unit/plugins/v2/test_catkin.py +++ b/tests/legacy/unit/plugins/v2/test_catkin.py @@ -282,7 +282,7 @@ class Options: '"s|\\${.*_DIR}/../../..|/snap/foo/current/opt/ros/${ROS_DISTRO}|g" {} \\;', "fi", 'if [ -d "${SNAPCRAFT_PART_BUILD}"/build_snaps/foo ]; then export ' - 'CMAKE_PREFIX_PATH="${SNAPCRAFT_PART_BUILD}/build_snaps/foo:${CMAKE_PREFIX_PATH}"; ' + 'CMAKE_PREFIX_PATH="${SNAPCRAFT_PART_BUILD}/build_snaps/foo:${CMAKE_PREFIX_PATH-}"; ' "fi", "## Build command", "catkin_make_isolated --install --merge " diff --git a/tests/legacy/unit/plugins/v2/test_colcon.py b/tests/legacy/unit/plugins/v2/test_colcon.py index 0d1389d666..8326f4e448 100644 --- a/tests/legacy/unit/plugins/v2/test_colcon.py +++ b/tests/legacy/unit/plugins/v2/test_colcon.py @@ -305,7 +305,7 @@ class Options: 'eval "${state}"', "## Prepare build", 'if [ -d "/snap/foo/current" ]; then export ' - 'CMAKE_PREFIX_PATH="/snap/foo/current:/snap/foo/current/usr:${CMAKE_PREFIX_PATH}"; ' + 'CMAKE_PREFIX_PATH="/snap/foo/current:/snap/foo/current/usr:${CMAKE_PREFIX_PATH-}"; ' "fi", "## Build command", "colcon build " diff --git a/tests/unit/parts/plugins/test_colcon.py b/tests/unit/parts/plugins/test_colcon.py index 00104c76e8..965bd93994 100644 --- a/tests/unit/parts/plugins/test_colcon.py +++ b/tests/unit/parts/plugins/test_colcon.py @@ -350,7 +350,7 @@ def test_get_build_commands_with_all_properties( 'eval "${state}"', "## Prepare build", 'if [ -d "/snap/foo/current" ]; then export ' - 'CMAKE_PREFIX_PATH="/snap/foo/current:/snap/foo/current/usr:${CMAKE_PREFIX_PATH}"; ' + 'CMAKE_PREFIX_PATH="/snap/foo/current:/snap/foo/current/usr:${CMAKE_PREFIX_PATH-}"; ' "fi", "## Build command", "colcon build " From 762f545d89e4211960b1c4d653dbd3f5928ae06b Mon Sep 17 00:00:00 2001 From: artivis Date: Sat, 22 Apr 2023 15:20:43 +0200 Subject: [PATCH 32/84] ros: fix LD_LIB export Signed-off-by: artivis --- extensions/ros2/launch | 2 ++ 1 file changed, 2 insertions(+) diff --git a/extensions/ros2/launch b/extensions/ros2/launch index 1cf3fd7016..2acada8e1b 100755 --- a/extensions/ros2/launch +++ b/extensions/ros2/launch @@ -18,6 +18,8 @@ if [ -d "$SNAP/opt/ros/underlay_ws/opt/ros/$ROS_DISTRO" ]; then fi if [ -d "$SNAP/opt/ros/underlay_ws/opt/ros/snap" ]; then source_with_prefix "$SNAP/opt/ros/underlay_ws/opt/ros/snap" +fi +if [[ -d "$SNAP/opt/ros/underlay_ws/opt/ros/$ROS_DISTRO" || -d "$SNAP/opt/ros/underlay_ws/opt/ros/snap" ]]; then export LD_LIBRARY_PATH="$SNAP/opt/ros/underlay_ws/usr/lib/x86_64-linux-gnu:${LD_LIBRARY_PATH}" fi From ed4eee40042c5167c958e809e028faceeb240f00 Mon Sep 17 00:00:00 2001 From: artivis Date: Tue, 25 Apr 2023 09:38:37 +0200 Subject: [PATCH 33/84] ros: enable more spread test Signed-off-by: artivis --- tests/spread/extensions/ros-meta/task.yaml | 55 ++++++++--------- tests/spread/extensions/ros2-meta/task.yaml | 61 +++++++++++-------- .../colcon-humble-ros-core/CMakeLists.txt | 34 +++++++++++ .../snaps/colcon-humble-ros-core/package.xml | 25 ++++++++ .../snap/snapcraft.yaml | 21 +++++++ .../colcon-humble-ros-core/src/hello.cpp | 28 +++++++++ 6 files changed, 167 insertions(+), 57 deletions(-) create mode 100644 tests/spread/extensions/snaps/colcon-humble-ros-core/CMakeLists.txt create mode 100644 tests/spread/extensions/snaps/colcon-humble-ros-core/package.xml create mode 100644 tests/spread/extensions/snaps/colcon-humble-ros-core/snap/snapcraft.yaml create mode 100644 tests/spread/extensions/snaps/colcon-humble-ros-core/src/hello.cpp diff --git a/tests/spread/extensions/ros-meta/task.yaml b/tests/spread/extensions/ros-meta/task.yaml index c9a89f9da7..9308220f47 100644 --- a/tests/spread/extensions/ros-meta/task.yaml +++ b/tests/spread/extensions/ros-meta/task.yaml @@ -4,13 +4,25 @@ kill-timeout: 180m environment: SNAP/catkin_noetic_ros_core: catkin-noetic-ros-core - META_SNAP/catkin_noetic_ros_core: ros-meta-ros-core - # SNAP/catkin_noetic_ros_base: catkin-noetic-ros-base - # META_SNAP/catkin_noetic_ros_base: ros-meta-ros-base - SNAP/catkin_noetic_robot: catkin-noetic-robot - META_SNAP/catkin_noetic_robot: ros-meta-robot - # SNAP/catkin_noetic_desktop: catkin-noetic-desktop - # META_SNAP/catkin_noetic_desktop: ros-meta-desktop + META_SNAP/catkin_noetic_ros_core: ros-noetic-ros-core + EXTENSION/catkin_noetic_ros_core: ros1-noetic-ros-core + INTERFACE/catkin_noetic_ros_core: ros-noetic + + SNAP/catkin_noetic_ros_base: catkin-noetic-ros-core + META_SNAP/catkin_noetic_ros_base: ros-noetic-ros-base + EXTENSION/catkin_noetic_ros_base: ros1-noetic-ros-base + INTERFACE/catkin_noetic_ros_base: ros-noetic + + SNAP/catkin_noetic_robot: catkin-noetic-ros-core + META_SNAP/catkin_noetic_robot: ros-noetic-robot + EXTENSION/catkin_noetic_robot: ros1-noetic-robot + INTERFACE/catkin_noetic_robot: ros-noetic + + SNAP/catkin_noetic_desktop: catkin-noetic-ros-core + META_SNAP/catkin_noetic_desktop: ros-noetic-desktop + EXTENSION/catkin_noetic_desktop: ros1-noetic-desktop + INTERFACE/catkin_noetic_desktop: ros-noetic + SNAP_DIR: "../snaps/$SNAP" # The content snap required for the test to succeed is only @@ -27,6 +39,9 @@ prepare: | . "$TOOLS_DIR/snapcraft-yaml.sh" set_base "$SNAP_DIR/snap/snapcraft.yaml" + # Overwrite the extension to test them all out of a single snap + sed -i "s|ros1-noetic-ros-core|${EXTENSION}|" "$SNAP_DIR/snap/snapcraft.yaml" + restore: | cd "$SNAP_DIR" snapcraft clean @@ -50,28 +65,8 @@ execute: | SNAP_SIZE=$(ls -s "${SNAP}"_1.0_*.snap | cut -d " " -f1) [ "100" -gt "$SNAP_SIZE" ] - snap connect ${SNAP}:ros-noetic ${META_SNAP}:ros-noetic - [ "$($SNAP)" = "hello world" ] + # # Install the providing snap + # snap install "${META_SNAP}" - # Clean the hello part, then build and run again. - snapcraft clean hello - snapcraft - snap install "${SNAP}"_1.0_*.snap --dangerous - - snap connect ${SNAP}:ros-noetic ${META_SNAP}:ros-noetic + snap connect ${SNAP}:${INTERFACE} ${META_SNAP}:${INTERFACE} [ "$($SNAP)" = "hello world" ] - - # Make sure that what we built runs with the changes applied. - if [ -f src/snapcraft_hello/src/hello.cpp ]; then - modified_file=src/snapcraft_hello/src/hello.cpp - else - FATAL "Cannot setup ${SNAP} for rebuilding" - fi - - sed -i "${modified_file}" -e 's/hello world/hello rebuilt world/' - - snapcraft - snap install "${SNAP}"_1.0_*.snap --dangerous - - snap connect ${SNAP}:ros-noetic ${META_SNAP}:ros-noetic - [ "$($SNAP)" = "hello rebuilt world" ] diff --git a/tests/spread/extensions/ros2-meta/task.yaml b/tests/spread/extensions/ros2-meta/task.yaml index 0bc5e4a79b..0a5b449abe 100644 --- a/tests/spread/extensions/ros2-meta/task.yaml +++ b/tests/spread/extensions/ros2-meta/task.yaml @@ -4,11 +4,35 @@ kill-timeout: 180m environment: SNAP/colcon_foxy_ros_core: colcon-foxy-ros-core - META_SNAP/colcon_foxy_ros_core: ros2-meta-ros-core + META_SNAP/colcon_foxy_ros_core: ros-foxy-ros-core + EXTENSION/colcon_foxy_ros_core: ros2-foxy-ros-core + INTERFACE/colcon_foxy_ros_core: ros-foxy + SNAP/colcon_foxy_ros_base: colcon-foxy-ros-core - META_SNAP/colcon_foxy_ros_base: ros2-meta-ros-base - # SNAP/colcon_foxy_desktop: colcon-foxy-desktop - # META_SNAP/colcon_foxy_desktop: ros-meta-desktop + META_SNAP/colcon_foxy_ros_base: ros-foxy-ros-base + EXTENSION/colcon_foxy_ros_base: ros2-foxy-ros-base + INTERFACE/colcon_foxy_ros_base: ros-foxy + + SNAP/colcon_foxy_desktop: colcon-foxy-ros-core + META_SNAP/colcon_foxy_desktop: ros-foxy-desktop + EXTENSION/colcon_foxy_desktop: ros2-foxy-desktop + INTERFACE/colcon_foxy_desktop: ros-foxy + + SNAP/colcon_humble_ros_core: colcon-humble-ros-core + META_SNAP/colcon_humble_ros_core: ros-humble-ros-base + EXTENSION/colcon_humble_ros_core: ros2-humble-ros-base + INTERFACE/colcon_humble_ros_core: ros-humble + + SNAP/colcon_humble_ros_base: colcon-humble-ros-core + META_SNAP/colcon_humble_ros_base: ros-humble-ros-base + EXTENSION/colcon_humble_ros_base: ros2-humble-ros-base + INTERFACE/colcon_humble_ros_base: ros-humble + + SNAP/colcon_humble_desktop: colcon-humble-ros-core + META_SNAP/colcon_humble_desktop: ros-humble-desktop + EXTENSION/colcon_humble_desktop: ros2-humble-desktop + INTERFACE/colcon_humble_desktop: ros-humble + SNAP_DIR: "../snaps/$SNAP" # The content snap required for the test to succeed is only @@ -25,6 +49,9 @@ prepare: | . "$TOOLS_DIR/snapcraft-yaml.sh" set_base "$SNAP_DIR/snap/snapcraft.yaml" + # Overwrite the extension to test them all out of a single snap + sed -i "s|ros2-foxy-ros-core|${EXTENSION}|" "$SNAP_DIR/snap/snapcraft.yaml" + restore: | cd "$SNAP_DIR" snapcraft clean @@ -48,28 +75,8 @@ execute: | SNAP_SIZE=$(ls -s "${SNAP}"_1.0_*.snap | cut -d " " -f1) [ "200" -gt "$SNAP_SIZE" ] - snap connect ${SNAP}:ros-meta ${META_SNAP} - [ "$($SNAP)" = "hello world" ] - - # Clean the hello part, then build and run again. - snapcraft clean hello - snapcraft - snap install "${SNAP}"_1.0_*.snap --dangerous + # Install the providing snap + # snap install "${META_SNAP}" - snap connect ${SNAP}:ros-meta ${META_SNAP} + snap connect ${SNAP}:${INTERFACE} ${META_SNAP}:${INTERFACE} [ "$($SNAP)" = "hello world" ] - - # Make sure that what we built runs with the changes applied. - if [ -f src/hello.cpp ]; then - modified_file=src/hello.cpp - else - FATAL "Cannot setup ${SNAP} for rebuilding" - fi - - sed -i "${modified_file}" -e 's/hello world/hello rebuilt world/' - - snapcraft - snap install "${SNAP}"_1.0_*.snap --dangerous - - snap connect ${SNAP}:ros-meta ${META_SNAP} - [ "$($SNAP)" = "hello rebuilt world" ] diff --git a/tests/spread/extensions/snaps/colcon-humble-ros-core/CMakeLists.txt b/tests/spread/extensions/snaps/colcon-humble-ros-core/CMakeLists.txt new file mode 100644 index 0000000000..c014f3f36d --- /dev/null +++ b/tests/spread/extensions/snaps/colcon-humble-ros-core/CMakeLists.txt @@ -0,0 +1,34 @@ +cmake_minimum_required(VERSION 3.5) +project(colcon_ros2_rlcpp_hello) + +# Default to C++14 +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 14) +endif() + +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() + +find_package(ament_cmake REQUIRED) +find_package(rclcpp REQUIRED) +find_package(rclcpp_components REQUIRED) +find_package(std_msgs REQUIRED) + +# This package installs libraries without exporting them. +# Export the library path to ensure that the installed libraries are available. +if(NOT WIN32) + ament_environment_hooks( + "${ament_cmake_package_templates_ENVIRONMENT_HOOK_LIBRARY_PATH}" + ) +endif() + +add_executable(colcon_ros2_rlcpp_hello src/hello.cpp) +target_link_libraries(colcon_ros2_rlcpp_hello) +ament_target_dependencies(colcon_ros2_rlcpp_hello rclcpp class_loader) + +install(TARGETS + colcon_ros2_rlcpp_hello + DESTINATION lib/${PROJECT_NAME}) + +ament_package() diff --git a/tests/spread/extensions/snaps/colcon-humble-ros-core/package.xml b/tests/spread/extensions/snaps/colcon-humble-ros-core/package.xml new file mode 100644 index 0000000000..133e482823 --- /dev/null +++ b/tests/spread/extensions/snaps/colcon-humble-ros-core/package.xml @@ -0,0 +1,25 @@ + + + + colcon_ros2_rlcpp_hello + 0.0.1 + snapcraft test for rlcpp + me + Apache License 2.0 + + ament_cmake + + rclcpp + rclcpp_components + std_msgs + fake_package_that_does_not_exists + + rclcpp + rclcpp_components + ros2run + std_msgs + + + ament_cmake + + diff --git a/tests/spread/extensions/snaps/colcon-humble-ros-core/snap/snapcraft.yaml b/tests/spread/extensions/snaps/colcon-humble-ros-core/snap/snapcraft.yaml new file mode 100644 index 0000000000..fd0faf5caa --- /dev/null +++ b/tests/spread/extensions/snaps/colcon-humble-ros-core/snap/snapcraft.yaml @@ -0,0 +1,21 @@ +name: colcon-humble-ros-core +version: "1.0" +summary: hello world +description: | + A ROS2 rlcpp-based workspace. + +grade: stable +confinement: strict +base: core22 + +apps: + colcon-foxy-ros-core: + command: ros2 run colcon_ros2_rlcpp_hello colcon_ros2_rlcpp_hello + plugs: [network, network-bind] + extensions: [ros2-humble-ros-core] + +parts: + hello: + plugin: colcon + source: . + build-packages: [g++, make] diff --git a/tests/spread/extensions/snaps/colcon-humble-ros-core/src/hello.cpp b/tests/spread/extensions/snaps/colcon-humble-ros-core/src/hello.cpp new file mode 100644 index 0000000000..770203acec --- /dev/null +++ b/tests/spread/extensions/snaps/colcon-humble-ros-core/src/hello.cpp @@ -0,0 +1,28 @@ +// Copyright 2016 Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include "rclcpp/rclcpp.hpp" + +int main(int argc, char * argv[]) +{ + rclcpp::init(argc, argv); + rclcpp::executors::SingleThreadedExecutor exec; + rclcpp::NodeOptions options; + + printf("hello world"); + + rclcpp::shutdown(); + return 0; +} From 632b7c32c71296301133ddb9ff3273c68e02b927 Mon Sep 17 00:00:00 2001 From: artivis Date: Tue, 25 Apr 2023 18:14:59 +0200 Subject: [PATCH 34/84] ros: get_installed_dependencies in colcon core22 Signed-off-by: artivis --- snapcraft/parts/plugins/_ros.py | 53 ++++++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 10 deletions(-) diff --git a/snapcraft/parts/plugins/_ros.py b/snapcraft/parts/plugins/_ros.py index 017f72aba4..19d9c7735a 100644 --- a/snapcraft/parts/plugins/_ros.py +++ b/snapcraft/parts/plugins/_ros.py @@ -256,6 +256,46 @@ def get_build_commands(self) -> List[str]: def plugin_cli(): """Define the plugin_cli Click group.""" +def get_installed_dependencies(installed_packages_path: str) -> Set[str]: + if os.path.isfile(installed_packages_path): + try: + with open(installed_packages_path, "r") as f: + build_snap_packages = set(f.read().split()) + package_dependencies = set() + for package in build_snap_packages: + try: + cmd = [ + "apt", + "depends", + "--recurse", + "--no-recommends", + "--no-suggests", + "--no-conflicts", + "--no-breaks", + "--no-replaces", + "--no-enhances", + f"{package}", + ] + click.echo(f"Running {cmd!r}") + proc = subprocess.run( + cmd, + check=True, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + env=dict(PATH=os.environ["PATH"]), + ) + except subprocess.CalledProcessError as error: + click.echo(f"failed to run {cmd!r}: {error.output}") + apt_dependency_regex = re.compile("^\w.*$") # noqa: W605 + for line in proc.stdout.decode().strip().split("\n"): + if apt_dependency_regex.match(line): + package_dependencies.add(line) + + build_snap_packages.update(package_dependencies) + click.echo(f"Will not fetch staged packages: {build_snap_packages!r}") + return build_snap_packages + except IOError: + return Set(str) @plugin_cli.command() @click.option("--part-src", envvar="CRAFT_PART_SRC", required=True) @@ -323,16 +363,9 @@ def stage_runtime_dependencies( if parsed: click.echo(f"unhandled dependencies: {parsed!r}") - build_snap_packages: Set[str] = set() - installed_packages_file = part_install + "/.installed_packages.txt" - if os.path.isfile(installed_packages_file): - try: - with open(installed_packages_file, "r") as f: - build_snap_packages = set(f.read().split()) - click.echo(f"Will not fetch staged packages: {build_snap_packages!r}") - except IOError: - click.echo(f"failed to open file {installed_packages_file}") - pass + build_snap_packages = get_installed_dependencies( + part_install + "/.installed_packages.txt" + ) if apt_packages: package_names = sorted(apt_packages) From ce3f7905023a18fbd03917b3d194e09ce6a7d91f Mon Sep 17 00:00:00 2001 From: artivis Date: Tue, 25 Apr 2023 19:08:02 +0200 Subject: [PATCH 35/84] ros: handle empty env var Signed-off-by: artivis --- extensions/ros1/launch | 2 +- extensions/ros2/launch | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/ros1/launch b/extensions/ros1/launch index 5b4f85ef98..63cf186f6b 100755 --- a/extensions/ros1/launch +++ b/extensions/ros1/launch @@ -18,7 +18,7 @@ original_args=("$@") # activate_workspace in content shared snaps if [ -d "$SNAP/opt/ros/underlay_ws/opt/ros/$ROS_DISTRO" ]; then activate_workspace "$SNAP/opt/ros/underlay_ws/opt/ros/$ROS_DISTRO" --local - export LD_LIBRARY_PATH="$SNAP/opt/ros/underlay_ws/usr/lib/x86_64-linux-gnu:${LD_LIBRARY_PATH}" + export LD_LIBRARY_PATH="$SNAP/opt/ros/underlay_ws/usr/lib/x86_64-linux-gnu:${LD_LIBRARY_PATH-}" fi activate_workspace "$SNAP/opt/ros/$ROS_DISTRO" --local --extend diff --git a/extensions/ros2/launch b/extensions/ros2/launch index 2acada8e1b..d8002a7ab6 100755 --- a/extensions/ros2/launch +++ b/extensions/ros2/launch @@ -20,7 +20,7 @@ if [ -d "$SNAP/opt/ros/underlay_ws/opt/ros/snap" ]; then source_with_prefix "$SNAP/opt/ros/underlay_ws/opt/ros/snap" fi if [[ -d "$SNAP/opt/ros/underlay_ws/opt/ros/$ROS_DISTRO" || -d "$SNAP/opt/ros/underlay_ws/opt/ros/snap" ]]; then - export LD_LIBRARY_PATH="$SNAP/opt/ros/underlay_ws/usr/lib/x86_64-linux-gnu:${LD_LIBRARY_PATH}" + export LD_LIBRARY_PATH="$SNAP/opt/ros/underlay_ws/usr/lib/x86_64-linux-gnu:${LD_LIBRARY_PATH-}" fi source_with_prefix "$SNAP/opt/ros/$ROS_DISTRO" From 59337167dbcf5e70b7c78947f4c12062d8d41487 Mon Sep 17 00:00:00 2001 From: artivis Date: Wed, 26 Apr 2023 08:41:30 +0200 Subject: [PATCH 36/84] ros: static tests fixes Signed-off-by: artivis --- snapcraft/extensions/_ros2_humble_meta.py | 4 ++-- snapcraft/parts/plugins/_ros.py | 4 ++-- snapcraft/parts/plugins/colcon_plugin.py | 4 ++-- tests/spread/extensions/ros-meta/task.yaml | 2 +- tests/spread/extensions/ros2-meta/task.yaml | 2 +- tests/unit/parts/plugins/test_colcon.py | 2 ++ 6 files changed, 10 insertions(+), 8 deletions(-) diff --git a/snapcraft/extensions/_ros2_humble_meta.py b/snapcraft/extensions/_ros2_humble_meta.py index d8db989328..ad617e423c 100644 --- a/snapcraft/extensions/_ros2_humble_meta.py +++ b/snapcraft/extensions/_ros2_humble_meta.py @@ -31,13 +31,13 @@ class ROS2HumbleMetaBase(ROS2HumbleExtension): @property @abstractmethod - def ROS_META(cls): + def ROS_META(self): """Abstract property to define the extension's content-sharing snap.""" raise NotImplementedError @property @abstractmethod - def ROS_META_DEV(cls): + def ROS_META_DEV(self): """Abstract property to define the extension's build snap.""" raise NotImplementedError diff --git a/snapcraft/parts/plugins/_ros.py b/snapcraft/parts/plugins/_ros.py index 19d9c7735a..612b9c573f 100644 --- a/snapcraft/parts/plugins/_ros.py +++ b/snapcraft/parts/plugins/_ros.py @@ -130,13 +130,13 @@ def _get_build_commands(self) -> List[str]: def _get_list_packages_commands(self) -> List[str]: """Generate a list of ROS 2 packages available in build snaps. + The ROS 2 workspaces contained in build snaps are crawled with `rospack` to establish the list of all available ROS 2 packages. The package names are then resolved with `rosdep` to map their names to debs. The list is finally saved in the part's install directory. """ - - cmd = list() + cmd = [] # Clean up previously established list of packages in build snaps cmd.append('rm -f "${CRAFT_PART_INSTALL}/.installed_packages.txt"') diff --git a/snapcraft/parts/plugins/colcon_plugin.py b/snapcraft/parts/plugins/colcon_plugin.py index abf6d6b255..499781169d 100644 --- a/snapcraft/parts/plugins/colcon_plugin.py +++ b/snapcraft/parts/plugins/colcon_plugin.py @@ -146,7 +146,7 @@ def _get_workspace_activation_commands(self) -> List[str]: specific functionality. """ - activation_commands = list() + activation_commands = [] # Source ROS ws in all build-snaps first activation_commands.append("## Sourcing ROS ws in build snaps") @@ -175,7 +175,7 @@ def _get_workspace_activation_commands(self) -> List[str]: def _get_build_commands(self) -> List[str]: options = cast(ColconPluginProperties, self._options) - export_command = list() + export_command = [] if self._options.build_snaps: for build_snap in self._options.build_snaps: diff --git a/tests/spread/extensions/ros-meta/task.yaml b/tests/spread/extensions/ros-meta/task.yaml index 9308220f47..e82bf3e33c 100644 --- a/tests/spread/extensions/ros-meta/task.yaml +++ b/tests/spread/extensions/ros-meta/task.yaml @@ -68,5 +68,5 @@ execute: | # # Install the providing snap # snap install "${META_SNAP}" - snap connect ${SNAP}:${INTERFACE} ${META_SNAP}:${INTERFACE} + snap connect "${SNAP}":"${INTERFACE}" "${META_SNAP}":"${INTERFACE}" [ "$($SNAP)" = "hello world" ] diff --git a/tests/spread/extensions/ros2-meta/task.yaml b/tests/spread/extensions/ros2-meta/task.yaml index 0a5b449abe..58b725ac36 100644 --- a/tests/spread/extensions/ros2-meta/task.yaml +++ b/tests/spread/extensions/ros2-meta/task.yaml @@ -78,5 +78,5 @@ execute: | # Install the providing snap # snap install "${META_SNAP}" - snap connect ${SNAP}:${INTERFACE} ${META_SNAP}:${INTERFACE} + snap connect "${SNAP}":"${INTERFACE}" "${META_SNAP}":"${INTERFACE}" [ "$($SNAP)" = "hello world" ] diff --git a/tests/unit/parts/plugins/test_colcon.py b/tests/unit/parts/plugins/test_colcon.py index 965bd93994..40cfcdff86 100644 --- a/tests/unit/parts/plugins/test_colcon.py +++ b/tests/unit/parts/plugins/test_colcon.py @@ -133,6 +133,7 @@ def test_out_of_source_build_property(self): assert colcon.ColconPlugin.get_out_of_source_build def test_get_build_commands(self, setup_method_fixture, new_dir, monkeypatch): + # pylint: disable=line-too-long plugin = setup_method_fixture(new_dir) monkeypatch.setattr(sys, "path", ["", "/test"]) @@ -223,6 +224,7 @@ def test_get_build_commands(self, setup_method_fixture, new_dir, monkeypatch): def test_get_build_commands_with_all_properties( self, setup_method_fixture, new_dir, monkeypatch ): + # pylint: disable=line-too-long plugin = setup_method_fixture( new_dir, properties={ From 3b3a5f2a7e332d7f20c445962d99fa7b4ee355c3 Mon Sep 17 00:00:00 2001 From: artivis Date: Wed, 26 Apr 2023 11:48:54 +0200 Subject: [PATCH 37/84] ros: handle empty env var Signed-off-by: artivis --- extensions/ros1/launch | 2 +- extensions/ros2/launch | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/ros1/launch b/extensions/ros1/launch index 63cf186f6b..c964d3137c 100755 --- a/extensions/ros1/launch +++ b/extensions/ros1/launch @@ -18,7 +18,7 @@ original_args=("$@") # activate_workspace in content shared snaps if [ -d "$SNAP/opt/ros/underlay_ws/opt/ros/$ROS_DISTRO" ]; then activate_workspace "$SNAP/opt/ros/underlay_ws/opt/ros/$ROS_DISTRO" --local - export LD_LIBRARY_PATH="$SNAP/opt/ros/underlay_ws/usr/lib/x86_64-linux-gnu:${LD_LIBRARY_PATH-}" + export LD_LIBRARY_PATH="$SNAP/opt/ros/underlay_ws/usr/lib/x86_64-linux-gnu${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}" fi activate_workspace "$SNAP/opt/ros/$ROS_DISTRO" --local --extend diff --git a/extensions/ros2/launch b/extensions/ros2/launch index d8002a7ab6..dc419a12b1 100755 --- a/extensions/ros2/launch +++ b/extensions/ros2/launch @@ -20,7 +20,7 @@ if [ -d "$SNAP/opt/ros/underlay_ws/opt/ros/snap" ]; then source_with_prefix "$SNAP/opt/ros/underlay_ws/opt/ros/snap" fi if [[ -d "$SNAP/opt/ros/underlay_ws/opt/ros/$ROS_DISTRO" || -d "$SNAP/opt/ros/underlay_ws/opt/ros/snap" ]]; then - export LD_LIBRARY_PATH="$SNAP/opt/ros/underlay_ws/usr/lib/x86_64-linux-gnu:${LD_LIBRARY_PATH-}" + export LD_LIBRARY_PATH="$SNAP/opt/ros/underlay_ws/usr/lib/x86_64-linux-gnu${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}" fi source_with_prefix "$SNAP/opt/ros/$ROS_DISTRO" From 7dbc17ed00a21dfa2a6de363f695a7222a0aee18 Mon Sep 17 00:00:00 2001 From: artivis Date: Wed, 26 Apr 2023 13:42:48 +0200 Subject: [PATCH 38/84] ros: static tests fixes Signed-off-by: artivis --- snapcraft/parts/plugins/_ros.py | 7 +++++-- snapcraft_legacy/plugins/v2/_ros.py | 1 + tests/unit/parts/plugins/test_colcon.py | 6 ++++-- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/snapcraft/parts/plugins/_ros.py b/snapcraft/parts/plugins/_ros.py index 612b9c573f..a46c759506 100644 --- a/snapcraft/parts/plugins/_ros.py +++ b/snapcraft/parts/plugins/_ros.py @@ -136,6 +136,7 @@ def _get_list_packages_commands(self) -> List[str]: The package names are then resolved with `rosdep` to map their names to debs. The list is finally saved in the part's install directory. """ + # pylint: disable=line-too-long cmd = [] # Clean up previously established list of packages in build snaps @@ -256,11 +257,13 @@ def get_build_commands(self) -> List[str]: def plugin_cli(): """Define the plugin_cli Click group.""" + def get_installed_dependencies(installed_packages_path: str) -> Set[str]: + """Retrieve recursive apt dependencies of a given package list.""" if os.path.isfile(installed_packages_path): try: - with open(installed_packages_path, "r") as f: - build_snap_packages = set(f.read().split()) + with open(installed_packages_path, "r") as file: + build_snap_packages = set(file.read().split()) package_dependencies = set() for package in build_snap_packages: try: diff --git a/snapcraft_legacy/plugins/v2/_ros.py b/snapcraft_legacy/plugins/v2/_ros.py index 3484e5faf0..5224ccb55b 100644 --- a/snapcraft_legacy/plugins/v2/_ros.py +++ b/snapcraft_legacy/plugins/v2/_ros.py @@ -239,6 +239,7 @@ def plugin_cli(): def get_installed_dependencies(installed_packages_path: str) -> Set[str]: + """Retrieve recursive apt dependencies of a given package list.""" if os.path.isfile(installed_packages_path): try: with open(installed_packages_path, "r") as f: diff --git a/tests/unit/parts/plugins/test_colcon.py b/tests/unit/parts/plugins/test_colcon.py index 40cfcdff86..2c8ffe4ce6 100644 --- a/tests/unit/parts/plugins/test_colcon.py +++ b/tests/unit/parts/plugins/test_colcon.py @@ -76,13 +76,15 @@ def test_property_default(self): def test_property_unexpected(self): try: - properties = colcon.ColconPlugin.properties_class(source=".") # noqa F841 + properties = colcon.ColconPlugin.properties_class( # noqa F841 + source="." # type: ignore + ) except ValidationError as e: raise AssertionError(f"{e}") from e with pytest.raises(ValidationError): properties = colcon.ColconPlugin.properties_class( # noqa F841 - source=".", foo="bar" + source=".", foo="bar" # type: ignore ) def test_property_all(self): From 725be463b74c4b9ba4fda8b70a2bc73b35b6fcd2 Mon Sep 17 00:00:00 2001 From: artivis Date: Wed, 26 Apr 2023 13:43:12 +0200 Subject: [PATCH 39/84] ros: fix unbound variable Signed-off-by: artivis --- snapcraft/parts/plugins/_ros.py | 39 ++++++++++++++++------------- snapcraft_legacy/plugins/v2/_ros.py | 37 ++++++++++++++------------- 2 files changed, 40 insertions(+), 36 deletions(-) diff --git a/snapcraft/parts/plugins/_ros.py b/snapcraft/parts/plugins/_ros.py index a46c759506..f2392717c2 100644 --- a/snapcraft/parts/plugins/_ros.py +++ b/snapcraft/parts/plugins/_ros.py @@ -266,20 +266,20 @@ def get_installed_dependencies(installed_packages_path: str) -> Set[str]: build_snap_packages = set(file.read().split()) package_dependencies = set() for package in build_snap_packages: + cmd = [ + "apt", + "depends", + "--recurse", + "--no-recommends", + "--no-suggests", + "--no-conflicts", + "--no-breaks", + "--no-replaces", + "--no-enhances", + f"{package}", + ] + click.echo(f"Running {cmd!r}") try: - cmd = [ - "apt", - "depends", - "--recurse", - "--no-recommends", - "--no-suggests", - "--no-conflicts", - "--no-breaks", - "--no-replaces", - "--no-enhances", - f"{package}", - ] - click.echo(f"Running {cmd!r}") proc = subprocess.run( cmd, check=True, @@ -289,16 +289,19 @@ def get_installed_dependencies(installed_packages_path: str) -> Set[str]: ) except subprocess.CalledProcessError as error: click.echo(f"failed to run {cmd!r}: {error.output}") - apt_dependency_regex = re.compile("^\w.*$") # noqa: W605 - for line in proc.stdout.decode().strip().split("\n"): - if apt_dependency_regex.match(line): - package_dependencies.add(line) + else: + apt_dependency_regex = re.compile("^\w.*$") # noqa: W605 + for line in proc.stdout.decode().strip().split("\n"): + if apt_dependency_regex.match(line): + package_dependencies.add(line) build_snap_packages.update(package_dependencies) click.echo(f"Will not fetch staged packages: {build_snap_packages!r}") return build_snap_packages except IOError: - return Set(str) + pass + return set() + @plugin_cli.command() @click.option("--part-src", envvar="CRAFT_PART_SRC", required=True) diff --git a/snapcraft_legacy/plugins/v2/_ros.py b/snapcraft_legacy/plugins/v2/_ros.py index 5224ccb55b..d4f1c42a30 100644 --- a/snapcraft_legacy/plugins/v2/_ros.py +++ b/snapcraft_legacy/plugins/v2/_ros.py @@ -246,20 +246,20 @@ def get_installed_dependencies(installed_packages_path: str) -> Set[str]: build_snap_packages = set(f.read().split()) package_dependencies = set() for package in build_snap_packages: + cmd = [ + "apt", + "depends", + "--recurse", + "--no-recommends", + "--no-suggests", + "--no-conflicts", + "--no-breaks", + "--no-replaces", + "--no-enhances", + f"{package}", + ] + click.echo(f"Running {cmd!r}") try: - cmd = [ - "apt", - "depends", - "--recurse", - "--no-recommends", - "--no-suggests", - "--no-conflicts", - "--no-breaks", - "--no-replaces", - "--no-enhances", - f"{package}", - ] - click.echo(f"Running {cmd!r}") proc = subprocess.run( cmd, check=True, @@ -269,16 +269,17 @@ def get_installed_dependencies(installed_packages_path: str) -> Set[str]: ) except subprocess.CalledProcessError as error: click.echo(f"failed to run {cmd!r}: {error.output}") - apt_dependency_regex = re.compile("^\w.*$") # noqa: W605 - for line in proc.stdout.decode().strip().split("\n"): - if apt_dependency_regex.match(line): - package_dependencies.add(line) + else: + apt_dependency_regex = re.compile("^\w.*$") # noqa: W605 + for line in proc.stdout.decode().strip().split("\n"): + if apt_dependency_regex.match(line): + package_dependencies.add(line) build_snap_packages.update(package_dependencies) click.echo(f"Will not fetch staged packages: {build_snap_packages!r}") return build_snap_packages except IOError: - return Set(str) + return set() @plugin_cli.command() From 95fa691ac2f162f9207686ddfde613fcac081785 Mon Sep 17 00:00:00 2001 From: artivis Date: Wed, 26 Apr 2023 14:02:20 +0200 Subject: [PATCH 40/84] ros: handle empty env var Signed-off-by: artivis --- snapcraft/parts/plugins/colcon_plugin.py | 2 +- snapcraft_legacy/plugins/v2/catkin.py | 2 +- snapcraft_legacy/plugins/v2/colcon.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/snapcraft/parts/plugins/colcon_plugin.py b/snapcraft/parts/plugins/colcon_plugin.py index 499781169d..581fb3dd1c 100644 --- a/snapcraft/parts/plugins/colcon_plugin.py +++ b/snapcraft/parts/plugins/colcon_plugin.py @@ -184,7 +184,7 @@ def _get_build_commands(self) -> List[str]: export_command.extend( [ 'if [ -d "/snap/{build_snap}/current" ]; then ' - 'export CMAKE_PREFIX_PATH="/snap/{build_snap}/current:/snap/{build_snap}/current/usr:${{CMAKE_PREFIX_PATH-}}"; ' + 'export CMAKE_PREFIX_PATH="/snap/{build_snap}/current:/snap/{build_snap}/current/usr${{CMAKE_PREFIX_PATH:+:${{CMAKE_PREFIX_PATH}}}}"; ' "fi".format(build_snap=build_snap) ] ) diff --git a/snapcraft_legacy/plugins/v2/catkin.py b/snapcraft_legacy/plugins/v2/catkin.py index 94a919bfe8..b3d774b7b9 100644 --- a/snapcraft_legacy/plugins/v2/catkin.py +++ b/snapcraft_legacy/plugins/v2/catkin.py @@ -148,7 +148,7 @@ def _get_build_commands(self) -> List[str]: ]) export_command.extend([ 'if [ -d "${{SNAPCRAFT_PART_BUILD}}"/build_snaps/{build_snap} ]; then ' - 'export CMAKE_PREFIX_PATH="${{SNAPCRAFT_PART_BUILD}}/build_snaps/{build_snap}:${{CMAKE_PREFIX_PATH-}}"; ' + 'export CMAKE_PREFIX_PATH="${{SNAPCRAFT_PART_BUILD}}/build_snaps/{build_snap}${{CMAKE_PREFIX_PATH:+:${{CMAKE_PREFIX_PATH}}}}"; ' 'fi'.format(build_snap=build_snap) ]) diff --git a/snapcraft_legacy/plugins/v2/colcon.py b/snapcraft_legacy/plugins/v2/colcon.py index 60e6d0f954..13b1f63fab 100644 --- a/snapcraft_legacy/plugins/v2/colcon.py +++ b/snapcraft_legacy/plugins/v2/colcon.py @@ -182,7 +182,7 @@ def _get_build_commands(self) -> List[str]: export_command.extend([ 'if [ -d "/snap/{build_snap}/current" ]; then ' - 'export CMAKE_PREFIX_PATH="/snap/{build_snap}/current:/snap/{build_snap}/current/usr:${{CMAKE_PREFIX_PATH-}}"; ' + 'export CMAKE_PREFIX_PATH="/snap/{build_snap}/current:/snap/{build_snap}/current/usr${{CMAKE_PREFIX_PATH:+:${{CMAKE_PREFIX_PATH}}}}"; ' 'fi'.format(build_snap=build_snap) ]) From c31e4bbb388124fb87ba4602ea6da7fc66b4aced Mon Sep 17 00:00:00 2001 From: artivis Date: Mon, 22 May 2023 14:57:29 +0200 Subject: [PATCH 41/84] ros: move cmake fixes to build-snap Signed-off-by: artivis --- .../_extensions/_ros1_noetic_meta.py | 4 +++ snapcraft_legacy/plugins/v2/catkin.py | 27 ------------------- 2 files changed, 4 insertions(+), 27 deletions(-) diff --git a/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py b/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py index bad3e33d8b..50c7a79363 100644 --- a/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py +++ b/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py @@ -43,4 +43,8 @@ def __init__(self, *, extension_name: str, yaml_data: Dict[str, Any]) -> None: } } + self.part_snippet["catkin-cmake-args"] = [ + f'-DCMAKE_SYSTEM_PREFIX_PATH="/snap/{self.ROS_META_DEV}/current/usr"' + ] + self.part_snippet["build-snaps"] = [self.ROS_META_DEV] diff --git a/snapcraft_legacy/plugins/v2/catkin.py b/snapcraft_legacy/plugins/v2/catkin.py index b3d774b7b9..6252a02213 100644 --- a/snapcraft_legacy/plugins/v2/catkin.py +++ b/snapcraft_legacy/plugins/v2/catkin.py @@ -125,33 +125,6 @@ def _get_build_commands(self) -> List[str]: prepare_build_command = list() export_command = list() - if self.options.build_snaps: - for build_snap in self.options.build_snaps: - build_snap = _get_parsed_snap(build_snap)[0] - # ROS workspaces present in buid-snaps have their '*.cmake' files pointing to hard-coded internal paths. - # We need to fix those paths so that they can be properly sourced. - # Since snaps are immutable, we copy the said '*.cmake' files to the current SNAPCRAFT_PART_BUILD path - # and edit these copies accordingly. - - pkg_path=f"/snap/{build_snap}/current/opt/ros/${{ROS_DISTRO}}/share" - - prepare_build_command.extend([ - f'if [ -d "{pkg_path}" ]; then ', - f'mkdir -p "${{SNAPCRAFT_PART_BUILD}}"/build_snaps/{build_snap}', - f'cp -r "{pkg_path}" "${{SNAPCRAFT_PART_BUILD}}/build_snaps/{build_snap}/."', - ( - 'find "${{SNAPCRAFT_PART_BUILD}}/build_snaps/{build_snap}" \( -name "*Config.cmake" -o -name "*extras.cmake" \) -exec ' # noqa: W605 - 'sed -i -e "s|/opt|/snap/{build_snap}/current&|g" -e "s|/usr|/snap/{build_snap}/current&|g" ' - '-e "s|\${{.*_DIR}}/../../..|/snap/{build_snap}/current/opt/ros/${{ROS_DISTRO}}|g" {{}} \;' # noqa: W605 - ).format(build_snap=build_snap), - "fi", - ]) - export_command.extend([ - 'if [ -d "${{SNAPCRAFT_PART_BUILD}}"/build_snaps/{build_snap} ]; then ' - 'export CMAKE_PREFIX_PATH="${{SNAPCRAFT_PART_BUILD}}/build_snaps/{build_snap}${{CMAKE_PREFIX_PATH:+:${{CMAKE_PREFIX_PATH}}}}"; ' - 'fi'.format(build_snap=build_snap) - ]) - build_command = [ "catkin_make_isolated", "--install", From c3097c50e508cb7fe18824af1f2a83d00e3123c8 Mon Sep 17 00:00:00 2001 From: artivis Date: Mon, 22 May 2023 14:58:35 +0200 Subject: [PATCH 42/84] ros: stage roslib Signed-off-by: artivis --- .../internal/project_loader/_extensions/ros1_noetic.py | 1 + 1 file changed, 1 insertion(+) diff --git a/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic.py b/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic.py index af5e1ad9ac..fcf0d2efe6 100644 --- a/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic.py +++ b/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic.py @@ -78,6 +78,7 @@ def __init__(self, *, extension_name: str, yaml_data: Dict[str, Any]) -> None: {"ROS_VERSION": self.ROS_VERSION}, {"ROS_DISTRO": self.ROS_DISTRO}, ], + "stage-packages": [f"ros-{self.ROS_DISTRO}-roslib"] } self.parts = { From e173c6073d5292d4bcf7d8b0e2e50667736eaa80 Mon Sep 17 00:00:00 2001 From: artivis Date: Mon, 22 May 2023 15:02:46 +0200 Subject: [PATCH 43/84] ros: content-sharing fix python paths Signed-off-by: artivis --- snapcraft/extensions/_ros2_humble_meta.py | 13 +++++++++++++ .../_extensions/_ros1_noetic_meta.py | 14 ++++++++------ .../_extensions/_ros2_foxy_meta.py | 18 ++++++++++++------ 3 files changed, 33 insertions(+), 12 deletions(-) diff --git a/snapcraft/extensions/_ros2_humble_meta.py b/snapcraft/extensions/_ros2_humble_meta.py index ad617e423c..675d9195ec 100644 --- a/snapcraft/extensions/_ros2_humble_meta.py +++ b/snapcraft/extensions/_ros2_humble_meta.py @@ -54,6 +54,19 @@ def get_root_snippet(self) -> Dict[str, Any]: } return root_snippet + @overrides + def get_app_snippet(self) -> Dict[str, Any]: + app_snippet = super().get_app_snippet() + python_paths = app_snippet["environment"]["PYTHONPATH"] + new_python_paths = [ + f"$SNAP/opt/ros/underlay_ws/opt/ros/{self.ROS_DISTRO}/lib/python3.8/site-packages", + f"$SNAP/opt/ros/underlay_ws/usr/lib/python3/dist-packages", + ] + + app_snippet["environment"]["PYTHONPATH"] = f'{python_paths}:{":".join(new_python_paths)}' + + return app_snippet + @overrides def get_part_snippet(self) -> Dict[str, Any]: part_snippet = super().get_part_snippet() diff --git a/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py b/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py index 50c7a79363..b648aa8a7a 100644 --- a/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py +++ b/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py @@ -27,12 +27,6 @@ class RosNoeticMetaBase(RosNoeticExtension): def __init__(self, *, extension_name: str, yaml_data: Dict[str, Any]) -> None: super().__init__(extension_name=extension_name, yaml_data=yaml_data) - # python_paths = [ - # f"$SNAP/opt/ros/{self.ROS_DISTRO}/lib/python3.8/site-packages", - # "$SNAP/usr/lib/python3/dist-packages", - # "${PYTHONPATH}", - # ] - self.root_snippet["plugs"] = { "ros-noetic": { @@ -48,3 +42,11 @@ def __init__(self, *, extension_name: str, yaml_data: Dict[str, Any]) -> None: ] self.part_snippet["build-snaps"] = [self.ROS_META_DEV] + + python_paths = self.app_snippet["environment"]["PYTHONPATH"] + new_python_paths = [ + f"$SNAP/opt/ros/underlay_ws/opt/ros/{self.ROS_DISTRO}/lib/python3.8/site-packages", + f"$SNAP/opt/ros/underlay_ws/usr/lib/python3/dist-packages", + ] + + self.app_snippet["environment"]["PYTHONPATH"] = f'{python_paths}:{":".join(new_python_paths)}' diff --git a/snapcraft_legacy/internal/project_loader/_extensions/_ros2_foxy_meta.py b/snapcraft_legacy/internal/project_loader/_extensions/_ros2_foxy_meta.py index 5cd04f8d8d..c11c88df08 100644 --- a/snapcraft_legacy/internal/project_loader/_extensions/_ros2_foxy_meta.py +++ b/snapcraft_legacy/internal/project_loader/_extensions/_ros2_foxy_meta.py @@ -27,12 +27,6 @@ class RosFoxyMetaBase(RosFoxyExtension): def __init__(self, *, extension_name: str, yaml_data: Dict[str, Any]) -> None: super().__init__(extension_name=extension_name, yaml_data=yaml_data) - # python_paths = [ - # f"$SNAP/opt/ros/{self.ROS_DISTRO}/lib/python3.8/site-packages", - # "$SNAP/usr/lib/python3/dist-packages", - # "${PYTHONPATH}", - # ] - # Very unlikely but it may happen that the snapped application doesn't # even pull those deps. In that case, there is no valid ROS 2 ws to source. # We make sure here that they are staged no matter what. @@ -53,4 +47,16 @@ def __init__(self, *, extension_name: str, yaml_data: Dict[str, Any]) -> None: } } + self.part_snippet["catkin-cmake-args"] = [ + f'-DCMAKE_SYSTEM_PREFIX_PATH="/snap/{self.ROS_META_DEV}/current/usr"' + ] + self.part_snippet["build-snaps"] = [self.ROS_META_DEV] + + python_paths = self.app_snippet["environment"]["PYTHONPATH"] + new_python_paths = [ + f"$SNAP/opt/ros/underlay_ws/opt/ros/{self.ROS_DISTRO}/lib/python3.8/site-packages", + f"$SNAP/opt/ros/underlay_ws/usr/lib/python3/dist-packages", + ] + + self.app_snippet["environment"]["PYTHONPATH"] = f'{python_paths}:{":".join(new_python_paths)}' From 68ff125a38cb150c314c7b4fc8d24b886cff4d88 Mon Sep 17 00:00:00 2001 From: artivis Date: Wed, 24 May 2023 10:19:39 +0200 Subject: [PATCH 44/84] ros: stage ros-environment Signed-off-by: artivis --- .../internal/project_loader/_extensions/ros1_noetic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic.py b/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic.py index fcf0d2efe6..627389f1cc 100644 --- a/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic.py +++ b/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic.py @@ -78,7 +78,7 @@ def __init__(self, *, extension_name: str, yaml_data: Dict[str, Any]) -> None: {"ROS_VERSION": self.ROS_VERSION}, {"ROS_DISTRO": self.ROS_DISTRO}, ], - "stage-packages": [f"ros-{self.ROS_DISTRO}-roslib"] + "stage-packages": [f"ros-{self.ROS_DISTRO}-ros-environment"] } self.parts = { From 7105484099221181f7720bb0262a78bcb050d876 Mon Sep 17 00:00:00 2001 From: artivis Date: Wed, 24 May 2023 10:28:33 +0200 Subject: [PATCH 45/84] ros: move/fix paths to extensions Signed-off-by: artivis --- extensions/ros1/launch | 1 - extensions/ros2/launch | 3 --- snapcraft/extensions/_ros2_humble_meta.py | 5 +++++ snapcraft/parts/plugins/colcon_plugin.py | 18 +----------------- .../_extensions/_ros1_noetic_meta.py | 3 +++ .../_extensions/_ros2_foxy_meta.py | 5 ++++- snapcraft_legacy/plugins/v2/catkin.py | 10 +--------- snapcraft_legacy/plugins/v2/colcon.py | 16 +--------------- tests/legacy/unit/plugins/v2/test_catkin.py | 14 -------------- tests/legacy/unit/plugins/v2/test_colcon.py | 5 ----- .../extensions/test_ros1_noetic_meta.py | 13 ++++++++++++- .../extensions/test_ros2_foxy_meta.py | 13 ++++++++++++- .../parts/extensions/test_ros2_humble_meta.py | 5 +++++ tests/unit/parts/plugins/test_colcon.py | 5 ----- 14 files changed, 44 insertions(+), 72 deletions(-) diff --git a/extensions/ros1/launch b/extensions/ros1/launch index c964d3137c..0338aad3fd 100755 --- a/extensions/ros1/launch +++ b/extensions/ros1/launch @@ -18,7 +18,6 @@ original_args=("$@") # activate_workspace in content shared snaps if [ -d "$SNAP/opt/ros/underlay_ws/opt/ros/$ROS_DISTRO" ]; then activate_workspace "$SNAP/opt/ros/underlay_ws/opt/ros/$ROS_DISTRO" --local - export LD_LIBRARY_PATH="$SNAP/opt/ros/underlay_ws/usr/lib/x86_64-linux-gnu${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}" fi activate_workspace "$SNAP/opt/ros/$ROS_DISTRO" --local --extend diff --git a/extensions/ros2/launch b/extensions/ros2/launch index dc419a12b1..a2e60dbc30 100755 --- a/extensions/ros2/launch +++ b/extensions/ros2/launch @@ -19,9 +19,6 @@ fi if [ -d "$SNAP/opt/ros/underlay_ws/opt/ros/snap" ]; then source_with_prefix "$SNAP/opt/ros/underlay_ws/opt/ros/snap" fi -if [[ -d "$SNAP/opt/ros/underlay_ws/opt/ros/$ROS_DISTRO" || -d "$SNAP/opt/ros/underlay_ws/opt/ros/snap" ]]; then - export LD_LIBRARY_PATH="$SNAP/opt/ros/underlay_ws/usr/lib/x86_64-linux-gnu${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}" -fi source_with_prefix "$SNAP/opt/ros/$ROS_DISTRO" source_with_prefix "$SNAP/opt/ros/snap" diff --git a/snapcraft/extensions/_ros2_humble_meta.py b/snapcraft/extensions/_ros2_humble_meta.py index 675d9195ec..fddfb01608 100644 --- a/snapcraft/extensions/_ros2_humble_meta.py +++ b/snapcraft/extensions/_ros2_humble_meta.py @@ -64,6 +64,8 @@ def get_app_snippet(self) -> Dict[str, Any]: ] app_snippet["environment"]["PYTHONPATH"] = f'{python_paths}:{":".join(new_python_paths)}' + app_snippet["environment"]["PATH"] = "$PATH:$SNAP/opt/ros/underlay_ws/usr/bin" + app_snippet["environment"]["LD_LIBRARY_PATH"] = "$LD_LIBRARY_PATH:$SNAP/opt/ros/underlay_ws/usr/lib/$SNAPCRAFT_ARCH_TRIPLET" return app_snippet @@ -71,6 +73,9 @@ def get_app_snippet(self) -> Dict[str, Any]: def get_part_snippet(self) -> Dict[str, Any]: part_snippet = super().get_part_snippet() part_snippet["build-snaps"] = [self.ROS_META_DEV] + part_snippet["colcon-cmake-args"] = [ + f'-DCMAKE_SYSTEM_PREFIX_PATH="/snap/{self.ROS_META_DEV}/current/usr"' + ] return part_snippet @overrides diff --git a/snapcraft/parts/plugins/colcon_plugin.py b/snapcraft/parts/plugins/colcon_plugin.py index 581fb3dd1c..cfa0fad1b3 100644 --- a/snapcraft/parts/plugins/colcon_plugin.py +++ b/snapcraft/parts/plugins/colcon_plugin.py @@ -175,20 +175,6 @@ def _get_workspace_activation_commands(self) -> List[str]: def _get_build_commands(self) -> List[str]: options = cast(ColconPluginProperties, self._options) - export_command = [] - - if self._options.build_snaps: - for build_snap in self._options.build_snaps: - build_snap = _get_parsed_snap(build_snap)[0] - - export_command.extend( - [ - 'if [ -d "/snap/{build_snap}/current" ]; then ' - 'export CMAKE_PREFIX_PATH="/snap/{build_snap}/current:/snap/{build_snap}/current/usr${{CMAKE_PREFIX_PATH:+:${{CMAKE_PREFIX_PATH}}}}"; ' - "fi".format(build_snap=build_snap) - ] - ) - build_command = [ "colcon", "build", @@ -224,9 +210,7 @@ def _get_build_commands(self) -> List[str]: build_command.extend(["--parallel-workers", '"${CRAFT_PARALLEL_BUILD_COUNT}"']) return ( - ["## Prepare build"] - + export_command - + ["## Build command", " ".join(build_command)] + ["## Build command", " ".join(build_command)] + [ "## Post build command", # Remove the COLCON_IGNORE marker so that, at staging, diff --git a/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py b/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py index b648aa8a7a..de00d88a8d 100644 --- a/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py +++ b/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py @@ -50,3 +50,6 @@ def __init__(self, *, extension_name: str, yaml_data: Dict[str, Any]) -> None: ] self.app_snippet["environment"]["PYTHONPATH"] = f'{python_paths}:{":".join(new_python_paths)}' + + self.app_snippet["environment"]["PATH"] = "$PATH:$SNAP/opt/ros/underlay_ws/usr/bin" + self.app_snippet["environment"]["LD_LIBRARY_PATH"] = "$LD_LIBRARY_PATH:$SNAP/opt/ros/underlay_ws/usr/lib/$SNAPCRAFT_ARCH_TRIPLET" diff --git a/snapcraft_legacy/internal/project_loader/_extensions/_ros2_foxy_meta.py b/snapcraft_legacy/internal/project_loader/_extensions/_ros2_foxy_meta.py index c11c88df08..2ea8dc869d 100644 --- a/snapcraft_legacy/internal/project_loader/_extensions/_ros2_foxy_meta.py +++ b/snapcraft_legacy/internal/project_loader/_extensions/_ros2_foxy_meta.py @@ -47,7 +47,7 @@ def __init__(self, *, extension_name: str, yaml_data: Dict[str, Any]) -> None: } } - self.part_snippet["catkin-cmake-args"] = [ + self.part_snippet["colcon-cmake-args"] = [ f'-DCMAKE_SYSTEM_PREFIX_PATH="/snap/{self.ROS_META_DEV}/current/usr"' ] @@ -60,3 +60,6 @@ def __init__(self, *, extension_name: str, yaml_data: Dict[str, Any]) -> None: ] self.app_snippet["environment"]["PYTHONPATH"] = f'{python_paths}:{":".join(new_python_paths)}' + + self.app_snippet["environment"]["PATH"] = "$PATH:$SNAP/opt/ros/underlay_ws/usr/bin" + self.app_snippet["environment"]["LD_LIBRARY_PATH"] = "$LD_LIBRARY_PATH:$SNAP/opt/ros/underlay_ws/usr/lib/$SNAPCRAFT_ARCH_TRIPLET" diff --git a/snapcraft_legacy/plugins/v2/catkin.py b/snapcraft_legacy/plugins/v2/catkin.py index 6252a02213..9aded3ae21 100644 --- a/snapcraft_legacy/plugins/v2/catkin.py +++ b/snapcraft_legacy/plugins/v2/catkin.py @@ -122,9 +122,6 @@ def _get_workspace_activation_commands(self) -> List[str]: def _get_build_commands(self) -> List[str]: - prepare_build_command = list() - export_command = list() - build_command = [ "catkin_make_isolated", "--install", @@ -148,9 +145,4 @@ def _get_build_commands(self) -> List[str]: if self.options.catkin_cmake_args: build_command.extend(["--cmake-args", *self.options.catkin_cmake_args]) - return ( - ["## Prepare build"] - + prepare_build_command - + export_command - + ["## Build command", " ".join(build_command)] - ) + return (["## Build command", " ".join(build_command)]) diff --git a/snapcraft_legacy/plugins/v2/colcon.py b/snapcraft_legacy/plugins/v2/colcon.py index 13b1f63fab..bdb00b15e0 100644 --- a/snapcraft_legacy/plugins/v2/colcon.py +++ b/snapcraft_legacy/plugins/v2/colcon.py @@ -174,18 +174,6 @@ def _get_workspace_activation_commands(self) -> List[str]: def _get_build_commands(self) -> List[str]: - export_command = list() - - if self.options.build_snaps: - for build_snap in self.options.build_snaps: - build_snap = _get_parsed_snap(build_snap)[0] - - export_command.extend([ - 'if [ -d "/snap/{build_snap}/current" ]; then ' - 'export CMAKE_PREFIX_PATH="/snap/{build_snap}/current:/snap/{build_snap}/current/usr${{CMAKE_PREFIX_PATH:+:${{CMAKE_PREFIX_PATH}}}}"; ' - 'fi'.format(build_snap=build_snap) - ]) - build_command = [ "colcon", "build", @@ -217,9 +205,7 @@ def _get_build_commands(self) -> List[str]: build_command.extend(["--parallel-workers", '"${SNAPCRAFT_PARALLEL_BUILD_COUNT}"']) return ( - ["## Prepare build"] - + export_command - + ["## Build command", " ".join(build_command)] + ["## Build command", " ".join(build_command)] + [ "## Post build command", # Remove the COLCON_IGNORE marker so that, at staging, diff --git a/tests/legacy/unit/plugins/v2/test_catkin.py b/tests/legacy/unit/plugins/v2/test_catkin.py index d3b73858c7..77dc8024f2 100644 --- a/tests/legacy/unit/plugins/v2/test_catkin.py +++ b/tests/legacy/unit/plugins/v2/test_catkin.py @@ -144,7 +144,6 @@ class Options: "fi", "", 'eval "${state}"', - "## Prepare build", "## Build command", "catkin_make_isolated --install --merge " '--source-space "${SNAPCRAFT_PART_SRC_WORK}" --build-space "${SNAPCRAFT_PART_BUILD}" ' @@ -271,19 +270,6 @@ class Options: "fi", "", 'eval "${state}"', - "## Prepare build", - 'if [ -d "/snap/foo/current/opt/ros/${ROS_DISTRO}/share" ]; then ', - 'mkdir -p "${SNAPCRAFT_PART_BUILD}"/build_snaps/foo', - 'cp -r "/snap/foo/current/opt/ros/${ROS_DISTRO}/share" ' - '"${SNAPCRAFT_PART_BUILD}/build_snaps/foo/."', - 'find "${SNAPCRAFT_PART_BUILD}/build_snaps/foo" \\( -name "*Config.cmake" -o ' - '-name "*extras.cmake" \\) -exec sed -i -e "s|/opt|/snap/foo/current&|g" -e ' - '"s|/usr|/snap/foo/current&|g" -e ' - '"s|\\${.*_DIR}/../../..|/snap/foo/current/opt/ros/${ROS_DISTRO}|g" {} \\;', - "fi", - 'if [ -d "${SNAPCRAFT_PART_BUILD}"/build_snaps/foo ]; then export ' - 'CMAKE_PREFIX_PATH="${SNAPCRAFT_PART_BUILD}/build_snaps/foo:${CMAKE_PREFIX_PATH-}"; ' - "fi", "## Build command", "catkin_make_isolated --install --merge " '--source-space "${SNAPCRAFT_PART_SRC_WORK}" --build-space "${SNAPCRAFT_PART_BUILD}" ' diff --git a/tests/legacy/unit/plugins/v2/test_colcon.py b/tests/legacy/unit/plugins/v2/test_colcon.py index 8326f4e448..dd76785d6e 100644 --- a/tests/legacy/unit/plugins/v2/test_colcon.py +++ b/tests/legacy/unit/plugins/v2/test_colcon.py @@ -165,7 +165,6 @@ class Options: "fi", "", 'eval "${state}"', - "## Prepare build", "## Build command", "colcon build " '--base-paths "${SNAPCRAFT_PART_SRC_WORK}" --build-base "${SNAPCRAFT_PART_BUILD}" ' @@ -303,10 +302,6 @@ class Options: "fi", "", 'eval "${state}"', - "## Prepare build", - 'if [ -d "/snap/foo/current" ]; then export ' - 'CMAKE_PREFIX_PATH="/snap/foo/current:/snap/foo/current/usr:${CMAKE_PREFIX_PATH-}"; ' - "fi", "## Build command", "colcon build " '--base-paths "${SNAPCRAFT_PART_SRC_WORK}" --build-base "${SNAPCRAFT_PART_BUILD}" ' diff --git a/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py b/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py index 1c75ef753c..92fe85ba48 100644 --- a/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py +++ b/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py @@ -99,10 +99,20 @@ def test_extension(self, extension_name, extension_class, meta, meta_dev): }, } + python_paths = [ + "$SNAP/opt/ros/noetic/lib/python3.8/site-packages", + "$SNAP/usr/lib/python3/dist-packages", + "${PYTHONPATH}", + "$SNAP/opt/ros/underlay_ws/opt/ros/noetic/lib/python3.8/site-packages", + "$SNAP/opt/ros/underlay_ws/usr/lib/python3/dist-packages", + ] + assert ros1_extension.app_snippet == { "command-chain": ["snap/command-chain/ros1-launch"], "environment": { - "PYTHONPATH": "$SNAP/opt/ros/noetic/lib/python3.8/site-packages:$SNAP/usr/lib/python3/dist-packages:${PYTHONPATH}", + "LD_LIBRARY_PATH": "$LD_LIBRARY_PATH:$SNAP/opt/ros/underlay_ws/usr/lib/$SNAPCRAFT_ARCH_TRIPLET", + "PATH": "$PATH:$SNAP/opt/ros/underlay_ws/usr/bin", + "PYTHONPATH": ":".join(python_paths), "ROS_VERSION": "1", "ROS_DISTRO": "noetic", }, @@ -111,6 +121,7 @@ def test_extension(self, extension_name, extension_class, meta, meta_dev): assert ros1_extension.part_snippet == { "build-environment": [{"ROS_VERSION": "1"}, {"ROS_DISTRO": "noetic"}], "build-snaps": [meta_dev], + "catkin-cmake-args": [f'-DCMAKE_SYSTEM_PREFIX_PATH="/snap/{meta_dev}/current/usr"'], } assert ros1_extension.parts == { diff --git a/tests/legacy/unit/project_loader/extensions/test_ros2_foxy_meta.py b/tests/legacy/unit/project_loader/extensions/test_ros2_foxy_meta.py index 0cefe27645..1aed059a8b 100644 --- a/tests/legacy/unit/project_loader/extensions/test_ros2_foxy_meta.py +++ b/tests/legacy/unit/project_loader/extensions/test_ros2_foxy_meta.py @@ -79,10 +79,20 @@ def test_extension(self, extension_name, extension_class, meta, meta_dev): }, } + python_paths = [ + "$SNAP/opt/ros/foxy/lib/python3.8/site-packages", + "$SNAP/usr/lib/python3/dist-packages", + "${PYTHONPATH}", + "$SNAP/opt/ros/underlay_ws/opt/ros/foxy/lib/python3.8/site-packages", + "$SNAP/opt/ros/underlay_ws/usr/lib/python3/dist-packages", + ] + assert ros_extension.app_snippet == { "command-chain": ["snap/command-chain/ros2-launch"], "environment": { - "PYTHONPATH": "$SNAP/opt/ros/foxy/lib/python3.8/site-packages:$SNAP/usr/lib/python3/dist-packages:${PYTHONPATH}", + "LD_LIBRARY_PATH": "$LD_LIBRARY_PATH:$SNAP/opt/ros/underlay_ws/usr/lib/$SNAPCRAFT_ARCH_TRIPLET", + "PATH": "$PATH:$SNAP/opt/ros/underlay_ws/usr/bin", + "PYTHONPATH": ":".join(python_paths), "ROS_VERSION": "2", "ROS_DISTRO": "foxy", }, @@ -91,6 +101,7 @@ def test_extension(self, extension_name, extension_class, meta, meta_dev): assert ros_extension.part_snippet == { "build-environment": [{"ROS_VERSION": "2"}, {"ROS_DISTRO": "foxy"}], "build-snaps": [meta_dev], + "colcon-cmake-args": [f'-DCMAKE_SYSTEM_PREFIX_PATH="/snap/{meta_dev}/current/usr"'], } assert ros_extension.parts == { diff --git a/tests/unit/parts/extensions/test_ros2_humble_meta.py b/tests/unit/parts/extensions/test_ros2_humble_meta.py index ebd3e8f9b6..66a73ac150 100644 --- a/tests/unit/parts/extensions/test_ros2_humble_meta.py +++ b/tests/unit/parts/extensions/test_ros2_humble_meta.py @@ -140,6 +140,8 @@ def test_get_app_snippet(self, extension_name, extension_class, meta, meta_dev): "$SNAP/opt/ros/humble/lib/python3.10/site-packages", "$SNAP/usr/lib/python3/dist-packages", "${PYTHONPATH}", + "$SNAP/opt/ros/underlay_ws/opt/ros/humble/lib/python3.8/site-packages", + "$SNAP/opt/ros/underlay_ws/usr/lib/python3/dist-packages", ] extension = setup_method_fixture(extension_class) assert extension.get_app_snippet() == { @@ -149,6 +151,8 @@ def test_get_app_snippet(self, extension_name, extension_class, meta, meta_dev): "ROS_DISTRO": "humble", "PYTHONPATH": ":".join(python_paths), "ROS_HOME": "$SNAP_USER_DATA/ros", + "LD_LIBRARY_PATH": "$LD_LIBRARY_PATH:$SNAP/opt/ros/underlay_ws/usr/lib/$SNAPCRAFT_ARCH_TRIPLET", + "PATH": "$PATH:$SNAP/opt/ros/underlay_ws/usr/bin", }, } @@ -158,6 +162,7 @@ def test_get_part_snippet(self, extension_name, extension_class, meta, meta_dev) assert extension.get_part_snippet() == { "build-environment": [{"ROS_VERSION": "2"}, {"ROS_DISTRO": "humble"}], "build-snaps": [meta_dev], + "colcon-cmake-args": [f'-DCMAKE_SYSTEM_PREFIX_PATH="/snap/{meta_dev}/current/usr"'] } @pytest.mark.parametrize(fixture_variables, fixture_values) diff --git a/tests/unit/parts/plugins/test_colcon.py b/tests/unit/parts/plugins/test_colcon.py index 2c8ffe4ce6..9eba012f30 100644 --- a/tests/unit/parts/plugins/test_colcon.py +++ b/tests/unit/parts/plugins/test_colcon.py @@ -204,7 +204,6 @@ def test_get_build_commands(self, setup_method_fixture, new_dir, monkeypatch): "fi", "", 'eval "${state}"', - "## Prepare build", "## Build command", "colcon build " '--base-paths "${CRAFT_PART_SRC_WORK}" --build-base "${CRAFT_PART_BUILD}" ' @@ -352,10 +351,6 @@ def test_get_build_commands_with_all_properties( "fi", "", 'eval "${state}"', - "## Prepare build", - 'if [ -d "/snap/foo/current" ]; then export ' - 'CMAKE_PREFIX_PATH="/snap/foo/current:/snap/foo/current/usr:${CMAKE_PREFIX_PATH-}"; ' - "fi", "## Build command", "colcon build " '--base-paths "${CRAFT_PART_SRC_WORK}" --build-base "${CRAFT_PART_BUILD}" ' From be57a2028d614351d30bf738c23e6d6ceacfc3ce Mon Sep 17 00:00:00 2001 From: artivis Date: Wed, 24 May 2023 10:30:03 +0200 Subject: [PATCH 46/84] ros: match extension/part names Signed-off-by: artivis --- snapcraft/extensions/_ros2_humble_meta.py | 12 +++++++++++- snapcraft/extensions/ros2_humble_desktop.py | 1 + snapcraft/extensions/ros2_humble_ros_base.py | 1 + snapcraft/extensions/ros2_humble_ros_core.py | 1 + tests/unit/parts/extensions/test_ros2_humble_meta.py | 2 +- 5 files changed, 15 insertions(+), 2 deletions(-) diff --git a/snapcraft/extensions/_ros2_humble_meta.py b/snapcraft/extensions/_ros2_humble_meta.py index fddfb01608..b7be5cf563 100644 --- a/snapcraft/extensions/_ros2_humble_meta.py +++ b/snapcraft/extensions/_ros2_humble_meta.py @@ -41,6 +41,12 @@ def ROS_META_DEV(self): """Abstract property to define the extension's build snap.""" raise NotImplementedError + @property + @abstractmethod + def ROS_VARIANT(self): + """Abstract property to define the extension's ROS variant.""" + raise NotImplementedError + @overrides def get_root_snippet(self) -> Dict[str, Any]: root_snippet = super().get_root_snippet() @@ -84,11 +90,15 @@ def get_parts_snippet(self) -> Dict[str, Any]: # Very unlikely but it may happen that the snapped application doesn't # even pull those deps. In that case, there is no valid ROS 2 ws to source. # We make sure here that they are staged no matter what. - print("parts_snippet ", parts_snippet) parts_snippet[f"ros2-{self.ROS_DISTRO}/ros2-launch"]["stage-packages"] = [ f"ros-{self.ROS_DISTRO}-ros-environment", f"ros-{self.ROS_DISTRO}-ros-workspace", f"ros-{self.ROS_DISTRO}-ament-index-cpp", f"ros-{self.ROS_DISTRO}-ament-index-python", ] + + # The part name must follow the format / + parts_snippet[f"ros2-{self.ROS_DISTRO}-{self.ROS_VARIANT}/ros2-launch"] = parts_snippet[f"ros2-{self.ROS_DISTRO}/ros2-launch"] + parts_snippet.pop(f"ros2-{self.ROS_DISTRO}/ros2-launch") + return parts_snippet diff --git a/snapcraft/extensions/ros2_humble_desktop.py b/snapcraft/extensions/ros2_humble_desktop.py index 5b404a20f2..6208ba162f 100644 --- a/snapcraft/extensions/ros2_humble_desktop.py +++ b/snapcraft/extensions/ros2_humble_desktop.py @@ -36,3 +36,4 @@ def is_experimental(base: Optional[str]) -> bool: ROS_META: Final[str] = "ros-humble-desktop" ROS_META_DEV: Final[str] = "ros-humble-desktop-dev" + ROS_VARIANT: Final[str] = "desktop" diff --git a/snapcraft/extensions/ros2_humble_ros_base.py b/snapcraft/extensions/ros2_humble_ros_base.py index a773e6ab3d..88b5addf6a 100644 --- a/snapcraft/extensions/ros2_humble_ros_base.py +++ b/snapcraft/extensions/ros2_humble_ros_base.py @@ -36,3 +36,4 @@ def is_experimental(base: Optional[str]) -> bool: ROS_META: Final[str] = "ros-humble-ros-base" ROS_META_DEV: Final[str] = "ros-humble-ros-base-dev" + ROS_VARIANT: Final[str] = "ros-base" diff --git a/snapcraft/extensions/ros2_humble_ros_core.py b/snapcraft/extensions/ros2_humble_ros_core.py index efc1ee4b97..6b8dadcec8 100644 --- a/snapcraft/extensions/ros2_humble_ros_core.py +++ b/snapcraft/extensions/ros2_humble_ros_core.py @@ -36,3 +36,4 @@ def is_experimental(base: Optional[str]) -> bool: ROS_META: Final[str] = "ros-humble-ros-core" ROS_META_DEV: Final[str] = "ros-humble-ros-core-dev" + ROS_VARIANT: Final[str] = "ros-core" diff --git a/tests/unit/parts/extensions/test_ros2_humble_meta.py b/tests/unit/parts/extensions/test_ros2_humble_meta.py index 66a73ac150..9d45368800 100644 --- a/tests/unit/parts/extensions/test_ros2_humble_meta.py +++ b/tests/unit/parts/extensions/test_ros2_humble_meta.py @@ -169,7 +169,7 @@ def test_get_part_snippet(self, extension_name, extension_class, meta, meta_dev) def test_get_parts_snippet(self, extension_name, extension_class, meta, meta_dev): extension = setup_method_fixture(extension_class) assert extension.get_parts_snippet() == { - "ros2-humble/ros2-launch": { + f"{extension_name}/ros2-launch": { "source": f"{get_extensions_data_dir()}/ros2", "plugin": "make", "build-packages": [ From fa198117ec33171e3d5aa9656f7462d1acb61bfb Mon Sep 17 00:00:00 2001 From: artivis Date: Wed, 24 May 2023 10:30:32 +0200 Subject: [PATCH 47/84] ros: ros-environment Signed-off-by: artivis --- .../legacy/unit/project_loader/extensions/test_ros1_noetic.py | 3 ++- .../unit/project_loader/extensions/test_ros1_noetic_meta.py | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/legacy/unit/project_loader/extensions/test_ros1_noetic.py b/tests/legacy/unit/project_loader/extensions/test_ros1_noetic.py index 5ebf5fdffe..f0e47a45c3 100644 --- a/tests/legacy/unit/project_loader/extensions/test_ros1_noetic.py +++ b/tests/legacy/unit/project_loader/extensions/test_ros1_noetic.py @@ -55,7 +55,8 @@ def test_extension(extension_class): } assert ros1_extension.part_snippet == { - "build-environment": [{"ROS_VERSION": "1"}, {"ROS_DISTRO": "noetic"}] + "build-environment": [{"ROS_VERSION": "1"}, {"ROS_DISTRO": "noetic"}], + "stage-packages": ["ros-noetic-ros-environment"], } assert ros1_extension.parts == { diff --git a/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py b/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py index 92fe85ba48..9b79963a59 100644 --- a/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py +++ b/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py @@ -122,6 +122,7 @@ def test_extension(self, extension_name, extension_class, meta, meta_dev): "build-environment": [{"ROS_VERSION": "1"}, {"ROS_DISTRO": "noetic"}], "build-snaps": [meta_dev], "catkin-cmake-args": [f'-DCMAKE_SYSTEM_PREFIX_PATH="/snap/{meta_dev}/current/usr"'], + "stage-packages": ["ros-noetic-ros-environment"], } assert ros1_extension.parts == { From 0d8956576369f28543256e546ee416862621e472 Mon Sep 17 00:00:00 2001 From: artivis Date: Wed, 24 May 2023 10:32:19 +0200 Subject: [PATCH 48/84] ros: revamp content-sharing spread tests Signed-off-by: artivis --- .../{ros-meta => ros-meta-hello}/task.yaml | 17 ++-- .../ros-meta-talker-listener/task.yaml | 78 +++++++++++++++++++ .../task.yaml | 28 ++----- .../ros2-humble-meta-hello/task.yaml | 70 +++++++++++++++++ .../catkin-noetic-robot/snap/snapcraft.yaml | 21 ----- .../src/snapcraft_hello/CMakeLists.txt | 22 ------ .../src/snapcraft_hello/package.xml | 13 ---- .../src/snapcraft_hello/src/hello.cpp | 24 ------ .../snap/snapcraft.yaml | 21 ----- .../src/snapcraft_hello/CMakeLists.txt | 22 ------ .../src/snapcraft_hello/package.xml | 13 ---- .../src/snapcraft_hello/src/hello.cpp | 24 ------ .../snap/snapcraft.yaml | 4 +- 13 files changed, 161 insertions(+), 196 deletions(-) rename tests/spread/extensions/{ros-meta => ros-meta-hello}/task.yaml (77%) create mode 100644 tests/spread/extensions/ros-meta-talker-listener/task.yaml rename tests/spread/extensions/{ros2-meta => ros2-foxy-meta-hello}/task.yaml (59%) create mode 100644 tests/spread/extensions/ros2-humble-meta-hello/task.yaml delete mode 100644 tests/spread/extensions/snaps/catkin-noetic-robot/snap/snapcraft.yaml delete mode 100644 tests/spread/extensions/snaps/catkin-noetic-robot/src/snapcraft_hello/CMakeLists.txt delete mode 100644 tests/spread/extensions/snaps/catkin-noetic-robot/src/snapcraft_hello/package.xml delete mode 100644 tests/spread/extensions/snaps/catkin-noetic-robot/src/snapcraft_hello/src/hello.cpp delete mode 100644 tests/spread/extensions/snaps/catkin-noetic-ros-core/snap/snapcraft.yaml delete mode 100644 tests/spread/extensions/snaps/catkin-noetic-ros-core/src/snapcraft_hello/CMakeLists.txt delete mode 100644 tests/spread/extensions/snaps/catkin-noetic-ros-core/src/snapcraft_hello/package.xml delete mode 100644 tests/spread/extensions/snaps/catkin-noetic-ros-core/src/snapcraft_hello/src/hello.cpp diff --git a/tests/spread/extensions/ros-meta/task.yaml b/tests/spread/extensions/ros-meta-hello/task.yaml similarity index 77% rename from tests/spread/extensions/ros-meta/task.yaml rename to tests/spread/extensions/ros-meta-hello/task.yaml index e82bf3e33c..293f1acf0d 100644 --- a/tests/spread/extensions/ros-meta/task.yaml +++ b/tests/spread/extensions/ros-meta-hello/task.yaml @@ -3,27 +3,22 @@ summary: Build and run a basic ROS snap using meta-ros extension kill-timeout: 180m environment: - SNAP/catkin_noetic_ros_core: catkin-noetic-ros-core + SNAP: catkin-noetic-hello + SNAP_DIR: "../../plugins/v2/snaps/$SNAP" + + INTERFACE: ros-noetic + META_SNAP/catkin_noetic_ros_core: ros-noetic-ros-core EXTENSION/catkin_noetic_ros_core: ros1-noetic-ros-core - INTERFACE/catkin_noetic_ros_core: ros-noetic - SNAP/catkin_noetic_ros_base: catkin-noetic-ros-core META_SNAP/catkin_noetic_ros_base: ros-noetic-ros-base EXTENSION/catkin_noetic_ros_base: ros1-noetic-ros-base - INTERFACE/catkin_noetic_ros_base: ros-noetic - SNAP/catkin_noetic_robot: catkin-noetic-ros-core META_SNAP/catkin_noetic_robot: ros-noetic-robot EXTENSION/catkin_noetic_robot: ros1-noetic-robot - INTERFACE/catkin_noetic_robot: ros-noetic - SNAP/catkin_noetic_desktop: catkin-noetic-ros-core META_SNAP/catkin_noetic_desktop: ros-noetic-desktop EXTENSION/catkin_noetic_desktop: ros1-noetic-desktop - INTERFACE/catkin_noetic_desktop: ros-noetic - - SNAP_DIR: "../snaps/$SNAP" # The content snap required for the test to succeed is only # available on a subset of all the architectures this testbed @@ -40,7 +35,7 @@ prepare: | set_base "$SNAP_DIR/snap/snapcraft.yaml" # Overwrite the extension to test them all out of a single snap - sed -i "s|ros1-noetic-ros-core|${EXTENSION}|" "$SNAP_DIR/snap/snapcraft.yaml" + sed -i "s|ros1-noetic|${EXTENSION}|" "$SNAP_DIR/snap/snapcraft.yaml" restore: | cd "$SNAP_DIR" diff --git a/tests/spread/extensions/ros-meta-talker-listener/task.yaml b/tests/spread/extensions/ros-meta-talker-listener/task.yaml new file mode 100644 index 0000000000..4b9bb01a2b --- /dev/null +++ b/tests/spread/extensions/ros-meta-talker-listener/task.yaml @@ -0,0 +1,78 @@ +summary: Build and run a basic ROS snap using meta-ros extension + +kill-timeout: 180m + +environment: + SNAP: catkin-ros1-run + # SNAP/catkin_ros1_run: catkin-ros1-run + # SNAP/catkin_roslaunch_wrapper: catkin-roslaunch-wrapper + + SNAP_DIR: "../../plugins/v2/snaps/$SNAP" + + INTERFACE: ros-noetic + + META_SNAP/catkin_noetic_ros_core: ros-noetic-ros-core + EXTENSION/catkin_noetic_ros_core: ros1-noetic-ros-core + + META_SNAP/catkin_noetic_ros_base: ros-noetic-ros-base + EXTENSION/catkin_noetic_ros_base: ros1-noetic-ros-base + + META_SNAP/catkin_noetic_robot: ros-noetic-robot + EXTENSION/catkin_noetic_robot: ros1-noetic-robot + + META_SNAP/catkin_noetic_desktop: ros-noetic-desktop + EXTENSION/catkin_noetic_desktop: ros1-noetic-desktop + +# The content snap required for the test to succeed is only +# available on a subset of all the architectures this testbed +# can run on. +systems: + - ubuntu-20.04 + - ubuntu-20.04-64 + - ubuntu-20.04-amd64 + - ubuntu-20.04-arm64 + +prepare: | + #shellcheck source=tests/spread/tools/snapcraft-yaml.sh + . "$TOOLS_DIR/snapcraft-yaml.sh" + set_base "$SNAP_DIR/snap/snapcraft.yaml" + + # Overwrite the extension to test them all out of a single snap + sed -i "s|ros1-noetic|${EXTENSION}|" "$SNAP_DIR/snap/snapcraft.yaml" + + sed -i "s|opt/ros/noetic/bin/||" "$SNAP_DIR/snap/snapcraft.yaml" + +restore: | + cd "$SNAP_DIR" + snapcraft clean + rm -f ./*.snap + + #shellcheck source=tests/spread/tools/snapcraft-yaml.sh + . "$TOOLS_DIR/snapcraft-yaml.sh" + restore_yaml "snap/snapcraft.yaml" + +execute: | + cd "$SNAP_DIR" + + # Build what we have and verify the snap runs as expected. + snapcraft + snap install "${SNAP}"_1.0_*.snap --dangerous + + # Check that the snap size is fairly small + # The non-content sharing snap is ~90M + SNAP_SIZE=$(ls -s "${SNAP}"_1.0_*.snap | cut -d " " -f1) + [ "100" -gt "$SNAP_SIZE" ] + + # # Install the providing snap + # snap install "${META_SNAP}" + + snap connect "${SNAP}":"${INTERFACE}" "${META_SNAP}":"${INTERFACE}" + + # Regression test for LP: #1660852. Make sure --help actually gets passed to + # roslaunch instead of being eaten by setup.sh. + "$SNAP" --help | MATCH "Usage: roslaunch" + + # Run the ROS system. By default this will never exit, but the snap supports + # an `exit_after_receive` parameter that, if true, will cause the system to + # shutdown after the listener has successfully received a message. + "$SNAP" exit_after_receive:=true | MATCH "I heard Hello world" diff --git a/tests/spread/extensions/ros2-meta/task.yaml b/tests/spread/extensions/ros2-foxy-meta-hello/task.yaml similarity index 59% rename from tests/spread/extensions/ros2-meta/task.yaml rename to tests/spread/extensions/ros2-foxy-meta-hello/task.yaml index 58b725ac36..4d2bfcd7a7 100644 --- a/tests/spread/extensions/ros2-meta/task.yaml +++ b/tests/spread/extensions/ros2-foxy-meta-hello/task.yaml @@ -3,38 +3,20 @@ summary: Build and run a basic ROS 2 snap using meta-ros extension kill-timeout: 180m environment: - SNAP/colcon_foxy_ros_core: colcon-foxy-ros-core META_SNAP/colcon_foxy_ros_core: ros-foxy-ros-core EXTENSION/colcon_foxy_ros_core: ros2-foxy-ros-core - INTERFACE/colcon_foxy_ros_core: ros-foxy - SNAP/colcon_foxy_ros_base: colcon-foxy-ros-core META_SNAP/colcon_foxy_ros_base: ros-foxy-ros-base EXTENSION/colcon_foxy_ros_base: ros2-foxy-ros-base - INTERFACE/colcon_foxy_ros_base: ros-foxy - SNAP/colcon_foxy_desktop: colcon-foxy-ros-core META_SNAP/colcon_foxy_desktop: ros-foxy-desktop EXTENSION/colcon_foxy_desktop: ros2-foxy-desktop - INTERFACE/colcon_foxy_desktop: ros-foxy - - SNAP/colcon_humble_ros_core: colcon-humble-ros-core - META_SNAP/colcon_humble_ros_core: ros-humble-ros-base - EXTENSION/colcon_humble_ros_core: ros2-humble-ros-base - INTERFACE/colcon_humble_ros_core: ros-humble - - SNAP/colcon_humble_ros_base: colcon-humble-ros-core - META_SNAP/colcon_humble_ros_base: ros-humble-ros-base - EXTENSION/colcon_humble_ros_base: ros2-humble-ros-base - INTERFACE/colcon_humble_ros_base: ros-humble - - SNAP/colcon_humble_desktop: colcon-humble-ros-core - META_SNAP/colcon_humble_desktop: ros-humble-desktop - EXTENSION/colcon_humble_desktop: ros2-humble-desktop - INTERFACE/colcon_humble_desktop: ros-humble + SNAP: colcon-foxy-ros-core SNAP_DIR: "../snaps/$SNAP" + INTERFACE: ros-foxy + # The content snap required for the test to succeed is only # available on a subset of all the architectures this testbed # can run on. @@ -50,14 +32,14 @@ prepare: | set_base "$SNAP_DIR/snap/snapcraft.yaml" # Overwrite the extension to test them all out of a single snap - sed -i "s|ros2-foxy-ros-core|${EXTENSION}|" "$SNAP_DIR/snap/snapcraft.yaml" + sed -i "s|ros2-.*-ros-core|${EXTENSION}|" "$SNAP_DIR/snap/snapcraft.yaml" restore: | cd "$SNAP_DIR" snapcraft clean rm -f ./*.snap - [ -f src/colcon-foxy-ros-core/src/hello.cpp ] && git checkout src/colcon-foxy-ros-core/src/hello.cpp + [ -f src/colcon-*-ros-core/src/hello.cpp ] && git checkout src/colcon-*-ros-core/src/hello.cpp #shellcheck source=tests/spread/tools/snapcraft-yaml.sh . "$TOOLS_DIR/snapcraft-yaml.sh" diff --git a/tests/spread/extensions/ros2-humble-meta-hello/task.yaml b/tests/spread/extensions/ros2-humble-meta-hello/task.yaml new file mode 100644 index 0000000000..9d1ce521a4 --- /dev/null +++ b/tests/spread/extensions/ros2-humble-meta-hello/task.yaml @@ -0,0 +1,70 @@ +summary: Build and run a basic ROS 2 snap using meta-ros extension + +kill-timeout: 180m + +environment: + + SNAPCRAFT_ENABLE_EXPERIMENTAL_EXTENSIONS: "1" + + # META_SNAP/colcon_humble_ros_core: ros-humble-ros-core + # EXTENSION/colcon_humble_ros_core: ros2-humble-ros-core + + # META_SNAP/colcon_humble_ros_base: ros-humble-ros-base + # EXTENSION/colcon_humble_ros_base: ros2-humble-ros-base + + META_SNAP/colcon_humble_desktop: ros-humble-desktop + EXTENSION/colcon_humble_desktop: ros2-humble-desktop + + META_SNAP/colcon_foxy_desktop: ros-foxy-desktop + EXTENSION/colcon_foxy_desktop: ros2-foxy-desktop + + SNAP: colcon-humble-ros-core + SNAP_DIR: "../snaps/$SNAP" + + INTERFACE: ros-humble + +# The content snap required for the test to succeed is only +# available on a subset of all the architectures this testbed +# can run on. +systems: + - ubuntu-22.04 + - ubuntu-22.04-64 + - ubuntu-22.04-amd64 + - ubuntu-22.04-arm64 + +prepare: | + #shellcheck source=tests/spread/tools/snapcraft-yaml.sh + . "$TOOLS_DIR/snapcraft-yaml.sh" + set_base "$SNAP_DIR/snap/snapcraft.yaml" + + # Overwrite the extension to test them all out of a single snap + sed -i "s|ros2-.*-ros-core|${EXTENSION}|" "$SNAP_DIR/snap/snapcraft.yaml" + +restore: | + cd "$SNAP_DIR" + snapcraft clean + rm -f ./*.snap + + [ -f src/colcon-*-ros-core/src/hello.cpp ] && git checkout src/colcon-*-ros-core/src/hello.cpp + + #shellcheck source=tests/spread/tools/snapcraft-yaml.sh + . "$TOOLS_DIR/snapcraft-yaml.sh" + restore_yaml "snap/snapcraft.yaml" + +execute: | + cd "$SNAP_DIR" + + # Build what we have and verify the snap runs as expected. + snapcraft + snap install "${SNAP}"_1.0_*.snap --dangerous + + # Check that the snap size is fairly small + # The non-content sharing snap is ~90M + SNAP_SIZE=$(ls -s "${SNAP}"_1.0_*.snap | cut -d " " -f1) + [ "200" -gt "$SNAP_SIZE" ] + + # Install the providing snap + # snap install "${META_SNAP}" + + snap connect "${SNAP}":"${INTERFACE}" "${META_SNAP}":"${INTERFACE}" + [ "$($SNAP)" = "hello world" ] diff --git a/tests/spread/extensions/snaps/catkin-noetic-robot/snap/snapcraft.yaml b/tests/spread/extensions/snaps/catkin-noetic-robot/snap/snapcraft.yaml deleted file mode 100644 index 4f70aae3e6..0000000000 --- a/tests/spread/extensions/snaps/catkin-noetic-robot/snap/snapcraft.yaml +++ /dev/null @@ -1,21 +0,0 @@ -name: catkin-noetic-robot -version: "1.0" -summary: hello world -description: | - A ROS 1 roscpp-based workspace. - -grade: stable -confinement: strict -base: core20 - -apps: - catkin-noetic-robot: - command: opt/ros/noetic/lib/snapcraft_hello/snapcraft_hello - plugs: [network, network-bind] - extensions: [ros1-noetic-robot] - -parts: - hello: - plugin: catkin - source: . - build-packages: [g++, make] diff --git a/tests/spread/extensions/snaps/catkin-noetic-robot/src/snapcraft_hello/CMakeLists.txt b/tests/spread/extensions/snaps/catkin-noetic-robot/src/snapcraft_hello/CMakeLists.txt deleted file mode 100644 index af5cba06c3..0000000000 --- a/tests/spread/extensions/snaps/catkin-noetic-robot/src/snapcraft_hello/CMakeLists.txt +++ /dev/null @@ -1,22 +0,0 @@ -cmake_minimum_required(VERSION 3.0.2) -project(snapcraft_hello) - -find_package(catkin REQUIRED COMPONENTS - roscpp -) - -catkin_package() - -include_directories( - ${catkin_INCLUDE_DIRS} -) - -add_executable(${PROJECT_NAME} src/hello.cpp) - -target_link_libraries(${PROJECT_NAME} - ${catkin_LIBRARIES} -) - -install(TARGETS ${PROJECT_NAME} - RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} -) diff --git a/tests/spread/extensions/snaps/catkin-noetic-robot/src/snapcraft_hello/package.xml b/tests/spread/extensions/snaps/catkin-noetic-robot/src/snapcraft_hello/package.xml deleted file mode 100644 index 3e92ea7b10..0000000000 --- a/tests/spread/extensions/snaps/catkin-noetic-robot/src/snapcraft_hello/package.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - snapcraft_hello - 0.0.1 - snapcraft test for roscpp - me - GPLv3 - catkin - roscpp - fake_package_that_does_not_exists - roscpp - roscpp - diff --git a/tests/spread/extensions/snaps/catkin-noetic-robot/src/snapcraft_hello/src/hello.cpp b/tests/spread/extensions/snaps/catkin-noetic-robot/src/snapcraft_hello/src/hello.cpp deleted file mode 100644 index 46e30f4564..0000000000 --- a/tests/spread/extensions/snaps/catkin-noetic-robot/src/snapcraft_hello/src/hello.cpp +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (C) 2020 Canonical Ltd -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License version 3 as -// published by the Free Software Foundation. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -#include -#include - -int main(int argc, char * argv[]) -{ - ros::init(argc, argv, "snapcraft_hello"); - std::cout << "hello world" << std::endl; - ros::shutdown(); - return 0; -} diff --git a/tests/spread/extensions/snaps/catkin-noetic-ros-core/snap/snapcraft.yaml b/tests/spread/extensions/snaps/catkin-noetic-ros-core/snap/snapcraft.yaml deleted file mode 100644 index f234a9c930..0000000000 --- a/tests/spread/extensions/snaps/catkin-noetic-ros-core/snap/snapcraft.yaml +++ /dev/null @@ -1,21 +0,0 @@ -name: catkin-noetic-ros-core -version: "1.0" -summary: hello world -description: | - A ROS 1 roscpp-based workspace. - -grade: stable -confinement: strict -base: core20 - -apps: - catkin-noetic-ros-core: - command: opt/ros/noetic/lib/snapcraft_hello/snapcraft_hello - plugs: [network, network-bind] - extensions: [ros1-noetic-ros-core] - -parts: - hello: - plugin: catkin - source: . - build-packages: [g++, make] diff --git a/tests/spread/extensions/snaps/catkin-noetic-ros-core/src/snapcraft_hello/CMakeLists.txt b/tests/spread/extensions/snaps/catkin-noetic-ros-core/src/snapcraft_hello/CMakeLists.txt deleted file mode 100644 index af5cba06c3..0000000000 --- a/tests/spread/extensions/snaps/catkin-noetic-ros-core/src/snapcraft_hello/CMakeLists.txt +++ /dev/null @@ -1,22 +0,0 @@ -cmake_minimum_required(VERSION 3.0.2) -project(snapcraft_hello) - -find_package(catkin REQUIRED COMPONENTS - roscpp -) - -catkin_package() - -include_directories( - ${catkin_INCLUDE_DIRS} -) - -add_executable(${PROJECT_NAME} src/hello.cpp) - -target_link_libraries(${PROJECT_NAME} - ${catkin_LIBRARIES} -) - -install(TARGETS ${PROJECT_NAME} - RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} -) diff --git a/tests/spread/extensions/snaps/catkin-noetic-ros-core/src/snapcraft_hello/package.xml b/tests/spread/extensions/snaps/catkin-noetic-ros-core/src/snapcraft_hello/package.xml deleted file mode 100644 index 3e92ea7b10..0000000000 --- a/tests/spread/extensions/snaps/catkin-noetic-ros-core/src/snapcraft_hello/package.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - snapcraft_hello - 0.0.1 - snapcraft test for roscpp - me - GPLv3 - catkin - roscpp - fake_package_that_does_not_exists - roscpp - roscpp - diff --git a/tests/spread/extensions/snaps/catkin-noetic-ros-core/src/snapcraft_hello/src/hello.cpp b/tests/spread/extensions/snaps/catkin-noetic-ros-core/src/snapcraft_hello/src/hello.cpp deleted file mode 100644 index 46e30f4564..0000000000 --- a/tests/spread/extensions/snaps/catkin-noetic-ros-core/src/snapcraft_hello/src/hello.cpp +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (C) 2020 Canonical Ltd -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License version 3 as -// published by the Free Software Foundation. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -#include -#include - -int main(int argc, char * argv[]) -{ - ros::init(argc, argv, "snapcraft_hello"); - std::cout << "hello world" << std::endl; - ros::shutdown(); - return 0; -} diff --git a/tests/spread/extensions/snaps/colcon-humble-ros-core/snap/snapcraft.yaml b/tests/spread/extensions/snaps/colcon-humble-ros-core/snap/snapcraft.yaml index fd0faf5caa..036e9355fd 100644 --- a/tests/spread/extensions/snaps/colcon-humble-ros-core/snap/snapcraft.yaml +++ b/tests/spread/extensions/snaps/colcon-humble-ros-core/snap/snapcraft.yaml @@ -2,14 +2,14 @@ name: colcon-humble-ros-core version: "1.0" summary: hello world description: | - A ROS2 rlcpp-based workspace. + A ROS 2 rlcpp-based workspace. grade: stable confinement: strict base: core22 apps: - colcon-foxy-ros-core: + colcon-humble-ros-core: command: ros2 run colcon_ros2_rlcpp_hello colcon_ros2_rlcpp_hello plugs: [network, network-bind] extensions: [ros2-humble-ros-core] From fc872851a086723df859898c7f4e4126c024dcd3 Mon Sep 17 00:00:00 2001 From: artivis Date: Fri, 26 May 2023 08:21:53 +0200 Subject: [PATCH 49/84] ros: mark meta extensions experimental Signed-off-by: artivis --- snapcraft/extensions/_ros2_humble_meta.py | 7 ++++++- snapcraft/extensions/ros2_humble_desktop.py | 8 -------- snapcraft/extensions/ros2_humble_ros_base.py | 8 -------- snapcraft/extensions/ros2_humble_ros_core.py | 8 -------- .../project_loader/_extensions/_ros1_noetic_meta.py | 9 ++++++++- .../project_loader/_extensions/_ros2_foxy_meta.py | 9 ++++++++- .../project_loader/extensions/test_ros1_noetic_meta.py | 2 ++ .../project_loader/extensions/test_ros2_foxy_meta.py | 2 ++ tests/unit/parts/extensions/test_ros2_humble_meta.py | 5 +++++ 9 files changed, 31 insertions(+), 27 deletions(-) diff --git a/snapcraft/extensions/_ros2_humble_meta.py b/snapcraft/extensions/_ros2_humble_meta.py index b7be5cf563..452b309c33 100644 --- a/snapcraft/extensions/_ros2_humble_meta.py +++ b/snapcraft/extensions/_ros2_humble_meta.py @@ -19,7 +19,7 @@ """Base for ROS 2 Humble extensions to the Colcon plugin using content-sharing.""" from abc import abstractmethod -from typing import Any, Dict +from typing import Any, Dict, Optional from overrides import overrides @@ -47,6 +47,11 @@ def ROS_VARIANT(self): """Abstract property to define the extension's ROS variant.""" raise NotImplementedError + @staticmethod + @overrides + def is_experimental(base: Optional[str]) -> bool: + return True + @overrides def get_root_snippet(self) -> Dict[str, Any]: root_snippet = super().get_root_snippet() diff --git a/snapcraft/extensions/ros2_humble_desktop.py b/snapcraft/extensions/ros2_humble_desktop.py index 6208ba162f..ac70936130 100644 --- a/snapcraft/extensions/ros2_humble_desktop.py +++ b/snapcraft/extensions/ros2_humble_desktop.py @@ -18,9 +18,6 @@ """Extension to the Colcon plugin for ROS 2 Humble using content sharing.""" -from typing import Optional - -from overrides import overrides from typing_extensions import Final from ._ros2_humble_meta import ROS2HumbleMetaBase @@ -29,11 +26,6 @@ class ROS2HumbleDesktopExtension(ROS2HumbleMetaBase): """Drives ROS 2 build and runtime environment for snap using content-sharing.""" - @staticmethod - @overrides - def is_experimental(base: Optional[str]) -> bool: - return True - ROS_META: Final[str] = "ros-humble-desktop" ROS_META_DEV: Final[str] = "ros-humble-desktop-dev" ROS_VARIANT: Final[str] = "desktop" diff --git a/snapcraft/extensions/ros2_humble_ros_base.py b/snapcraft/extensions/ros2_humble_ros_base.py index 88b5addf6a..26e504db22 100644 --- a/snapcraft/extensions/ros2_humble_ros_base.py +++ b/snapcraft/extensions/ros2_humble_ros_base.py @@ -18,9 +18,6 @@ """Extension to the Colcon plugin for ROS 2 Humble using content sharing.""" -from typing import Optional - -from overrides import overrides from typing_extensions import Final from ._ros2_humble_meta import ROS2HumbleMetaBase @@ -29,11 +26,6 @@ class ROS2HumbleRosBaseExtension(ROS2HumbleMetaBase): """Drives ROS 2 build and runtime environment for snap using content-sharing.""" - @staticmethod - @overrides - def is_experimental(base: Optional[str]) -> bool: - return True - ROS_META: Final[str] = "ros-humble-ros-base" ROS_META_DEV: Final[str] = "ros-humble-ros-base-dev" ROS_VARIANT: Final[str] = "ros-base" diff --git a/snapcraft/extensions/ros2_humble_ros_core.py b/snapcraft/extensions/ros2_humble_ros_core.py index 6b8dadcec8..62a2d4db26 100644 --- a/snapcraft/extensions/ros2_humble_ros_core.py +++ b/snapcraft/extensions/ros2_humble_ros_core.py @@ -18,9 +18,6 @@ """Extension to the Colcon plugin for ROS 2 Humble using content sharing.""" -from typing import Optional - -from overrides import overrides from typing_extensions import Final from ._ros2_humble_meta import ROS2HumbleMetaBase @@ -29,11 +26,6 @@ class ROS2HumbleRosCoreExtension(ROS2HumbleMetaBase): """Drives ROS 2 build and runtime environment for snap using content-sharing.""" - @staticmethod - @overrides - def is_experimental(base: Optional[str]) -> bool: - return True - ROS_META: Final[str] = "ros-humble-ros-core" ROS_META_DEV: Final[str] = "ros-humble-ros-core-dev" ROS_VARIANT: Final[str] = "ros-core" diff --git a/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py b/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py index de00d88a8d..2a9f7c8c57 100644 --- a/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py +++ b/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py @@ -16,7 +16,9 @@ # Import types and tell flake8 to ignore the "unused" List. -from typing import Any, Dict +from typing import Any, Dict, Optional + +from overrides import overrides from .ros1_noetic import ExtensionImpl as RosNoeticExtension @@ -24,6 +26,11 @@ class RosNoeticMetaBase(RosNoeticExtension): """Setup a ROS 1 build and runtime environment suitable for a snap.""" + @staticmethod + @overrides + def is_experimental(base: Optional[str]) -> bool: + return True + def __init__(self, *, extension_name: str, yaml_data: Dict[str, Any]) -> None: super().__init__(extension_name=extension_name, yaml_data=yaml_data) diff --git a/snapcraft_legacy/internal/project_loader/_extensions/_ros2_foxy_meta.py b/snapcraft_legacy/internal/project_loader/_extensions/_ros2_foxy_meta.py index 2ea8dc869d..0af915b45e 100644 --- a/snapcraft_legacy/internal/project_loader/_extensions/_ros2_foxy_meta.py +++ b/snapcraft_legacy/internal/project_loader/_extensions/_ros2_foxy_meta.py @@ -16,7 +16,9 @@ # Import types and tell flake8 to ignore the "unused" List. -from typing import Any, Dict +from typing import Any, Dict, Optional + +from overrides import overrides from .ros2_foxy import ExtensionImpl as RosFoxyExtension @@ -24,6 +26,11 @@ class RosFoxyMetaBase(RosFoxyExtension): """Setup a ROS 2 build and runtime environment suitable for a snap.""" + @staticmethod + @overrides + def is_experimental(base: Optional[str]) -> bool: + return True + def __init__(self, *, extension_name: str, yaml_data: Dict[str, Any]) -> None: super().__init__(extension_name=extension_name, yaml_data=yaml_data) diff --git a/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py b/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py index 9b79963a59..b63aa8972e 100644 --- a/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py +++ b/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py @@ -77,6 +77,8 @@ def test_extension(self, extension_name, extension_class, meta, meta_dev): extension_name=extension_name, yaml_data=dict(base="core20") ) + assert ros1_extension.is_experimental(None) + assert ros1_extension.root_snippet == { "package-repositories": [ { diff --git a/tests/legacy/unit/project_loader/extensions/test_ros2_foxy_meta.py b/tests/legacy/unit/project_loader/extensions/test_ros2_foxy_meta.py index 1aed059a8b..c991f21d16 100644 --- a/tests/legacy/unit/project_loader/extensions/test_ros2_foxy_meta.py +++ b/tests/legacy/unit/project_loader/extensions/test_ros2_foxy_meta.py @@ -57,6 +57,8 @@ def test_extension(self, extension_name, extension_class, meta, meta_dev): extension_name=extension_name, yaml_data=dict(base="core20") ) + assert ros_extension.is_experimental(None) + assert ros_extension.root_snippet == { "package-repositories": [ { diff --git a/tests/unit/parts/extensions/test_ros2_humble_meta.py b/tests/unit/parts/extensions/test_ros2_humble_meta.py index 9d45368800..dc04f37bc6 100644 --- a/tests/unit/parts/extensions/test_ros2_humble_meta.py +++ b/tests/unit/parts/extensions/test_ros2_humble_meta.py @@ -69,6 +69,11 @@ def test_is_registered(self, extension_name, extension_class, meta, meta_dev): except errors.ExtensionError as exc: raise AssertionError(f"Couldn't get extension '{extension_name}': {exc}") + @pytest.mark.parametrize(fixture_variables, fixture_values) + def test_experimental(self, extension_name, extension_class, meta, meta_dev): + extension = setup_method_fixture(extension_class) + assert extension.is_experimental(None) + @pytest.mark.parametrize(fixture_variables, fixture_values) def test_ros_version(self, extension_name, extension_class, meta, meta_dev): extension = setup_method_fixture(extension_class) From 4a7454a49c466582493f73d34716508d7c09a805 Mon Sep 17 00:00:00 2001 From: artivis Date: Fri, 26 May 2023 08:23:56 +0200 Subject: [PATCH 50/84] ros: revamp spread tests Signed-off-by: artivis --- .../extensions/ros-meta-hello/task.yaml | 3 ++ .../ros-meta-talker-listener/task.yaml | 9 +++-- .../extensions/ros2-foxy-meta-hello/task.yaml | 17 ++++++---- .../ros2-humble-meta-hello/task.yaml | 26 +++++++------- .../snaps/colcon-foxy-ros-core/CMakeLists.txt | 34 ------------------- .../snaps/colcon-foxy-ros-core/package.xml | 25 -------------- .../colcon-foxy-ros-core/snap/snapcraft.yaml | 21 ------------ .../snaps/colcon-foxy-ros-core/src/hello.cpp | 28 --------------- .../colcon-humble-ros-core/CMakeLists.txt | 34 ------------------- .../snaps/colcon-humble-ros-core/package.xml | 25 -------------- .../snap/snapcraft.yaml | 21 ------------ .../colcon-humble-ros-core/src/hello.cpp | 28 --------------- 12 files changed, 31 insertions(+), 240 deletions(-) delete mode 100644 tests/spread/extensions/snaps/colcon-foxy-ros-core/CMakeLists.txt delete mode 100644 tests/spread/extensions/snaps/colcon-foxy-ros-core/package.xml delete mode 100644 tests/spread/extensions/snaps/colcon-foxy-ros-core/snap/snapcraft.yaml delete mode 100644 tests/spread/extensions/snaps/colcon-foxy-ros-core/src/hello.cpp delete mode 100644 tests/spread/extensions/snaps/colcon-humble-ros-core/CMakeLists.txt delete mode 100644 tests/spread/extensions/snaps/colcon-humble-ros-core/package.xml delete mode 100644 tests/spread/extensions/snaps/colcon-humble-ros-core/snap/snapcraft.yaml delete mode 100644 tests/spread/extensions/snaps/colcon-humble-ros-core/src/hello.cpp diff --git a/tests/spread/extensions/ros-meta-hello/task.yaml b/tests/spread/extensions/ros-meta-hello/task.yaml index 293f1acf0d..b5730c8393 100644 --- a/tests/spread/extensions/ros-meta-hello/task.yaml +++ b/tests/spread/extensions/ros-meta-hello/task.yaml @@ -3,6 +3,9 @@ summary: Build and run a basic ROS snap using meta-ros extension kill-timeout: 180m environment: + + SNAPCRAFT_ENABLE_EXPERIMENTAL_EXTENSIONS: "1" + SNAP: catkin-noetic-hello SNAP_DIR: "../../plugins/v2/snaps/$SNAP" diff --git a/tests/spread/extensions/ros-meta-talker-listener/task.yaml b/tests/spread/extensions/ros-meta-talker-listener/task.yaml index 4b9bb01a2b..1d7691bb98 100644 --- a/tests/spread/extensions/ros-meta-talker-listener/task.yaml +++ b/tests/spread/extensions/ros-meta-talker-listener/task.yaml @@ -3,9 +3,10 @@ summary: Build and run a basic ROS snap using meta-ros extension kill-timeout: 180m environment: - SNAP: catkin-ros1-run - # SNAP/catkin_ros1_run: catkin-ros1-run - # SNAP/catkin_roslaunch_wrapper: catkin-roslaunch-wrapper + + SNAPCRAFT_ENABLE_EXPERIMENTAL_EXTENSIONS: "1" + + SNAP: catkin-roslaunch-wrapper SNAP_DIR: "../../plugins/v2/snaps/$SNAP" @@ -40,8 +41,6 @@ prepare: | # Overwrite the extension to test them all out of a single snap sed -i "s|ros1-noetic|${EXTENSION}|" "$SNAP_DIR/snap/snapcraft.yaml" - sed -i "s|opt/ros/noetic/bin/||" "$SNAP_DIR/snap/snapcraft.yaml" - restore: | cd "$SNAP_DIR" snapcraft clean diff --git a/tests/spread/extensions/ros2-foxy-meta-hello/task.yaml b/tests/spread/extensions/ros2-foxy-meta-hello/task.yaml index 4d2bfcd7a7..65ca7f95b4 100644 --- a/tests/spread/extensions/ros2-foxy-meta-hello/task.yaml +++ b/tests/spread/extensions/ros2-foxy-meta-hello/task.yaml @@ -3,6 +3,13 @@ summary: Build and run a basic ROS 2 snap using meta-ros extension kill-timeout: 180m environment: + SNAPCRAFT_ENABLE_EXPERIMENTAL_EXTENSIONS: "1" + + SNAP: colcon-ros2-wrapper + SNAP_DIR: "../../plugins/v2/snaps/$SNAP" + + INTERFACE: ros-foxy + META_SNAP/colcon_foxy_ros_core: ros-foxy-ros-core EXTENSION/colcon_foxy_ros_core: ros2-foxy-ros-core @@ -12,11 +19,6 @@ environment: META_SNAP/colcon_foxy_desktop: ros-foxy-desktop EXTENSION/colcon_foxy_desktop: ros2-foxy-desktop - SNAP: colcon-foxy-ros-core - SNAP_DIR: "../snaps/$SNAP" - - INTERFACE: ros-foxy - # The content snap required for the test to succeed is only # available on a subset of all the architectures this testbed # can run on. @@ -32,7 +34,10 @@ prepare: | set_base "$SNAP_DIR/snap/snapcraft.yaml" # Overwrite the extension to test them all out of a single snap - sed -i "s|ros2-.*-ros-core|${EXTENSION}|" "$SNAP_DIR/snap/snapcraft.yaml" + sed -i "s|ros2-foxy|${EXTENSION}|" "$SNAP_DIR/snap/snapcraft.yaml" + + # The snap stages ros2run which will be available through content-sharing + sed -i "\|stage-packages|d" "$SNAP_DIR/snap/snapcraft.yaml" restore: | cd "$SNAP_DIR" diff --git a/tests/spread/extensions/ros2-humble-meta-hello/task.yaml b/tests/spread/extensions/ros2-humble-meta-hello/task.yaml index 9d1ce521a4..4324021d88 100644 --- a/tests/spread/extensions/ros2-humble-meta-hello/task.yaml +++ b/tests/spread/extensions/ros2-humble-meta-hello/task.yaml @@ -6,22 +6,19 @@ environment: SNAPCRAFT_ENABLE_EXPERIMENTAL_EXTENSIONS: "1" - # META_SNAP/colcon_humble_ros_core: ros-humble-ros-core - # EXTENSION/colcon_humble_ros_core: ros2-humble-ros-core + SNAP: colcon-ros2-wrapper + SNAP_DIR: "../../plugins/craft-parts/build-and-run-hello/$SNAP" - # META_SNAP/colcon_humble_ros_base: ros-humble-ros-base - # EXTENSION/colcon_humble_ros_base: ros2-humble-ros-base - - META_SNAP/colcon_humble_desktop: ros-humble-desktop - EXTENSION/colcon_humble_desktop: ros2-humble-desktop + INTERFACE: ros-humble - META_SNAP/colcon_foxy_desktop: ros-foxy-desktop - EXTENSION/colcon_foxy_desktop: ros2-foxy-desktop + META_SNAP/colcon_humble_ros_core: ros-humble-ros-core + EXTENSION/colcon_humble_ros_core: ros2-humble-ros-core - SNAP: colcon-humble-ros-core - SNAP_DIR: "../snaps/$SNAP" + META_SNAP/colcon_humble_ros_base: ros-humble-ros-base + EXTENSION/colcon_humble_ros_base: ros2-humble-ros-base - INTERFACE: ros-humble + META_SNAP/colcon_humble_desktop: ros-humble-desktop + EXTENSION/colcon_humble_desktop: ros2-humble-desktop # The content snap required for the test to succeed is only # available on a subset of all the architectures this testbed @@ -38,7 +35,10 @@ prepare: | set_base "$SNAP_DIR/snap/snapcraft.yaml" # Overwrite the extension to test them all out of a single snap - sed -i "s|ros2-.*-ros-core|${EXTENSION}|" "$SNAP_DIR/snap/snapcraft.yaml" + sed -i "s|ros2-humble|${EXTENSION}|" "$SNAP_DIR/snap/snapcraft.yaml" + + # The snap stages ros2run which will be available through content-sharing + sed -i "\|stage-packages|d" "$SNAP_DIR/snap/snapcraft.yaml" restore: | cd "$SNAP_DIR" diff --git a/tests/spread/extensions/snaps/colcon-foxy-ros-core/CMakeLists.txt b/tests/spread/extensions/snaps/colcon-foxy-ros-core/CMakeLists.txt deleted file mode 100644 index c014f3f36d..0000000000 --- a/tests/spread/extensions/snaps/colcon-foxy-ros-core/CMakeLists.txt +++ /dev/null @@ -1,34 +0,0 @@ -cmake_minimum_required(VERSION 3.5) -project(colcon_ros2_rlcpp_hello) - -# Default to C++14 -if(NOT CMAKE_CXX_STANDARD) - set(CMAKE_CXX_STANDARD 14) -endif() - -if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") - add_compile_options(-Wall -Wextra -Wpedantic) -endif() - -find_package(ament_cmake REQUIRED) -find_package(rclcpp REQUIRED) -find_package(rclcpp_components REQUIRED) -find_package(std_msgs REQUIRED) - -# This package installs libraries without exporting them. -# Export the library path to ensure that the installed libraries are available. -if(NOT WIN32) - ament_environment_hooks( - "${ament_cmake_package_templates_ENVIRONMENT_HOOK_LIBRARY_PATH}" - ) -endif() - -add_executable(colcon_ros2_rlcpp_hello src/hello.cpp) -target_link_libraries(colcon_ros2_rlcpp_hello) -ament_target_dependencies(colcon_ros2_rlcpp_hello rclcpp class_loader) - -install(TARGETS - colcon_ros2_rlcpp_hello - DESTINATION lib/${PROJECT_NAME}) - -ament_package() diff --git a/tests/spread/extensions/snaps/colcon-foxy-ros-core/package.xml b/tests/spread/extensions/snaps/colcon-foxy-ros-core/package.xml deleted file mode 100644 index 133e482823..0000000000 --- a/tests/spread/extensions/snaps/colcon-foxy-ros-core/package.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - colcon_ros2_rlcpp_hello - 0.0.1 - snapcraft test for rlcpp - me - Apache License 2.0 - - ament_cmake - - rclcpp - rclcpp_components - std_msgs - fake_package_that_does_not_exists - - rclcpp - rclcpp_components - ros2run - std_msgs - - - ament_cmake - - diff --git a/tests/spread/extensions/snaps/colcon-foxy-ros-core/snap/snapcraft.yaml b/tests/spread/extensions/snaps/colcon-foxy-ros-core/snap/snapcraft.yaml deleted file mode 100644 index 80e185c970..0000000000 --- a/tests/spread/extensions/snaps/colcon-foxy-ros-core/snap/snapcraft.yaml +++ /dev/null @@ -1,21 +0,0 @@ -name: colcon-foxy-ros-core -version: "1.0" -summary: hello world -description: | - A ROS2 rlcpp-based workspace. - -grade: stable -confinement: strict -base: core20 - -apps: - colcon-foxy-ros-core: - command: ros2 run colcon_ros2_rlcpp_hello colcon_ros2_rlcpp_hello - plugs: [network, network-bind] - extensions: [ros2-foxy-ros-core] - -parts: - hello: - plugin: colcon - source: . - build-packages: [g++, make] diff --git a/tests/spread/extensions/snaps/colcon-foxy-ros-core/src/hello.cpp b/tests/spread/extensions/snaps/colcon-foxy-ros-core/src/hello.cpp deleted file mode 100644 index 770203acec..0000000000 --- a/tests/spread/extensions/snaps/colcon-foxy-ros-core/src/hello.cpp +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2016 Open Source Robotics Foundation, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include -#include "rclcpp/rclcpp.hpp" - -int main(int argc, char * argv[]) -{ - rclcpp::init(argc, argv); - rclcpp::executors::SingleThreadedExecutor exec; - rclcpp::NodeOptions options; - - printf("hello world"); - - rclcpp::shutdown(); - return 0; -} diff --git a/tests/spread/extensions/snaps/colcon-humble-ros-core/CMakeLists.txt b/tests/spread/extensions/snaps/colcon-humble-ros-core/CMakeLists.txt deleted file mode 100644 index c014f3f36d..0000000000 --- a/tests/spread/extensions/snaps/colcon-humble-ros-core/CMakeLists.txt +++ /dev/null @@ -1,34 +0,0 @@ -cmake_minimum_required(VERSION 3.5) -project(colcon_ros2_rlcpp_hello) - -# Default to C++14 -if(NOT CMAKE_CXX_STANDARD) - set(CMAKE_CXX_STANDARD 14) -endif() - -if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") - add_compile_options(-Wall -Wextra -Wpedantic) -endif() - -find_package(ament_cmake REQUIRED) -find_package(rclcpp REQUIRED) -find_package(rclcpp_components REQUIRED) -find_package(std_msgs REQUIRED) - -# This package installs libraries without exporting them. -# Export the library path to ensure that the installed libraries are available. -if(NOT WIN32) - ament_environment_hooks( - "${ament_cmake_package_templates_ENVIRONMENT_HOOK_LIBRARY_PATH}" - ) -endif() - -add_executable(colcon_ros2_rlcpp_hello src/hello.cpp) -target_link_libraries(colcon_ros2_rlcpp_hello) -ament_target_dependencies(colcon_ros2_rlcpp_hello rclcpp class_loader) - -install(TARGETS - colcon_ros2_rlcpp_hello - DESTINATION lib/${PROJECT_NAME}) - -ament_package() diff --git a/tests/spread/extensions/snaps/colcon-humble-ros-core/package.xml b/tests/spread/extensions/snaps/colcon-humble-ros-core/package.xml deleted file mode 100644 index 133e482823..0000000000 --- a/tests/spread/extensions/snaps/colcon-humble-ros-core/package.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - colcon_ros2_rlcpp_hello - 0.0.1 - snapcraft test for rlcpp - me - Apache License 2.0 - - ament_cmake - - rclcpp - rclcpp_components - std_msgs - fake_package_that_does_not_exists - - rclcpp - rclcpp_components - ros2run - std_msgs - - - ament_cmake - - diff --git a/tests/spread/extensions/snaps/colcon-humble-ros-core/snap/snapcraft.yaml b/tests/spread/extensions/snaps/colcon-humble-ros-core/snap/snapcraft.yaml deleted file mode 100644 index 036e9355fd..0000000000 --- a/tests/spread/extensions/snaps/colcon-humble-ros-core/snap/snapcraft.yaml +++ /dev/null @@ -1,21 +0,0 @@ -name: colcon-humble-ros-core -version: "1.0" -summary: hello world -description: | - A ROS 2 rlcpp-based workspace. - -grade: stable -confinement: strict -base: core22 - -apps: - colcon-humble-ros-core: - command: ros2 run colcon_ros2_rlcpp_hello colcon_ros2_rlcpp_hello - plugs: [network, network-bind] - extensions: [ros2-humble-ros-core] - -parts: - hello: - plugin: colcon - source: . - build-packages: [g++, make] diff --git a/tests/spread/extensions/snaps/colcon-humble-ros-core/src/hello.cpp b/tests/spread/extensions/snaps/colcon-humble-ros-core/src/hello.cpp deleted file mode 100644 index 770203acec..0000000000 --- a/tests/spread/extensions/snaps/colcon-humble-ros-core/src/hello.cpp +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2016 Open Source Robotics Foundation, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include -#include "rclcpp/rclcpp.hpp" - -int main(int argc, char * argv[]) -{ - rclcpp::init(argc, argv); - rclcpp::executors::SingleThreadedExecutor exec; - rclcpp::NodeOptions options; - - printf("hello world"); - - rclcpp::shutdown(); - return 0; -} From 0e3a3fde18f291865d33b7c7f8e4c99232ad971e Mon Sep 17 00:00:00 2001 From: artivis Date: Fri, 26 May 2023 08:26:38 +0200 Subject: [PATCH 51/84] ros: core22 add build-pkg libpython3.10 Signed-off-by: artivis --- snapcraft/extensions/_ros2_humble_meta.py | 4 ++++ tests/unit/parts/extensions/test_ros2_humble_meta.py | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/snapcraft/extensions/_ros2_humble_meta.py b/snapcraft/extensions/_ros2_humble_meta.py index 452b309c33..797ba58e65 100644 --- a/snapcraft/extensions/_ros2_humble_meta.py +++ b/snapcraft/extensions/_ros2_humble_meta.py @@ -102,6 +102,10 @@ def get_parts_snippet(self) -> Dict[str, Any]: f"ros-{self.ROS_DISTRO}-ament-index-python", ] + parts_snippet[f"ros2-{self.ROS_DISTRO}/ros2-launch"][ + "build-packages" + ].append("libpython3.10-dev") + # The part name must follow the format / parts_snippet[f"ros2-{self.ROS_DISTRO}-{self.ROS_VARIANT}/ros2-launch"] = parts_snippet[f"ros2-{self.ROS_DISTRO}/ros2-launch"] parts_snippet.pop(f"ros2-{self.ROS_DISTRO}/ros2-launch") diff --git a/tests/unit/parts/extensions/test_ros2_humble_meta.py b/tests/unit/parts/extensions/test_ros2_humble_meta.py index dc04f37bc6..b21606dff1 100644 --- a/tests/unit/parts/extensions/test_ros2_humble_meta.py +++ b/tests/unit/parts/extensions/test_ros2_humble_meta.py @@ -145,7 +145,7 @@ def test_get_app_snippet(self, extension_name, extension_class, meta, meta_dev): "$SNAP/opt/ros/humble/lib/python3.10/site-packages", "$SNAP/usr/lib/python3/dist-packages", "${PYTHONPATH}", - "$SNAP/opt/ros/underlay_ws/opt/ros/humble/lib/python3.8/site-packages", + "$SNAP/opt/ros/underlay_ws/opt/ros/humble/lib/python3.10/site-packages", "$SNAP/opt/ros/underlay_ws/usr/lib/python3/dist-packages", ] extension = setup_method_fixture(extension_class) @@ -182,6 +182,7 @@ def test_get_parts_snippet(self, extension_name, extension_class, meta, meta_dev "ros-humble-ros-workspace", "ros-humble-ament-index-cpp", "ros-humble-ament-index-python", + 'libpython3.10-dev', ], "stage-packages": [ "ros-humble-ros-environment", From febd8854d987ec0b05589d041874e6fe6aaf9b70 Mon Sep 17 00:00:00 2001 From: artivis Date: Fri, 26 May 2023 08:35:14 +0200 Subject: [PATCH 52/84] ros: fix paths Signed-off-by: artivis --- snapcraft/extensions/_ros2_humble_meta.py | 13 +++++++++++-- .../project_loader/_extensions/_ros1_noetic_meta.py | 10 +++++++--- .../project_loader/_extensions/_ros2_foxy_meta.py | 8 ++++++-- .../extensions/test_ros1_noetic_meta.py | 4 ++-- .../extensions/test_ros2_foxy_meta.py | 4 ++-- .../unit/parts/extensions/test_ros2_humble_meta.py | 4 ++-- 6 files changed, 30 insertions(+), 13 deletions(-) diff --git a/snapcraft/extensions/_ros2_humble_meta.py b/snapcraft/extensions/_ros2_humble_meta.py index 797ba58e65..a1938d1e05 100644 --- a/snapcraft/extensions/_ros2_humble_meta.py +++ b/snapcraft/extensions/_ros2_humble_meta.py @@ -23,6 +23,7 @@ from overrides import overrides +# from .extension import prepend_to_env from .ros2_humble import ROS2HumbleExtension @@ -75,8 +76,16 @@ def get_app_snippet(self) -> Dict[str, Any]: ] app_snippet["environment"]["PYTHONPATH"] = f'{python_paths}:{":".join(new_python_paths)}' - app_snippet["environment"]["PATH"] = "$PATH:$SNAP/opt/ros/underlay_ws/usr/bin" - app_snippet["environment"]["LD_LIBRARY_PATH"] = "$LD_LIBRARY_PATH:$SNAP/opt/ros/underlay_ws/usr/lib/$SNAPCRAFT_ARCH_TRIPLET" + app_snippet["environment"]["PATH"] = "$SNAP/opt/ros/underlay_ws/usr/bin:$PATH" + app_snippet["environment"]["LD_LIBRARY_PATH"] = "$SNAP/opt/ros/underlay_ws/usr/lib/$SNAPCRAFT_ARCH_TRIPLET:$LD_LIBRARY_PATH" + + # @todo: for some reason ${VAR:+:$VAR} resulsts in empty substitution + # prepend_to_env( + # "PATH", ["$SNAP/opt/ros/underlay_ws/usr/bin"] + # ) + # prepend_to_env( + # "LD_LIBRARY_PATH", ["$SNAP/opt/ros/underlay_ws/usr/lib/$SNAPCRAFT_ARCH_TRIPLET"] + # ) return app_snippet diff --git a/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py b/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py index 2a9f7c8c57..021bd84cad 100644 --- a/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py +++ b/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py @@ -53,10 +53,14 @@ def __init__(self, *, extension_name: str, yaml_data: Dict[str, Any]) -> None: python_paths = self.app_snippet["environment"]["PYTHONPATH"] new_python_paths = [ f"$SNAP/opt/ros/underlay_ws/opt/ros/{self.ROS_DISTRO}/lib/python3.8/site-packages", - f"$SNAP/opt/ros/underlay_ws/usr/lib/python3/dist-packages", + "$SNAP/opt/ros/underlay_ws/usr/lib/python3/dist-packages", ] self.app_snippet["environment"]["PYTHONPATH"] = f'{python_paths}:{":".join(new_python_paths)}' - self.app_snippet["environment"]["PATH"] = "$PATH:$SNAP/opt/ros/underlay_ws/usr/bin" - self.app_snippet["environment"]["LD_LIBRARY_PATH"] = "$LD_LIBRARY_PATH:$SNAP/opt/ros/underlay_ws/usr/lib/$SNAPCRAFT_ARCH_TRIPLET" + self.app_snippet["environment"]["PATH"] = "$SNAP/opt/ros/underlay_ws/usr/bin:$PATH" + self.app_snippet["environment"]["LD_LIBRARY_PATH"] = "$SNAP/opt/ros/underlay_ws/usr/lib/$SNAPCRAFT_ARCH_TRIPLET:$LD_LIBRARY_PATH" + + # @todo: for some reason ${VAR:+:$VAR} resulsts in empty substitution + # self.app_snippet["environment"]["PATH"] = "$SNAP/opt/ros/underlay_ws/usr/bin${PATH:+:$PATH}" + # self.app_snippet["environment"]["LD_LIBRARY_PATH"] = "$SNAP/opt/ros/underlay_ws/usr/lib/$SNAPCRAFT_ARCH_TRIPLET${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" diff --git a/snapcraft_legacy/internal/project_loader/_extensions/_ros2_foxy_meta.py b/snapcraft_legacy/internal/project_loader/_extensions/_ros2_foxy_meta.py index 0af915b45e..f457d20c45 100644 --- a/snapcraft_legacy/internal/project_loader/_extensions/_ros2_foxy_meta.py +++ b/snapcraft_legacy/internal/project_loader/_extensions/_ros2_foxy_meta.py @@ -68,5 +68,9 @@ def __init__(self, *, extension_name: str, yaml_data: Dict[str, Any]) -> None: self.app_snippet["environment"]["PYTHONPATH"] = f'{python_paths}:{":".join(new_python_paths)}' - self.app_snippet["environment"]["PATH"] = "$PATH:$SNAP/opt/ros/underlay_ws/usr/bin" - self.app_snippet["environment"]["LD_LIBRARY_PATH"] = "$LD_LIBRARY_PATH:$SNAP/opt/ros/underlay_ws/usr/lib/$SNAPCRAFT_ARCH_TRIPLET" + self.app_snippet["environment"]["PATH"] = "$SNAP/opt/ros/underlay_ws/usr/bin:$PATH" + self.app_snippet["environment"]["LD_LIBRARY_PATH"] = "$SNAP/opt/ros/underlay_ws/usr/lib/$SNAPCRAFT_ARCH_TRIPLET:$LD_LIBRARY_PATH" + + # @todo: for some reason ${VAR:+:$VAR} resulsts in empty substitution + # self.app_snippet["environment"]["PATH"] = "$SNAP/opt/ros/underlay_ws/usr/bin${PATH:+:$PATH}" + # self.app_snippet["environment"]["LD_LIBRARY_PATH"] = "$SNAP/opt/ros/underlay_ws/usr/lib/$SNAPCRAFT_ARCH_TRIPLET${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" diff --git a/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py b/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py index b63aa8972e..44c8927662 100644 --- a/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py +++ b/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py @@ -112,8 +112,8 @@ def test_extension(self, extension_name, extension_class, meta, meta_dev): assert ros1_extension.app_snippet == { "command-chain": ["snap/command-chain/ros1-launch"], "environment": { - "LD_LIBRARY_PATH": "$LD_LIBRARY_PATH:$SNAP/opt/ros/underlay_ws/usr/lib/$SNAPCRAFT_ARCH_TRIPLET", - "PATH": "$PATH:$SNAP/opt/ros/underlay_ws/usr/bin", + "LD_LIBRARY_PATH": "$SNAP/opt/ros/underlay_ws/usr/lib/$SNAPCRAFT_ARCH_TRIPLET:$LD_LIBRARY_PATH", + "PATH": "$SNAP/opt/ros/underlay_ws/usr/bin:$PATH", "PYTHONPATH": ":".join(python_paths), "ROS_VERSION": "1", "ROS_DISTRO": "noetic", diff --git a/tests/legacy/unit/project_loader/extensions/test_ros2_foxy_meta.py b/tests/legacy/unit/project_loader/extensions/test_ros2_foxy_meta.py index c991f21d16..f13636c189 100644 --- a/tests/legacy/unit/project_loader/extensions/test_ros2_foxy_meta.py +++ b/tests/legacy/unit/project_loader/extensions/test_ros2_foxy_meta.py @@ -92,8 +92,8 @@ def test_extension(self, extension_name, extension_class, meta, meta_dev): assert ros_extension.app_snippet == { "command-chain": ["snap/command-chain/ros2-launch"], "environment": { - "LD_LIBRARY_PATH": "$LD_LIBRARY_PATH:$SNAP/opt/ros/underlay_ws/usr/lib/$SNAPCRAFT_ARCH_TRIPLET", - "PATH": "$PATH:$SNAP/opt/ros/underlay_ws/usr/bin", + "LD_LIBRARY_PATH": "$SNAP/opt/ros/underlay_ws/usr/lib/$SNAPCRAFT_ARCH_TRIPLET:$LD_LIBRARY_PATH", + "PATH": "$SNAP/opt/ros/underlay_ws/usr/bin:$PATH", "PYTHONPATH": ":".join(python_paths), "ROS_VERSION": "2", "ROS_DISTRO": "foxy", diff --git a/tests/unit/parts/extensions/test_ros2_humble_meta.py b/tests/unit/parts/extensions/test_ros2_humble_meta.py index b21606dff1..5fa94f7027 100644 --- a/tests/unit/parts/extensions/test_ros2_humble_meta.py +++ b/tests/unit/parts/extensions/test_ros2_humble_meta.py @@ -156,8 +156,8 @@ def test_get_app_snippet(self, extension_name, extension_class, meta, meta_dev): "ROS_DISTRO": "humble", "PYTHONPATH": ":".join(python_paths), "ROS_HOME": "$SNAP_USER_DATA/ros", - "LD_LIBRARY_PATH": "$LD_LIBRARY_PATH:$SNAP/opt/ros/underlay_ws/usr/lib/$SNAPCRAFT_ARCH_TRIPLET", - "PATH": "$PATH:$SNAP/opt/ros/underlay_ws/usr/bin", + "LD_LIBRARY_PATH": "$SNAP/opt/ros/underlay_ws/usr/lib/$SNAPCRAFT_ARCH_TRIPLET:$LD_LIBRARY_PATH", + "PATH": "$SNAP/opt/ros/underlay_ws/usr/bin:$PATH", }, } From ce95bb0a3dfadf1e67c912395806fe30506da05e Mon Sep 17 00:00:00 2001 From: artivis Date: Fri, 26 May 2023 10:24:35 +0200 Subject: [PATCH 53/84] ros: mv from var to property Signed-off-by: artivis --- snapcraft/extensions/_ros2_humble_meta.py | 36 +++++++++---------- snapcraft/extensions/ros2_humble_desktop.py | 17 ++++++--- snapcraft/extensions/ros2_humble_ros_base.py | 17 ++++++--- snapcraft/extensions/ros2_humble_ros_core.py | 17 ++++++--- .../_extensions/_ros1_noetic_meta.py | 21 +++++++++-- .../_extensions/_ros2_foxy_meta.py | 21 +++++++++-- .../_extensions/ros1_noetic_desktop.py | 14 +++++--- .../_extensions/ros1_noetic_perception.py | 14 +++++--- .../_extensions/ros1_noetic_robot.py | 14 +++++--- .../_extensions/ros1_noetic_ros_base.py | 14 +++++--- .../_extensions/ros1_noetic_ros_core.py | 14 +++++--- .../_extensions/ros2_foxy_desktop.py | 14 +++++--- .../_extensions/ros2_foxy_ros_base.py | 14 +++++--- .../_extensions/ros2_foxy_ros_core.py | 14 +++++--- 14 files changed, 170 insertions(+), 71 deletions(-) diff --git a/snapcraft/extensions/_ros2_humble_meta.py b/snapcraft/extensions/_ros2_humble_meta.py index a1938d1e05..34857808a1 100644 --- a/snapcraft/extensions/_ros2_humble_meta.py +++ b/snapcraft/extensions/_ros2_humble_meta.py @@ -18,6 +18,7 @@ """Base for ROS 2 Humble extensions to the Colcon plugin using content-sharing.""" +import dataclasses from abc import abstractmethod from typing import Any, Dict, Optional @@ -27,25 +28,21 @@ from .ros2_humble import ROS2HumbleExtension -class ROS2HumbleMetaBase(ROS2HumbleExtension): - """Drives ROS 2 build and runtime environment for snap using content-sharing.""" +@dataclasses.dataclass +class ROS2HumbleSnaps: + """A structure of ROS 2 Humble related snaps.""" - @property - @abstractmethod - def ROS_META(self): - """Abstract property to define the extension's content-sharing snap.""" - raise NotImplementedError + sdk: str + content: str + variant: str - @property - @abstractmethod - def ROS_META_DEV(self): - """Abstract property to define the extension's build snap.""" - raise NotImplementedError + +class ROS2HumbleMetaBase(ROS2HumbleExtension): + """Drives ROS 2 build and runtime environment for snap using content-sharing.""" @property @abstractmethod - def ROS_VARIANT(self): - """Abstract property to define the extension's ROS variant.""" + def ros2_humble_snaps(self) -> ROS2HumbleSnaps: raise NotImplementedError @staticmethod @@ -61,7 +58,7 @@ def get_root_snippet(self) -> Dict[str, Any]: "interface": "content", "content": "ros-humble", "target": "$SNAP/opt/ros/underlay_ws", - "default-provider": self.ROS_META, + "default-provider": self.ros2_humble_snaps.content, } } return root_snippet @@ -92,10 +89,11 @@ def get_app_snippet(self) -> Dict[str, Any]: @overrides def get_part_snippet(self) -> Dict[str, Any]: part_snippet = super().get_part_snippet() - part_snippet["build-snaps"] = [self.ROS_META_DEV] + part_snippet["build-snaps"] = [self.ros2_humble_snaps.sdk] part_snippet["colcon-cmake-args"] = [ - f'-DCMAKE_SYSTEM_PREFIX_PATH="/snap/{self.ROS_META_DEV}/current/usr"' + f'-DCMAKE_SYSTEM_PREFIX_PATH="/snap/{self.ros2_humble_snaps.sdk}/current/usr"' ] + return part_snippet @overrides @@ -116,7 +114,9 @@ def get_parts_snippet(self) -> Dict[str, Any]: ].append("libpython3.10-dev") # The part name must follow the format / - parts_snippet[f"ros2-{self.ROS_DISTRO}-{self.ROS_VARIANT}/ros2-launch"] = parts_snippet[f"ros2-{self.ROS_DISTRO}/ros2-launch"] + parts_snippet[ + f"ros2-{self.ROS_DISTRO}-{self.ros2_humble_snaps.variant}/ros2-launch" + ] = parts_snippet[f"ros2-{self.ROS_DISTRO}/ros2-launch"] parts_snippet.pop(f"ros2-{self.ROS_DISTRO}/ros2-launch") return parts_snippet diff --git a/snapcraft/extensions/ros2_humble_desktop.py b/snapcraft/extensions/ros2_humble_desktop.py index ac70936130..376bbb02f1 100644 --- a/snapcraft/extensions/ros2_humble_desktop.py +++ b/snapcraft/extensions/ros2_humble_desktop.py @@ -18,14 +18,21 @@ """Extension to the Colcon plugin for ROS 2 Humble using content sharing.""" -from typing_extensions import Final +import functools -from ._ros2_humble_meta import ROS2HumbleMetaBase +from overrides import overrides + +from ._ros2_humble_meta import ROS2HumbleMetaBase, ROS2HumbleSnaps class ROS2HumbleDesktopExtension(ROS2HumbleMetaBase): """Drives ROS 2 build and runtime environment for snap using content-sharing.""" - ROS_META: Final[str] = "ros-humble-desktop" - ROS_META_DEV: Final[str] = "ros-humble-desktop-dev" - ROS_VARIANT: Final[str] = "desktop" + @functools.cached_property + @overrides + def ros2_humble_snaps(self) -> ROS2HumbleSnaps: + return ROS2HumbleSnaps( + sdk="ros-humble-desktop-dev", + content="ros-humble-desktop", + variant="desktop", + ) diff --git a/snapcraft/extensions/ros2_humble_ros_base.py b/snapcraft/extensions/ros2_humble_ros_base.py index 26e504db22..a1f7efc707 100644 --- a/snapcraft/extensions/ros2_humble_ros_base.py +++ b/snapcraft/extensions/ros2_humble_ros_base.py @@ -18,14 +18,21 @@ """Extension to the Colcon plugin for ROS 2 Humble using content sharing.""" -from typing_extensions import Final +import functools -from ._ros2_humble_meta import ROS2HumbleMetaBase +from overrides import overrides + +from ._ros2_humble_meta import ROS2HumbleMetaBase, ROS2HumbleSnaps class ROS2HumbleRosBaseExtension(ROS2HumbleMetaBase): """Drives ROS 2 build and runtime environment for snap using content-sharing.""" - ROS_META: Final[str] = "ros-humble-ros-base" - ROS_META_DEV: Final[str] = "ros-humble-ros-base-dev" - ROS_VARIANT: Final[str] = "ros-base" + @functools.cached_property + @overrides + def ros2_humble_snaps(self) -> ROS2HumbleSnaps: + return ROS2HumbleSnaps( + sdk="ros-humble-ros-base-dev", + content="ros-humble-ros-base", + variant="ros-base", + ) diff --git a/snapcraft/extensions/ros2_humble_ros_core.py b/snapcraft/extensions/ros2_humble_ros_core.py index 62a2d4db26..ca520a2f6e 100644 --- a/snapcraft/extensions/ros2_humble_ros_core.py +++ b/snapcraft/extensions/ros2_humble_ros_core.py @@ -18,14 +18,21 @@ """Extension to the Colcon plugin for ROS 2 Humble using content sharing.""" -from typing_extensions import Final +import functools -from ._ros2_humble_meta import ROS2HumbleMetaBase +from overrides import overrides + +from ._ros2_humble_meta import ROS2HumbleMetaBase, ROS2HumbleSnaps class ROS2HumbleRosCoreExtension(ROS2HumbleMetaBase): """Drives ROS 2 build and runtime environment for snap using content-sharing.""" - ROS_META: Final[str] = "ros-humble-ros-core" - ROS_META_DEV: Final[str] = "ros-humble-ros-core-dev" - ROS_VARIANT: Final[str] = "ros-core" + @functools.cached_property + @overrides + def ros2_humble_snaps(self) -> ROS2HumbleSnaps: + return ROS2HumbleSnaps( + sdk="ros-humble-ros-core-dev", + content="ros-humble-ros-core", + variant="ros-core", + ) diff --git a/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py b/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py index 021bd84cad..f9f7746e57 100644 --- a/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py +++ b/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py @@ -16,6 +16,8 @@ # Import types and tell flake8 to ignore the "unused" List. +import dataclasses +from abc import abstractmethod from typing import Any, Dict, Optional from overrides import overrides @@ -23,9 +25,22 @@ from .ros1_noetic import ExtensionImpl as RosNoeticExtension +@dataclasses.dataclass +class ROS2NoeticSnaps: + """A structure of ROS 2 Noetic related snaps.""" + + sdk: str + content: str + + class RosNoeticMetaBase(RosNoeticExtension): """Setup a ROS 1 build and runtime environment suitable for a snap.""" + @property + @abstractmethod + def ros_noetic_snaps(self) -> ROS2NoeticSnaps: + raise NotImplementedError + @staticmethod @overrides def is_experimental(base: Optional[str]) -> bool: @@ -40,15 +55,15 @@ def __init__(self, *, extension_name: str, yaml_data: Dict[str, Any]) -> None: "interface": "content", "content": "ros-noetic", "target": "$SNAP/opt/ros/underlay_ws", - "default-provider": self.ROS_META, + "default-provider": self.ros_noetic_snaps.content, } } self.part_snippet["catkin-cmake-args"] = [ - f'-DCMAKE_SYSTEM_PREFIX_PATH="/snap/{self.ROS_META_DEV}/current/usr"' + f'-DCMAKE_SYSTEM_PREFIX_PATH="/snap/{self.ros_noetic_snaps.sdk}/current/usr"' ] - self.part_snippet["build-snaps"] = [self.ROS_META_DEV] + self.part_snippet["build-snaps"] = [self.ros_noetic_snaps.sdk] python_paths = self.app_snippet["environment"]["PYTHONPATH"] new_python_paths = [ diff --git a/snapcraft_legacy/internal/project_loader/_extensions/_ros2_foxy_meta.py b/snapcraft_legacy/internal/project_loader/_extensions/_ros2_foxy_meta.py index f457d20c45..268f2e1c70 100644 --- a/snapcraft_legacy/internal/project_loader/_extensions/_ros2_foxy_meta.py +++ b/snapcraft_legacy/internal/project_loader/_extensions/_ros2_foxy_meta.py @@ -16,6 +16,8 @@ # Import types and tell flake8 to ignore the "unused" List. +import dataclasses +from abc import abstractmethod from typing import Any, Dict, Optional from overrides import overrides @@ -23,9 +25,22 @@ from .ros2_foxy import ExtensionImpl as RosFoxyExtension +@dataclasses.dataclass +class ROS2FoxySnaps: + """A structure of ROS 2 Foxy related snaps.""" + + sdk: str + content: str + + class RosFoxyMetaBase(RosFoxyExtension): """Setup a ROS 2 build and runtime environment suitable for a snap.""" + @property + @abstractmethod + def ros2_foxy_snaps(self) -> ROS2FoxySnaps: + raise NotImplementedError + @staticmethod @overrides def is_experimental(base: Optional[str]) -> bool: @@ -50,15 +65,15 @@ def __init__(self, *, extension_name: str, yaml_data: Dict[str, Any]) -> None: "interface": "content", "content": "ros-foxy", "target": "$SNAP/opt/ros/underlay_ws", - "default-provider": self.ROS_META, + "default-provider": self.ros2_foxy_snaps.content, } } self.part_snippet["colcon-cmake-args"] = [ - f'-DCMAKE_SYSTEM_PREFIX_PATH="/snap/{self.ROS_META_DEV}/current/usr"' + f'-DCMAKE_SYSTEM_PREFIX_PATH="/snap/{self.ros2_foxy_snaps.sdk}/current/usr"' ] - self.part_snippet["build-snaps"] = [self.ROS_META_DEV] + self.part_snippet["build-snaps"] = [self.ros2_foxy_snaps.sdk] python_paths = self.app_snippet["environment"]["PYTHONPATH"] new_python_paths = [ diff --git a/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_desktop.py b/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_desktop.py index ff2b924629..56bdd7b9b9 100644 --- a/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_desktop.py +++ b/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_desktop.py @@ -16,13 +16,19 @@ # Import types and tell flake8 to ignore the "unused" List. -from typing_extensions import Final +import functools -from ._ros1_noetic_meta import RosNoeticMetaBase +from overrides import overrides + +from ._ros1_noetic_meta import ROS2NoeticSnaps, RosNoeticMetaBase class ExtensionImpl(RosNoeticMetaBase): """Setup a ROS 1 build and runtime environment suitable for a snap.""" - ROS_META: Final[str] = "ros-noetic-desktop" - ROS_META_DEV: Final[str] = "ros-noetic-desktop-dev" + @functools.cached_property + @overrides + def ros_noetic_snaps(self) -> ROS2NoeticSnaps: + return ROS2NoeticSnaps( + content="ros-noetic-desktop", sdk="ros-noetic-desktop-dev" + ) diff --git a/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_perception.py b/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_perception.py index 57681585fd..3b389d3ff4 100644 --- a/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_perception.py +++ b/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_perception.py @@ -16,13 +16,19 @@ # Import types and tell flake8 to ignore the "unused" List. -from typing_extensions import Final +import functools -from ._ros1_noetic_meta import RosNoeticMetaBase +from overrides import overrides + +from ._ros1_noetic_meta import ROS2NoeticSnaps, RosNoeticMetaBase class ExtensionImpl(RosNoeticMetaBase): """Setup a ROS 1 build and runtime environment suitable for a snap.""" - ROS_META: Final[str] = "ros-noetic-perception" - ROS_META_DEV: Final[str] = "ros-noetic-perception" + @functools.cached_property + @overrides + def ros_noetic_snaps(self) -> ROS2NoeticSnaps: + return ROS2NoeticSnaps( + content="ros-noetic-perception", sdk="ros-noetic-perception-dev" + ) diff --git a/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_robot.py b/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_robot.py index 16aabb7d19..5d4c763ea8 100644 --- a/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_robot.py +++ b/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_robot.py @@ -16,13 +16,19 @@ # Import types and tell flake8 to ignore the "unused" List. -from typing_extensions import Final +import functools -from ._ros1_noetic_meta import RosNoeticMetaBase +from overrides import overrides + +from ._ros1_noetic_meta import ROS2NoeticSnaps, RosNoeticMetaBase class ExtensionImpl(RosNoeticMetaBase): """Setup a ROS 1 build and runtime environment suitable for a snap.""" - ROS_META: Final[str] = "ros-noetic-robot" - ROS_META_DEV: Final[str] = "ros-noetic-robot-dev" + @functools.cached_property + @overrides + def ros_noetic_snaps(self) -> ROS2NoeticSnaps: + return ROS2NoeticSnaps( + content="ros-noetic-robot", sdk="ros-noetic-robot-dev" + ) diff --git a/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_ros_base.py b/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_ros_base.py index edc821146b..933cabd5c5 100644 --- a/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_ros_base.py +++ b/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_ros_base.py @@ -16,13 +16,19 @@ # Import types and tell flake8 to ignore the "unused" List. -from typing_extensions import Final +import functools -from ._ros1_noetic_meta import RosNoeticMetaBase +from overrides import overrides + +from ._ros1_noetic_meta import ROS2NoeticSnaps, RosNoeticMetaBase class ExtensionImpl(RosNoeticMetaBase): """Setup a ROS 1 build and runtime environment suitable for a snap.""" - ROS_META: Final[str] = "ros-noetic-ros-base" - ROS_META_DEV: Final[str] = "ros-noetic-ros-base-dev" + @functools.cached_property + @overrides + def ros_noetic_snaps(self) -> ROS2NoeticSnaps: + return ROS2NoeticSnaps( + content="ros-noetic-ros-base", sdk="ros-noetic-ros-base-dev" + ) diff --git a/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_ros_core.py b/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_ros_core.py index a0849fb0a9..316c35a72f 100644 --- a/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_ros_core.py +++ b/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic_ros_core.py @@ -16,13 +16,19 @@ # Import types and tell flake8 to ignore the "unused" List. -from typing_extensions import Final +import functools -from ._ros1_noetic_meta import RosNoeticMetaBase +from overrides import overrides + +from ._ros1_noetic_meta import ROS2NoeticSnaps, RosNoeticMetaBase class ExtensionImpl(RosNoeticMetaBase): """Setup a ROS 1 build and runtime environment suitable for a snap.""" - ROS_META: Final[str] = "ros-noetic-ros-core" - ROS_META_DEV: Final[str] = "ros-noetic-ros-core-dev" + @functools.cached_property + @overrides + def ros_noetic_snaps(self) -> ROS2NoeticSnaps: + return ROS2NoeticSnaps( + content="ros-noetic-ros-core", sdk="ros-noetic-ros-core-dev" + ) diff --git a/snapcraft_legacy/internal/project_loader/_extensions/ros2_foxy_desktop.py b/snapcraft_legacy/internal/project_loader/_extensions/ros2_foxy_desktop.py index 63cba51047..5c1f6327a7 100644 --- a/snapcraft_legacy/internal/project_loader/_extensions/ros2_foxy_desktop.py +++ b/snapcraft_legacy/internal/project_loader/_extensions/ros2_foxy_desktop.py @@ -16,13 +16,19 @@ # Import types and tell flake8 to ignore the "unused" List. -from typing_extensions import Final +import functools -from ._ros2_foxy_meta import RosFoxyMetaBase +from overrides import overrides + +from ._ros2_foxy_meta import ROS2FoxySnaps, RosFoxyMetaBase class ExtensionImpl(RosFoxyMetaBase): """Setup a ROS 2 build and runtime environment suitable for a snap.""" - ROS_META: Final[str] = "ros-foxy-desktop" - ROS_META_DEV: Final[str] = "ros-foxy-desktop-dev" + @functools.cached_property + @overrides + def ros2_foxy_snaps(self) -> ROS2FoxySnaps: + return ROS2FoxySnaps( + content="ros-foxy-desktop", sdk="ros-foxy-desktop-dev" + ) diff --git a/snapcraft_legacy/internal/project_loader/_extensions/ros2_foxy_ros_base.py b/snapcraft_legacy/internal/project_loader/_extensions/ros2_foxy_ros_base.py index 5b91cdcdc3..806a7c81ce 100644 --- a/snapcraft_legacy/internal/project_loader/_extensions/ros2_foxy_ros_base.py +++ b/snapcraft_legacy/internal/project_loader/_extensions/ros2_foxy_ros_base.py @@ -16,13 +16,19 @@ # Import types and tell flake8 to ignore the "unused" List. -from typing_extensions import Final +import functools -from ._ros2_foxy_meta import RosFoxyMetaBase +from overrides import overrides + +from ._ros2_foxy_meta import ROS2FoxySnaps, RosFoxyMetaBase class ExtensionImpl(RosFoxyMetaBase): """Setup a ROS 2 build and runtime environment suitable for a snap.""" - ROS_META: Final[str] = "ros-foxy-ros-base" - ROS_META_DEV: Final[str] = "ros-foxy-ros-base-dev" + @functools.cached_property + @overrides + def ros2_foxy_snaps(self) -> ROS2FoxySnaps: + return ROS2FoxySnaps( + content="ros-foxy-ros-base", sdk="ros-foxy-ros-base-dev" + ) diff --git a/snapcraft_legacy/internal/project_loader/_extensions/ros2_foxy_ros_core.py b/snapcraft_legacy/internal/project_loader/_extensions/ros2_foxy_ros_core.py index cfa95a7478..b6671149c0 100644 --- a/snapcraft_legacy/internal/project_loader/_extensions/ros2_foxy_ros_core.py +++ b/snapcraft_legacy/internal/project_loader/_extensions/ros2_foxy_ros_core.py @@ -16,13 +16,19 @@ # Import types and tell flake8 to ignore the "unused" List. -from typing_extensions import Final +import functools -from ._ros2_foxy_meta import RosFoxyMetaBase +from overrides import overrides + +from ._ros2_foxy_meta import ROS2FoxySnaps, RosFoxyMetaBase class ExtensionImpl(RosFoxyMetaBase): """Setup a ROS 2 build and runtime environment suitable for a snap.""" - ROS_META: Final[str] = "ros-foxy-ros-core" - ROS_META_DEV: Final[str] = "ros-foxy-ros-core-dev" + @functools.cached_property + @overrides + def ros2_foxy_snaps(self) -> ROS2FoxySnaps: + return ROS2FoxySnaps( + content="ros-foxy-ros-core", sdk="ros-foxy-ros-core-dev" + ) From 920648de4bd2a00f13dade280ffda7a152f89409 Mon Sep 17 00:00:00 2001 From: artivis Date: Fri, 26 May 2023 10:25:16 +0200 Subject: [PATCH 54/84] ros: please linting Signed-off-by: artivis --- snapcraft/extensions/_ros2_humble_meta.py | 18 +++++++++++------- snapcraft/parts/plugins/_ros.py | 2 +- snapcraft/parts/plugins/colcon_plugin.py | 19 ++++++++----------- .../_extensions/_ros2_foxy_meta.py | 2 +- .../extensions/test_ros1_noetic_meta.py | 4 +++- .../extensions/test_ros2_foxy_meta.py | 4 +++- .../parts/extensions/test_ros2_humble_meta.py | 6 ++++-- 7 files changed, 31 insertions(+), 24 deletions(-) diff --git a/snapcraft/extensions/_ros2_humble_meta.py b/snapcraft/extensions/_ros2_humble_meta.py index 34857808a1..5d813f77e2 100644 --- a/snapcraft/extensions/_ros2_humble_meta.py +++ b/snapcraft/extensions/_ros2_humble_meta.py @@ -68,13 +68,17 @@ def get_app_snippet(self) -> Dict[str, Any]: app_snippet = super().get_app_snippet() python_paths = app_snippet["environment"]["PYTHONPATH"] new_python_paths = [ - f"$SNAP/opt/ros/underlay_ws/opt/ros/{self.ROS_DISTRO}/lib/python3.8/site-packages", - f"$SNAP/opt/ros/underlay_ws/usr/lib/python3/dist-packages", + f"$SNAP/opt/ros/underlay_ws/opt/ros/{self.ROS_DISTRO}/lib/python3.10/site-packages", + "$SNAP/opt/ros/underlay_ws/usr/lib/python3/dist-packages", ] - app_snippet["environment"]["PYTHONPATH"] = f'{python_paths}:{":".join(new_python_paths)}' + app_snippet["environment"][ + "PYTHONPATH" + ] = f'{python_paths}:{":".join(new_python_paths)}' app_snippet["environment"]["PATH"] = "$SNAP/opt/ros/underlay_ws/usr/bin:$PATH" - app_snippet["environment"]["LD_LIBRARY_PATH"] = "$SNAP/opt/ros/underlay_ws/usr/lib/$SNAPCRAFT_ARCH_TRIPLET:$LD_LIBRARY_PATH" + app_snippet["environment"][ + "LD_LIBRARY_PATH" + ] = "$SNAP/opt/ros/underlay_ws/usr/lib/$SNAPCRAFT_ARCH_TRIPLET:$LD_LIBRARY_PATH" # @todo: for some reason ${VAR:+:$VAR} resulsts in empty substitution # prepend_to_env( @@ -109,9 +113,9 @@ def get_parts_snippet(self) -> Dict[str, Any]: f"ros-{self.ROS_DISTRO}-ament-index-python", ] - parts_snippet[f"ros2-{self.ROS_DISTRO}/ros2-launch"][ - "build-packages" - ].append("libpython3.10-dev") + parts_snippet[f"ros2-{self.ROS_DISTRO}/ros2-launch"]["build-packages"].append( + "libpython3.10-dev" + ) # The part name must follow the format / parts_snippet[ diff --git a/snapcraft/parts/plugins/_ros.py b/snapcraft/parts/plugins/_ros.py index f2392717c2..dabc877d28 100644 --- a/snapcraft/parts/plugins/_ros.py +++ b/snapcraft/parts/plugins/_ros.py @@ -387,7 +387,7 @@ def stage_runtime_dependencies( arch=target_arch, base=base, stage_packages_path=stage_packages_path, - packages_filters=build_snap_packages, + packages_filters=build_snap_packages, # type: ignore ) click.echo(f"Unpacking stage packages: {fetched_stage_packages!r}") diff --git a/snapcraft/parts/plugins/colcon_plugin.py b/snapcraft/parts/plugins/colcon_plugin.py index cfa0fad1b3..c4823e4bc1 100644 --- a/snapcraft/parts/plugins/colcon_plugin.py +++ b/snapcraft/parts/plugins/colcon_plugin.py @@ -209,14 +209,11 @@ def _get_build_commands(self) -> List[str]: # Specify the number of workers build_command.extend(["--parallel-workers", '"${CRAFT_PARALLEL_BUILD_COUNT}"']) - return ( - ["## Build command", " ".join(build_command)] - + [ - "## Post build command", - # Remove the COLCON_IGNORE marker so that, at staging, - # catkin can crawl the entire folder to look up for packages. - 'if [ -f "${CRAFT_PART_INSTALL}"/opt/ros/snap/COLCON_IGNORE ]; then', - 'rm "${CRAFT_PART_INSTALL}"/opt/ros/snap/COLCON_IGNORE', - "fi", - ] - ) + return ["## Build command", " ".join(build_command)] + [ + "## Post build command", + # Remove the COLCON_IGNORE marker so that, at staging, + # catkin can crawl the entire folder to look up for packages. + 'if [ -f "${CRAFT_PART_INSTALL}"/opt/ros/snap/COLCON_IGNORE ]; then', + 'rm "${CRAFT_PART_INSTALL}"/opt/ros/snap/COLCON_IGNORE', + "fi", + ] diff --git a/snapcraft_legacy/internal/project_loader/_extensions/_ros2_foxy_meta.py b/snapcraft_legacy/internal/project_loader/_extensions/_ros2_foxy_meta.py index 268f2e1c70..4206a133cc 100644 --- a/snapcraft_legacy/internal/project_loader/_extensions/_ros2_foxy_meta.py +++ b/snapcraft_legacy/internal/project_loader/_extensions/_ros2_foxy_meta.py @@ -78,7 +78,7 @@ def __init__(self, *, extension_name: str, yaml_data: Dict[str, Any]) -> None: python_paths = self.app_snippet["environment"]["PYTHONPATH"] new_python_paths = [ f"$SNAP/opt/ros/underlay_ws/opt/ros/{self.ROS_DISTRO}/lib/python3.8/site-packages", - f"$SNAP/opt/ros/underlay_ws/usr/lib/python3/dist-packages", + "$SNAP/opt/ros/underlay_ws/usr/lib/python3/dist-packages", ] self.app_snippet["environment"]["PYTHONPATH"] = f'{python_paths}:{":".join(new_python_paths)}' diff --git a/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py b/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py index 44c8927662..33eb18ab2c 100644 --- a/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py +++ b/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py @@ -123,7 +123,9 @@ def test_extension(self, extension_name, extension_class, meta, meta_dev): assert ros1_extension.part_snippet == { "build-environment": [{"ROS_VERSION": "1"}, {"ROS_DISTRO": "noetic"}], "build-snaps": [meta_dev], - "catkin-cmake-args": [f'-DCMAKE_SYSTEM_PREFIX_PATH="/snap/{meta_dev}/current/usr"'], + "catkin-cmake-args": [ + f'-DCMAKE_SYSTEM_PREFIX_PATH="/snap/{meta_dev}/current/usr"' + ], "stage-packages": ["ros-noetic-ros-environment"], } diff --git a/tests/legacy/unit/project_loader/extensions/test_ros2_foxy_meta.py b/tests/legacy/unit/project_loader/extensions/test_ros2_foxy_meta.py index f13636c189..ea465e22e4 100644 --- a/tests/legacy/unit/project_loader/extensions/test_ros2_foxy_meta.py +++ b/tests/legacy/unit/project_loader/extensions/test_ros2_foxy_meta.py @@ -103,7 +103,9 @@ def test_extension(self, extension_name, extension_class, meta, meta_dev): assert ros_extension.part_snippet == { "build-environment": [{"ROS_VERSION": "2"}, {"ROS_DISTRO": "foxy"}], "build-snaps": [meta_dev], - "colcon-cmake-args": [f'-DCMAKE_SYSTEM_PREFIX_PATH="/snap/{meta_dev}/current/usr"'], + "colcon-cmake-args": [ + f'-DCMAKE_SYSTEM_PREFIX_PATH="/snap/{meta_dev}/current/usr"' + ], } assert ros_extension.parts == { diff --git a/tests/unit/parts/extensions/test_ros2_humble_meta.py b/tests/unit/parts/extensions/test_ros2_humble_meta.py index 5fa94f7027..76e31c86f3 100644 --- a/tests/unit/parts/extensions/test_ros2_humble_meta.py +++ b/tests/unit/parts/extensions/test_ros2_humble_meta.py @@ -167,7 +167,9 @@ def test_get_part_snippet(self, extension_name, extension_class, meta, meta_dev) assert extension.get_part_snippet() == { "build-environment": [{"ROS_VERSION": "2"}, {"ROS_DISTRO": "humble"}], "build-snaps": [meta_dev], - "colcon-cmake-args": [f'-DCMAKE_SYSTEM_PREFIX_PATH="/snap/{meta_dev}/current/usr"'] + "colcon-cmake-args": [ + f'-DCMAKE_SYSTEM_PREFIX_PATH="/snap/{meta_dev}/current/usr"' + ], } @pytest.mark.parametrize(fixture_variables, fixture_values) @@ -182,7 +184,7 @@ def test_get_parts_snippet(self, extension_name, extension_class, meta, meta_dev "ros-humble-ros-workspace", "ros-humble-ament-index-cpp", "ros-humble-ament-index-python", - 'libpython3.10-dev', + "libpython3.10-dev", ], "stage-packages": [ "ros-humble-ros-environment", From f829641c776b065a392ae8dee972f72f4881acfb Mon Sep 17 00:00:00 2001 From: artivis Date: Fri, 26 May 2023 13:03:09 +0200 Subject: [PATCH 55/84] ros: please static-test Signed-off-by: artivis --- snapcraft/extensions/_ros2_humble_meta.py | 1 + snapcraft/parts/plugins/_ros.py | 10 +++++++--- .../project_loader/_extensions/_ros1_noetic_meta.py | 1 + .../project_loader/_extensions/_ros2_foxy_meta.py | 1 + tests/spread/extensions/ros-meta-hello/task.yaml | 4 +--- .../extensions/ros-meta-talker-listener/task.yaml | 2 +- tests/spread/extensions/ros2-foxy-meta-hello/task.yaml | 4 +--- .../spread/extensions/ros2-humble-meta-hello/task.yaml | 4 +--- tests/unit/parts/plugins/test_colcon.py | 2 ++ 9 files changed, 16 insertions(+), 13 deletions(-) diff --git a/snapcraft/extensions/_ros2_humble_meta.py b/snapcraft/extensions/_ros2_humble_meta.py index 5d813f77e2..373ccc0e4c 100644 --- a/snapcraft/extensions/_ros2_humble_meta.py +++ b/snapcraft/extensions/_ros2_humble_meta.py @@ -43,6 +43,7 @@ class ROS2HumbleMetaBase(ROS2HumbleExtension): @property @abstractmethod def ros2_humble_snaps(self) -> ROS2HumbleSnaps: + """Return the ROS 2 Humble related snaps to use to construct the environment.""" raise NotImplementedError @staticmethod diff --git a/snapcraft/parts/plugins/_ros.py b/snapcraft/parts/plugins/_ros.py index dabc877d28..6ed6fef463 100644 --- a/snapcraft/parts/plugins/_ros.py +++ b/snapcraft/parts/plugins/_ros.py @@ -136,7 +136,6 @@ def _get_list_packages_commands(self) -> List[str]: The package names are then resolved with `rosdep` to map their names to debs. The list is finally saved in the part's install directory. """ - # pylint: disable=line-too-long cmd = [] # Clean up previously established list of packages in build snaps @@ -147,6 +146,7 @@ def _get_list_packages_commands(self) -> List[str]: for build_snap in self._options.build_snaps: # type: ignore snap_name = _get_parsed_snap(build_snap)[0] path = f"/snap/{snap_name}/current/opt/ros" + # pylint: disable=line-too-long cmd.extend( [ # Retrieve the list of all ROS packages available in the build snap @@ -166,6 +166,7 @@ def _get_list_packages_commands(self) -> List[str]: "fi", ] ) + # pylint: enable=line-too-long cmd.append("") return cmd @@ -241,6 +242,7 @@ def get_build_commands(self) -> List[str]: + [ 'rosdep install --default-yes --ignore-packages-from-source --from-paths "${CRAFT_PART_SRC_WORK}"', ] + # pylint: enable=line-too-long + [ 'state="$(set +o); set -$-"', "set +u", @@ -262,7 +264,7 @@ def get_installed_dependencies(installed_packages_path: str) -> Set[str]: """Retrieve recursive apt dependencies of a given package list.""" if os.path.isfile(installed_packages_path): try: - with open(installed_packages_path, "r") as file: + with open(installed_packages_path, "r", encoding="utf8") as file: build_snap_packages = set(file.read().split()) package_dependencies = set() for package in build_snap_packages: @@ -285,12 +287,14 @@ def get_installed_dependencies(installed_packages_path: str) -> Set[str]: check=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, - env=dict(PATH=os.environ["PATH"]), + env={"PATH": os.environ["PATH"]}, ) except subprocess.CalledProcessError as error: click.echo(f"failed to run {cmd!r}: {error.output}") else: + # pylint: disable=anomalous-backslash-in-string apt_dependency_regex = re.compile("^\w.*$") # noqa: W605 + # pylint: enable=anomalous-backslash-in-string for line in proc.stdout.decode().strip().split("\n"): if apt_dependency_regex.match(line): package_dependencies.add(line) diff --git a/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py b/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py index f9f7746e57..618e9a7ed7 100644 --- a/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py +++ b/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py @@ -39,6 +39,7 @@ class RosNoeticMetaBase(RosNoeticExtension): @property @abstractmethod def ros_noetic_snaps(self) -> ROS2NoeticSnaps: + """Return the ROS Noetic related snaps to use to construct the environment.""" raise NotImplementedError @staticmethod diff --git a/snapcraft_legacy/internal/project_loader/_extensions/_ros2_foxy_meta.py b/snapcraft_legacy/internal/project_loader/_extensions/_ros2_foxy_meta.py index 4206a133cc..6b1f11f4b1 100644 --- a/snapcraft_legacy/internal/project_loader/_extensions/_ros2_foxy_meta.py +++ b/snapcraft_legacy/internal/project_loader/_extensions/_ros2_foxy_meta.py @@ -39,6 +39,7 @@ class RosFoxyMetaBase(RosFoxyExtension): @property @abstractmethod def ros2_foxy_snaps(self) -> ROS2FoxySnaps: + """Return the ROS 2 Foxy related snaps to use to construct the environment.""" raise NotImplementedError @staticmethod diff --git a/tests/spread/extensions/ros-meta-hello/task.yaml b/tests/spread/extensions/ros-meta-hello/task.yaml index b5730c8393..7443c70006 100644 --- a/tests/spread/extensions/ros-meta-hello/task.yaml +++ b/tests/spread/extensions/ros-meta-hello/task.yaml @@ -45,8 +45,6 @@ restore: | snapcraft clean rm -f ./*.snap - [ -f src/snapcraft_hello/src/hello.cpp ] && git checkout src/snapcraft_hello/src/hello.cpp - #shellcheck source=tests/spread/tools/snapcraft-yaml.sh . "$TOOLS_DIR/snapcraft-yaml.sh" restore_yaml "snap/snapcraft.yaml" @@ -60,7 +58,7 @@ execute: | # Check that the snap size is fairly small # The non-content sharing snap is ~90M - SNAP_SIZE=$(ls -s "${SNAP}"_1.0_*.snap | cut -d " " -f1) + SNAP_SIZE=$(find . -maxdepth 1 -mindepth 1 -name '*_1.0_*.snap' -exec ls -s {} + | cut -d " " -f1) [ "100" -gt "$SNAP_SIZE" ] # # Install the providing snap diff --git a/tests/spread/extensions/ros-meta-talker-listener/task.yaml b/tests/spread/extensions/ros-meta-talker-listener/task.yaml index 1d7691bb98..25b0371b17 100644 --- a/tests/spread/extensions/ros-meta-talker-listener/task.yaml +++ b/tests/spread/extensions/ros-meta-talker-listener/task.yaml @@ -59,7 +59,7 @@ execute: | # Check that the snap size is fairly small # The non-content sharing snap is ~90M - SNAP_SIZE=$(ls -s "${SNAP}"_1.0_*.snap | cut -d " " -f1) + SNAP_SIZE=$(find . -maxdepth 1 -mindepth 1 -name '*_1.0_*.snap' -exec ls -s {} + | cut -d " " -f1) [ "100" -gt "$SNAP_SIZE" ] # # Install the providing snap diff --git a/tests/spread/extensions/ros2-foxy-meta-hello/task.yaml b/tests/spread/extensions/ros2-foxy-meta-hello/task.yaml index 65ca7f95b4..440f9a1b1a 100644 --- a/tests/spread/extensions/ros2-foxy-meta-hello/task.yaml +++ b/tests/spread/extensions/ros2-foxy-meta-hello/task.yaml @@ -44,8 +44,6 @@ restore: | snapcraft clean rm -f ./*.snap - [ -f src/colcon-*-ros-core/src/hello.cpp ] && git checkout src/colcon-*-ros-core/src/hello.cpp - #shellcheck source=tests/spread/tools/snapcraft-yaml.sh . "$TOOLS_DIR/snapcraft-yaml.sh" restore_yaml "snap/snapcraft.yaml" @@ -59,7 +57,7 @@ execute: | # Check that the snap size is fairly small # The non-content sharing snap is ~90M - SNAP_SIZE=$(ls -s "${SNAP}"_1.0_*.snap | cut -d " " -f1) + SNAP_SIZE=$(find . -maxdepth 1 -mindepth 1 -name '*_1.0_*.snap' -exec ls -s {} + | cut -d " " -f1) [ "200" -gt "$SNAP_SIZE" ] # Install the providing snap diff --git a/tests/spread/extensions/ros2-humble-meta-hello/task.yaml b/tests/spread/extensions/ros2-humble-meta-hello/task.yaml index 4324021d88..6d1bad0ea1 100644 --- a/tests/spread/extensions/ros2-humble-meta-hello/task.yaml +++ b/tests/spread/extensions/ros2-humble-meta-hello/task.yaml @@ -45,8 +45,6 @@ restore: | snapcraft clean rm -f ./*.snap - [ -f src/colcon-*-ros-core/src/hello.cpp ] && git checkout src/colcon-*-ros-core/src/hello.cpp - #shellcheck source=tests/spread/tools/snapcraft-yaml.sh . "$TOOLS_DIR/snapcraft-yaml.sh" restore_yaml "snap/snapcraft.yaml" @@ -60,7 +58,7 @@ execute: | # Check that the snap size is fairly small # The non-content sharing snap is ~90M - SNAP_SIZE=$(ls -s "${SNAP}"_1.0_*.snap | cut -d " " -f1) + SNAP_SIZE=$(find . -maxdepth 1 -mindepth 1 -name '*_1.0_*.snap' -exec ls -s {} + | cut -d " " -f1) [ "200" -gt "$SNAP_SIZE" ] # Install the providing snap diff --git a/tests/unit/parts/plugins/test_colcon.py b/tests/unit/parts/plugins/test_colcon.py index 9eba012f30..dda794262f 100644 --- a/tests/unit/parts/plugins/test_colcon.py +++ b/tests/unit/parts/plugins/test_colcon.py @@ -76,9 +76,11 @@ def test_property_default(self): def test_property_unexpected(self): try: + # pylint: disable=unused-variable properties = colcon.ColconPlugin.properties_class( # noqa F841 source="." # type: ignore ) + # pylint: enable=unused-variable except ValidationError as e: raise AssertionError(f"{e}") from e From 07800a4dc845f3b3d3e4656eb7709e53429cf5fa Mon Sep 17 00:00:00 2001 From: artivis Date: Tue, 30 May 2023 11:21:15 +0200 Subject: [PATCH 56/84] ros: rename spread test Signed-off-by: artivis --- .../task.yaml | 8 ++++++++ .../task.yaml | 8 ++++++++ tests/spread/extensions/ros2-foxy-meta-hello/task.yaml | 10 ++++++++++ .../spread/extensions/ros2-humble-meta-hello/task.yaml | 10 ++++++++++ 4 files changed, 36 insertions(+) rename tests/spread/extensions/{ros-meta-hello => ros-noetic-meta-hello}/task.yaml (89%) rename tests/spread/extensions/{ros-meta-talker-listener => ros-noetic-meta-talker-listener}/task.yaml (91%) diff --git a/tests/spread/extensions/ros-meta-hello/task.yaml b/tests/spread/extensions/ros-noetic-meta-hello/task.yaml similarity index 89% rename from tests/spread/extensions/ros-meta-hello/task.yaml rename to tests/spread/extensions/ros-noetic-meta-hello/task.yaml index 7443c70006..3fd2ae5944 100644 --- a/tests/spread/extensions/ros-meta-hello/task.yaml +++ b/tests/spread/extensions/ros-noetic-meta-hello/task.yaml @@ -40,6 +40,10 @@ prepare: | # Overwrite the extension to test them all out of a single snap sed -i "s|ros1-noetic|${EXTENSION}|" "$SNAP_DIR/snap/snapcraft.yaml" + #shellcheck source=tests/spread/tools/package-utils.sh + . "$TOOLS_DIR/package-utils.sh" + create_dpkg_restore_point + restore: | cd "$SNAP_DIR" snapcraft clean @@ -49,6 +53,10 @@ restore: | . "$TOOLS_DIR/snapcraft-yaml.sh" restore_yaml "snap/snapcraft.yaml" + #shellcheck source=tests/spread/tools/package-utils.sh + . "$TOOLS_DIR/package-utils.sh" + dpkg_restore_point + execute: | cd "$SNAP_DIR" diff --git a/tests/spread/extensions/ros-meta-talker-listener/task.yaml b/tests/spread/extensions/ros-noetic-meta-talker-listener/task.yaml similarity index 91% rename from tests/spread/extensions/ros-meta-talker-listener/task.yaml rename to tests/spread/extensions/ros-noetic-meta-talker-listener/task.yaml index 25b0371b17..7ac468d365 100644 --- a/tests/spread/extensions/ros-meta-talker-listener/task.yaml +++ b/tests/spread/extensions/ros-noetic-meta-talker-listener/task.yaml @@ -41,6 +41,10 @@ prepare: | # Overwrite the extension to test them all out of a single snap sed -i "s|ros1-noetic|${EXTENSION}|" "$SNAP_DIR/snap/snapcraft.yaml" + #shellcheck source=tests/spread/tools/package-utils.sh + . "$TOOLS_DIR/package-utils.sh" + create_dpkg_restore_point + restore: | cd "$SNAP_DIR" snapcraft clean @@ -50,6 +54,10 @@ restore: | . "$TOOLS_DIR/snapcraft-yaml.sh" restore_yaml "snap/snapcraft.yaml" + #shellcheck source=tests/spread/tools/package-utils.sh + . "$TOOLS_DIR/package-utils.sh" + dpkg_restore_point + execute: | cd "$SNAP_DIR" diff --git a/tests/spread/extensions/ros2-foxy-meta-hello/task.yaml b/tests/spread/extensions/ros2-foxy-meta-hello/task.yaml index 440f9a1b1a..36bc7e8224 100644 --- a/tests/spread/extensions/ros2-foxy-meta-hello/task.yaml +++ b/tests/spread/extensions/ros2-foxy-meta-hello/task.yaml @@ -39,6 +39,10 @@ prepare: | # The snap stages ros2run which will be available through content-sharing sed -i "\|stage-packages|d" "$SNAP_DIR/snap/snapcraft.yaml" + #shellcheck source=tests/spread/tools/package-utils.sh + . "$TOOLS_DIR/package-utils.sh" + create_dpkg_restore_point + restore: | cd "$SNAP_DIR" snapcraft clean @@ -48,6 +52,12 @@ restore: | . "$TOOLS_DIR/snapcraft-yaml.sh" restore_yaml "snap/snapcraft.yaml" + #shellcheck source=tests/spread/tools/package-utils.sh + . "$TOOLS_DIR/package-utils.sh" + dpkg_restore_point + + snap remove --purge "${META_SNAP}" + execute: | cd "$SNAP_DIR" diff --git a/tests/spread/extensions/ros2-humble-meta-hello/task.yaml b/tests/spread/extensions/ros2-humble-meta-hello/task.yaml index 6d1bad0ea1..17ba9f6c11 100644 --- a/tests/spread/extensions/ros2-humble-meta-hello/task.yaml +++ b/tests/spread/extensions/ros2-humble-meta-hello/task.yaml @@ -40,6 +40,10 @@ prepare: | # The snap stages ros2run which will be available through content-sharing sed -i "\|stage-packages|d" "$SNAP_DIR/snap/snapcraft.yaml" + #shellcheck source=tests/spread/tools/package-utils.sh + . "$TOOLS_DIR/package-utils.sh" + create_dpkg_restore_point + restore: | cd "$SNAP_DIR" snapcraft clean @@ -49,6 +53,12 @@ restore: | . "$TOOLS_DIR/snapcraft-yaml.sh" restore_yaml "snap/snapcraft.yaml" + #shellcheck source=tests/spread/tools/package-utils.sh + . "$TOOLS_DIR/package-utils.sh" + dpkg_restore_point + + snap remove --purge "${META_SNAP}" + execute: | cd "$SNAP_DIR" From 75bcb5d15131eaf03f1610aafb88e778000b6b47 Mon Sep 17 00:00:00 2001 From: artivis Date: Tue, 30 May 2023 11:21:39 +0200 Subject: [PATCH 57/84] ros: add comment Signed-off-by: artivis --- snapcraft/extensions/_ros2_humble_meta.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/snapcraft/extensions/_ros2_humble_meta.py b/snapcraft/extensions/_ros2_humble_meta.py index 373ccc0e4c..a63c0dd7dc 100644 --- a/snapcraft/extensions/_ros2_humble_meta.py +++ b/snapcraft/extensions/_ros2_humble_meta.py @@ -114,6 +114,8 @@ def get_parts_snippet(self) -> Dict[str, Any]: f"ros-{self.ROS_DISTRO}-ament-index-python", ] + # Something in the ROS 2 build chain requires to find this lib during cmake call, + # however its cmake files ship with the '-dev' package. parts_snippet[f"ros2-{self.ROS_DISTRO}/ros2-launch"]["build-packages"].append( "libpython3.10-dev" ) From 3f7ee45b8012ed837784407678b45fabdb356ec9 Mon Sep 17 00:00:00 2001 From: artivis Date: Thu, 1 Jun 2023 08:22:43 +0200 Subject: [PATCH 58/84] ros: move stage package to meta extension Signed-off-by: artivis --- .../internal/project_loader/_extensions/_ros1_noetic_meta.py | 2 ++ .../internal/project_loader/_extensions/ros1_noetic.py | 1 - .../legacy/unit/project_loader/extensions/test_ros1_noetic.py | 3 +-- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py b/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py index 618e9a7ed7..05a07d0a96 100644 --- a/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py +++ b/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py @@ -64,6 +64,8 @@ def __init__(self, *, extension_name: str, yaml_data: Dict[str, Any]) -> None: f'-DCMAKE_SYSTEM_PREFIX_PATH="/snap/{self.ros_noetic_snaps.sdk}/current/usr"' ] + self.part_snippet["stage-packages"] = [f"ros-{self.ROS_DISTRO}-ros-environment"] + self.part_snippet["build-snaps"] = [self.ros_noetic_snaps.sdk] python_paths = self.app_snippet["environment"]["PYTHONPATH"] diff --git a/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic.py b/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic.py index 627389f1cc..af5e1ad9ac 100644 --- a/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic.py +++ b/snapcraft_legacy/internal/project_loader/_extensions/ros1_noetic.py @@ -78,7 +78,6 @@ def __init__(self, *, extension_name: str, yaml_data: Dict[str, Any]) -> None: {"ROS_VERSION": self.ROS_VERSION}, {"ROS_DISTRO": self.ROS_DISTRO}, ], - "stage-packages": [f"ros-{self.ROS_DISTRO}-ros-environment"] } self.parts = { diff --git a/tests/legacy/unit/project_loader/extensions/test_ros1_noetic.py b/tests/legacy/unit/project_loader/extensions/test_ros1_noetic.py index f0e47a45c3..5ebf5fdffe 100644 --- a/tests/legacy/unit/project_loader/extensions/test_ros1_noetic.py +++ b/tests/legacy/unit/project_loader/extensions/test_ros1_noetic.py @@ -55,8 +55,7 @@ def test_extension(extension_class): } assert ros1_extension.part_snippet == { - "build-environment": [{"ROS_VERSION": "1"}, {"ROS_DISTRO": "noetic"}], - "stage-packages": ["ros-noetic-ros-environment"], + "build-environment": [{"ROS_VERSION": "1"}, {"ROS_DISTRO": "noetic"}] } assert ros1_extension.parts == { From 5547a8bd344d81a43e7185f2c2f16888de827ace Mon Sep 17 00:00:00 2001 From: artivis Date: Thu, 1 Jun 2023 08:24:27 +0200 Subject: [PATCH 59/84] ros: add spread tests Signed-off-by: artivis --- .../ros2-foxy-meta-talker-listener/task.yaml | 78 +++++++++++++++++++ .../task.yaml | 78 +++++++++++++++++++ .../colcon-talker-listener/CMakeLists.txt | 37 +++++++++ .../launch/talker_listener.launch.py | 28 +++++++ .../colcon-talker-listener/package.xml | 23 ++++++ .../snap/snapcraft.yaml | 21 +++++ .../src/publisher_member_function.cpp | 56 +++++++++++++ .../src/subscriber_member_function.cpp | 51 ++++++++++++ .../colcon-talker-listener/task.yaml | 38 +++++++++ .../plugins/v2/colcon-ros2-run/task.yaml | 38 +++++++++ .../CMakeLists.txt | 37 +++++++++ .../launch/talker_listener.launch.py | 28 +++++++ .../colcon-ros2-talker-listener/package.xml | 23 ++++++ .../snap/snapcraft.yaml | 21 +++++ .../src/publisher_member_function.cpp | 56 +++++++++++++ .../src/subscriber_member_function.cpp | 51 ++++++++++++ 16 files changed, 664 insertions(+) create mode 100644 tests/spread/extensions/ros2-foxy-meta-talker-listener/task.yaml create mode 100644 tests/spread/extensions/ros2-humble-meta-talker-listener/task.yaml create mode 100644 tests/spread/plugins/craft-parts/colcon-talker-listener/colcon-talker-listener/CMakeLists.txt create mode 100644 tests/spread/plugins/craft-parts/colcon-talker-listener/colcon-talker-listener/launch/talker_listener.launch.py create mode 100644 tests/spread/plugins/craft-parts/colcon-talker-listener/colcon-talker-listener/package.xml create mode 100644 tests/spread/plugins/craft-parts/colcon-talker-listener/colcon-talker-listener/snap/snapcraft.yaml create mode 100644 tests/spread/plugins/craft-parts/colcon-talker-listener/colcon-talker-listener/src/publisher_member_function.cpp create mode 100644 tests/spread/plugins/craft-parts/colcon-talker-listener/colcon-talker-listener/src/subscriber_member_function.cpp create mode 100644 tests/spread/plugins/craft-parts/colcon-talker-listener/task.yaml create mode 100644 tests/spread/plugins/v2/colcon-ros2-run/task.yaml create mode 100644 tests/spread/plugins/v2/snaps/colcon-ros2-talker-listener/CMakeLists.txt create mode 100644 tests/spread/plugins/v2/snaps/colcon-ros2-talker-listener/launch/talker_listener.launch.py create mode 100644 tests/spread/plugins/v2/snaps/colcon-ros2-talker-listener/package.xml create mode 100644 tests/spread/plugins/v2/snaps/colcon-ros2-talker-listener/snap/snapcraft.yaml create mode 100644 tests/spread/plugins/v2/snaps/colcon-ros2-talker-listener/src/publisher_member_function.cpp create mode 100644 tests/spread/plugins/v2/snaps/colcon-ros2-talker-listener/src/subscriber_member_function.cpp diff --git a/tests/spread/extensions/ros2-foxy-meta-talker-listener/task.yaml b/tests/spread/extensions/ros2-foxy-meta-talker-listener/task.yaml new file mode 100644 index 0000000000..1d2c380f09 --- /dev/null +++ b/tests/spread/extensions/ros2-foxy-meta-talker-listener/task.yaml @@ -0,0 +1,78 @@ +summary: Build and run a basic ROS 2 snap using meta-ros extension + +kill-timeout: 180m + +environment: + SNAPCRAFT_ENABLE_EXPERIMENTAL_EXTENSIONS: "1" + + SNAP: colcon-ros2-talker-listener + SNAP_DIR: "../../plugins/v2/snaps/$SNAP" + + INTERFACE: ros-foxy + + META_SNAP/colcon_foxy_ros_core: ros-foxy-ros-core + EXTENSION/colcon_foxy_ros_core: ros2-foxy-ros-core + + META_SNAP/colcon_foxy_ros_base: ros-foxy-ros-base + EXTENSION/colcon_foxy_ros_base: ros2-foxy-ros-base + + META_SNAP/colcon_foxy_desktop: ros-foxy-desktop + EXTENSION/colcon_foxy_desktop: ros2-foxy-desktop + +# The content snap required for the test to succeed is only +# available on a subset of all the architectures this testbed +# can run on. +systems: + - ubuntu-20.04 + - ubuntu-20.04-64 + - ubuntu-20.04-amd64 + - ubuntu-20.04-arm64 + +prepare: | + #shellcheck source=tests/spread/tools/snapcraft-yaml.sh + . "$TOOLS_DIR/snapcraft-yaml.sh" + set_base "$SNAP_DIR/snap/snapcraft.yaml" + + # Overwrite the extension to test them all out of a single snap + sed -i "s|ros2-foxy|${EXTENSION}|" "$SNAP_DIR/snap/snapcraft.yaml" + + #shellcheck source=tests/spread/tools/package-utils.sh + . "$TOOLS_DIR/package-utils.sh" + create_dpkg_restore_point + +restore: | + cd "$SNAP_DIR" + snapcraft clean + rm -f ./*.snap + + #shellcheck source=tests/spread/tools/snapcraft-yaml.sh + . "$TOOLS_DIR/snapcraft-yaml.sh" + restore_yaml "snap/snapcraft.yaml" + + #shellcheck source=tests/spread/tools/package-utils.sh + . "$TOOLS_DIR/package-utils.sh" + dpkg_restore_point + + snap remove --purge "${META_SNAP}" + +execute: | + cd "$SNAP_DIR" + + # Build what we have and verify the snap runs as expected. + snapcraft + snap install "${SNAP}"_1.0_*.snap --dangerous + + # Check that the snap size is fairly small + # The non-content sharing snap is ~90M + SNAP_SIZE=$(find . -maxdepth 1 -mindepth 1 -name '*_1.0_*.snap' -exec ls -s {} + | cut -d " " -f1) + [ "600" -gt "$SNAP_SIZE" ] + + # Install the providing snap + # snap install "${META_SNAP}" + + snap connect "${SNAP}":"${INTERFACE}" "${META_SNAP}":"${INTERFACE}" + + # Run the ROS system. By default this will never exit, but the snap supports + # an `exit_after_receive` parameter that, if true, will cause the system to + # shutdown after the listener has successfully received a message. + "$SNAP" exit_after_receive:=true | MATCH "I heard: 'Hello, world! 0'" diff --git a/tests/spread/extensions/ros2-humble-meta-talker-listener/task.yaml b/tests/spread/extensions/ros2-humble-meta-talker-listener/task.yaml new file mode 100644 index 0000000000..bca490c48b --- /dev/null +++ b/tests/spread/extensions/ros2-humble-meta-talker-listener/task.yaml @@ -0,0 +1,78 @@ +summary: Build and run a basic ROS 2 snap using meta-ros extension + +kill-timeout: 180m + +environment: + SNAPCRAFT_ENABLE_EXPERIMENTAL_EXTENSIONS: "1" + + SNAP: colcon-talker-listener + SNAP_DIR: "../../plugins/craft-parts/$SNAP/$SNAP" + + INTERFACE: ros-humble + + META_SNAP/colcon_humble_ros_core: ros-humble-ros-core + EXTENSION/colcon_humble_ros_core: ros2-humble-ros-core + + META_SNAP/colcon_humble_ros_base: ros-humble-ros-base + EXTENSION/colcon_humble_ros_base: ros2-humble-ros-base + + META_SNAP/colcon_humble_desktop: ros-humble-desktop + EXTENSION/colcon_humble_desktop: ros2-humble-desktop + +# The content snap required for the test to succeed is only +# available on a subset of all the architectures this testbed +# can run on. +systems: + - ubuntu-22.04 + - ubuntu-22.04-64 + - ubuntu-22.04-amd64 + - ubuntu-22.04-arm64 + +prepare: | + #shellcheck source=tests/spread/tools/snapcraft-yaml.sh + . "$TOOLS_DIR/snapcraft-yaml.sh" + set_base "$SNAP_DIR/snap/snapcraft.yaml" + + # Overwrite the extension to test them all out of a single snap + sed -i "s|ros2-humble|${EXTENSION}|" "$SNAP_DIR/snap/snapcraft.yaml" + + #shellcheck source=tests/spread/tools/package-utils.sh + . "$TOOLS_DIR/package-utils.sh" + create_dpkg_restore_point + +restore: | + cd "$SNAP_DIR" + snapcraft clean + rm -f ./*.snap + + #shellcheck source=tests/spread/tools/snapcraft-yaml.sh + . "$TOOLS_DIR/snapcraft-yaml.sh" + restore_yaml "snap/snapcraft.yaml" + + #shellcheck source=tests/spread/tools/package-utils.sh + . "$TOOLS_DIR/package-utils.sh" + dpkg_restore_point + + snap remove --purge "${META_SNAP}" + +execute: | + cd "$SNAP_DIR" + + # Build what we have and verify the snap runs as expected. + snapcraft + snap install "${SNAP}"_1.0_*.snap --dangerous + + # Check that the snap size is fairly small + # The non-content sharing snap is ~90M + SNAP_SIZE=$(find . -maxdepth 1 -mindepth 1 -name '*_1.0_*.snap' -exec ls -s {} + | cut -d " " -f1) + [ "800" -gt "$SNAP_SIZE" ] + + # Install the providing snap + # snap install "${META_SNAP}" + + snap connect "${SNAP}":"${INTERFACE}" "${META_SNAP}":"${INTERFACE}" + + # Run the ROS system. By default this will never exit, but the snap supports + # an `exit_after_receive` parameter that, if true, will cause the system to + # shutdown after the listener has successfully received a message. + "$SNAP" exit_after_receive:=true | MATCH "I heard: 'Hello, world! 0'" diff --git a/tests/spread/plugins/craft-parts/colcon-talker-listener/colcon-talker-listener/CMakeLists.txt b/tests/spread/plugins/craft-parts/colcon-talker-listener/colcon-talker-listener/CMakeLists.txt new file mode 100644 index 0000000000..55b98b7cd4 --- /dev/null +++ b/tests/spread/plugins/craft-parts/colcon-talker-listener/colcon-talker-listener/CMakeLists.txt @@ -0,0 +1,37 @@ +cmake_minimum_required(VERSION 3.5) +project(colcon-ros2-talker-listener) + +# Default to C++14 +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 14) +endif() + +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() + +# find dependencies +find_package(ament_cmake REQUIRED) +find_package(rclcpp REQUIRED) +find_package(std_msgs REQUIRED) + +if(NOT WIN32) + ament_environment_hooks( + "${ament_cmake_package_templates_ENVIRONMENT_HOOK_LIBRARY_PATH}" + ) +endif() + +add_executable(talker src/publisher_member_function.cpp) +ament_target_dependencies(talker rclcpp std_msgs) + +add_executable(listener src/subscriber_member_function.cpp) +ament_target_dependencies(listener rclcpp std_msgs) + +install( + TARGETS talker listener + DESTINATION lib/${PROJECT_NAME} +) + +install(DIRECTORY launch DESTINATION share/${PROJECT_NAME}/) + +ament_package() diff --git a/tests/spread/plugins/craft-parts/colcon-talker-listener/colcon-talker-listener/launch/talker_listener.launch.py b/tests/spread/plugins/craft-parts/colcon-talker-listener/colcon-talker-listener/launch/talker_listener.launch.py new file mode 100644 index 0000000000..97685ac468 --- /dev/null +++ b/tests/spread/plugins/craft-parts/colcon-talker-listener/colcon-talker-listener/launch/talker_listener.launch.py @@ -0,0 +1,28 @@ +import launch +import launch_ros.actions +from launch.actions import DeclareLaunchArgument +from launch.substitutions import LaunchConfiguration + + +def generate_launch_description(): + return launch.LaunchDescription( + [ + launch_ros.actions.Node( + package="colcon-ros2-talker-listener", + executable="talker", + name="talker", + output="screen", + ), + DeclareLaunchArgument("exit_after_receive", default_value="False"), + launch_ros.actions.Node( + package="colcon-ros2-talker-listener", + executable="listener", + name="listener", + output="screen", + parameters=[ + {"exit_after_receive": LaunchConfiguration("exit_after_receive")} + ], + on_exit=launch.actions.Shutdown(), + ), + ] + ) diff --git a/tests/spread/plugins/craft-parts/colcon-talker-listener/colcon-talker-listener/package.xml b/tests/spread/plugins/craft-parts/colcon-talker-listener/colcon-talker-listener/package.xml new file mode 100644 index 0000000000..6b2b7e4be5 --- /dev/null +++ b/tests/spread/plugins/craft-parts/colcon-talker-listener/colcon-talker-listener/package.xml @@ -0,0 +1,23 @@ + + + + colcon-ros2-talker-listener + 0.0.0 + A talker listener demo + ubuntu-robotics + GPLv3 + + ament_cmake + + rclcpp + std_msgs + + ros2launch + + ament_lint_auto + ament_lint_common + + + ament_cmake + + diff --git a/tests/spread/plugins/craft-parts/colcon-talker-listener/colcon-talker-listener/snap/snapcraft.yaml b/tests/spread/plugins/craft-parts/colcon-talker-listener/colcon-talker-listener/snap/snapcraft.yaml new file mode 100644 index 0000000000..98fe315535 --- /dev/null +++ b/tests/spread/plugins/craft-parts/colcon-talker-listener/colcon-talker-listener/snap/snapcraft.yaml @@ -0,0 +1,21 @@ +name: colcon-talker-listener +version: "1.0" +summary: hello world +description: | + A ROS 2 talker-listener. + +grade: stable +confinement: strict +base: core22 + +apps: + colcon-talker-listener: + command: ros2 launch colcon-ros2-talker-listener talker_listener.launch.py + plugs: [network, network-bind] + extensions: [ros2-humble] + +parts: + hello: + plugin: colcon + source: . + build-packages: [g++, make] diff --git a/tests/spread/plugins/craft-parts/colcon-talker-listener/colcon-talker-listener/src/publisher_member_function.cpp b/tests/spread/plugins/craft-parts/colcon-talker-listener/colcon-talker-listener/src/publisher_member_function.cpp new file mode 100644 index 0000000000..c8d2ebfe00 --- /dev/null +++ b/tests/spread/plugins/craft-parts/colcon-talker-listener/colcon-talker-listener/src/publisher_member_function.cpp @@ -0,0 +1,56 @@ +// Copyright 2016 Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include + +#include "rclcpp/rclcpp.hpp" +#include "std_msgs/msg/string.hpp" + +using namespace std::chrono_literals; + +/* This example creates a subclass of Node and uses std::bind() to register a + * member function as a callback from the timer. */ + +class MinimalPublisher : public rclcpp::Node +{ +public: + MinimalPublisher() + : Node("minimal_publisher"), count_(0) + { + publisher_ = this->create_publisher("topic", 10); + timer_ = this->create_wall_timer( + 500ms, std::bind(&MinimalPublisher::timer_callback, this)); + } + +private: + void timer_callback() + { + auto message = std_msgs::msg::String(); + message.data = "Hello, world! " + std::to_string(count_++); + RCLCPP_INFO(this->get_logger(), "Publishing: '%s'", message.data.c_str()); + publisher_->publish(message); + } + rclcpp::TimerBase::SharedPtr timer_; + rclcpp::Publisher::SharedPtr publisher_; + size_t count_; +}; + +int main(int argc, char * argv[]) +{ + rclcpp::init(argc, argv); + rclcpp::spin(std::make_shared()); + rclcpp::shutdown(); + return 0; +} diff --git a/tests/spread/plugins/craft-parts/colcon-talker-listener/colcon-talker-listener/src/subscriber_member_function.cpp b/tests/spread/plugins/craft-parts/colcon-talker-listener/colcon-talker-listener/src/subscriber_member_function.cpp new file mode 100644 index 0000000000..655a4ffd57 --- /dev/null +++ b/tests/spread/plugins/craft-parts/colcon-talker-listener/colcon-talker-listener/src/subscriber_member_function.cpp @@ -0,0 +1,51 @@ +// Copyright 2016 Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +#include "rclcpp/rclcpp.hpp" +#include "std_msgs/msg/string.hpp" +using std::placeholders::_1; + +class MinimalSubscriber : public rclcpp::Node +{ +public: + MinimalSubscriber() + : Node("minimal_subscriber") + { + subscription_ = this->create_subscription( + "topic", 10, std::bind(&MinimalSubscriber::topic_callback, this, _1)); + + this->declare_parameter("exit_after_receive", false); + } + +private: + void topic_callback(const std_msgs::msg::String::SharedPtr msg) const + { + RCLCPP_INFO(this->get_logger(), "I heard: '%s'", msg->data.c_str()); + + if (this->get_parameter("exit_after_receive").as_bool()) { + rclcpp::shutdown(); + } + } + rclcpp::Subscription::SharedPtr subscription_; +}; + +int main(int argc, char * argv[]) +{ + rclcpp::init(argc, argv); + rclcpp::spin(std::make_shared()); + rclcpp::shutdown(); + return 0; +} diff --git a/tests/spread/plugins/craft-parts/colcon-talker-listener/task.yaml b/tests/spread/plugins/craft-parts/colcon-talker-listener/task.yaml new file mode 100644 index 0000000000..16efdf61a3 --- /dev/null +++ b/tests/spread/plugins/craft-parts/colcon-talker-listener/task.yaml @@ -0,0 +1,38 @@ +summary: Build and run a basic colcon snap + +kill-timeout: 180m + +environment: + SNAP/catkin_ros2_run: colcon-talker-listener + +systems: + - ubuntu-22.04 + - ubuntu-22.04-64 + - ubuntu-22.04-amd64 + - ubuntu-22.04-arm64 + +prepare: | + #shellcheck source=tests/spread/tools/snapcraft-yaml.sh + . "$TOOLS_DIR/snapcraft-yaml.sh" + set_base "$SNAP/snap/snapcraft.yaml" + +restore: | + cd "$SNAP" + snapcraft clean + rm -f ./*.snap + + #shellcheck source=tests/spread/tools/snapcraft-yaml.sh + . "$TOOLS_DIR/snapcraft-yaml.sh" + restore_yaml "snap/snapcraft.yaml" + +execute: | + cd "$SNAP" + + # Build what and install the snap + snapcraft + snap install "${SNAP}"_1.0_*.snap --dangerous + + # Run the ROS system. By default this will never exit, but the snap supports + # an `exit_after_receive` parameter that, if true, will cause the system to + # shutdown after the listener has successfully received a message. + "$SNAP" exit_after_receive:=true | MATCH "I heard: 'Hello, world! 0'" diff --git a/tests/spread/plugins/v2/colcon-ros2-run/task.yaml b/tests/spread/plugins/v2/colcon-ros2-run/task.yaml new file mode 100644 index 0000000000..4af02d594f --- /dev/null +++ b/tests/spread/plugins/v2/colcon-ros2-run/task.yaml @@ -0,0 +1,38 @@ +summary: Build and run a basic colcon snap + +kill-timeout: 180m + +environment: + SNAP/catkin_ros2_run: colcon-ros2-talker-listener + +systems: + - ubuntu-20.04 + - ubuntu-20.04-64 + - ubuntu-20.04-amd64 + - ubuntu-20.04-arm64 + +prepare: | + #shellcheck source=tests/spread/tools/snapcraft-yaml.sh + . "$TOOLS_DIR/snapcraft-yaml.sh" + set_base "../snaps/$SNAP/snap/snapcraft.yaml" + +restore: | + cd "../snaps/$SNAP" + snapcraft clean + rm -f ./*.snap + + #shellcheck source=tests/spread/tools/snapcraft-yaml.sh + . "$TOOLS_DIR/snapcraft-yaml.sh" + restore_yaml "snap/snapcraft.yaml" + +execute: | + cd "../snaps/$SNAP" + + # Build what and install the snap + snapcraft + snap install "${SNAP}"_1.0_*.snap --dangerous + + # Run the ROS system. By default this will never exit, but the snap supports + # an `exit_after_receive` parameter that, if true, will cause the system to + # shutdown after the listener has successfully received a message. + "$SNAP" exit_after_receive:=true | MATCH "I heard: 'Hello, world! 0'" diff --git a/tests/spread/plugins/v2/snaps/colcon-ros2-talker-listener/CMakeLists.txt b/tests/spread/plugins/v2/snaps/colcon-ros2-talker-listener/CMakeLists.txt new file mode 100644 index 0000000000..55b98b7cd4 --- /dev/null +++ b/tests/spread/plugins/v2/snaps/colcon-ros2-talker-listener/CMakeLists.txt @@ -0,0 +1,37 @@ +cmake_minimum_required(VERSION 3.5) +project(colcon-ros2-talker-listener) + +# Default to C++14 +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 14) +endif() + +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() + +# find dependencies +find_package(ament_cmake REQUIRED) +find_package(rclcpp REQUIRED) +find_package(std_msgs REQUIRED) + +if(NOT WIN32) + ament_environment_hooks( + "${ament_cmake_package_templates_ENVIRONMENT_HOOK_LIBRARY_PATH}" + ) +endif() + +add_executable(talker src/publisher_member_function.cpp) +ament_target_dependencies(talker rclcpp std_msgs) + +add_executable(listener src/subscriber_member_function.cpp) +ament_target_dependencies(listener rclcpp std_msgs) + +install( + TARGETS talker listener + DESTINATION lib/${PROJECT_NAME} +) + +install(DIRECTORY launch DESTINATION share/${PROJECT_NAME}/) + +ament_package() diff --git a/tests/spread/plugins/v2/snaps/colcon-ros2-talker-listener/launch/talker_listener.launch.py b/tests/spread/plugins/v2/snaps/colcon-ros2-talker-listener/launch/talker_listener.launch.py new file mode 100644 index 0000000000..97685ac468 --- /dev/null +++ b/tests/spread/plugins/v2/snaps/colcon-ros2-talker-listener/launch/talker_listener.launch.py @@ -0,0 +1,28 @@ +import launch +import launch_ros.actions +from launch.actions import DeclareLaunchArgument +from launch.substitutions import LaunchConfiguration + + +def generate_launch_description(): + return launch.LaunchDescription( + [ + launch_ros.actions.Node( + package="colcon-ros2-talker-listener", + executable="talker", + name="talker", + output="screen", + ), + DeclareLaunchArgument("exit_after_receive", default_value="False"), + launch_ros.actions.Node( + package="colcon-ros2-talker-listener", + executable="listener", + name="listener", + output="screen", + parameters=[ + {"exit_after_receive": LaunchConfiguration("exit_after_receive")} + ], + on_exit=launch.actions.Shutdown(), + ), + ] + ) diff --git a/tests/spread/plugins/v2/snaps/colcon-ros2-talker-listener/package.xml b/tests/spread/plugins/v2/snaps/colcon-ros2-talker-listener/package.xml new file mode 100644 index 0000000000..6b2b7e4be5 --- /dev/null +++ b/tests/spread/plugins/v2/snaps/colcon-ros2-talker-listener/package.xml @@ -0,0 +1,23 @@ + + + + colcon-ros2-talker-listener + 0.0.0 + A talker listener demo + ubuntu-robotics + GPLv3 + + ament_cmake + + rclcpp + std_msgs + + ros2launch + + ament_lint_auto + ament_lint_common + + + ament_cmake + + diff --git a/tests/spread/plugins/v2/snaps/colcon-ros2-talker-listener/snap/snapcraft.yaml b/tests/spread/plugins/v2/snaps/colcon-ros2-talker-listener/snap/snapcraft.yaml new file mode 100644 index 0000000000..e2476e8bfb --- /dev/null +++ b/tests/spread/plugins/v2/snaps/colcon-ros2-talker-listener/snap/snapcraft.yaml @@ -0,0 +1,21 @@ +name: colcon-ros2-talker-listener +version: "1.0" +summary: hello world +description: | + A ROS 2 talker-listener. + +grade: stable +confinement: strict +base: core20 + +apps: + colcon-ros2-talker-listener: + command: ros2 launch colcon-ros2-talker-listener talker_listener.launch.py + plugs: [network, network-bind] + extensions: [ros2-foxy] + +parts: + hello: + plugin: colcon + source: . + build-packages: [g++, make] diff --git a/tests/spread/plugins/v2/snaps/colcon-ros2-talker-listener/src/publisher_member_function.cpp b/tests/spread/plugins/v2/snaps/colcon-ros2-talker-listener/src/publisher_member_function.cpp new file mode 100644 index 0000000000..c8d2ebfe00 --- /dev/null +++ b/tests/spread/plugins/v2/snaps/colcon-ros2-talker-listener/src/publisher_member_function.cpp @@ -0,0 +1,56 @@ +// Copyright 2016 Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include + +#include "rclcpp/rclcpp.hpp" +#include "std_msgs/msg/string.hpp" + +using namespace std::chrono_literals; + +/* This example creates a subclass of Node and uses std::bind() to register a + * member function as a callback from the timer. */ + +class MinimalPublisher : public rclcpp::Node +{ +public: + MinimalPublisher() + : Node("minimal_publisher"), count_(0) + { + publisher_ = this->create_publisher("topic", 10); + timer_ = this->create_wall_timer( + 500ms, std::bind(&MinimalPublisher::timer_callback, this)); + } + +private: + void timer_callback() + { + auto message = std_msgs::msg::String(); + message.data = "Hello, world! " + std::to_string(count_++); + RCLCPP_INFO(this->get_logger(), "Publishing: '%s'", message.data.c_str()); + publisher_->publish(message); + } + rclcpp::TimerBase::SharedPtr timer_; + rclcpp::Publisher::SharedPtr publisher_; + size_t count_; +}; + +int main(int argc, char * argv[]) +{ + rclcpp::init(argc, argv); + rclcpp::spin(std::make_shared()); + rclcpp::shutdown(); + return 0; +} diff --git a/tests/spread/plugins/v2/snaps/colcon-ros2-talker-listener/src/subscriber_member_function.cpp b/tests/spread/plugins/v2/snaps/colcon-ros2-talker-listener/src/subscriber_member_function.cpp new file mode 100644 index 0000000000..655a4ffd57 --- /dev/null +++ b/tests/spread/plugins/v2/snaps/colcon-ros2-talker-listener/src/subscriber_member_function.cpp @@ -0,0 +1,51 @@ +// Copyright 2016 Open Source Robotics Foundation, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +#include "rclcpp/rclcpp.hpp" +#include "std_msgs/msg/string.hpp" +using std::placeholders::_1; + +class MinimalSubscriber : public rclcpp::Node +{ +public: + MinimalSubscriber() + : Node("minimal_subscriber") + { + subscription_ = this->create_subscription( + "topic", 10, std::bind(&MinimalSubscriber::topic_callback, this, _1)); + + this->declare_parameter("exit_after_receive", false); + } + +private: + void topic_callback(const std_msgs::msg::String::SharedPtr msg) const + { + RCLCPP_INFO(this->get_logger(), "I heard: '%s'", msg->data.c_str()); + + if (this->get_parameter("exit_after_receive").as_bool()) { + rclcpp::shutdown(); + } + } + rclcpp::Subscription::SharedPtr subscription_; +}; + +int main(int argc, char * argv[]) +{ + rclcpp::init(argc, argv); + rclcpp::spin(std::make_shared()); + rclcpp::shutdown(); + return 0; +} From f5dad45077653b5aa72880c9ac4c52f62578ab84 Mon Sep 17 00:00:00 2001 From: artivis Date: Fri, 2 Jun 2023 14:53:56 +0200 Subject: [PATCH 60/84] ros: meta rename build-snaps -> ros-build-snaps Signed-off-by: artivis --- snapcraft/extensions/_ros2_humble_meta.py | 2 +- snapcraft/parts/plugins/_ros.py | 8 +++--- snapcraft/parts/plugins/colcon_plugin.py | 14 ++++++---- .../_extensions/_ros1_noetic_meta.py | 2 +- .../_extensions/_ros2_foxy_meta.py | 2 +- snapcraft_legacy/plugins/v2/_ros.py | 8 +++--- snapcraft_legacy/plugins/v2/catkin.py | 13 ++++++--- snapcraft_legacy/plugins/v2/colcon.py | 13 ++++++--- tests/legacy/unit/plugins/v2/test_catkin.py | 27 +++++++++++++++++-- tests/legacy/unit/plugins/v2/test_colcon.py | 27 +++++++++++++++++-- .../extensions/test_ros1_noetic_meta.py | 2 +- .../extensions/test_ros2_foxy_meta.py | 2 +- .../parts/extensions/test_ros2_humble_meta.py | 2 +- tests/unit/parts/plugins/test_colcon.py | 26 +++++++++++++++--- 14 files changed, 116 insertions(+), 32 deletions(-) diff --git a/snapcraft/extensions/_ros2_humble_meta.py b/snapcraft/extensions/_ros2_humble_meta.py index a63c0dd7dc..3c7ae6d952 100644 --- a/snapcraft/extensions/_ros2_humble_meta.py +++ b/snapcraft/extensions/_ros2_humble_meta.py @@ -94,7 +94,7 @@ def get_app_snippet(self) -> Dict[str, Any]: @overrides def get_part_snippet(self) -> Dict[str, Any]: part_snippet = super().get_part_snippet() - part_snippet["build-snaps"] = [self.ros2_humble_snaps.sdk] + part_snippet["ros-build-snaps"] = [self.ros2_humble_snaps.sdk] part_snippet["colcon-cmake-args"] = [ f'-DCMAKE_SYSTEM_PREFIX_PATH="/snap/{self.ros2_humble_snaps.sdk}/current/usr"' ] diff --git a/snapcraft/parts/plugins/_ros.py b/snapcraft/parts/plugins/_ros.py index 6ed6fef463..fc1668bfcb 100644 --- a/snapcraft/parts/plugins/_ros.py +++ b/snapcraft/parts/plugins/_ros.py @@ -86,7 +86,7 @@ class RosPlugin(plugins.Plugin): @overrides def get_build_snaps(self) -> Set[str]: - return set() + return set(self._options.ros_build_snaps) if self._options.ros_build_snaps else set() @overrides def get_build_packages(self) -> Set[str]: @@ -142,9 +142,9 @@ def _get_list_packages_commands(self) -> List[str]: cmd.append('rm -f "${CRAFT_PART_INSTALL}/.installed_packages.txt"') cmd.append('rm -f "${CRAFT_PART_INSTALL}/.build_snaps.txt"') - if self._options.build_snaps: # type: ignore - for build_snap in self._options.build_snaps: # type: ignore - snap_name = _get_parsed_snap(build_snap)[0] + if self._options.ros_build_snaps: # type: ignore + for ros_build_snap in self._options.ros_build_snaps: # type: ignore + snap_name = _get_parsed_snap(ros_build_snap)[0] path = f"/snap/{snap_name}/current/opt/ros" # pylint: disable=line-too-long cmd.extend( diff --git a/snapcraft/parts/plugins/colcon_plugin.py b/snapcraft/parts/plugins/colcon_plugin.py index c4823e4bc1..01cfec6092 100644 --- a/snapcraft/parts/plugins/colcon_plugin.py +++ b/snapcraft/parts/plugins/colcon_plugin.py @@ -72,7 +72,7 @@ class ColconPluginProperties(plugins.PluginProperties, plugins.PluginModel): colcon_cmake_args: List[str] = [] colcon_packages: List[str] = [] colcon_packages_ignore: List[str] = [] - build_snaps: List[str] = [] + ros_build_snaps: List[str] = [] # part properties required by the plugin source: str @@ -88,8 +88,12 @@ def unmarshal(cls, data: Dict[str, Any]) -> "ColconPluginProperties": :raise pydantic.ValidationError: If validation fails. """ + + # plugin specific parameters have to be prefixed with the plugin name. + # However we'd like to avoid that for 'ros-build-snaps'. + # Marking it required allows us to circumvent the prefix requirement. plugin_data = plugins.extract_plugin_properties( - data, plugin_name="colcon", required=["source", "build-snaps"] + data, plugin_name="colcon", required=["source", "ros-build-snaps"] ) return cls(**plugin_data) @@ -151,9 +155,9 @@ def _get_workspace_activation_commands(self) -> List[str]: # Source ROS ws in all build-snaps first activation_commands.append("## Sourcing ROS ws in build snaps") self._options: ColconPluginProperties - if self._options.build_snaps: - for build_snap in self._options.build_snaps: - snap_name = _get_parsed_snap(build_snap)[0] + if self._options.ros_build_snaps: + for ros_build_snap in self._options.ros_build_snaps: + snap_name = _get_parsed_snap(ros_build_snap)[0] activation_commands.extend( self._get_source_command(f"/snap/{snap_name}/current") ) diff --git a/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py b/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py index 05a07d0a96..3fe250bf00 100644 --- a/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py +++ b/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py @@ -66,7 +66,7 @@ def __init__(self, *, extension_name: str, yaml_data: Dict[str, Any]) -> None: self.part_snippet["stage-packages"] = [f"ros-{self.ROS_DISTRO}-ros-environment"] - self.part_snippet["build-snaps"] = [self.ros_noetic_snaps.sdk] + self.part_snippet["ros-build-snaps"] = [self.ros_noetic_snaps.sdk] python_paths = self.app_snippet["environment"]["PYTHONPATH"] new_python_paths = [ diff --git a/snapcraft_legacy/internal/project_loader/_extensions/_ros2_foxy_meta.py b/snapcraft_legacy/internal/project_loader/_extensions/_ros2_foxy_meta.py index 6b1f11f4b1..adb8b4ac76 100644 --- a/snapcraft_legacy/internal/project_loader/_extensions/_ros2_foxy_meta.py +++ b/snapcraft_legacy/internal/project_loader/_extensions/_ros2_foxy_meta.py @@ -74,7 +74,7 @@ def __init__(self, *, extension_name: str, yaml_data: Dict[str, Any]) -> None: f'-DCMAKE_SYSTEM_PREFIX_PATH="/snap/{self.ros2_foxy_snaps.sdk}/current/usr"' ] - self.part_snippet["build-snaps"] = [self.ros2_foxy_snaps.sdk] + self.part_snippet["ros-build-snaps"] = [self.ros2_foxy_snaps.sdk] python_paths = self.app_snippet["environment"]["PYTHONPATH"] new_python_paths = [ diff --git a/snapcraft_legacy/plugins/v2/_ros.py b/snapcraft_legacy/plugins/v2/_ros.py index d4f1c42a30..066e39c500 100644 --- a/snapcraft_legacy/plugins/v2/_ros.py +++ b/snapcraft_legacy/plugins/v2/_ros.py @@ -77,7 +77,7 @@ class RosPlugin(PluginV2): """Base class for ROS-related plugins. Not intended for use by end users.""" def get_build_snaps(self) -> Set[str]: - return set() + return set(self.options.ros_build_snaps) if self.options.ros_build_snaps else set() def get_build_packages(self) -> Set[str]: return { @@ -129,9 +129,9 @@ def _get_list_packages_commands(self) -> List[str]: cmd.append('rm -f "${SNAPCRAFT_PART_INSTALL}/.installed_packages.txt"') cmd.append('rm -f "${SNAPCRAFT_PART_INSTALL}/.build_snaps.txt"') - if self.options.build_snaps: - for build_snap in self.options.build_snaps: - snap_name = _get_parsed_snap(build_snap)[0] + if self.options.ros_build_snaps: + for ros_build_snap in self.options.ros_build_snaps: + snap_name = _get_parsed_snap(ros_build_snap)[0] path = f"/snap/{snap_name}/current/opt/ros" cmd.extend([ # Retrieve the list of all ROS packages available in the build snap diff --git a/snapcraft_legacy/plugins/v2/catkin.py b/snapcraft_legacy/plugins/v2/catkin.py index 9aded3ae21..d24e62b604 100644 --- a/snapcraft_legacy/plugins/v2/catkin.py +++ b/snapcraft_legacy/plugins/v2/catkin.py @@ -69,6 +69,13 @@ def get_schema(cls) -> Dict[str, Any]: "items": {"type": "string"}, "default": [], }, + "ros-build-snaps": { + "type": "array", + "minItems": 0, + "uniqueItems": True, + "items": {"type": "string"}, + "default": [], + }, }, } @@ -102,9 +109,9 @@ def _get_workspace_activation_commands(self) -> List[str]: # Source ROS ws in all build-snaps first activation_commands.append("## Sourcing ROS ws in build snaps") - if self.options.build_snaps: - for build_snap in self.options.build_snaps: - snap_name = _get_parsed_snap(build_snap)[0] + if self.options.ros_build_snaps: + for ros_build_snap in self.options.ros_build_snaps: + snap_name = _get_parsed_snap(ros_build_snap)[0] activation_commands.extend(self._get_source_command(f"/snap/{snap_name}/current")) activation_commands.append("") diff --git a/snapcraft_legacy/plugins/v2/colcon.py b/snapcraft_legacy/plugins/v2/colcon.py index bdb00b15e0..4ed2e93752 100644 --- a/snapcraft_legacy/plugins/v2/colcon.py +++ b/snapcraft_legacy/plugins/v2/colcon.py @@ -99,6 +99,13 @@ def get_schema(cls) -> Dict[str, Any]: "items": {"type": "string"}, "default": [], }, + "ros-build-snaps": { + "type": "array", + "minItems": 0, + "uniqueItems": True, + "items": {"type": "string"}, + "default": [], + }, }, } @@ -150,9 +157,9 @@ def _get_workspace_activation_commands(self) -> List[str]: # Source ROS ws in all build-snaps first activation_commands.append("## Sourcing ROS ws in build snaps") - if self.options.build_snaps: - for build_snap in self.options.build_snaps: - snap_name = _get_parsed_snap(build_snap)[0] + if self.options.ros_build_snaps: + for ros_build_snap in self.options.ros_build_snaps: + snap_name = _get_parsed_snap(ros_build_snap)[0] activation_commands.extend( self._get_source_command(f"/snap/{snap_name}/current") ) diff --git a/tests/legacy/unit/plugins/v2/test_catkin.py b/tests/legacy/unit/plugins/v2/test_catkin.py index 77dc8024f2..af4024e881 100644 --- a/tests/legacy/unit/plugins/v2/test_catkin.py +++ b/tests/legacy/unit/plugins/v2/test_catkin.py @@ -45,6 +45,13 @@ def test_schema(): "type": "array", "uniqueItems": True, }, + "ros-build-snaps": { + "default": [], + "items": {"type": "string"}, + "minItems": 0, + "type": "array", + "uniqueItems": True, + }, }, "type": "object", } @@ -60,6 +67,22 @@ def test_get_build_packages(): } +def test_get_build_snaps(): + class OptionsDefault: + ros_build_snaps = list() + + plugin = catkin.CatkinPlugin(part_name="my-part", options=OptionsDefault()) + + assert plugin.get_build_snaps() == set() + + class Options: + ros_build_snaps = ["Foo"] + + plugin = catkin.CatkinPlugin(part_name="my-part", options=Options()) + + assert plugin.get_build_snaps() == {"Foo"} + + def test_get_build_environment(): plugin = catkin.CatkinPlugin(part_name="my-part", options=lambda: None) @@ -79,7 +102,7 @@ class Options: catkin_cmake_args = list() catkin_packages = list() catkin_packages_ignore = list() - build_snaps = list() + ros_build_snaps = list() plugin = catkin.CatkinPlugin(part_name="my-part", options=Options()) @@ -161,7 +184,7 @@ class Options: catkin_cmake_args = ["cmake", "args..."] catkin_packages = ["package1", "package2..."] catkin_packages_ignore = ["ipackage1", "ipackage2..."] - build_snaps = ["foo"] + ros_build_snaps = ["foo"] plugin = catkin.CatkinPlugin(part_name="my-part", options=Options()) diff --git a/tests/legacy/unit/plugins/v2/test_colcon.py b/tests/legacy/unit/plugins/v2/test_colcon.py index dd76785d6e..284bbf59ae 100644 --- a/tests/legacy/unit/plugins/v2/test_colcon.py +++ b/tests/legacy/unit/plugins/v2/test_colcon.py @@ -57,6 +57,13 @@ def test_schema(): "type": "array", "uniqueItems": True, }, + "ros-build-snaps": { + "type": "array", + "minItems": 0, + "uniqueItems": True, + "items": {"type": "string"}, + "default": [], + }, }, "type": "object", } @@ -74,6 +81,22 @@ def test_get_build_packages(): } +def test_get_build_snaps(): + class OptionsDefault: + ros_build_snaps = list() + + plugin = colcon.ColconPlugin(part_name="my-part", options=OptionsDefault()) + + assert plugin.get_build_snaps() == set() + + class Options: + ros_build_snaps = ["Foo"] + + plugin = colcon.ColconPlugin(part_name="my-part", options=Options()) + + assert plugin.get_build_snaps() == {"Foo"} + + def test_get_build_environment(): plugin = colcon.ColconPlugin(part_name="my-part", options=lambda: None) @@ -97,7 +120,7 @@ class Options: colcon_cmake_args = list() colcon_packages = list() colcon_packages_ignore = list() - build_snaps = list() + ros_build_snaps = list() plugin = colcon.ColconPlugin(part_name="my-part", options=Options()) @@ -188,7 +211,7 @@ class Options: colcon_cmake_args = ["cmake", "args..."] colcon_packages = ["package1", "package2..."] colcon_packages_ignore = ["ipackage1", "ipackage2..."] - build_snaps = ["foo"] + ros_build_snaps = ["foo"] plugin = colcon.ColconPlugin(part_name="my-part", options=Options()) diff --git a/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py b/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py index 33eb18ab2c..e90bc328df 100644 --- a/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py +++ b/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py @@ -122,7 +122,7 @@ def test_extension(self, extension_name, extension_class, meta, meta_dev): assert ros1_extension.part_snippet == { "build-environment": [{"ROS_VERSION": "1"}, {"ROS_DISTRO": "noetic"}], - "build-snaps": [meta_dev], + "ros-build-snaps": [meta_dev], "catkin-cmake-args": [ f'-DCMAKE_SYSTEM_PREFIX_PATH="/snap/{meta_dev}/current/usr"' ], diff --git a/tests/legacy/unit/project_loader/extensions/test_ros2_foxy_meta.py b/tests/legacy/unit/project_loader/extensions/test_ros2_foxy_meta.py index ea465e22e4..dfca38062b 100644 --- a/tests/legacy/unit/project_loader/extensions/test_ros2_foxy_meta.py +++ b/tests/legacy/unit/project_loader/extensions/test_ros2_foxy_meta.py @@ -102,7 +102,7 @@ def test_extension(self, extension_name, extension_class, meta, meta_dev): assert ros_extension.part_snippet == { "build-environment": [{"ROS_VERSION": "2"}, {"ROS_DISTRO": "foxy"}], - "build-snaps": [meta_dev], + "ros-build-snaps": [meta_dev], "colcon-cmake-args": [ f'-DCMAKE_SYSTEM_PREFIX_PATH="/snap/{meta_dev}/current/usr"' ], diff --git a/tests/unit/parts/extensions/test_ros2_humble_meta.py b/tests/unit/parts/extensions/test_ros2_humble_meta.py index 76e31c86f3..a0bc8da80d 100644 --- a/tests/unit/parts/extensions/test_ros2_humble_meta.py +++ b/tests/unit/parts/extensions/test_ros2_humble_meta.py @@ -166,7 +166,7 @@ def test_get_part_snippet(self, extension_name, extension_class, meta, meta_dev) extension = setup_method_fixture(extension_class) assert extension.get_part_snippet() == { "build-environment": [{"ROS_VERSION": "2"}, {"ROS_DISTRO": "humble"}], - "build-snaps": [meta_dev], + "ros-build-snaps": [meta_dev], "colcon-cmake-args": [ f'-DCMAKE_SYSTEM_PREFIX_PATH="/snap/{meta_dev}/current/usr"' ], diff --git a/tests/unit/parts/plugins/test_colcon.py b/tests/unit/parts/plugins/test_colcon.py index dda794262f..b804d43c1d 100644 --- a/tests/unit/parts/plugins/test_colcon.py +++ b/tests/unit/parts/plugins/test_colcon.py @@ -99,7 +99,7 @@ def test_property_all(self): "colcon-cmake-args": ["cmake", "args..."], "colcon-packages": ["package1", "package2..."], "colcon-packages-ignore": ["ipackage1", "ipackage2..."], - "build-snaps": ["ros-core"], + "ros-build-snaps": ["ros-core"], } ) except ValidationError as e: @@ -111,7 +111,7 @@ def test_property_all(self): assert properties.colcon_cmake_args == ["cmake", "args..."] # type: ignore assert properties.colcon_packages == ["package1", "package2..."] # type: ignore assert properties.colcon_packages_ignore == ["ipackage1", "ipackage2..."] # type: ignore - assert properties.build_snaps == ["ros-core"] # type: ignore + assert properties.ros_build_snaps == ["ros-core"] # type: ignore def test_get_build_packages(self, setup_method_fixture, new_dir): plugin = setup_method_fixture(new_dir) @@ -124,6 +124,26 @@ def test_get_build_packages(self, setup_method_fixture, new_dir): "rospack-tools", } + def test_get_build_snaps(self, setup_method_fixture, new_dir): + plugin = setup_method_fixture(new_dir) + + assert plugin.get_build_snaps() == set() + + plugin = setup_method_fixture( + new_dir, + properties={ + "source": ".", + "colcon-ament-cmake-args": [], + "colcon-catkin-cmake-args": [], + "colcon-cmake-args": [], + "colcon-packages": [], + "colcon-packages-ignore": [], + "ros-build-snaps": ["Foo"], + }, + ) + + assert plugin.get_build_snaps() == {"Foo"} + def test_get_build_environment(self, setup_method_fixture, new_dir): plugin = setup_method_fixture(new_dir) @@ -237,7 +257,7 @@ def test_get_build_commands_with_all_properties( "colcon-cmake-args": ["cmake", "args..."], "colcon-packages": ["package1", "package2..."], "colcon-packages-ignore": ["ipackage1", "ipackage2..."], - "build-snaps": ["foo"], + "ros-build-snaps": ["foo"], }, ) From 23ed7bfa737ef16a88f4f3f09880aec4d0536318 Mon Sep 17 00:00:00 2001 From: artivis Date: Thu, 8 Jun 2023 12:58:50 +0200 Subject: [PATCH 61/84] ros: noetic plugins common cmake args var Signed-off-by: artivis --- .../project_loader/_extensions/_ros1_noetic_meta.py | 2 +- snapcraft_legacy/plugins/v2/catkin.py | 12 ++++++++++-- tests/legacy/unit/plugins/v2/test_catkin.py | 10 +++++++++- .../extensions/test_ros1_noetic_meta.py | 2 +- 4 files changed, 21 insertions(+), 5 deletions(-) diff --git a/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py b/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py index 3fe250bf00..27615baa97 100644 --- a/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py +++ b/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py @@ -60,7 +60,7 @@ def __init__(self, *, extension_name: str, yaml_data: Dict[str, Any]) -> None: } } - self.part_snippet["catkin-cmake-args"] = [ + self.part_snippet["ros-content-sharing-extension-cmake-args"] = [ f'-DCMAKE_SYSTEM_PREFIX_PATH="/snap/{self.ros_noetic_snaps.sdk}/current/usr"' ] diff --git a/snapcraft_legacy/plugins/v2/catkin.py b/snapcraft_legacy/plugins/v2/catkin.py index d24e62b604..52c21bdac2 100644 --- a/snapcraft_legacy/plugins/v2/catkin.py +++ b/snapcraft_legacy/plugins/v2/catkin.py @@ -76,6 +76,12 @@ def get_schema(cls) -> Dict[str, Any]: "items": {"type": "string"}, "default": [], }, + "ros-content-sharing-extension-cmake-args": { + "type": "array", + "minItems": 0, + "items": {"type": "string"}, + "default": [], + }, }, } @@ -149,7 +155,9 @@ def _get_build_commands(self) -> List[str]: if self.options.catkin_packages_ignore: build_command.extend(["--ignore-pkg", *self.options.catkin_packages_ignore]) - if self.options.catkin_cmake_args: - build_command.extend(["--cmake-args", *self.options.catkin_cmake_args]) + if self.options.catkin_cmake_args or self.options.ros_content_sharing_extension_cmake_args: + build_command.append("--cmake-args") + build_command.extend(self.options.catkin_cmake_args) + build_command.extend(self.options.ros_content_sharing_extension_cmake_args) return (["## Build command", " ".join(build_command)]) diff --git a/tests/legacy/unit/plugins/v2/test_catkin.py b/tests/legacy/unit/plugins/v2/test_catkin.py index af4024e881..6493afb46f 100644 --- a/tests/legacy/unit/plugins/v2/test_catkin.py +++ b/tests/legacy/unit/plugins/v2/test_catkin.py @@ -52,6 +52,12 @@ def test_schema(): "type": "array", "uniqueItems": True, }, + "ros-content-sharing-extension-cmake-args": { + "type": "array", + "minItems": 0, + "items": {"type": "string"}, + "default": [], + }, }, "type": "object", } @@ -103,6 +109,7 @@ class Options: catkin_packages = list() catkin_packages_ignore = list() ros_build_snaps = list() + ros_content_sharing_extension_cmake_args = list() plugin = catkin.CatkinPlugin(part_name="my-part", options=Options()) @@ -185,6 +192,7 @@ class Options: catkin_packages = ["package1", "package2..."] catkin_packages_ignore = ["ipackage1", "ipackage2..."] ros_build_snaps = ["foo"] + ros_content_sharing_extension_cmake_args = ["DCMAKE_EXNTENSION_ARGS", "bar"] plugin = catkin.CatkinPlugin(part_name="my-part", options=Options()) @@ -298,7 +306,7 @@ class Options: '--source-space "${SNAPCRAFT_PART_SRC_WORK}" --build-space "${SNAPCRAFT_PART_BUILD}" ' '--install-space "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}" ' '-j "${SNAPCRAFT_PARALLEL_BUILD_COUNT}" --pkg package1 package2... ' - "--ignore-pkg ipackage1 ipackage2... --cmake-args cmake args...", + "--ignore-pkg ipackage1 ipackage2... --cmake-args cmake args... DCMAKE_EXNTENSION_ARGS bar", "env -i LANG=C.UTF-8 LC_ALL=C.UTF-8 PATH=/bin:/test SNAP=TESTSNAP " "SNAP_ARCH=TESTARCH SNAP_NAME=TESTSNAPNAME SNAP_VERSION=TESTV1 " "http_proxy=http://foo https_proxy=https://bar " diff --git a/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py b/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py index e90bc328df..2f64b4db39 100644 --- a/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py +++ b/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py @@ -123,7 +123,7 @@ def test_extension(self, extension_name, extension_class, meta, meta_dev): assert ros1_extension.part_snippet == { "build-environment": [{"ROS_VERSION": "1"}, {"ROS_DISTRO": "noetic"}], "ros-build-snaps": [meta_dev], - "catkin-cmake-args": [ + "ros-content-sharing-extension-cmake-args": [ f'-DCMAKE_SYSTEM_PREFIX_PATH="/snap/{meta_dev}/current/usr"' ], "stage-packages": ["ros-noetic-ros-environment"], From 6a47ebd8ff3652103279c39473692bef4999c927 Mon Sep 17 00:00:00 2001 From: artivis Date: Thu, 8 Jun 2023 13:00:12 +0200 Subject: [PATCH 62/84] ros: catkin_tools support for content sharing Signed-off-by: artivis --- snapcraft_legacy/plugins/v2/catkin_tools.py | 56 +++++- .../unit/plugins/v2/test_catkin_tools.py | 165 ++++++++++++++++-- .../catkin-tools-noetic-meta-hello/task.yaml | 76 ++++++++ 3 files changed, 283 insertions(+), 14 deletions(-) create mode 100644 tests/spread/extensions/catkin-tools-noetic-meta-hello/task.yaml diff --git a/snapcraft_legacy/plugins/v2/catkin_tools.py b/snapcraft_legacy/plugins/v2/catkin_tools.py index 6270e4cf1b..5c466525af 100644 --- a/snapcraft_legacy/plugins/v2/catkin_tools.py +++ b/snapcraft_legacy/plugins/v2/catkin_tools.py @@ -33,6 +33,7 @@ from typing import Any, Dict, List, Set +from snapcraft_legacy.internal.repo.snaps import _get_parsed_snap from snapcraft_legacy.plugins.v2 import _ros @@ -56,6 +57,19 @@ def get_schema(cls) -> Dict[str, Any]: "uniqueItems": True, "items": {"type": "string"}, }, + "ros-build-snaps": { + "type": "array", + "minItems": 0, + "uniqueItems": True, + "items": {"type": "string"}, + "default": [], + }, + "ros-content-sharing-extension-cmake-args": { + "type": "array", + "minItems": 0, + "items": {"type": "string"}, + "default": [], + }, }, } @@ -64,6 +78,17 @@ def get_build_packages(self) -> Set[str]: "python3-catkin-tools", } + def _get_source_command(self, path: str) -> List[str]: + return [ + f'if [ -f "{path}/opt/ros/${{ROS_DISTRO}}/setup.sh" ]; then', + 'set -- --local "${_EXTEND_WS}"', + '_CATKIN_SETUP_DIR="{fpath}" . "{fpath}/setup.sh"'.format( + fpath=f"{path}/opt/ros/${{ROS_DISTRO}}" + ), + 'if [ -z ${_EXTEND_WS} ]; then _EXTEND_WS="--extend"; fi', + "fi", + ] + def _get_workspace_activation_commands(self) -> List[str]: """Return a list of commands to source a ROS workspace. @@ -76,6 +101,28 @@ def _get_workspace_activation_commands(self) -> List[str]: specific functionality. """ + activation_commands = list() + + # Source ROS ws in all build-snaps first + activation_commands.append("## Sourcing ROS ws in build snaps") + if self.options.ros_build_snaps: + for ros_build_snap in self.options.ros_build_snaps: + snap_name = _get_parsed_snap(ros_build_snap)[0] + activation_commands.extend(self._get_source_command(f"/snap/{snap_name}/current")) + activation_commands.append("") + + # Source ROS ws in stage-snaps next + activation_commands.append("## Sourcing ROS ws in stage snaps") + activation_commands.extend(self._get_source_command("${SNAPCRAFT_PART_INSTALL}")) + activation_commands.append("") + + # Finally source system's ROS ws + activation_commands.append("## Sourcing ROS ws in system") + activation_commands.extend(self._get_source_command("")) + activation_commands.append("") + + return activation_commands + # There are a number of unbound vars, disable flag # after saving current state to restore after. return [ @@ -119,9 +166,14 @@ def _get_build_commands(self) -> List[str]: '"${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}"', ] - if self.options.catkin_tools_cmake_args: + if self.options.catkin_tools_cmake_args or self.options.ros_content_sharing_extension_cmake_args: + cmake_args = [] + if self.options.catkin_tools_cmake_args: + cmake_args.extend(self.options.catkin_tools_cmake_args) + if self.options.ros_content_sharing_extension_cmake_args: + cmake_args.extend(self.options.ros_content_sharing_extension_cmake_args) catkin_config_command.extend( - ["--cmake-args", *self.options.catkin_tools_cmake_args] + ["--cmake-args", *cmake_args] ) commands.append(" ".join(catkin_config_command)) diff --git a/tests/legacy/unit/plugins/v2/test_catkin_tools.py b/tests/legacy/unit/plugins/v2/test_catkin_tools.py index fc1c7905af..a3e1deb554 100644 --- a/tests/legacy/unit/plugins/v2/test_catkin_tools.py +++ b/tests/legacy/unit/plugins/v2/test_catkin_tools.py @@ -38,6 +38,19 @@ def test_schema(): "type": "array", "uniqueItems": True, }, + "ros-build-snaps": { + "type": "array", + "minItems": 0, + "uniqueItems": True, + "items": {"type": "string"}, + "default": [], + }, + "ros-content-sharing-extension-cmake-args": { + "type": "array", + "minItems": 0, + "items": {"type": "string"}, + "default": [], + }, }, "type": "object", } @@ -49,9 +62,26 @@ def test_get_build_packages(): assert plugin.get_build_packages() == { "python3-rosdep", "python3-catkin-tools", + "rospack-tools", } +def test_get_build_snaps(): + class OptionsDefault: + ros_build_snaps = list() + + plugin = catkin_tools.CatkinToolsPlugin(part_name="my-part", options=OptionsDefault()) + + assert plugin.get_build_snaps() == set() + + class Options: + ros_build_snaps = ["Foo"] + + plugin = catkin_tools.CatkinToolsPlugin(part_name="my-part", options=Options()) + + assert plugin.get_build_snaps() == {"Foo"} + + def test_get_build_environment(): plugin = catkin_tools.CatkinToolsPlugin(part_name="my-part", options=lambda: None) @@ -70,6 +100,8 @@ def test_get_build_commands(monkeypatch): class Options: catkin_tools_cmake_args = list() catkin_tools_packages = list() + ros_build_snaps = list() + ros_content_sharing_extension_cmake_args = list() plugin = catkin_tools.CatkinToolsPlugin(part_name="my-part", options=Options()) @@ -79,6 +111,7 @@ class Options: monkeypatch.setattr(os, "environ", dict()) assert plugin.get_build_commands() == [ +<<<<<<< HEAD 'state="$(set +o); set -$-"', "set +u", 'if [ -f "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/setup.sh" ]; then', @@ -92,18 +125,57 @@ class Options: 'eval "${state}"', "if [ ! -f /etc/ros/rosdep/sources.list.d/20-default.list ]; then", "sudo --preserve-env=http_proxy,https_proxy rosdep init; fi", +======= + "if [ ! -f /etc/ros/rosdep/sources.list.d/20-default.list ]; then sudo rosdep " + "init; fi", +>>>>>>> 699b39a7 (ros: catkin_tools support for content sharing) 'rosdep update --include-eol-distros --rosdistro "${ROS_DISTRO}"', + 'state="$(set +o); set -$-"', + "set +u", + '', + '## Sourcing ROS ws in build snaps', + '## Sourcing ROS ws in stage snaps', + + 'if [ -f "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/setup.sh" ]; then', + 'set -- --local "${_EXTEND_WS}"', + '_CATKIN_SETUP_DIR="${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}" . ' + '"${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/setup.sh"', + 'if [ -z ${_EXTEND_WS} ]; then _EXTEND_WS="--extend"; fi', + 'fi', + '', + '## Sourcing ROS ws in system', + 'if [ -f "/opt/ros/${ROS_DISTRO}/setup.sh" ]; then', + 'set -- --local "${_EXTEND_WS}"', + '_CATKIN_SETUP_DIR="/opt/ros/${ROS_DISTRO}" . ' + '"/opt/ros/${ROS_DISTRO}/setup.sh"', + 'if [ -z ${_EXTEND_WS} ]; then _EXTEND_WS="--extend"; fi', + 'fi', + '', + 'eval "${state}"', + 'rm -f "${SNAPCRAFT_PART_INSTALL}/.installed_packages.txt"', + 'rm -f "${SNAPCRAFT_PART_INSTALL}/.build_snaps.txt"', + 'rosdep install --default-yes --ignore-packages-from-source --from-paths "${SNAPCRAFT_PART_SRC_WORK}"', 'state="$(set +o); set -$-"', "set +u", + '', + '## Sourcing ROS ws in build snaps', + '## Sourcing ROS ws in stage snaps', 'if [ -f "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/setup.sh" ]; then', - "set -- --local", - '_CATKIN_SETUP_DIR="${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}" . "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/setup.sh"', - "set -- --local --extend", - "else", - "set -- --local", + 'set -- --local "${_EXTEND_WS}"', + '_CATKIN_SETUP_DIR="${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}" . ' + '"${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/setup.sh"', + 'if [ -z ${_EXTEND_WS} ]; then _EXTEND_WS="--extend"; fi', "fi", - '. /opt/ros/"${ROS_DISTRO}"/setup.sh', + '', + '## Sourcing ROS ws in system', + 'if [ -f "/opt/ros/${ROS_DISTRO}/setup.sh" ]; then', + 'set -- --local "${_EXTEND_WS}"', + '_CATKIN_SETUP_DIR="/opt/ros/${ROS_DISTRO}" . ' + '"/opt/ros/${ROS_DISTRO}/setup.sh"', + 'if [ -z ${_EXTEND_WS} ]; then _EXTEND_WS="--extend"; fi', + 'fi', + '', 'eval "${state}"', "catkin init", "catkin profile add -f default", @@ -122,6 +194,8 @@ def test_get_build_commands_with_all_properties(monkeypatch): class Options: catkin_tools_cmake_args = ["cmake", "args..."] catkin_tools_packages = ["package1", "package2..."] + ros_build_snaps = ["foo"] + ros_content_sharing_extension_cmake_args = ["DCMAKE_EXNTENSION_ARGS", "bar"] plugin = catkin_tools.CatkinToolsPlugin(part_name="my-part", options=Options()) @@ -158,23 +232,90 @@ class Options: "if [ ! -f /etc/ros/rosdep/sources.list.d/20-default.list ]; then", "sudo --preserve-env=http_proxy,https_proxy rosdep init; fi", 'rosdep update --include-eol-distros --rosdistro "${ROS_DISTRO}"', + + 'state="$(set +o); set -$-"', + 'set +u', + '', + '## Sourcing ROS ws in build snaps', + 'if [ -f "/snap/foo/current/opt/ros/${ROS_DISTRO}/setup.sh" ]; then', + 'set -- --local "${_EXTEND_WS}"', + '_CATKIN_SETUP_DIR="/snap/foo/current/opt/ros/${ROS_DISTRO}" . ' + '"/snap/foo/current/opt/ros/${ROS_DISTRO}/setup.sh"', + 'if [ -z ${_EXTEND_WS} ]; then _EXTEND_WS="--extend"; fi', + 'fi', + '', + '## Sourcing ROS ws in stage snaps', + 'if [ -f "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/setup.sh" ]; then', + 'set -- --local "${_EXTEND_WS}"', + '_CATKIN_SETUP_DIR="${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}" . ' + '"${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/setup.sh"', + 'if [ -z ${_EXTEND_WS} ]; then _EXTEND_WS="--extend"; fi', + 'fi', + '', + '## Sourcing ROS ws in system', + 'if [ -f "/opt/ros/${ROS_DISTRO}/setup.sh" ]; then', + 'set -- --local "${_EXTEND_WS}"', + '_CATKIN_SETUP_DIR="/opt/ros/${ROS_DISTRO}" . ' + '"/opt/ros/${ROS_DISTRO}/setup.sh"', + 'if [ -z ${_EXTEND_WS} ]; then _EXTEND_WS="--extend"; fi', + 'fi', + '', + 'eval "${state}"', + 'rm -f "${SNAPCRAFT_PART_INSTALL}/.installed_packages.txt"', + 'rm -f "${SNAPCRAFT_PART_INSTALL}/.build_snaps.txt"', + 'if [ -d /snap/foo/current/opt/ros ]; then', + 'ROS_PACKAGE_PATH=/snap/foo/current/opt/ros rospack list-names | (xargs ' + 'rosdep resolve --rosdistro "${ROS_DISTRO}" || echo "") | awk ' + '"/#apt/{getline;print;}" >> ' + '"${SNAPCRAFT_PART_INSTALL}/.installed_packages.txt"', + 'fi', + 'if [ -d "/snap/foo/current/opt/ros/${ROS_DISTRO}/" ]; then', + 'rosdep keys --rosdistro "${ROS_DISTRO}" --from-paths ' + '"/snap/foo/current/opt/ros/${ROS_DISTRO}" --ignore-packages-from-source | ' + '(xargs rosdep resolve --rosdistro "${ROS_DISTRO}" || echo "") | grep -v "#" ' + '>> "${SNAPCRAFT_PART_INSTALL}"/.installed_packages.txt', + 'fi', + 'if [ -d "/snap/foo/current/opt/ros/snap/" ]; then', + 'rosdep keys --rosdistro "${ROS_DISTRO}" --from-paths ' + '"/snap/foo/current/opt/ros/snap" --ignore-packages-from-source | (xargs ' + 'rosdep resolve --rosdistro "${ROS_DISTRO}" || echo "") | grep -v "#" >> ' + '"${SNAPCRAFT_PART_INSTALL}"/.installed_packages.txt', + 'fi', + '', + 'rosdep install --default-yes --ignore-packages-from-source --from-paths "${SNAPCRAFT_PART_SRC_WORK}"', 'state="$(set +o); set -$-"', "set +u", + '', + '## Sourcing ROS ws in build snaps', + 'if [ -f "/snap/foo/current/opt/ros/${ROS_DISTRO}/setup.sh" ]; then', + 'set -- --local "${_EXTEND_WS}"', + '_CATKIN_SETUP_DIR="/snap/foo/current/opt/ros/${ROS_DISTRO}" . ' + '"/snap/foo/current/opt/ros/${ROS_DISTRO}/setup.sh"', + 'if [ -z ${_EXTEND_WS} ]; then _EXTEND_WS="--extend"; fi', + 'fi', + '', + '## Sourcing ROS ws in stage snaps', 'if [ -f "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/setup.sh" ]; then', - "set -- --local", + 'set -- --local "${_EXTEND_WS}"', '_CATKIN_SETUP_DIR="${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}" . "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/setup.sh"', - "set -- --local --extend", - "else", - "set -- --local", + 'if [ -z ${_EXTEND_WS} ]; then _EXTEND_WS="--extend"; fi', "fi", - '. /opt/ros/"${ROS_DISTRO}"/setup.sh', + '', + '## Sourcing ROS ws in system', + 'if [ -f "/opt/ros/${ROS_DISTRO}/setup.sh" ]; then', + 'set -- --local "${_EXTEND_WS}"', + '_CATKIN_SETUP_DIR="/opt/ros/${ROS_DISTRO}" . ' + '"/opt/ros/${ROS_DISTRO}/setup.sh"', + 'if [ -z ${_EXTEND_WS} ]; then _EXTEND_WS="--extend"; fi', + 'fi', + '', 'eval "${state}"', "catkin init", "catkin profile add -f default", "catkin config --profile default --install " '--source-space "${SNAPCRAFT_PART_SRC_WORK}" --build-space "${SNAPCRAFT_PART_BUILD}" ' - '--install-space "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}" --cmake-args cmake args...', + '--install-space "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}" --cmake-args cmake args... DCMAKE_EXNTENSION_ARGS bar', 'catkin build --no-notify --profile default -j "${SNAPCRAFT_PARALLEL_BUILD_COUNT}" package1 package2...', "env -i LANG=C.UTF-8 LC_ALL=C.UTF-8 PATH=/bin:/test SNAP=TESTSNAP " "SNAP_ARCH=TESTARCH SNAP_NAME=TESTSNAPNAME SNAP_VERSION=TESTV1 " diff --git a/tests/spread/extensions/catkin-tools-noetic-meta-hello/task.yaml b/tests/spread/extensions/catkin-tools-noetic-meta-hello/task.yaml new file mode 100644 index 0000000000..6d673f43cb --- /dev/null +++ b/tests/spread/extensions/catkin-tools-noetic-meta-hello/task.yaml @@ -0,0 +1,76 @@ +summary: Build and run a basic ROS snap using meta-ros extension + +kill-timeout: 180m + +environment: + + SNAPCRAFT_ENABLE_EXPERIMENTAL_EXTENSIONS: "1" + + SNAP: catkin-tools-noetic-hello + SNAP_DIR: "../../plugins/v2/snaps/$SNAP" + + INTERFACE: ros-noetic + + META_SNAP/catkin_noetic_ros_core: ros-noetic-ros-core + EXTENSION/catkin_noetic_ros_core: ros1-noetic-ros-core + + META_SNAP/catkin_noetic_ros_base: ros-noetic-ros-base + EXTENSION/catkin_noetic_ros_base: ros1-noetic-ros-base + + META_SNAP/catkin_noetic_robot: ros-noetic-robot + EXTENSION/catkin_noetic_robot: ros1-noetic-robot + + META_SNAP/catkin_noetic_desktop: ros-noetic-desktop + EXTENSION/catkin_noetic_desktop: ros1-noetic-desktop + +# The content snap required for the test to succeed is only +# available on a subset of all the architectures this testbed +# can run on. +systems: + - ubuntu-20.04 + - ubuntu-20.04-64 + - ubuntu-20.04-amd64 + - ubuntu-20.04-arm64 + +prepare: | + #shellcheck source=tests/spread/tools/snapcraft-yaml.sh + . "$TOOLS_DIR/snapcraft-yaml.sh" + set_base "$SNAP_DIR/snap/snapcraft.yaml" + + # Overwrite the extension to test them all out of a single snap + sed -i "s|ros1-noetic|${EXTENSION}|" "$SNAP_DIR/snap/snapcraft.yaml" + + #shellcheck source=tests/spread/tools/package-utils.sh + . "$TOOLS_DIR/package-utils.sh" + create_dpkg_restore_point + +restore: | + cd "$SNAP_DIR" + snapcraft clean + rm -f ./*.snap + + #shellcheck source=tests/spread/tools/snapcraft-yaml.sh + . "$TOOLS_DIR/snapcraft-yaml.sh" + restore_yaml "snap/snapcraft.yaml" + + #shellcheck source=tests/spread/tools/package-utils.sh + . "$TOOLS_DIR/package-utils.sh" + dpkg_restore_point + +execute: | + cd "$SNAP_DIR" + + # Build what we have and verify the snap runs as expected. + snapcraft + snap install "${SNAP}"_1.0_*.snap --dangerous + + # Check that the snap size is fairly small + # The non-content sharing snap is ~90M + SNAP_SIZE=$(find . -maxdepth 1 -mindepth 1 -name '*_1.0_*.snap' -exec ls -s {} + | cut -d " " -f1) + [ "100" -gt "$SNAP_SIZE" ] + + # # Install the providing snap + # snap install "${META_SNAP}" + + snap connect "${SNAP}":"${INTERFACE}" "${META_SNAP}":"${INTERFACE}" + [ "$($SNAP)" = "hello world" ] From f1babb29ee8fcc160dfd9b11d05ec81e87e1bdd2 Mon Sep 17 00:00:00 2001 From: artivis Date: Thu, 8 Jun 2023 13:29:24 +0200 Subject: [PATCH 63/84] ros: please linters Signed-off-by: artivis --- snapcraft/parts/plugins/_ros.py | 6 +- .../unit/plugins/v2/test_catkin_tools.py | 90 +++++++++---------- 2 files changed, 49 insertions(+), 47 deletions(-) diff --git a/snapcraft/parts/plugins/_ros.py b/snapcraft/parts/plugins/_ros.py index fc1668bfcb..0710a25d19 100644 --- a/snapcraft/parts/plugins/_ros.py +++ b/snapcraft/parts/plugins/_ros.py @@ -86,7 +86,11 @@ class RosPlugin(plugins.Plugin): @overrides def get_build_snaps(self) -> Set[str]: - return set(self._options.ros_build_snaps) if self._options.ros_build_snaps else set() + return ( + set(self._options.ros_build_snaps) # type: ignore + if self._options.ros_build_snaps # type: ignore + else set() + ) @overrides def get_build_packages(self) -> Set[str]: diff --git a/tests/legacy/unit/plugins/v2/test_catkin_tools.py b/tests/legacy/unit/plugins/v2/test_catkin_tools.py index a3e1deb554..52beb8b0cc 100644 --- a/tests/legacy/unit/plugins/v2/test_catkin_tools.py +++ b/tests/legacy/unit/plugins/v2/test_catkin_tools.py @@ -70,7 +70,9 @@ def test_get_build_snaps(): class OptionsDefault: ros_build_snaps = list() - plugin = catkin_tools.CatkinToolsPlugin(part_name="my-part", options=OptionsDefault()) + plugin = catkin_tools.CatkinToolsPlugin( + part_name="my-part", options=OptionsDefault() + ) assert plugin.get_build_snaps() == set() @@ -132,50 +134,48 @@ class Options: 'rosdep update --include-eol-distros --rosdistro "${ROS_DISTRO}"', 'state="$(set +o); set -$-"', "set +u", - '', - '## Sourcing ROS ws in build snaps', - '## Sourcing ROS ws in stage snaps', - + "", + "## Sourcing ROS ws in build snaps", + "## Sourcing ROS ws in stage snaps", 'if [ -f "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/setup.sh" ]; then', 'set -- --local "${_EXTEND_WS}"', '_CATKIN_SETUP_DIR="${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}" . ' '"${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/setup.sh"', 'if [ -z ${_EXTEND_WS} ]; then _EXTEND_WS="--extend"; fi', - 'fi', - '', - '## Sourcing ROS ws in system', + "fi", + "", + "## Sourcing ROS ws in system", 'if [ -f "/opt/ros/${ROS_DISTRO}/setup.sh" ]; then', 'set -- --local "${_EXTEND_WS}"', '_CATKIN_SETUP_DIR="/opt/ros/${ROS_DISTRO}" . ' '"/opt/ros/${ROS_DISTRO}/setup.sh"', 'if [ -z ${_EXTEND_WS} ]; then _EXTEND_WS="--extend"; fi', - 'fi', - '', + "fi", + "", 'eval "${state}"', 'rm -f "${SNAPCRAFT_PART_INSTALL}/.installed_packages.txt"', 'rm -f "${SNAPCRAFT_PART_INSTALL}/.build_snaps.txt"', - 'rosdep install --default-yes --ignore-packages-from-source --from-paths "${SNAPCRAFT_PART_SRC_WORK}"', 'state="$(set +o); set -$-"', "set +u", - '', - '## Sourcing ROS ws in build snaps', - '## Sourcing ROS ws in stage snaps', + "", + "## Sourcing ROS ws in build snaps", + "## Sourcing ROS ws in stage snaps", 'if [ -f "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/setup.sh" ]; then', 'set -- --local "${_EXTEND_WS}"', '_CATKIN_SETUP_DIR="${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}" . ' '"${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/setup.sh"', 'if [ -z ${_EXTEND_WS} ]; then _EXTEND_WS="--extend"; fi', "fi", - '', - '## Sourcing ROS ws in system', + "", + "## Sourcing ROS ws in system", 'if [ -f "/opt/ros/${ROS_DISTRO}/setup.sh" ]; then', 'set -- --local "${_EXTEND_WS}"', '_CATKIN_SETUP_DIR="/opt/ros/${ROS_DISTRO}" . ' '"/opt/ros/${ROS_DISTRO}/setup.sh"', 'if [ -z ${_EXTEND_WS} ]; then _EXTEND_WS="--extend"; fi', - 'fi', - '', + "fi", + "", 'eval "${state}"', "catkin init", "catkin profile add -f default", @@ -232,84 +232,82 @@ class Options: "if [ ! -f /etc/ros/rosdep/sources.list.d/20-default.list ]; then", "sudo --preserve-env=http_proxy,https_proxy rosdep init; fi", 'rosdep update --include-eol-distros --rosdistro "${ROS_DISTRO}"', - 'state="$(set +o); set -$-"', - 'set +u', - '', - '## Sourcing ROS ws in build snaps', + "set +u", + "", + "## Sourcing ROS ws in build snaps", 'if [ -f "/snap/foo/current/opt/ros/${ROS_DISTRO}/setup.sh" ]; then', 'set -- --local "${_EXTEND_WS}"', '_CATKIN_SETUP_DIR="/snap/foo/current/opt/ros/${ROS_DISTRO}" . ' '"/snap/foo/current/opt/ros/${ROS_DISTRO}/setup.sh"', 'if [ -z ${_EXTEND_WS} ]; then _EXTEND_WS="--extend"; fi', - 'fi', - '', - '## Sourcing ROS ws in stage snaps', + "fi", + "", + "## Sourcing ROS ws in stage snaps", 'if [ -f "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/setup.sh" ]; then', 'set -- --local "${_EXTEND_WS}"', '_CATKIN_SETUP_DIR="${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}" . ' '"${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/setup.sh"', 'if [ -z ${_EXTEND_WS} ]; then _EXTEND_WS="--extend"; fi', - 'fi', - '', - '## Sourcing ROS ws in system', + "fi", + "", + "## Sourcing ROS ws in system", 'if [ -f "/opt/ros/${ROS_DISTRO}/setup.sh" ]; then', 'set -- --local "${_EXTEND_WS}"', '_CATKIN_SETUP_DIR="/opt/ros/${ROS_DISTRO}" . ' '"/opt/ros/${ROS_DISTRO}/setup.sh"', 'if [ -z ${_EXTEND_WS} ]; then _EXTEND_WS="--extend"; fi', - 'fi', - '', + "fi", + "", 'eval "${state}"', 'rm -f "${SNAPCRAFT_PART_INSTALL}/.installed_packages.txt"', 'rm -f "${SNAPCRAFT_PART_INSTALL}/.build_snaps.txt"', - 'if [ -d /snap/foo/current/opt/ros ]; then', - 'ROS_PACKAGE_PATH=/snap/foo/current/opt/ros rospack list-names | (xargs ' + "if [ -d /snap/foo/current/opt/ros ]; then", + "ROS_PACKAGE_PATH=/snap/foo/current/opt/ros rospack list-names | (xargs " 'rosdep resolve --rosdistro "${ROS_DISTRO}" || echo "") | awk ' '"/#apt/{getline;print;}" >> ' '"${SNAPCRAFT_PART_INSTALL}/.installed_packages.txt"', - 'fi', + "fi", 'if [ -d "/snap/foo/current/opt/ros/${ROS_DISTRO}/" ]; then', 'rosdep keys --rosdistro "${ROS_DISTRO}" --from-paths ' '"/snap/foo/current/opt/ros/${ROS_DISTRO}" --ignore-packages-from-source | ' '(xargs rosdep resolve --rosdistro "${ROS_DISTRO}" || echo "") | grep -v "#" ' '>> "${SNAPCRAFT_PART_INSTALL}"/.installed_packages.txt', - 'fi', + "fi", 'if [ -d "/snap/foo/current/opt/ros/snap/" ]; then', 'rosdep keys --rosdistro "${ROS_DISTRO}" --from-paths ' '"/snap/foo/current/opt/ros/snap" --ignore-packages-from-source | (xargs ' 'rosdep resolve --rosdistro "${ROS_DISTRO}" || echo "") | grep -v "#" >> ' '"${SNAPCRAFT_PART_INSTALL}"/.installed_packages.txt', - 'fi', - '', - + "fi", + "", 'rosdep install --default-yes --ignore-packages-from-source --from-paths "${SNAPCRAFT_PART_SRC_WORK}"', 'state="$(set +o); set -$-"', "set +u", - '', - '## Sourcing ROS ws in build snaps', + "", + "## Sourcing ROS ws in build snaps", 'if [ -f "/snap/foo/current/opt/ros/${ROS_DISTRO}/setup.sh" ]; then', 'set -- --local "${_EXTEND_WS}"', '_CATKIN_SETUP_DIR="/snap/foo/current/opt/ros/${ROS_DISTRO}" . ' '"/snap/foo/current/opt/ros/${ROS_DISTRO}/setup.sh"', 'if [ -z ${_EXTEND_WS} ]; then _EXTEND_WS="--extend"; fi', - 'fi', - '', - '## Sourcing ROS ws in stage snaps', + "fi", + "", + "## Sourcing ROS ws in stage snaps", 'if [ -f "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/setup.sh" ]; then', 'set -- --local "${_EXTEND_WS}"', '_CATKIN_SETUP_DIR="${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}" . "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/setup.sh"', 'if [ -z ${_EXTEND_WS} ]; then _EXTEND_WS="--extend"; fi', "fi", - '', - '## Sourcing ROS ws in system', + "", + "## Sourcing ROS ws in system", 'if [ -f "/opt/ros/${ROS_DISTRO}/setup.sh" ]; then', 'set -- --local "${_EXTEND_WS}"', '_CATKIN_SETUP_DIR="/opt/ros/${ROS_DISTRO}" . ' '"/opt/ros/${ROS_DISTRO}/setup.sh"', 'if [ -z ${_EXTEND_WS} ]; then _EXTEND_WS="--extend"; fi', - 'fi', - '', + "fi", + "", 'eval "${state}"', "catkin init", "catkin profile add -f default", From 1dd7350e8598e20e21c0103b096d4f74140546e8 Mon Sep 17 00:00:00 2001 From: artivis Date: Mon, 19 Jun 2023 09:27:22 +0200 Subject: [PATCH 64/84] ros: add missing LD_LIBRARY_PATH path Signed-off-by: artivis --- snapcraft/extensions/_ros2_humble_meta.py | 10 +++++++--- .../project_loader/_extensions/_ros1_noetic_meta.py | 9 ++++++++- .../project_loader/_extensions/_ros2_foxy_meta.py | 9 ++++++++- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/snapcraft/extensions/_ros2_humble_meta.py b/snapcraft/extensions/_ros2_humble_meta.py index 3c7ae6d952..0399f1cd4b 100644 --- a/snapcraft/extensions/_ros2_humble_meta.py +++ b/snapcraft/extensions/_ros2_humble_meta.py @@ -77,9 +77,13 @@ def get_app_snippet(self) -> Dict[str, Any]: "PYTHONPATH" ] = f'{python_paths}:{":".join(new_python_paths)}' app_snippet["environment"]["PATH"] = "$SNAP/opt/ros/underlay_ws/usr/bin:$PATH" - app_snippet["environment"][ - "LD_LIBRARY_PATH" - ] = "$SNAP/opt/ros/underlay_ws/usr/lib/$SNAPCRAFT_ARCH_TRIPLET:$LD_LIBRARY_PATH" + app_snippet["environment"]["LD_LIBRARY_PATH"] = ":".join( + [ + "$SNAP/opt/ros/underlay_ws/usr/lib", + "$SNAP/opt/ros/underlay_ws/usr/lib/$SNAPCRAFT_ARCH_TRIPLET", + "$LD_LIBRARY_PATH", + ] + ) # @todo: for some reason ${VAR:+:$VAR} resulsts in empty substitution # prepend_to_env( diff --git a/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py b/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py index 27615baa97..8fdecd5fa3 100644 --- a/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py +++ b/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py @@ -77,7 +77,14 @@ def __init__(self, *, extension_name: str, yaml_data: Dict[str, Any]) -> None: self.app_snippet["environment"]["PYTHONPATH"] = f'{python_paths}:{":".join(new_python_paths)}' self.app_snippet["environment"]["PATH"] = "$SNAP/opt/ros/underlay_ws/usr/bin:$PATH" - self.app_snippet["environment"]["LD_LIBRARY_PATH"] = "$SNAP/opt/ros/underlay_ws/usr/lib/$SNAPCRAFT_ARCH_TRIPLET:$LD_LIBRARY_PATH" + + self.app_snippet["environment"]["LD_LIBRARY_PATH"] = ":".join( + [ + "$SNAP/opt/ros/underlay_ws/usr/lib", + "$SNAP/opt/ros/underlay_ws/usr/lib/$SNAPCRAFT_ARCH_TRIPLET", + "$LD_LIBRARY_PATH", + ] + ) # @todo: for some reason ${VAR:+:$VAR} resulsts in empty substitution # self.app_snippet["environment"]["PATH"] = "$SNAP/opt/ros/underlay_ws/usr/bin${PATH:+:$PATH}" diff --git a/snapcraft_legacy/internal/project_loader/_extensions/_ros2_foxy_meta.py b/snapcraft_legacy/internal/project_loader/_extensions/_ros2_foxy_meta.py index adb8b4ac76..048c7639e2 100644 --- a/snapcraft_legacy/internal/project_loader/_extensions/_ros2_foxy_meta.py +++ b/snapcraft_legacy/internal/project_loader/_extensions/_ros2_foxy_meta.py @@ -85,7 +85,14 @@ def __init__(self, *, extension_name: str, yaml_data: Dict[str, Any]) -> None: self.app_snippet["environment"]["PYTHONPATH"] = f'{python_paths}:{":".join(new_python_paths)}' self.app_snippet["environment"]["PATH"] = "$SNAP/opt/ros/underlay_ws/usr/bin:$PATH" - self.app_snippet["environment"]["LD_LIBRARY_PATH"] = "$SNAP/opt/ros/underlay_ws/usr/lib/$SNAPCRAFT_ARCH_TRIPLET:$LD_LIBRARY_PATH" + + self.app_snippet["environment"]["LD_LIBRARY_PATH"] = ":".join( + [ + "$SNAP/opt/ros/underlay_ws/usr/lib", + "$SNAP/opt/ros/underlay_ws/usr/lib/$SNAPCRAFT_ARCH_TRIPLET", + "$LD_LIBRARY_PATH", + ] + ) # @todo: for some reason ${VAR:+:$VAR} resulsts in empty substitution # self.app_snippet["environment"]["PATH"] = "$SNAP/opt/ros/underlay_ws/usr/bin${PATH:+:$PATH}" From 432107bbb466747dc42fd19d64f0e753af3f56e6 Mon Sep 17 00:00:00 2001 From: artivis Date: Tue, 20 Jun 2023 08:41:29 +0200 Subject: [PATCH 65/84] legacy _deb: better handle default packages_filters Signed-off-by: artivis --- snapcraft_legacy/internal/repo/_deb.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/snapcraft_legacy/internal/repo/_deb.py b/snapcraft_legacy/internal/repo/_deb.py index 4e67ef932b..186bf82917 100644 --- a/snapcraft_legacy/internal/repo/_deb.py +++ b/snapcraft_legacy/internal/repo/_deb.py @@ -476,7 +476,7 @@ def fetch_stage_packages( base: str, stage_packages_path: pathlib.Path, target_arch: str, - packages_filters: Set[str] = set(), + packages_filters: Optional[Set[str]] = None, ) -> List[str]: logger.debug(f"Requested stage-packages: {sorted(package_names)!r}") @@ -487,7 +487,8 @@ def fetch_stage_packages( base=base, package_list=package_list ) - filtered_names.update(packages_filters) + if packages_filters: + filtered_names.update(packages_filters) stage_packages_path.mkdir(exist_ok=True) with AptCache( From 91ee0c0c1f269157ec1e8abe3f8eb54880709249 Mon Sep 17 00:00:00 2001 From: artivis Date: Tue, 20 Jun 2023 08:43:00 +0200 Subject: [PATCH 66/84] ros: small return fix Signed-off-by: artivis --- snapcraft_legacy/plugins/v2/_ros.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/snapcraft_legacy/plugins/v2/_ros.py b/snapcraft_legacy/plugins/v2/_ros.py index 066e39c500..000918a64a 100644 --- a/snapcraft_legacy/plugins/v2/_ros.py +++ b/snapcraft_legacy/plugins/v2/_ros.py @@ -279,7 +279,8 @@ def get_installed_dependencies(installed_packages_path: str) -> Set[str]: click.echo(f"Will not fetch staged packages: {build_snap_packages!r}") return build_snap_packages except IOError: - return set() + pass + return set() @plugin_cli.command() From c84e4b799a1f6615f0cbe552ccb9232ae92ed147 Mon Sep 17 00:00:00 2001 From: artivis Date: Tue, 20 Jun 2023 11:36:47 +0200 Subject: [PATCH 67/84] ros: fix spread tests Signed-off-by: artivis --- tests/spread/plugins/v2/ros1-hello/task.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/spread/plugins/v2/ros1-hello/task.yaml b/tests/spread/plugins/v2/ros1-hello/task.yaml index bf965c8870..64cc610f52 100644 --- a/tests/spread/plugins/v2/ros1-hello/task.yaml +++ b/tests/spread/plugins/v2/ros1-hello/task.yaml @@ -12,6 +12,8 @@ environment: SNAP/catkin_rosrun_wrapper: catkin-rosrun-wrapper SNAP/catkin_noetic_content_sharing: catkin-noetic-content-sharing + SNAPCRAFT_ENABLE_EXPERIMENTAL_EXTENSIONS/catkin_noetic_content_sharing: "1" + systems: - ubuntu-20.04 - ubuntu-20.04-64 @@ -56,7 +58,7 @@ execute: | done # Connect the content sharing snap - snap connect "${SNAP}":ros-meta ros-meta-ros-core:ros-core + snap connect "${SNAP}":ros-noetic ros-noetic-ros-core fi [ "$($SNAP)" = "hello world" ] From 568dbc547889831e7eb303a04428cc5ce91500d7 Mon Sep 17 00:00:00 2001 From: artivis Date: Wed, 21 Jun 2023 09:20:59 +0200 Subject: [PATCH 68/84] ros: fix unit tests LD_LIBRARY_PATH Signed-off-by: artivis --- .../unit/project_loader/extensions/test_ros1_noetic_meta.py | 2 +- .../unit/project_loader/extensions/test_ros2_foxy_meta.py | 2 +- tests/unit/parts/extensions/test_ros2_humble_meta.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py b/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py index 2f64b4db39..82e1b70512 100644 --- a/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py +++ b/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py @@ -112,7 +112,7 @@ def test_extension(self, extension_name, extension_class, meta, meta_dev): assert ros1_extension.app_snippet == { "command-chain": ["snap/command-chain/ros1-launch"], "environment": { - "LD_LIBRARY_PATH": "$SNAP/opt/ros/underlay_ws/usr/lib/$SNAPCRAFT_ARCH_TRIPLET:$LD_LIBRARY_PATH", + "LD_LIBRARY_PATH": "$SNAP/opt/ros/underlay_ws/usr/lib:$SNAP/opt/ros/underlay_ws/usr/lib/$SNAPCRAFT_ARCH_TRIPLET:$LD_LIBRARY_PATH", "PATH": "$SNAP/opt/ros/underlay_ws/usr/bin:$PATH", "PYTHONPATH": ":".join(python_paths), "ROS_VERSION": "1", diff --git a/tests/legacy/unit/project_loader/extensions/test_ros2_foxy_meta.py b/tests/legacy/unit/project_loader/extensions/test_ros2_foxy_meta.py index dfca38062b..ae57b5e733 100644 --- a/tests/legacy/unit/project_loader/extensions/test_ros2_foxy_meta.py +++ b/tests/legacy/unit/project_loader/extensions/test_ros2_foxy_meta.py @@ -92,7 +92,7 @@ def test_extension(self, extension_name, extension_class, meta, meta_dev): assert ros_extension.app_snippet == { "command-chain": ["snap/command-chain/ros2-launch"], "environment": { - "LD_LIBRARY_PATH": "$SNAP/opt/ros/underlay_ws/usr/lib/$SNAPCRAFT_ARCH_TRIPLET:$LD_LIBRARY_PATH", + "LD_LIBRARY_PATH": "$SNAP/opt/ros/underlay_ws/usr/lib:$SNAP/opt/ros/underlay_ws/usr/lib/$SNAPCRAFT_ARCH_TRIPLET:$LD_LIBRARY_PATH", "PATH": "$SNAP/opt/ros/underlay_ws/usr/bin:$PATH", "PYTHONPATH": ":".join(python_paths), "ROS_VERSION": "2", diff --git a/tests/unit/parts/extensions/test_ros2_humble_meta.py b/tests/unit/parts/extensions/test_ros2_humble_meta.py index a0bc8da80d..457d94988a 100644 --- a/tests/unit/parts/extensions/test_ros2_humble_meta.py +++ b/tests/unit/parts/extensions/test_ros2_humble_meta.py @@ -156,7 +156,7 @@ def test_get_app_snippet(self, extension_name, extension_class, meta, meta_dev): "ROS_DISTRO": "humble", "PYTHONPATH": ":".join(python_paths), "ROS_HOME": "$SNAP_USER_DATA/ros", - "LD_LIBRARY_PATH": "$SNAP/opt/ros/underlay_ws/usr/lib/$SNAPCRAFT_ARCH_TRIPLET:$LD_LIBRARY_PATH", + "LD_LIBRARY_PATH": "$SNAP/opt/ros/underlay_ws/usr/lib:$SNAP/opt/ros/underlay_ws/usr/lib/$SNAPCRAFT_ARCH_TRIPLET:$LD_LIBRARY_PATH", "PATH": "$SNAP/opt/ros/underlay_ws/usr/bin:$PATH", }, } From 3e571681e566670709634a010e8aeab3535a289f Mon Sep 17 00:00:00 2001 From: artivis Date: Wed, 21 Jun 2023 09:40:40 +0200 Subject: [PATCH 69/84] ros: humble rename ros-build-snaps -> colcon-ros-build-snaps Signed-off-by: artivis --- snapcraft/extensions/_ros2_humble_meta.py | 2 +- snapcraft/parts/plugins/_ros.py | 8 ++++---- snapcraft/parts/plugins/colcon_plugin.py | 8 ++++---- tests/unit/parts/extensions/test_ros2_humble_meta.py | 2 +- tests/unit/parts/plugins/test_colcon.py | 8 ++++---- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/snapcraft/extensions/_ros2_humble_meta.py b/snapcraft/extensions/_ros2_humble_meta.py index 0399f1cd4b..59645c5df9 100644 --- a/snapcraft/extensions/_ros2_humble_meta.py +++ b/snapcraft/extensions/_ros2_humble_meta.py @@ -98,7 +98,7 @@ def get_app_snippet(self) -> Dict[str, Any]: @overrides def get_part_snippet(self) -> Dict[str, Any]: part_snippet = super().get_part_snippet() - part_snippet["ros-build-snaps"] = [self.ros2_humble_snaps.sdk] + part_snippet["colcon-ros-build-snaps"] = [self.ros2_humble_snaps.sdk] part_snippet["colcon-cmake-args"] = [ f'-DCMAKE_SYSTEM_PREFIX_PATH="/snap/{self.ros2_humble_snaps.sdk}/current/usr"' ] diff --git a/snapcraft/parts/plugins/_ros.py b/snapcraft/parts/plugins/_ros.py index 0710a25d19..f8fa196691 100644 --- a/snapcraft/parts/plugins/_ros.py +++ b/snapcraft/parts/plugins/_ros.py @@ -87,8 +87,8 @@ class RosPlugin(plugins.Plugin): @overrides def get_build_snaps(self) -> Set[str]: return ( - set(self._options.ros_build_snaps) # type: ignore - if self._options.ros_build_snaps # type: ignore + set(self._options.colcon_ros_build_snaps) # type: ignore + if self._options.colcon_ros_build_snaps # type: ignore else set() ) @@ -146,8 +146,8 @@ def _get_list_packages_commands(self) -> List[str]: cmd.append('rm -f "${CRAFT_PART_INSTALL}/.installed_packages.txt"') cmd.append('rm -f "${CRAFT_PART_INSTALL}/.build_snaps.txt"') - if self._options.ros_build_snaps: # type: ignore - for ros_build_snap in self._options.ros_build_snaps: # type: ignore + if self._options.colcon_ros_build_snaps: # type: ignore + for ros_build_snap in self._options.colcon_ros_build_snaps: # type: ignore snap_name = _get_parsed_snap(ros_build_snap)[0] path = f"/snap/{snap_name}/current/opt/ros" # pylint: disable=line-too-long diff --git a/snapcraft/parts/plugins/colcon_plugin.py b/snapcraft/parts/plugins/colcon_plugin.py index 01cfec6092..4b8a740ca7 100644 --- a/snapcraft/parts/plugins/colcon_plugin.py +++ b/snapcraft/parts/plugins/colcon_plugin.py @@ -72,7 +72,7 @@ class ColconPluginProperties(plugins.PluginProperties, plugins.PluginModel): colcon_cmake_args: List[str] = [] colcon_packages: List[str] = [] colcon_packages_ignore: List[str] = [] - ros_build_snaps: List[str] = [] + colcon_ros_build_snaps: List[str] = [] # part properties required by the plugin source: str @@ -93,7 +93,7 @@ def unmarshal(cls, data: Dict[str, Any]) -> "ColconPluginProperties": # However we'd like to avoid that for 'ros-build-snaps'. # Marking it required allows us to circumvent the prefix requirement. plugin_data = plugins.extract_plugin_properties( - data, plugin_name="colcon", required=["source", "ros-build-snaps"] + data, plugin_name="colcon", required=["source"] ) return cls(**plugin_data) @@ -155,8 +155,8 @@ def _get_workspace_activation_commands(self) -> List[str]: # Source ROS ws in all build-snaps first activation_commands.append("## Sourcing ROS ws in build snaps") self._options: ColconPluginProperties - if self._options.ros_build_snaps: - for ros_build_snap in self._options.ros_build_snaps: + if self._options.colcon_ros_build_snaps: + for ros_build_snap in self._options.colcon_ros_build_snaps: snap_name = _get_parsed_snap(ros_build_snap)[0] activation_commands.extend( self._get_source_command(f"/snap/{snap_name}/current") diff --git a/tests/unit/parts/extensions/test_ros2_humble_meta.py b/tests/unit/parts/extensions/test_ros2_humble_meta.py index 457d94988a..3a462e9358 100644 --- a/tests/unit/parts/extensions/test_ros2_humble_meta.py +++ b/tests/unit/parts/extensions/test_ros2_humble_meta.py @@ -166,7 +166,7 @@ def test_get_part_snippet(self, extension_name, extension_class, meta, meta_dev) extension = setup_method_fixture(extension_class) assert extension.get_part_snippet() == { "build-environment": [{"ROS_VERSION": "2"}, {"ROS_DISTRO": "humble"}], - "ros-build-snaps": [meta_dev], + "colcon-ros-build-snaps": [meta_dev], "colcon-cmake-args": [ f'-DCMAKE_SYSTEM_PREFIX_PATH="/snap/{meta_dev}/current/usr"' ], diff --git a/tests/unit/parts/plugins/test_colcon.py b/tests/unit/parts/plugins/test_colcon.py index b804d43c1d..8b6ef5cc9b 100644 --- a/tests/unit/parts/plugins/test_colcon.py +++ b/tests/unit/parts/plugins/test_colcon.py @@ -99,7 +99,7 @@ def test_property_all(self): "colcon-cmake-args": ["cmake", "args..."], "colcon-packages": ["package1", "package2..."], "colcon-packages-ignore": ["ipackage1", "ipackage2..."], - "ros-build-snaps": ["ros-core"], + "colcon-ros-build-snaps": ["ros-core"], } ) except ValidationError as e: @@ -111,7 +111,7 @@ def test_property_all(self): assert properties.colcon_cmake_args == ["cmake", "args..."] # type: ignore assert properties.colcon_packages == ["package1", "package2..."] # type: ignore assert properties.colcon_packages_ignore == ["ipackage1", "ipackage2..."] # type: ignore - assert properties.ros_build_snaps == ["ros-core"] # type: ignore + assert properties.colcon_ros_build_snaps == ["ros-core"] # type: ignore def test_get_build_packages(self, setup_method_fixture, new_dir): plugin = setup_method_fixture(new_dir) @@ -138,7 +138,7 @@ def test_get_build_snaps(self, setup_method_fixture, new_dir): "colcon-cmake-args": [], "colcon-packages": [], "colcon-packages-ignore": [], - "ros-build-snaps": ["Foo"], + "colcon-ros-build-snaps": ["Foo"], }, ) @@ -257,7 +257,7 @@ def test_get_build_commands_with_all_properties( "colcon-cmake-args": ["cmake", "args..."], "colcon-packages": ["package1", "package2..."], "colcon-packages-ignore": ["ipackage1", "ipackage2..."], - "ros-build-snaps": ["foo"], + "colcon-ros-build-snaps": ["foo"], }, ) From 68d5638c570e66e2c443b4c35cf6650e4fc9a98f Mon Sep 17 00:00:00 2001 From: artivis Date: Thu, 22 Jun 2023 14:27:34 +0200 Subject: [PATCH 70/84] ros: mv PATH extension to command-chain Signed-off-by: artivis --- extensions/ros1/launch | 16 ++++++++++++++++ extensions/ros2/launch | 18 ++++++++++++++++++ snapcraft/extensions/_ros2_humble_meta.py | 16 ---------------- .../_extensions/_ros1_noetic_meta.py | 14 -------------- .../_extensions/_ros2_foxy_meta.py | 14 -------------- .../extensions/test_ros1_noetic_meta.py | 2 -- .../extensions/test_ros2_foxy_meta.py | 2 -- .../parts/extensions/test_ros2_humble_meta.py | 2 -- 8 files changed, 34 insertions(+), 50 deletions(-) diff --git a/extensions/ros1/launch b/extensions/ros1/launch index 0338aad3fd..52b53ca6f1 100755 --- a/extensions/ros1/launch +++ b/extensions/ros1/launch @@ -18,6 +18,22 @@ original_args=("$@") # activate_workspace in content shared snaps if [ -d "$SNAP/opt/ros/underlay_ws/opt/ros/$ROS_DISTRO" ]; then activate_workspace "$SNAP/opt/ros/underlay_ws/opt/ros/$ROS_DISTRO" --local + + case "$SNAP_ARCH" in + "amd64") ARCH_TRIPLET='x86_64-linux-gnu' + ;; + "arm64") ARCH_TRIPLET="aarch64-linux-gnu" + ;; + "armhf") ARCH_TRIPLET="arm-linux-gnueabihf" + ;; + *) + echo "Unsupported architecture '$SNAP_ARCH' for this app build." + exit 1 + ;; + esac + + export PATH="$SNAP/opt/ros/underlay_ws/usr/bin:$PATH" + export LD_LIBRARY_PATH="$SNAP/opt/ros/underlay_ws/usr/lib:$SNAP/opt/ros/underlay_ws/usr/lib/$ARCH_TRIPLET:$LD_LIBRARY_PATH" fi activate_workspace "$SNAP/opt/ros/$ROS_DISTRO" --local --extend diff --git a/extensions/ros2/launch b/extensions/ros2/launch index a2e60dbc30..cc7638ea31 100755 --- a/extensions/ros2/launch +++ b/extensions/ros2/launch @@ -19,6 +19,24 @@ fi if [ -d "$SNAP/opt/ros/underlay_ws/opt/ros/snap" ]; then source_with_prefix "$SNAP/opt/ros/underlay_ws/opt/ros/snap" fi +if [ -d "$SNAP/opt/ros/underlay_ws/opt/ros/$ROS_DISTRO" ] || [ -d "$SNAP/opt/ros/underlay_ws/opt/ros/snap" ]; then + + case "$SNAP_ARCH" in + "amd64") ARCH_TRIPLET='x86_64-linux-gnu' + ;; + "arm64") ARCH_TRIPLET="aarch64-linux-gnu" + ;; + "armhf") ARCH_TRIPLET="arm-linux-gnueabihf" + ;; + *) + echo "Unsupported architecture '$SNAP_ARCH' for this app build." + exit 1 + ;; + esac + + export PATH="$SNAP/opt/ros/underlay_ws/usr/bin:$PATH" + export LD_LIBRARY_PATH="$SNAP/opt/ros/underlay_ws/usr/lib:$SNAP/opt/ros/underlay_ws/usr/lib/$ARCH_TRIPLET:$LD_LIBRARY_PATH" +fi source_with_prefix "$SNAP/opt/ros/$ROS_DISTRO" source_with_prefix "$SNAP/opt/ros/snap" diff --git a/snapcraft/extensions/_ros2_humble_meta.py b/snapcraft/extensions/_ros2_humble_meta.py index 59645c5df9..795c60e59f 100644 --- a/snapcraft/extensions/_ros2_humble_meta.py +++ b/snapcraft/extensions/_ros2_humble_meta.py @@ -76,22 +76,6 @@ def get_app_snippet(self) -> Dict[str, Any]: app_snippet["environment"][ "PYTHONPATH" ] = f'{python_paths}:{":".join(new_python_paths)}' - app_snippet["environment"]["PATH"] = "$SNAP/opt/ros/underlay_ws/usr/bin:$PATH" - app_snippet["environment"]["LD_LIBRARY_PATH"] = ":".join( - [ - "$SNAP/opt/ros/underlay_ws/usr/lib", - "$SNAP/opt/ros/underlay_ws/usr/lib/$SNAPCRAFT_ARCH_TRIPLET", - "$LD_LIBRARY_PATH", - ] - ) - - # @todo: for some reason ${VAR:+:$VAR} resulsts in empty substitution - # prepend_to_env( - # "PATH", ["$SNAP/opt/ros/underlay_ws/usr/bin"] - # ) - # prepend_to_env( - # "LD_LIBRARY_PATH", ["$SNAP/opt/ros/underlay_ws/usr/lib/$SNAPCRAFT_ARCH_TRIPLET"] - # ) return app_snippet diff --git a/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py b/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py index 8fdecd5fa3..c43b14755e 100644 --- a/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py +++ b/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py @@ -75,17 +75,3 @@ def __init__(self, *, extension_name: str, yaml_data: Dict[str, Any]) -> None: ] self.app_snippet["environment"]["PYTHONPATH"] = f'{python_paths}:{":".join(new_python_paths)}' - - self.app_snippet["environment"]["PATH"] = "$SNAP/opt/ros/underlay_ws/usr/bin:$PATH" - - self.app_snippet["environment"]["LD_LIBRARY_PATH"] = ":".join( - [ - "$SNAP/opt/ros/underlay_ws/usr/lib", - "$SNAP/opt/ros/underlay_ws/usr/lib/$SNAPCRAFT_ARCH_TRIPLET", - "$LD_LIBRARY_PATH", - ] - ) - - # @todo: for some reason ${VAR:+:$VAR} resulsts in empty substitution - # self.app_snippet["environment"]["PATH"] = "$SNAP/opt/ros/underlay_ws/usr/bin${PATH:+:$PATH}" - # self.app_snippet["environment"]["LD_LIBRARY_PATH"] = "$SNAP/opt/ros/underlay_ws/usr/lib/$SNAPCRAFT_ARCH_TRIPLET${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" diff --git a/snapcraft_legacy/internal/project_loader/_extensions/_ros2_foxy_meta.py b/snapcraft_legacy/internal/project_loader/_extensions/_ros2_foxy_meta.py index 048c7639e2..95390250ea 100644 --- a/snapcraft_legacy/internal/project_loader/_extensions/_ros2_foxy_meta.py +++ b/snapcraft_legacy/internal/project_loader/_extensions/_ros2_foxy_meta.py @@ -83,17 +83,3 @@ def __init__(self, *, extension_name: str, yaml_data: Dict[str, Any]) -> None: ] self.app_snippet["environment"]["PYTHONPATH"] = f'{python_paths}:{":".join(new_python_paths)}' - - self.app_snippet["environment"]["PATH"] = "$SNAP/opt/ros/underlay_ws/usr/bin:$PATH" - - self.app_snippet["environment"]["LD_LIBRARY_PATH"] = ":".join( - [ - "$SNAP/opt/ros/underlay_ws/usr/lib", - "$SNAP/opt/ros/underlay_ws/usr/lib/$SNAPCRAFT_ARCH_TRIPLET", - "$LD_LIBRARY_PATH", - ] - ) - - # @todo: for some reason ${VAR:+:$VAR} resulsts in empty substitution - # self.app_snippet["environment"]["PATH"] = "$SNAP/opt/ros/underlay_ws/usr/bin${PATH:+:$PATH}" - # self.app_snippet["environment"]["LD_LIBRARY_PATH"] = "$SNAP/opt/ros/underlay_ws/usr/lib/$SNAPCRAFT_ARCH_TRIPLET${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" diff --git a/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py b/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py index 82e1b70512..caf3e0a34e 100644 --- a/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py +++ b/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py @@ -112,8 +112,6 @@ def test_extension(self, extension_name, extension_class, meta, meta_dev): assert ros1_extension.app_snippet == { "command-chain": ["snap/command-chain/ros1-launch"], "environment": { - "LD_LIBRARY_PATH": "$SNAP/opt/ros/underlay_ws/usr/lib:$SNAP/opt/ros/underlay_ws/usr/lib/$SNAPCRAFT_ARCH_TRIPLET:$LD_LIBRARY_PATH", - "PATH": "$SNAP/opt/ros/underlay_ws/usr/bin:$PATH", "PYTHONPATH": ":".join(python_paths), "ROS_VERSION": "1", "ROS_DISTRO": "noetic", diff --git a/tests/legacy/unit/project_loader/extensions/test_ros2_foxy_meta.py b/tests/legacy/unit/project_loader/extensions/test_ros2_foxy_meta.py index ae57b5e733..57c1dfe3ed 100644 --- a/tests/legacy/unit/project_loader/extensions/test_ros2_foxy_meta.py +++ b/tests/legacy/unit/project_loader/extensions/test_ros2_foxy_meta.py @@ -92,8 +92,6 @@ def test_extension(self, extension_name, extension_class, meta, meta_dev): assert ros_extension.app_snippet == { "command-chain": ["snap/command-chain/ros2-launch"], "environment": { - "LD_LIBRARY_PATH": "$SNAP/opt/ros/underlay_ws/usr/lib:$SNAP/opt/ros/underlay_ws/usr/lib/$SNAPCRAFT_ARCH_TRIPLET:$LD_LIBRARY_PATH", - "PATH": "$SNAP/opt/ros/underlay_ws/usr/bin:$PATH", "PYTHONPATH": ":".join(python_paths), "ROS_VERSION": "2", "ROS_DISTRO": "foxy", diff --git a/tests/unit/parts/extensions/test_ros2_humble_meta.py b/tests/unit/parts/extensions/test_ros2_humble_meta.py index 3a462e9358..768f4c054d 100644 --- a/tests/unit/parts/extensions/test_ros2_humble_meta.py +++ b/tests/unit/parts/extensions/test_ros2_humble_meta.py @@ -156,8 +156,6 @@ def test_get_app_snippet(self, extension_name, extension_class, meta, meta_dev): "ROS_DISTRO": "humble", "PYTHONPATH": ":".join(python_paths), "ROS_HOME": "$SNAP_USER_DATA/ros", - "LD_LIBRARY_PATH": "$SNAP/opt/ros/underlay_ws/usr/lib:$SNAP/opt/ros/underlay_ws/usr/lib/$SNAPCRAFT_ARCH_TRIPLET:$LD_LIBRARY_PATH", - "PATH": "$SNAP/opt/ros/underlay_ws/usr/bin:$PATH", }, } From 9cca729806861265651b03d81b0e59fe349b8b2f Mon Sep 17 00:00:00 2001 From: artivis Date: Mon, 10 Jul 2023 09:43:24 +0200 Subject: [PATCH 71/84] ros: pedantic default Signed-off-by: artivis --- snapcraft/parts/plugins/_ros.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snapcraft/parts/plugins/_ros.py b/snapcraft/parts/plugins/_ros.py index f8fa196691..4ca1825233 100644 --- a/snapcraft/parts/plugins/_ros.py +++ b/snapcraft/parts/plugins/_ros.py @@ -268,7 +268,7 @@ def get_installed_dependencies(installed_packages_path: str) -> Set[str]: """Retrieve recursive apt dependencies of a given package list.""" if os.path.isfile(installed_packages_path): try: - with open(installed_packages_path, "r", encoding="utf8") as file: + with open(installed_packages_path, encoding="utf8") as file: build_snap_packages = set(file.read().split()) package_dependencies = set() for package in build_snap_packages: From 61959455630f22a4a07c2a292a33f151f979eba1 Mon Sep 17 00:00:00 2001 From: artivis Date: Mon, 10 Jul 2023 09:44:27 +0200 Subject: [PATCH 72/84] ros: IOError -> OSError Signed-off-by: artivis --- snapcraft/parts/plugins/_ros.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snapcraft/parts/plugins/_ros.py b/snapcraft/parts/plugins/_ros.py index 4ca1825233..9b254fc127 100644 --- a/snapcraft/parts/plugins/_ros.py +++ b/snapcraft/parts/plugins/_ros.py @@ -306,7 +306,7 @@ def get_installed_dependencies(installed_packages_path: str) -> Set[str]: build_snap_packages.update(package_dependencies) click.echo(f"Will not fetch staged packages: {build_snap_packages!r}") return build_snap_packages - except IOError: + except OSError: pass return set() From 62327176ccd9837340633c939ec215b828874612 Mon Sep 17 00:00:00 2001 From: artivis Date: Mon, 10 Jul 2023 09:55:46 +0200 Subject: [PATCH 73/84] ros: fix import Signed-off-by: artivis --- tests/unit/parts/extensions/test_ros2_humble_meta.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/unit/parts/extensions/test_ros2_humble_meta.py b/tests/unit/parts/extensions/test_ros2_humble_meta.py index 768f4c054d..e14f052d77 100644 --- a/tests/unit/parts/extensions/test_ros2_humble_meta.py +++ b/tests/unit/parts/extensions/test_ros2_humble_meta.py @@ -16,8 +16,8 @@ import pytest -import snapcraft.extensions.registry as reg from snapcraft import errors +from snapcraft.extensions import registry from snapcraft.extensions.extension import get_extensions_data_dir from snapcraft.extensions.ros2_humble_desktop import ROS2HumbleDesktopExtension from snapcraft.extensions.ros2_humble_ros_base import ROS2HumbleRosBaseExtension @@ -62,10 +62,10 @@ class TestExtensionROS2HumbleMetaExtensions: @pytest.mark.parametrize(fixture_variables, fixture_values) def test_is_registered(self, extension_name, extension_class, meta, meta_dev): - assert extension_name in reg.get_extension_names() + assert extension_name in registry.get_extension_names() try: - reg.get_extension_class(extension_name) + registry.get_extension_class(extension_name) except errors.ExtensionError as exc: raise AssertionError(f"Couldn't get extension '{extension_name}': {exc}") From 789f7cd919e86b2ec150c28a37cc726aa993674c Mon Sep 17 00:00:00 2001 From: artivis Date: Mon, 10 Jul 2023 10:37:59 +0200 Subject: [PATCH 74/84] ros: test simplifications Signed-off-by: artivis --- tests/unit/parts/extensions/test_ros2_humble_meta.py | 7 ------- tests/unit/parts/plugins/test_colcon.py | 6 ++---- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/tests/unit/parts/extensions/test_ros2_humble_meta.py b/tests/unit/parts/extensions/test_ros2_humble_meta.py index e14f052d77..d697bde39d 100644 --- a/tests/unit/parts/extensions/test_ros2_humble_meta.py +++ b/tests/unit/parts/extensions/test_ros2_humble_meta.py @@ -25,13 +25,6 @@ def setup_method_fixture(extension, yaml_data=None, arch=None, target_arch=None): - if yaml_data is None: - yaml_data = {} - if arch is None: - arch = "amd64" - if target_arch is None: - target_arch = "amd64" - return extension(yaml_data=yaml_data, arch=arch, target_arch=target_arch) diff --git a/tests/unit/parts/plugins/test_colcon.py b/tests/unit/parts/plugins/test_colcon.py index 8b6ef5cc9b..7e17f1d3ff 100644 --- a/tests/unit/parts/plugins/test_colcon.py +++ b/tests/unit/parts/plugins/test_colcon.py @@ -76,16 +76,14 @@ def test_property_default(self): def test_property_unexpected(self): try: - # pylint: disable=unused-variable - properties = colcon.ColconPlugin.properties_class( # noqa F841 + colcon.ColconPlugin.properties_class( # noqa F841 source="." # type: ignore ) - # pylint: enable=unused-variable except ValidationError as e: raise AssertionError(f"{e}") from e with pytest.raises(ValidationError): - properties = colcon.ColconPlugin.properties_class( # noqa F841 + colcon.ColconPlugin.properties_class( # noqa F841 source=".", foo="bar" # type: ignore ) From e1d765d8c297c166d0799995ba97d2519ec16391 Mon Sep 17 00:00:00 2001 From: artivis Date: Mon, 10 Jul 2023 10:45:00 +0200 Subject: [PATCH 75/84] ros: cleanup comments & quote Signed-off-by: artivis --- snapcraft/extensions/_ros2_humble_meta.py | 1 - .../extensions/catkin-tools-noetic-meta-hello/task.yaml | 4 ++-- tests/spread/extensions/ros-noetic-meta-hello/task.yaml | 4 ++-- .../extensions/ros-noetic-meta-talker-listener/task.yaml | 4 ++-- tests/spread/extensions/ros2-foxy-meta-hello/task.yaml | 4 ++-- .../extensions/ros2-foxy-meta-talker-listener/task.yaml | 4 ++-- tests/spread/extensions/ros2-humble-meta-hello/task.yaml | 4 ++-- .../extensions/ros2-humble-meta-talker-listener/task.yaml | 4 ++-- 8 files changed, 14 insertions(+), 15 deletions(-) diff --git a/snapcraft/extensions/_ros2_humble_meta.py b/snapcraft/extensions/_ros2_humble_meta.py index 795c60e59f..e54b776d78 100644 --- a/snapcraft/extensions/_ros2_humble_meta.py +++ b/snapcraft/extensions/_ros2_humble_meta.py @@ -24,7 +24,6 @@ from overrides import overrides -# from .extension import prepend_to_env from .ros2_humble import ROS2HumbleExtension diff --git a/tests/spread/extensions/catkin-tools-noetic-meta-hello/task.yaml b/tests/spread/extensions/catkin-tools-noetic-meta-hello/task.yaml index 6d673f43cb..828112480d 100644 --- a/tests/spread/extensions/catkin-tools-noetic-meta-hello/task.yaml +++ b/tests/spread/extensions/catkin-tools-noetic-meta-hello/task.yaml @@ -69,8 +69,8 @@ execute: | SNAP_SIZE=$(find . -maxdepth 1 -mindepth 1 -name '*_1.0_*.snap' -exec ls -s {} + | cut -d " " -f1) [ "100" -gt "$SNAP_SIZE" ] - # # Install the providing snap + # The default providing snap is installed automatically # snap install "${META_SNAP}" - snap connect "${SNAP}":"${INTERFACE}" "${META_SNAP}":"${INTERFACE}" + snap connect "${SNAP}:${INTERFACE}" "${META_SNAP}:${INTERFACE}" [ "$($SNAP)" = "hello world" ] diff --git a/tests/spread/extensions/ros-noetic-meta-hello/task.yaml b/tests/spread/extensions/ros-noetic-meta-hello/task.yaml index 3fd2ae5944..fc1ce2d070 100644 --- a/tests/spread/extensions/ros-noetic-meta-hello/task.yaml +++ b/tests/spread/extensions/ros-noetic-meta-hello/task.yaml @@ -69,8 +69,8 @@ execute: | SNAP_SIZE=$(find . -maxdepth 1 -mindepth 1 -name '*_1.0_*.snap' -exec ls -s {} + | cut -d " " -f1) [ "100" -gt "$SNAP_SIZE" ] - # # Install the providing snap + # The default providing snap is installed automatically # snap install "${META_SNAP}" - snap connect "${SNAP}":"${INTERFACE}" "${META_SNAP}":"${INTERFACE}" + snap connect "${SNAP}:${INTERFACE}" "${META_SNAP}:${INTERFACE}" [ "$($SNAP)" = "hello world" ] diff --git a/tests/spread/extensions/ros-noetic-meta-talker-listener/task.yaml b/tests/spread/extensions/ros-noetic-meta-talker-listener/task.yaml index 7ac468d365..d702e84cb5 100644 --- a/tests/spread/extensions/ros-noetic-meta-talker-listener/task.yaml +++ b/tests/spread/extensions/ros-noetic-meta-talker-listener/task.yaml @@ -70,10 +70,10 @@ execute: | SNAP_SIZE=$(find . -maxdepth 1 -mindepth 1 -name '*_1.0_*.snap' -exec ls -s {} + | cut -d " " -f1) [ "100" -gt "$SNAP_SIZE" ] - # # Install the providing snap + # The default providing snap is installed automatically # snap install "${META_SNAP}" - snap connect "${SNAP}":"${INTERFACE}" "${META_SNAP}":"${INTERFACE}" + snap connect "${SNAP}:${INTERFACE}" "${META_SNAP}:${INTERFACE}" # Regression test for LP: #1660852. Make sure --help actually gets passed to # roslaunch instead of being eaten by setup.sh. diff --git a/tests/spread/extensions/ros2-foxy-meta-hello/task.yaml b/tests/spread/extensions/ros2-foxy-meta-hello/task.yaml index 36bc7e8224..095005808f 100644 --- a/tests/spread/extensions/ros2-foxy-meta-hello/task.yaml +++ b/tests/spread/extensions/ros2-foxy-meta-hello/task.yaml @@ -70,8 +70,8 @@ execute: | SNAP_SIZE=$(find . -maxdepth 1 -mindepth 1 -name '*_1.0_*.snap' -exec ls -s {} + | cut -d " " -f1) [ "200" -gt "$SNAP_SIZE" ] - # Install the providing snap + # The default providing snap is installed automatically # snap install "${META_SNAP}" - snap connect "${SNAP}":"${INTERFACE}" "${META_SNAP}":"${INTERFACE}" + snap connect "${SNAP}:${INTERFACE}" "${META_SNAP}:${INTERFACE}" [ "$($SNAP)" = "hello world" ] diff --git a/tests/spread/extensions/ros2-foxy-meta-talker-listener/task.yaml b/tests/spread/extensions/ros2-foxy-meta-talker-listener/task.yaml index 1d2c380f09..bba345e2b7 100644 --- a/tests/spread/extensions/ros2-foxy-meta-talker-listener/task.yaml +++ b/tests/spread/extensions/ros2-foxy-meta-talker-listener/task.yaml @@ -67,10 +67,10 @@ execute: | SNAP_SIZE=$(find . -maxdepth 1 -mindepth 1 -name '*_1.0_*.snap' -exec ls -s {} + | cut -d " " -f1) [ "600" -gt "$SNAP_SIZE" ] - # Install the providing snap + # The default providing snap is installed automatically # snap install "${META_SNAP}" - snap connect "${SNAP}":"${INTERFACE}" "${META_SNAP}":"${INTERFACE}" + snap connect "${SNAP}:${INTERFACE}" "${META_SNAP}:${INTERFACE}" # Run the ROS system. By default this will never exit, but the snap supports # an `exit_after_receive` parameter that, if true, will cause the system to diff --git a/tests/spread/extensions/ros2-humble-meta-hello/task.yaml b/tests/spread/extensions/ros2-humble-meta-hello/task.yaml index 17ba9f6c11..7a0af11f65 100644 --- a/tests/spread/extensions/ros2-humble-meta-hello/task.yaml +++ b/tests/spread/extensions/ros2-humble-meta-hello/task.yaml @@ -71,8 +71,8 @@ execute: | SNAP_SIZE=$(find . -maxdepth 1 -mindepth 1 -name '*_1.0_*.snap' -exec ls -s {} + | cut -d " " -f1) [ "200" -gt "$SNAP_SIZE" ] - # Install the providing snap + # The default providing snap is installed automatically # snap install "${META_SNAP}" - snap connect "${SNAP}":"${INTERFACE}" "${META_SNAP}":"${INTERFACE}" + snap connect "${SNAP}:${INTERFACE}" "${META_SNAP}:${INTERFACE}" [ "$($SNAP)" = "hello world" ] diff --git a/tests/spread/extensions/ros2-humble-meta-talker-listener/task.yaml b/tests/spread/extensions/ros2-humble-meta-talker-listener/task.yaml index bca490c48b..7c594ad2f8 100644 --- a/tests/spread/extensions/ros2-humble-meta-talker-listener/task.yaml +++ b/tests/spread/extensions/ros2-humble-meta-talker-listener/task.yaml @@ -67,10 +67,10 @@ execute: | SNAP_SIZE=$(find . -maxdepth 1 -mindepth 1 -name '*_1.0_*.snap' -exec ls -s {} + | cut -d " " -f1) [ "800" -gt "$SNAP_SIZE" ] - # Install the providing snap + # The default providing snap is installed automatically # snap install "${META_SNAP}" - snap connect "${SNAP}":"${INTERFACE}" "${META_SNAP}":"${INTERFACE}" + snap connect "${SNAP}:${INTERFACE}" "${META_SNAP}:${INTERFACE}" # Run the ROS system. By default this will never exit, but the snap supports # an `exit_after_receive` parameter that, if true, will cause the system to From 98f950f2a4e38a8ce6e225732bee3d26e8c2d63d Mon Sep 17 00:00:00 2001 From: artivis Date: Mon, 10 Jul 2023 10:53:56 +0200 Subject: [PATCH 76/84] ros: use raw string for regex expr Signed-off-by: artivis --- snapcraft/parts/plugins/_ros.py | 4 +--- snapcraft_legacy/plugins/v2/_ros.py | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/snapcraft/parts/plugins/_ros.py b/snapcraft/parts/plugins/_ros.py index 9b254fc127..8116ccb9f0 100644 --- a/snapcraft/parts/plugins/_ros.py +++ b/snapcraft/parts/plugins/_ros.py @@ -296,9 +296,7 @@ def get_installed_dependencies(installed_packages_path: str) -> Set[str]: except subprocess.CalledProcessError as error: click.echo(f"failed to run {cmd!r}: {error.output}") else: - # pylint: disable=anomalous-backslash-in-string - apt_dependency_regex = re.compile("^\w.*$") # noqa: W605 - # pylint: enable=anomalous-backslash-in-string + apt_dependency_regex = re.compile(r"^\w.*$") for line in proc.stdout.decode().strip().split("\n"): if apt_dependency_regex.match(line): package_dependencies.add(line) diff --git a/snapcraft_legacy/plugins/v2/_ros.py b/snapcraft_legacy/plugins/v2/_ros.py index 000918a64a..0aa2681cb3 100644 --- a/snapcraft_legacy/plugins/v2/_ros.py +++ b/snapcraft_legacy/plugins/v2/_ros.py @@ -270,7 +270,7 @@ def get_installed_dependencies(installed_packages_path: str) -> Set[str]: except subprocess.CalledProcessError as error: click.echo(f"failed to run {cmd!r}: {error.output}") else: - apt_dependency_regex = re.compile("^\w.*$") # noqa: W605 + apt_dependency_regex = re.compile(r"^\w.*$") for line in proc.stdout.decode().strip().split("\n"): if apt_dependency_regex.match(line): package_dependencies.add(line) From f7bd3da392d8be93a654f0b13a5c2864e5e2fd2a Mon Sep 17 00:00:00 2001 From: artivis Date: Tue, 11 Jul 2023 16:11:43 +0200 Subject: [PATCH 77/84] ros: fix unit test Signed-off-by: artivis --- tests/unit/commands/test_list_extensions.py | 80 +++++++++++++-------- tests/unit/extensions/test_registry.py | 3 + 2 files changed, 54 insertions(+), 29 deletions(-) diff --git a/tests/unit/commands/test_list_extensions.py b/tests/unit/commands/test_list_extensions.py index 2fef48836d..3ea1536796 100644 --- a/tests/unit/commands/test_list_extensions.py +++ b/tests/unit/commands/test_list_extensions.py @@ -30,21 +30,32 @@ def test_command(emitter, command): emitter.assert_message( dedent( """\ - Extension name Supported bases - ---------------- ---------------------- - fake-extension core22 - flutter-beta core18 - flutter-dev core18 - flutter-master core18 - flutter-stable core18 - gnome core22 - gnome-3-28 core18 - gnome-3-34 core18 - gnome-3-38 core20 - kde-neon core18, core20, core22 - ros1-noetic core20 - ros2-foxy core20 - ros2-humble core22""" + Extension name Supported bases + ---------------------- ---------------------- + fake-extension core22 + flutter-beta core18 + flutter-dev core18 + flutter-master core18 + flutter-stable core18 + gnome core22 + gnome-3-28 core18 + gnome-3-34 core18 + gnome-3-38 core20 + kde-neon core18, core20, core22 + ros1-noetic core20 + ros1-noetic-desktop core20 + ros1-noetic-perception core20 + ros1-noetic-robot core20 + ros1-noetic-ros-base core20 + ros1-noetic-ros-core core20 + ros2-foxy core20 + ros2-foxy-desktop core20 + ros2-foxy-ros-base core20 + ros2-foxy-ros-core core20 + ros2-humble core22 + ros2-humble-desktop core22 + ros2-humble-ros-base core22 + ros2-humble-ros-core core22""" ) ) @@ -57,19 +68,30 @@ def test_command_extension_dups(emitter, command): emitter.assert_message( dedent( """\ - Extension name Supported bases - ---------------- ---------------------- - flutter-beta core18 - flutter-dev core18 - flutter-master core18 - flutter-stable core18 - gnome core22 - gnome-3-28 core18 - gnome-3-34 core18 - gnome-3-38 core20 - kde-neon core18, core20, core22 - ros1-noetic core20 - ros2-foxy core20 - ros2-humble core22""" + Extension name Supported bases + ---------------------- ---------------------- + flutter-beta core18 + flutter-dev core18 + flutter-master core18 + flutter-stable core18 + gnome core22 + gnome-3-28 core18 + gnome-3-34 core18 + gnome-3-38 core20 + kde-neon core18, core20, core22 + ros1-noetic core20 + ros1-noetic-desktop core20 + ros1-noetic-perception core20 + ros1-noetic-robot core20 + ros1-noetic-ros-base core20 + ros1-noetic-ros-core core20 + ros2-foxy core20 + ros2-foxy-desktop core20 + ros2-foxy-ros-base core20 + ros2-foxy-ros-core core20 + ros2-humble core22 + ros2-humble-desktop core22 + ros2-humble-ros-base core22 + ros2-humble-ros-core core22""" ) ) diff --git a/tests/unit/extensions/test_registry.py b/tests/unit/extensions/test_registry.py index 118e815171..1e3c5385db 100644 --- a/tests/unit/extensions/test_registry.py +++ b/tests/unit/extensions/test_registry.py @@ -26,6 +26,9 @@ def test_get_extension_names(): assert extensions.get_extension_names() == [ "gnome", "ros2-humble", + "ros2-humble-ros-core", + "ros2-humble-ros-base", + "ros2-humble-desktop", "kde-neon", "fake-extension-experimental", "fake-extension-extra", From 4bf037c60a9616e201e5106fbf2161122cf9d0be Mon Sep 17 00:00:00 2001 From: artivis Date: Thu, 13 Jul 2023 10:48:03 +0200 Subject: [PATCH 78/84] ros: fix rebase Signed-off-by: artivis --- snapcraft/parts/plugins/_ros.py | 4 +-- snapcraft_legacy/plugins/v2/_ros.py | 3 +-- tests/legacy/unit/plugins/v2/test_catkin.py | 22 --------------- .../unit/plugins/v2/test_catkin_tools.py | 27 ------------------- tests/legacy/unit/plugins/v2/test_colcon.py | 20 -------------- tests/unit/parts/plugins/test_colcon.py | 24 ----------------- 6 files changed, 3 insertions(+), 97 deletions(-) diff --git a/snapcraft/parts/plugins/_ros.py b/snapcraft/parts/plugins/_ros.py index 8116ccb9f0..2379e19197 100644 --- a/snapcraft/parts/plugins/_ros.py +++ b/snapcraft/parts/plugins/_ros.py @@ -223,8 +223,7 @@ def _get_stage_runtime_dependencies_commands(self) -> List[str]: @overrides def get_build_commands(self) -> List[str]: return ( - self._get_workspace_activation_commands() - + [ + [ "if [ ! -f /etc/ros/rosdep/sources.list.d/20-default.list ]; then", # Preserve http(s)_proxy env var in root for remote-build proxy since rosdep # doesn't support proxy @@ -243,6 +242,7 @@ def get_build_commands(self) -> List[str]: # Restore saved state + ['eval "${state}"'] + self._get_list_packages_commands() + # pylint: disable=line-too-long + [ 'rosdep install --default-yes --ignore-packages-from-source --from-paths "${CRAFT_PART_SRC_WORK}"', ] diff --git a/snapcraft_legacy/plugins/v2/_ros.py b/snapcraft_legacy/plugins/v2/_ros.py index 0aa2681cb3..a97a7aaa70 100644 --- a/snapcraft_legacy/plugins/v2/_ros.py +++ b/snapcraft_legacy/plugins/v2/_ros.py @@ -198,8 +198,7 @@ def _get_stage_runtime_dependencies_commands(self) -> List[str]: def get_build_commands(self) -> List[str]: return ( - self._get_workspace_activation_commands() - + [ + [ "if [ ! -f /etc/ros/rosdep/sources.list.d/20-default.list ]; then", # Preserve http(s)_proxy env var in root for remote-build proxy since rosdep # doesn't support proxy diff --git a/tests/legacy/unit/plugins/v2/test_catkin.py b/tests/legacy/unit/plugins/v2/test_catkin.py index 6493afb46f..812305f3fa 100644 --- a/tests/legacy/unit/plugins/v2/test_catkin.py +++ b/tests/legacy/unit/plugins/v2/test_catkin.py @@ -119,17 +119,6 @@ class Options: monkeypatch.setattr(os, "environ", dict()) assert plugin.get_build_commands() == [ - 'state="$(set +o); set -$-"', - "set +u", - 'if [ -f "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/setup.sh" ]; then', - "set -- --local", - '_CATKIN_SETUP_DIR="${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}" . "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/setup.sh"', - "set -- --local --extend", - "else", - "set -- --local", - "fi", - '. /opt/ros/"${ROS_DISTRO}"/setup.sh', - 'eval "${state}"', "if [ ! -f /etc/ros/rosdep/sources.list.d/20-default.list ]; then", "sudo --preserve-env=http_proxy,https_proxy rosdep init; fi", 'rosdep update --include-eol-distros --rosdistro "${ROS_DISTRO}"', @@ -215,17 +204,6 @@ class Options: ) assert plugin.get_build_commands() == [ - 'state="$(set +o); set -$-"', - "set +u", - 'if [ -f "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/setup.sh" ]; then', - "set -- --local", - '_CATKIN_SETUP_DIR="${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}" . "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/setup.sh"', - "set -- --local --extend", - "else", - "set -- --local", - "fi", - '. /opt/ros/"${ROS_DISTRO}"/setup.sh', - 'eval "${state}"', "if [ ! -f /etc/ros/rosdep/sources.list.d/20-default.list ]; then", "sudo --preserve-env=http_proxy,https_proxy rosdep init; fi", 'rosdep update --include-eol-distros --rosdistro "${ROS_DISTRO}"', diff --git a/tests/legacy/unit/plugins/v2/test_catkin_tools.py b/tests/legacy/unit/plugins/v2/test_catkin_tools.py index 52beb8b0cc..debf267f42 100644 --- a/tests/legacy/unit/plugins/v2/test_catkin_tools.py +++ b/tests/legacy/unit/plugins/v2/test_catkin_tools.py @@ -113,24 +113,8 @@ class Options: monkeypatch.setattr(os, "environ", dict()) assert plugin.get_build_commands() == [ -<<<<<<< HEAD - 'state="$(set +o); set -$-"', - "set +u", - 'if [ -f "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/setup.sh" ]; then', - "set -- --local", - '_CATKIN_SETUP_DIR="${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}" . "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/setup.sh"', - "set -- --local --extend", - "else", - "set -- --local", - "fi", - '. /opt/ros/"${ROS_DISTRO}"/setup.sh', - 'eval "${state}"', "if [ ! -f /etc/ros/rosdep/sources.list.d/20-default.list ]; then", "sudo --preserve-env=http_proxy,https_proxy rosdep init; fi", -======= - "if [ ! -f /etc/ros/rosdep/sources.list.d/20-default.list ]; then sudo rosdep " - "init; fi", ->>>>>>> 699b39a7 (ros: catkin_tools support for content sharing) 'rosdep update --include-eol-distros --rosdistro "${ROS_DISTRO}"', 'state="$(set +o); set -$-"', "set +u", @@ -218,17 +202,6 @@ class Options: ) assert plugin.get_build_commands() == [ - 'state="$(set +o); set -$-"', - "set +u", - 'if [ -f "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/setup.sh" ]; then', - "set -- --local", - '_CATKIN_SETUP_DIR="${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}" . "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/setup.sh"', - "set -- --local --extend", - "else", - "set -- --local", - "fi", - '. /opt/ros/"${ROS_DISTRO}"/setup.sh', - 'eval "${state}"', "if [ ! -f /etc/ros/rosdep/sources.list.d/20-default.list ]; then", "sudo --preserve-env=http_proxy,https_proxy rosdep init; fi", 'rosdep update --include-eol-distros --rosdistro "${ROS_DISTRO}"', diff --git a/tests/legacy/unit/plugins/v2/test_colcon.py b/tests/legacy/unit/plugins/v2/test_colcon.py index 284bbf59ae..1267afbbb5 100644 --- a/tests/legacy/unit/plugins/v2/test_colcon.py +++ b/tests/legacy/unit/plugins/v2/test_colcon.py @@ -130,16 +130,6 @@ class Options: monkeypatch.setattr(os, "environ", dict()) assert plugin.get_build_commands() == [ - 'state="$(set +o); set -$-"', - "set +u", - 'if [ -f "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/local_setup.sh" ]; then', - 'AMENT_CURRENT_PREFIX="${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}" . "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/local_setup.sh"', - "fi", - 'if [ -f "${SNAPCRAFT_PART_INSTALL}"/opt/ros/snap/local_setup.sh ]; then', - 'COLCON_CURRENT_PREFIX="${SNAPCRAFT_PART_INSTALL}"/opt/ros/snap . "${SNAPCRAFT_PART_INSTALL}"/opt/ros/snap/local_setup.sh', - "fi", - '. /opt/ros/"${ROS_DISTRO}"/local_setup.sh', - 'eval "${state}"', "if [ ! -f /etc/ros/rosdep/sources.list.d/20-default.list ]; then", "sudo --preserve-env=http_proxy,https_proxy rosdep init; fi", 'rosdep update --include-eol-distros --rosdistro "${ROS_DISTRO}"', @@ -234,16 +224,6 @@ class Options: ) assert plugin.get_build_commands() == [ - 'state="$(set +o); set -$-"', - "set +u", - 'if [ -f "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/local_setup.sh" ]; then', - 'AMENT_CURRENT_PREFIX="${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}" . "${SNAPCRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/local_setup.sh"', - "fi", - 'if [ -f "${SNAPCRAFT_PART_INSTALL}"/opt/ros/snap/local_setup.sh ]; then', - 'COLCON_CURRENT_PREFIX="${SNAPCRAFT_PART_INSTALL}"/opt/ros/snap . "${SNAPCRAFT_PART_INSTALL}"/opt/ros/snap/local_setup.sh', - "fi", - '. /opt/ros/"${ROS_DISTRO}"/local_setup.sh', - 'eval "${state}"', "if [ ! -f /etc/ros/rosdep/sources.list.d/20-default.list ]; then", "sudo --preserve-env=http_proxy,https_proxy rosdep init; fi", 'rosdep update --include-eol-distros --rosdistro "${ROS_DISTRO}"', diff --git a/tests/unit/parts/plugins/test_colcon.py b/tests/unit/parts/plugins/test_colcon.py index 7e17f1d3ff..2e27a13c4c 100644 --- a/tests/unit/parts/plugins/test_colcon.py +++ b/tests/unit/parts/plugins/test_colcon.py @@ -164,18 +164,6 @@ def test_get_build_commands(self, setup_method_fixture, new_dir, monkeypatch): monkeypatch.setattr(os, "environ", {}) assert plugin.get_build_commands() == [ - 'state="$(set +o); set -$-"', - "set +u", - 'if [ -f "${CRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/local_setup.sh" ]; then', - 'COLCON_CURRENT_PREFIX="${CRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}" . ' - '"${CRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/local_setup.sh"', - "fi", - 'if [ -f "${CRAFT_PART_INSTALL}/opt/ros/snap/local_setup.sh" ]; then', - 'COLCON_CURRENT_PREFIX="${CRAFT_PART_INSTALL}/opt/ros/snap" . ' - '"${CRAFT_PART_INSTALL}/opt/ros/snap/local_setup.sh"', - "fi", - '. "/opt/ros/${ROS_DISTRO}/local_setup.sh"', - 'eval "${state}"', "if [ ! -f /etc/ros/rosdep/sources.list.d/20-default.list ]; then", "sudo --preserve-env=http_proxy,https_proxy rosdep init; fi", 'rosdep update --include-eol-distros --rosdistro "${ROS_DISTRO}"', @@ -278,18 +266,6 @@ def test_get_build_commands_with_all_properties( ) assert plugin.get_build_commands() == [ - 'state="$(set +o); set -$-"', - "set +u", - 'if [ -f "${CRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/local_setup.sh" ]; then', - 'COLCON_CURRENT_PREFIX="${CRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}" . ' - '"${CRAFT_PART_INSTALL}/opt/ros/${ROS_DISTRO}/local_setup.sh"', - "fi", - 'if [ -f "${CRAFT_PART_INSTALL}/opt/ros/snap/local_setup.sh" ]; then', - 'COLCON_CURRENT_PREFIX="${CRAFT_PART_INSTALL}/opt/ros/snap" . ' - '"${CRAFT_PART_INSTALL}/opt/ros/snap/local_setup.sh"', - "fi", - '. "/opt/ros/${ROS_DISTRO}/local_setup.sh"', - 'eval "${state}"', "if [ ! -f /etc/ros/rosdep/sources.list.d/20-default.list ]; then", "sudo --preserve-env=http_proxy,https_proxy rosdep init; fi", 'rosdep update --include-eol-distros --rosdistro "${ROS_DISTRO}"', From 2d5b98a130bea31e3a1bab12d64603c32564210b Mon Sep 17 00:00:00 2001 From: artivis Date: Thu, 13 Jul 2023 11:54:06 +0200 Subject: [PATCH 79/84] ros: plugin-aware meta extensions Signed-off-by: artivis --- snapcraft/extensions/_ros2_humble_meta.py | 15 +++++++++------ .../_extensions/_ros1_noetic_meta.py | 10 ++++++++++ .../project_loader/extensions/test_extensions.py | 2 ++ .../parts/extensions/test_ros2_humble_meta.py | 6 +++++- 4 files changed, 26 insertions(+), 7 deletions(-) diff --git a/snapcraft/extensions/_ros2_humble_meta.py b/snapcraft/extensions/_ros2_humble_meta.py index e54b776d78..e4204d5f93 100644 --- a/snapcraft/extensions/_ros2_humble_meta.py +++ b/snapcraft/extensions/_ros2_humble_meta.py @@ -79,12 +79,15 @@ def get_app_snippet(self) -> Dict[str, Any]: return app_snippet @overrides - def get_part_snippet(self) -> Dict[str, Any]: - part_snippet = super().get_part_snippet() - part_snippet["colcon-ros-build-snaps"] = [self.ros2_humble_snaps.sdk] - part_snippet["colcon-cmake-args"] = [ - f'-DCMAKE_SYSTEM_PREFIX_PATH="/snap/{self.ros2_humble_snaps.sdk}/current/usr"' - ] + def get_part_snippet(self, *, plugin_name: str) -> Dict[str, Any]: + part_snippet = super().get_part_snippet(plugin_name=plugin_name) + + # These are colcon-plugin specific entries + if plugin_name == "colcon": + part_snippet["colcon-ros-build-snaps"] = [self.ros2_humble_snaps.sdk] + part_snippet["colcon-cmake-args"] = [ + f'-DCMAKE_SYSTEM_PREFIX_PATH="/snap/{self.ros2_humble_snaps.sdk}/current/usr"' + ] return part_snippet diff --git a/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py b/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py index c43b14755e..59f9e9b19b 100644 --- a/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py +++ b/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py @@ -50,6 +50,8 @@ def is_experimental(base: Optional[str]) -> bool: def __init__(self, *, extension_name: str, yaml_data: Dict[str, Any]) -> None: super().__init__(extension_name=extension_name, yaml_data=yaml_data) + self.part_snippet_extra = dict() + self.root_snippet["plugs"] = { "ros-noetic": { @@ -75,3 +77,11 @@ def __init__(self, *, extension_name: str, yaml_data: Dict[str, Any]) -> None: ] self.app_snippet["environment"]["PYTHONPATH"] = f'{python_paths}:{":".join(new_python_paths)}' + + @overrides + def get_part_snippet(self, *, plugin_name: str) -> Dict[str, Any]: + # If the part uses a ROS plugin, return the extra bits containing ROS plugin specifics entries + # If not, still return the base ROS plugin entries. + if plugin_name in ["catkin", "catkin-tools", "colcon"]: + return self.part_snippet | self.part_snippet_extra + return self.part_snippet diff --git a/tests/legacy/unit/project_loader/extensions/test_extensions.py b/tests/legacy/unit/project_loader/extensions/test_extensions.py index fe15ce7045..08e0c4f22e 100644 --- a/tests/legacy/unit/project_loader/extensions/test_extensions.py +++ b/tests/legacy/unit/project_loader/extensions/test_extensions.py @@ -17,6 +17,7 @@ import inspect import textwrap +import pytest from testscenarios import multiply_scenarios from snapcraft_legacy.internal.project_loader import ( @@ -47,6 +48,7 @@ class ExtensionCombinationTest(ProjectLoaderBaseTest): ) ) + @pytest.mark.skip(reason="Doesn't scale") def test_extensions_all_combinations_validate(self): common_bases = set(["core20"]) diff --git a/tests/unit/parts/extensions/test_ros2_humble_meta.py b/tests/unit/parts/extensions/test_ros2_humble_meta.py index d697bde39d..39b5e4827e 100644 --- a/tests/unit/parts/extensions/test_ros2_humble_meta.py +++ b/tests/unit/parts/extensions/test_ros2_humble_meta.py @@ -155,7 +155,7 @@ def test_get_app_snippet(self, extension_name, extension_class, meta, meta_dev): @pytest.mark.parametrize(fixture_variables, fixture_values) def test_get_part_snippet(self, extension_name, extension_class, meta, meta_dev): extension = setup_method_fixture(extension_class) - assert extension.get_part_snippet() == { + assert extension.get_part_snippet(plugin_name="colcon") == { "build-environment": [{"ROS_VERSION": "2"}, {"ROS_DISTRO": "humble"}], "colcon-ros-build-snaps": [meta_dev], "colcon-cmake-args": [ @@ -163,6 +163,10 @@ def test_get_part_snippet(self, extension_name, extension_class, meta, meta_dev) ], } + assert extension.get_part_snippet(plugin_name="cmake") == { + "build-environment": [{"ROS_VERSION": "2"}, {"ROS_DISTRO": "humble"}], + } + @pytest.mark.parametrize(fixture_variables, fixture_values) def test_get_parts_snippet(self, extension_name, extension_class, meta, meta_dev): extension = setup_method_fixture(extension_class) From 434d32c2ec205258c4a1ae2d538f8ae5e95cbe8b Mon Sep 17 00:00:00 2001 From: artivis Date: Wed, 26 Jul 2023 16:31:02 +0200 Subject: [PATCH 80/84] ros: source colcon ws only if it exists Signed-off-by: artivis --- extensions/ros2/launch | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/extensions/ros2/launch b/extensions/ros2/launch index cc7638ea31..4c94591eda 100755 --- a/extensions/ros2/launch +++ b/extensions/ros2/launch @@ -39,6 +39,9 @@ if [ -d "$SNAP/opt/ros/underlay_ws/opt/ros/$ROS_DISTRO" ] || [ -d "$SNAP/opt/ros fi source_with_prefix "$SNAP/opt/ros/$ROS_DISTRO" -source_with_prefix "$SNAP/opt/ros/snap" + +if [ -f "$SNAP/opt/ros/snap/local_setup.bash" ]; then + source_with_prefix "$SNAP/opt/ros/snap" +fi exec "${original_args[@]}" From 1dba7e79556574aba3ea5f57ae823e613b860f38 Mon Sep 17 00:00:00 2001 From: artivis Date: Thu, 27 Jul 2023 17:24:04 +0200 Subject: [PATCH 81/84] ros: fix ros1 noetic ext part-snippet Signed-off-by: artivis --- .../project_loader/_extensions/_ros1_noetic_meta.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py b/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py index 59f9e9b19b..24d1f3fc84 100644 --- a/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py +++ b/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py @@ -62,13 +62,13 @@ def __init__(self, *, extension_name: str, yaml_data: Dict[str, Any]) -> None: } } - self.part_snippet["ros-content-sharing-extension-cmake-args"] = [ + self.part_snippet_extra["ros-content-sharing-extension-cmake-args"] = [ f'-DCMAKE_SYSTEM_PREFIX_PATH="/snap/{self.ros_noetic_snaps.sdk}/current/usr"' ] - self.part_snippet["stage-packages"] = [f"ros-{self.ROS_DISTRO}-ros-environment"] + self.part_snippet_extra["stage-packages"] = [f"ros-{self.ROS_DISTRO}-ros-environment"] - self.part_snippet["ros-build-snaps"] = [self.ros_noetic_snaps.sdk] + self.part_snippet_extra["ros-build-snaps"] = [self.ros_noetic_snaps.sdk] python_paths = self.app_snippet["environment"]["PYTHONPATH"] new_python_paths = [ From 80e30d2c1add151a7cde37c9e6f24b86d8f70fc6 Mon Sep 17 00:00:00 2001 From: artivis Date: Thu, 27 Jul 2023 20:03:55 +0200 Subject: [PATCH 82/84] ros: comply with python 3.8 Signed-off-by: artivis --- .../internal/project_loader/_extensions/_ros1_noetic_meta.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py b/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py index 24d1f3fc84..d9fceafafb 100644 --- a/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py +++ b/snapcraft_legacy/internal/project_loader/_extensions/_ros1_noetic_meta.py @@ -83,5 +83,5 @@ def get_part_snippet(self, *, plugin_name: str) -> Dict[str, Any]: # If the part uses a ROS plugin, return the extra bits containing ROS plugin specifics entries # If not, still return the base ROS plugin entries. if plugin_name in ["catkin", "catkin-tools", "colcon"]: - return self.part_snippet | self.part_snippet_extra + return {**self.part_snippet,**self.part_snippet_extra} return self.part_snippet From 8af39ade5a01ffb373c0b2ef017256beaa98811d Mon Sep 17 00:00:00 2001 From: artivis Date: Thu, 27 Jul 2023 20:04:10 +0200 Subject: [PATCH 83/84] ros: fix unit test Signed-off-by: artivis --- .../extensions/test_ros1_noetic_meta.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py b/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py index caf3e0a34e..78661abe69 100644 --- a/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py +++ b/tests/legacy/unit/project_loader/extensions/test_ros1_noetic_meta.py @@ -120,6 +120,19 @@ def test_extension(self, extension_name, extension_class, meta, meta_dev): assert ros1_extension.part_snippet == { "build-environment": [{"ROS_VERSION": "1"}, {"ROS_DISTRO": "noetic"}], + } + + assert ros1_extension.get_part_snippet(plugin_name="catkin") == { + "build-environment": [{"ROS_VERSION": "1"}, {"ROS_DISTRO": "noetic"}], + "ros-build-snaps": [meta_dev], + "ros-content-sharing-extension-cmake-args": [ + f'-DCMAKE_SYSTEM_PREFIX_PATH="/snap/{meta_dev}/current/usr"' + ], + "stage-packages": ["ros-noetic-ros-environment"], + } + + assert ros1_extension.get_part_snippet(plugin_name="catkin-tools") == { + "build-environment": [{"ROS_VERSION": "1"}, {"ROS_DISTRO": "noetic"}], "ros-build-snaps": [meta_dev], "ros-content-sharing-extension-cmake-args": [ f'-DCMAKE_SYSTEM_PREFIX_PATH="/snap/{meta_dev}/current/usr"' From a784fd927806e0661f2a19d15b5581556623f640 Mon Sep 17 00:00:00 2001 From: artivis Date: Fri, 28 Jul 2023 09:04:02 +0200 Subject: [PATCH 84/84] ros: pedantic Signed-off-by: artivis --- extensions/ros2/launch | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/extensions/ros2/launch b/extensions/ros2/launch index 4c94591eda..0111a278f8 100755 --- a/extensions/ros2/launch +++ b/extensions/ros2/launch @@ -2,12 +2,13 @@ function source_with_prefix() { export ROS_WORKSPACE_CURRENT_PREFIX="$1" - if [ ! -f "$ROS_WORKSPACE_CURRENT_PREFIX/local_setup.bash" ]; then - echo "error: $ROS_WORKSPACE_CURRENT_PREFIX/local_setup.bash not found" + SETUP_SCRIPT="$ROS_WORKSPACE_CURRENT_PREFIX/local_setup.bash" + if [ ! -f "$SETUP_SCRIPT" ]; then + echo "error: $SETUP_SCRIPT not found" exit 1 fi # shellcheck disable=SC1090,SC1091 - source "$ROS_WORKSPACE_CURRENT_PREFIX/local_setup.bash" + source "$SETUP_SCRIPT" } # Save off parameters, the sourced setup scripts may manipulate them.