doom_ros2_lsp_docker.png

Doom, ROS2 and lsp-docker

While going through a udemy course for ROS2 I realized that installing ROS on Arch wasn’t as easy as a yay away. Here I’ll explain how I use lsp-docker to get a docker container with the ROS2 libraries installed which can run a LSP server for doom emacs. This way I can get proper LSP support even though I don’t have the libraries installed on my computer.

How?

First we need to tell doom to install the package we’re about to use.

...
(package! lsp-docker)
...

We then tell doom to let the package take over when it comes to starting a LSP server. But only for specific languages, Python and C++. And only while beneath a specific path.

...
(use-package! lsp-docker
  :config
   ; For which LSP clients do we want to hijack the server starting?
   (defvar lsp-docker-client-packages
    '(lsp-clients lsp-pylsp lsp-clangd))

   ; The settings for this hijacking
   (setq lsp-docker-client-configs
    '((:server-id clangd
       :docker-server-id clangd-docker
       :server-command "ccls"
       :docker-image-id  "0x57/ccls-ros-lsp"
       :docker-container-name "0x57-cpp-ros-lsp")
      (:server-id pylsp
       :docker-server-id pylsp-docker
       :server-command "pylsp"
       :docker-image-id "0x57/pylsp-ros-lsp"
       :docker-container-name "0x57-py-ros-lsp")))

   ; Initalize above
   (lsp-docker-init-clients
    :path-mappings '(
                    ("/path/to/a/project/on/host"  . "/path/to/mount/it/in/container")
                    ("/path/to/another/project/on/host" . "/path/to/mount/it/in/container")
                     )
    :client-packages lsp-docker-client-packages
    :client-configs lsp-docker-client-configs))
...

We’re using custom docker images which is why we specify :docker-image-id. We do this since they need to contain ROS and other related libraries (otherwise LSP wouldn’t be able to find them). These images have to be pulled first with docker pull 0x57/ccls-ros-lsp for the package to be able to start them. See listing 3 and 4 for the images setup. We’re naming the containers since it’s demanded by the package. :path-mappings allows us to tell the package to mount different projects under different paths in the container. With the help of this, and a compile_commands.json file in the project root (e.g. /path/to/a/project/on/host), LSP will be able to find project specific files that might be needed. Such as project libraries.

With this done you should be able to open a C++/Python file beneath any of the given project paths and the package should start a container with the specified LSP server. You can check if the container shows up with docker container ps.

The dockerfiles

The image used by the docker container that start LSP for C++ is shown below.

FROM ros:foxy

RUN apt-get update \
    && apt-get upgrade -y \
    && apt-get install -y ccls \
      ros-${ROS_DISTRO}-demo-nodes-cpp

Every concievable thing related to ROS2 foxy won’t be installed from this. As time moves on you might find yourself with a missing library, and thus have to extend the dockerfile. A bit more has to be done for the Python LSP server, but not that much.

FROM ros:foxy

RUN apt-get update \
    && apt-get upgrade -y \
    && apt-get install -y python3-pip git

RUN mkdir -p rclpy_ws/src
WORKDIR rclpy_ws/src
RUN git clone https://github.com/ros2/rclpy.git
WORKDIR rclpy_ws
RUN colcon build --symlink-install

RUN pip install python-lsp-server

Both images will be updated to work with the udemy course. So if you’re following that, you might not have to update these dockerfiles and can just pull the ones I’ve already built.



Updates:
2022-11-20: Changed info about :path-mappings.