diff --git a/.bazelignore b/.bazelignore index 1e107f52..d88dd6d6 100644 --- a/.bazelignore +++ b/.bazelignore @@ -1 +1,2 @@ examples +bazel-rules_ros2 diff --git a/ros2/cc_defs.bzl b/ros2/cc_defs.bzl index 44285fad..8b79d2fb 100644 --- a/ros2/cc_defs.bzl +++ b/ros2/cc_defs.bzl @@ -64,14 +64,15 @@ def ros2_c_binary(name, ros2_package_name = None, **kwargs): """ _ros2_cc_target(cc_binary, "c", name, ros2_package_name, **kwargs) -def _ros2_cpp_exec(target, name, ros2_package_name = None, set_up_ament = False, **kwargs): - if set_up_ament == False: +def _ros2_cpp_exec(target, name, ros2_package_name = None, set_up_ament = False, set_up_ros_home = False, **kwargs): + if not (set_up_ament or set_up_ros_home): _ros2_cc_target(target, "cpp", name, ros2_package_name, **kwargs) return target_impl = name + "_impl" tags = kwargs.pop("tags", []) visibility = kwargs.pop("visibility", None) + size = kwargs.pop("size", None) _ros2_cc_target(cc_binary, "cpp", target_impl, ros2_package_name, tags = ["manual"], **kwargs) is_test = target == cc_test @@ -82,7 +83,9 @@ def _ros2_cpp_exec(target, name, ros2_package_name = None, set_up_ament = False, deps = [target_impl], template = "@com_github_mvukov_rules_ros2//ros2:launch.sh.tpl", substitutions = { - "{entry_point}": "$(rootpath {})".format(target_impl), + "{{set_up_ros_home}}": "set_up_ros_home" if set_up_ros_home else "", + "{{set_up_ament}}": "set_up_ament" if set_up_ament else "", + "{{entry_point}}": "$(rootpath {})".format(target_impl), }, tags = ["manual"], data = [target_impl], @@ -92,6 +95,7 @@ def _ros2_cpp_exec(target, name, ros2_package_name = None, set_up_ament = False, sh_target = native.sh_test if is_test else native.sh_binary sh_target( name = name, + size = size, srcs = [launcher], data = [target_impl], tags = tags, @@ -110,9 +114,11 @@ def ros2_cpp_binary(name, ros2_package_name = None, set_up_ament = False, **kwar set_up_ament: If true, sets up ament file tree for the binary target. **kwargs: https://bazel.build/reference/be/common-definitions#common-attributes-binaries """ + if "set_up_ros_home" in kwargs: + fail("set_up_ros_home only makes sense for test targets.") _ros2_cpp_exec(cc_binary, name, ros2_package_name, set_up_ament, **kwargs) -def ros2_cpp_test(name, ros2_package_name = None, set_up_ament = False, **kwargs): +def ros2_cpp_test(name, ros2_package_name = None, set_up_ament = False, set_up_ros_home = True, **kwargs): """ Defines a ROS 2 C++ test. Adds common ROS 2 C++ definitions on top of a cc_test. @@ -122,9 +128,7 @@ def ros2_cpp_test(name, ros2_package_name = None, set_up_ament = False, **kwargs ros2_package_name: If given, defines a ROS package name for the target. Otherwise, the `name` is used as the package name. set_up_ament: If true, sets up ament file tree for the test target. + set_up_ros_home: If true, sets up ROS_HOME for the test target. **kwargs: https://bazel.build/reference/be/common-definitions#common-attributes-tests """ - env = kwargs.pop("env", {}) - env["ROS_HOME"] = env.get("ROS_HOME", "$TEST_UNDECLARED_OUTPUTS_DIR") - env["ROS_LOG_DIR"] = env.get("ROS_LOG_DIR", "$TEST_UNDECLARED_OUTPUTS_DIR") - _ros2_cpp_exec(cc_test, name, ros2_package_name, set_up_ament, env = env, **kwargs) + _ros2_cpp_exec(cc_test, name, ros2_package_name, set_up_ament, set_up_ros_home, **kwargs) diff --git a/ros2/launch.sh.tpl b/ros2/launch.sh.tpl index b3d2f0a2..60e91515 100644 --- a/ros2/launch.sh.tpl +++ b/ros2/launch.sh.tpl @@ -2,10 +2,21 @@ set -o errexit -o nounset -o pipefail -ament_prefix_path="{{ament_prefix_path}}" -if [ -z "${ament_prefix_path}" ]; then +if [ -n "{{set_up_ros_home}}" ]; then + if [ -z "${ROS_HOME:-}" ] && [ -z "${ROS_LOG_DIR:-}" ]; then + ros_output_dir="${TEST_UNDECLARED_OUTPUTS_DIR:-${TEST_TMPDIR:-}}" + if [ -n "${ros_output_dir}" ]; then + export ROS_HOME="${ros_output_dir}" + export ROS_LOG_DIR="${ros_output_dir}" + fi + fi +fi + +if [ -n "{{set_up_ament}}" ]; then unset AMENT_PREFIX_PATH - {entry_point} "$@" -else - AMENT_PREFIX_PATH="${ament_prefix_path}" {entry_point} "$@" + if [ -n "{{ament_prefix_path}}" ]; then + export AMENT_PREFIX_PATH="{{ament_prefix_path}}" + fi fi + +"{{entry_point}}" "$@" diff --git a/ros2/py_defs.bzl b/ros2/py_defs.bzl index 0d251c2e..7bf65b9d 100644 --- a/ros2/py_defs.bzl +++ b/ros2/py_defs.bzl @@ -5,14 +5,15 @@ load("@com_github_mvukov_rules_ros2//ros2:ament.bzl", "sh_launcher") load("@com_github_mvukov_rules_ros2//third_party:symlink.bzl", "symlink") load("@rules_python//python:defs.bzl", "py_binary", "py_test") -def _ros2_py_exec(target, name, srcs, main, set_up_ament, **kwargs): - if set_up_ament == False: +def _ros2_py_exec(target, name, srcs, main, set_up_ament = False, set_up_ros_home = False, **kwargs): + if not (set_up_ament or set_up_ros_home): target(name = name, srcs = srcs, main = main, **kwargs) return target_impl = name + "_impl" tags = kwargs.pop("tags", []) visibility = kwargs.pop("visibility", None) + size = kwargs.pop("size", None) target(name = target_impl, srcs = srcs, main = main, tags = ["manual"], **kwargs) is_test = target == py_test @@ -31,7 +32,9 @@ def _ros2_py_exec(target, name, srcs, main, set_up_ament, **kwargs): deps = [target_impl], template = "@com_github_mvukov_rules_ros2//ros2:launch.sh.tpl", substitutions = { - "{entry_point}": "$(rootpath {})".format(target_impl_symlink), + "{{set_up_ros_home}}": "set_up_ros_home" if set_up_ros_home else "", + "{{set_up_ament}}": "set_up_ament" if set_up_ament else "", + "{{entry_point}}": "$(rootpath {})".format(target_impl_symlink), }, tags = ["manual"], data = [target_impl_symlink], @@ -41,6 +44,7 @@ def _ros2_py_exec(target, name, srcs, main, set_up_ament, **kwargs): sh_target = native.sh_test if is_test else native.sh_binary sh_target( name = name, + size = size, srcs = [launcher], data = [target_impl_symlink], tags = tags, @@ -57,9 +61,11 @@ def ros2_py_binary(name, srcs, main, set_up_ament = False, **kwargs): set_up_ament: If true, sets up ament file tree for the binary target. **kwargs: https://bazel.build/reference/be/common-definitions#common-attributes-binaries """ + if "set_up_ros_home" in kwargs: + fail("set_up_ros_home only makes sense for test targets.") _ros2_py_exec(py_binary, name, srcs, main, set_up_ament, **kwargs) -def ros2_py_test(name, srcs, main, set_up_ament = False, **kwargs): +def ros2_py_test(name, srcs, main, set_up_ament = False, set_up_ros_home = True, **kwargs): """ Defines a ROS 2 Python test. Args: @@ -67,6 +73,7 @@ def ros2_py_test(name, srcs, main, set_up_ament = False, **kwargs): srcs: List of source files. main: Source file to use as entrypoint. set_up_ament: If true, sets up ament file tree for the test target. + set_up_ros_home: If true, sets up ROS_HOME for the test target. **kwargs: https://bazel.build/reference/be/common-definitions#common-attributes-tests """ - _ros2_py_exec(py_test, name, srcs, main, set_up_ament, **kwargs) + _ros2_py_exec(py_test, name, srcs, main, set_up_ament, set_up_ros_home, **kwargs) diff --git a/ros2/pytest_wrapper.py.tpl b/ros2/pytest_wrapper.py.tpl index 5d0983f6..280e6b0c 100644 --- a/ros2/pytest_wrapper.py.tpl +++ b/ros2/pytest_wrapper.py.tpl @@ -33,7 +33,7 @@ def finalize_coverage_session(coverage_session: coverage.Coverage) -> None: def main() -> None: - test_outputs_dir = os.environ.get('TEST_UNDECLARED_OUTPUTS_DIR') + test_outputs_dir = os.environ.get('TEST_UNDECLARED_OUTPUTS_DIR') or os.environ.get('TEST_TMPDIR') if test_outputs_dir: os.environ['ROS_HOME'] = test_outputs_dir os.environ['ROS_LOG_DIR'] = test_outputs_dir diff --git a/ros2/test.py.tpl b/ros2/test.py.tpl index a820f147..1b46b934 100644 --- a/ros2/test.py.tpl +++ b/ros2/test.py.tpl @@ -17,7 +17,7 @@ sys.argv = sys.argv[:1] + [ LAUNCH_FILE, ] + sys.argv[1:] -test_outputs_dir = os.environ.get('TEST_UNDECLARED_OUTPUTS_DIR') +test_outputs_dir = os.environ.get('TEST_UNDECLARED_OUTPUTS_DIR') or os.environ.get('TEST_TMPDIR') if test_outputs_dir: os.environ['ROS_HOME'] = test_outputs_dir os.environ['ROS_LOG_DIR'] = test_outputs_dir diff --git a/ros2/test/BUILD.bazel b/ros2/test/BUILD.bazel index 169a974f..15b9b8ff 100644 --- a/ros2/test/BUILD.bazel +++ b/ros2/test/BUILD.bazel @@ -3,6 +3,7 @@ load("@com_github_mvukov_rules_ros2//ros2:cc_defs.bzl", "ros2_cpp_test") load("@com_github_mvukov_rules_ros2//ros2:interfaces.bzl", "py_ros2_interface_library", "ros2_interface_library") +load("@com_github_mvukov_rules_ros2//ros2:py_defs.bzl", "ros2_py_test") load("@rules_python//python:defs.bzl", "py_test") py_test( @@ -49,3 +50,11 @@ ros2_cpp_test( srcs = ["test_rclcpp.cpp"], deps = ["@ros2_rclcpp//:rclcpp"], ) + +ros2_py_test( + name = "test_rclpy", + size = "small", + srcs = ["test_rclpy.py"], + main = "test_rclpy.py", + deps = ["@ros2_rclpy//:rclpy"], +) diff --git a/ros2/test/test_rclpy.py b/ros2/test/test_rclpy.py new file mode 100644 index 00000000..153c2006 --- /dev/null +++ b/ros2/test/test_rclpy.py @@ -0,0 +1,3 @@ +import rclpy + +rclpy.init()