Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add VS Code Setup Instructions #338

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,9 @@ RUN pip install --upgrade pytest
# Install the colcon-cargo and colcon-ros-cargo plugins
RUN pip install git+https://github.com/colcon/colcon-cargo.git git+https://github.com/colcon/colcon-ros-cargo.git

# Default source the ros environment, this correctly sets up the environment
# For vscode and rust-analyzer to work inside the docker image
RUN echo "source /opt/ros/$ROS_DISTRO/setup.bash" >> /root/.bashrc
Comment on lines +24 to +26
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I personally disagree with the approach of adding source to the user's bashrc.

Apart from being (imho) a bad habit, it is convenient for "most" cases but can cause footguns in others. For example let's say a user wanted to do any change on the ROS 2 source code that requires them to compile it from source.

If they did a ROS 2 source build and naively sourced the install/setup.bash they would end up with two overlays. I believe multiple overlays can create a fair bit of trouble if ABI / API compatibility is not respected, as documented in this discussion colcon/colcon-core#465 and in the extensive warnings printed at compile time.
Also, there is a minor footgun for the source build case in which, since a ROS installation is automatically sourced, if users forget the source install/setup.bash command, their commands will "just work" which might not be what they expect.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No that is a super fair point, and I felt dirty doing this.

Do you know of a workaround / alternative? Party of why I wrote these instructions was because of how hard I found it to get the basic Rust tooling that I'm used to having working with this project.

VS Code supports loading environment variables in a few different ways, but I don't think there is any good way to "export" the right variable definitions out of a terminal instance inside the container and then load them into VS Code. Even if you did this it would be really brittle (maybe a VS Code plugin could update automatically).

I can find stack-overflow questions looking for a way of doing this, but no answers.

The crux of the issue is that rust-analyzer and programs launched via its launch configurations, don't provide a way to say "run this bash command ahead of time"...

I can keep digging... But this shouldn't be this hard.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I went on a rabbit hole to try to find other ROS projects that have "solved this problem".

I found Nav2 which is doing a fancier (and probably better) version of sourcing in the .bashrc: https://github.com/ros-planning/navigation2/blob/main/Dockerfile#L153

I'm don't 100% understand what they are doing with their UNDERLAY_WS, but it seems like the better thing to do would be to invoke colcon build in the Dockerfile to get setup.bash to generate, and then source that instead of directly sourcing iron/setup.bash

Is that a good enough solution?

I'll be frank I'm coming from ROS1 and haven't touched ROS2 workspaces yet, so learning while doing here.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my opinion, it's fine to source ros setup.bash in the docker's .bashrc.

To my understanding, this is a docker setup, not a local host system setup. The user of the docker has less possibility to rebuild ROS2 from source.


RUN mkdir -p /workspace && echo "Did you forget to mount the repository into the Docker container?" > /workspace/HELLO.txt
WORKDIR /workspace
78 changes: 52 additions & 26 deletions docs/building.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
# Building `ros2_rust` packages

This is a more detailed guide on how to build ROS 2 packages written in Rust that expands on the minimal steps in the README.

In this guide, the Humble distribution of ROS 2 is used, but newer distributions can be used by simply replacing 'humble' with the distribution name everywhere.


## Choosing a workspace directory and cloning `ros2_rust`

A "workspace directory", or just "workspace", is simply a directory of your choosing that contains your `ros2_rust` checkout and potentially other ROS 2 packages. It will also usually be your working directory for building. There is only one limitation: It must not contain the ROS 2 installation, so it can't be `/`, for instance. Note that this has **nothing** to do with a [`cargo` workspace](https://doc.rust-lang.org/book/ch14-03-cargo-workspaces.html).

If you don't have a workspace directory already, simply create an empty directory in a convenient location.
Expand All @@ -23,19 +21,16 @@ git clone https://github.com/ros2-rust/ros2_rust.git src/ros2_rust


## Environment setup

Building `rclrs` requires a standard [ROS 2 installation](https://docs.ros.org/en/humble/Installation.html), and a few extensions.
These extensions are: `colcon-cargo`, `colcon-ros-cargo`, `cargo-ament-build`. The first two are `colcon` plugins, and the third is a `cargo` plugin.
Building `rclrs` requires a standard [ROS 2 installation](https://docs.ros.org/en/humble/Installation.html), and a few extensions. These extensions are: `colcon-cargo`, `colcon-ros-cargo`, `cargo-ament-build`. The first two are `colcon` plugins, and the third is a `cargo` plugin.

The `libclang` library is also required for automatically generating FFI bindings with `bindgen`. See the [`bindgen` docs](https://rust-lang.github.io/rust-bindgen/requirements.html) on how to install it. As a side note, on Ubuntu the `clang` package is not required, only the `libclang-dev` package.

The `python3-vcstool` package is used in [importing auxiliary repositories](#importing-repositories). It can also be installed through `pip` instead of `apt`.

You can either install these dependencies on your computer, or use the [premade Docker image](#using-the-docker-image).
You can either install these dependencies on your computer, or use the [premade Docker image](#option-2:-using-the-docker-image).


### Option 1: Installing the dependencies

The exact steps may differ between platforms, but as an example, here is how you would install the dependencies on Ubuntu:

<!--- These steps should be kept in sync with README.md --->
Expand All @@ -51,7 +46,6 @@ pip install git+https://github.com/colcon/colcon-ros-cargo.git
```

### Option 2: Using the Docker image

Build the Docker image with

```shell
Expand All @@ -71,7 +65,6 @@ As you can see, this maps the workspace directory to `/workspace` inside the con


### Importing repositories

`ros2_rust` also expects a few other repositories to be in the workspace. They can be imported from a `repos` file contained in `ros2_rust`, like this:

```shell
Expand All @@ -81,29 +74,25 @@ vcs import src < src/ros2_rust/ros2_rust_humble.repos

This uses the [`vcs` tool](https://github.com/dirk-thomas/vcstool), which is preinstalled in the Docker image.

The new repositories are now in `src/ros2`.
The list of needed repositories should very rarely change, so you typically only need to do this once.
The new repositories are now in `src/ros2`. The list of needed repositories should very rarely change, so you typically only need to do this once.


### Sourcing the ROS 2 installation

Before building, the ROS 2 installation, and ideally _only_ the ROS 2 installation, should be sourced.
Sourcing an installation populates a few environment variables such as `$AMENT_PREFIX_PATH`, so if you are not sure, you can check that the `$AMENT_PREFIX_PATH` environment variable contains the ROS 2 installation, e.g. `/opt/ros/humble`.
Before building, the ROS 2 installation, and ideally _only_ the ROS 2 installation, should be sourced. Sourcing an installation populates a few environment variables such as `$AMENT_PREFIX_PATH`, so if you are not sure, you can check that the `$AMENT_PREFIX_PATH` environment variable contains the ROS 2 installation, e.g. `/opt/ros/humble`.

In the pre-made Docker image, sourcing is already done for you. Otherwise, if `$AMENT_PREFIX_PATH` is empty, you need to source the ROS 2 installation yourself:

```shell
# You can also do `source /opt/ros/humble/setup.bash` in bash
. /opt/ros/humble/setup.sh
````
```

If `$AMENT_PREFIX_PATH` contains undesired paths, exit and reopen your shell. If the problem persists, it's probably because of a sourcing command in your `~/.bashrc` or similar.

It's convenient to install `tmux`, especially in Docker, and open separate windows or panes for building and running.


### Checking your setup

To verify that you've correctly installed dependencies and sourced your ROS 2 installation, you should be able to run

```shell
Expand All @@ -120,7 +109,6 @@ The build type `ament_cargo` means that the `colcon-ros-cargo` plugin works as e


## Building with `colcon`

Now that everything is set up, you can build with `colcon`. The basic command to build a package and its dependencies is

```shell
Expand All @@ -136,21 +124,17 @@ In addition to the standard `build`, `install` and `log` directories, `colcon` w


### Tips and limitations
1. Don't start two build processes involving Rust packages in parallel; they might overwrite each other's `.cargo/config.toml`.

Don't start two build processes involving Rust packages in parallel; they might overwrite each other's `.cargo/config.toml`.
1. A clean build will always be much slower than an incremental rebuild.

A clean build will always be much slower than an incremental rebuild.

`colcon test` is not currently implemented for Rust packages.

The plugin to build `cargo` projects with `colcon` currently has the issue that both `cargo` and `colcon` will [rebuild all dependencies for each package](https://github.com/colcon/colcon-ros-cargo/). This makes building large projects with `colcon` less efficient, but if this is an issue, you can build with `cargo` instead.
1. `colcon test` is not currently implemented for Rust packages.

1. The plugin to build `cargo` projects with `colcon` currently has the issue that both `cargo` and `colcon` will [rebuild all dependencies for each package](https://github.com/colcon/colcon-ros-cargo/). This makes building large projects with `colcon` less efficient, but if this is an issue, you can build with `cargo` instead.

## Building with `cargo`

Rust packages for ROS 2 can also be built with pure `cargo`, and still integrate with ROS 2 tools like `ros2 run`.


### Learning by doing

*Note: The following needs to be adapted once we publish `rclrs` on crates.io.*
Expand Down Expand Up @@ -190,8 +174,50 @@ cargo build

If you'd like to not have any of that "overriding dependencies through `.cargo/config.toml`", you can do that too of course. You just need to use concrete paths for any dependency that isn't published on `crates.io`, such as message packages. For instance, you might have to write `std_msgs = {path = '/workspace/install/std_msgs/share/std_msgs/rust'}`.

## VS Code Setup with .devcontainer
A convienent (and reccomended) development setup is use the provided Dockerfile with VS Code's `Dev Containers` extension. To set this up:
Carter12s marked this conversation as resolved.
Show resolved Hide resolved

- Follow the steps in [using the docker image](#option-2-using-the-docker-image) to build an imaged tagged with `ros2_rust_dev` and your preffered ROS2 version.
Carter12s marked this conversation as resolved.
Show resolved Hide resolved
- Install [VS Code](https://code.visualstudio.com/download) and the [Dev Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) extension.
- In the root folder of your workspace (alongside `src/`) create a folder named .devcontainer with a file named devcontainer.json and the contents:
Carter12s marked this conversation as resolved.
Show resolved Hide resolved
```json
{
"name": "rclrs",
"image": "ros2_rust_dev",
// Provide rust-analyzer and lldb within the container
// These are the two most popular and useful rust extensions
"customizations": {
"vscode": {
"extensions": [
"rust-lang.rust-analyzer",
"vadimcn.vscode-lldb"
]
}
}
}
```
- In the root folder of your workspace (alongside `src/`) create a folder named .vscode with a file named settings.json and the contents:
Carter12s marked this conversation as resolved.
Show resolved Hide resolved
```json
{
"rust-analyzer.linkedProjects": [
// List the rust crates you want rust-analyzer to index here
// The more you list the slower start-up time can be
"src/ros2_rust/rclrs/Cargo.toml",
"src/ros2_rust/examples/minimal_pub_sub/Cargo.toml"
],
}
```
- Now open your workspace's root folder in VS Code on your host, then switch into the container by hitting `Ctrl + Shift + P` and running the command `Dev Containers: Reopen in Container`

VS Code will now automatically startup a container with your image, mount your workspace into the container, and connect your VS Code session so that you are operating within the container. Rust Analyzer and Code LLDB should be providing correct intellisense features and the ability to graphically debug. However, `rust-analyzer` may fail to startup correctly if you haven't run `colcon build` from the root of your workspace and correctly generated your `.cargo/config.toml`, see [here](#learning-by-doing) for help.

Note: You may need to manually start the rust-analyzer with `Ctrl + Shift + P` and `rust-analyzer: Start server`.

Instructions provided here are a minimal guide, refer to these documents for additional information:
- [Creating a Dev Container](https://code.visualstudio.com/docs/devcontainers/create-dev-container)
- [Rust with VS Code](https://code.visualstudio.com/docs/languages/rust)

### Integration with ROS 2 tools
## Integration with ROS 2 tools

How can a binary created in Rust be made available to `ros2 run`, `ros2 launch` etc.? And how can other ROS 2 packages use a `cdylib` created in Rust? For that to work, the correct files must be placed at the correct location in the install directory, see [REP 122](https://www.ros.org/reps/rep-0122.html).

Expand Down
Loading