Skip to content

Commit

Permalink
Adds VSCode integration and deployment image
Browse files Browse the repository at this point in the history
  • Loading branch information
robbiefish committed Jul 28, 2021
1 parent 1226e8a commit 85e9557
Show file tree
Hide file tree
Showing 12 changed files with 261 additions and 65 deletions.
2 changes: 2 additions & 0 deletions .devcontainer/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

/.artifacts
18 changes: 18 additions & 0 deletions .devcontainer/.vscode-docker/c_cpp_properties.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/**",
"/opt/ros/**",
"/usr/share/c++-mscl/source/**"
],
"defines": [],
"compilerPath": "/usr/bin/gcc",
"cStandard": "gnu17",
"cppStandard": "gnu++14",
"intelliSenseMode": "linux-gcc-x64"
}
],
"version": 4
}
15 changes: 15 additions & 0 deletions .devcontainer/.vscode-docker/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "microstrain launch",
"request": "launch",
"target": "/home/microstrain/src/ros_mscl/launch/microstrain.launch",
"type": "ros",
"preLaunchTask": "build"
}
]
}
10 changes: 10 additions & 0 deletions .devcontainer/.vscode-docker/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"python.autoComplete.extraPaths": [
"/home/ros-mscl/devel/lib/python3/dist-packages",
"/opt/ros/noetic/lib/python3/dist-packages"
],
"python.analysis.extraPaths": [
"/home/ros-mscl/devel/lib/python3/dist-packages",
"/opt/ros/noetic/lib/python3/dist-packages"
]
}
20 changes: 20 additions & 0 deletions .devcontainer/.vscode-docker/tasks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "build",
"type": "shell",
"command": "/ros_entrypoint.sh",
"args": [
"catkin_make",
"-DCMAKE_BUILD_TYPE=DEBUG"
],
"group": {
"kind": "build",
"isDefault": true
}
}
]
}
31 changes: 31 additions & 0 deletions .devcontainer/Dockerfile.deploy
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
ARG DEV_IMAGE
ARG ARCH="amd64"
ARG ROS_VERSION="noetic"
ARG ROS_MSCL_DIR="/usr/share/ros-mscl"
FROM ${DEV_IMAGE} as builder

# We will do everything from now on as root since we will be building and copying to global directories
USER root

# Build the driver and it's messages
ARG ROS_MSCL_DIR
COPY ros_mscl "${ROS_MSCL_DIR}/src/ros_mscl"
COPY mscl_msgs "${ROS_MSCL_DIR}/src/mscl_msgs"
RUN set -ex \
&& cd "${ROS_MSCL_DIR}" \
&& /ros_entrypoint.sh catkin_make install -DCMAKE_BUILD_TYPE="RELEASE"

# Build a lighter runtime image from the core ros image which is smaller
FROM ${ARCH}/ros:${ROS_VERSION}-ros-core

# Copy the built binaries from the dev image as well as any dependencies
ARG ROS_MSCL_DIR
ENV ROS_MSCL_DIR "${ROS_MSCL_DIR}"
COPY --from=builder ${ROS_MSCL_DIR}/install ${ROS_MSCL_DIR}/install
COPY --from=builder /usr/share/c++-mscl/libmscl.so /usr/share/c++-mscl/libmscl.so

# Make sure that MSCL is loadable
ENV LD_LIBRARY_PATH "${LD_LIBRARY_PATH}:/usr/share/c++-mscl"

# Default command will be to run ros launch file
CMD ["/bin/bash", "-c", ". ${ROS_MSCL_DIR}/install/setup.bash && roslaunch ros_mscl microstrain.launch"]
19 changes: 18 additions & 1 deletion docker/Dockerfile → .devcontainer/Dockerfile.dev
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
FROM ros:noetic-ros-base-focal
ARG ARCH="amd64"
ARG ROS_VERSION="noetic"
FROM ${ARCH}/ros:${ROS_VERSION}-ros-base

# Install MSCL (github deb install is kind of a pain)
ENV DEBIAN_FRONTEND="noninteractive"
RUN set -ex \
&& apt-get update && apt-get install -y \
jq \
gdb \
git \
curl \
sudo \
&& install_github_deb () { \
org="${1}"; \
repo="${2}"; \
Expand All @@ -25,3 +30,15 @@ COPY mscl_msgs /tmp/src/mscl_msgs
RUN set -ex \
&& rosdep install --from-paths /tmp/src --ignore-src -r -y \
&& rm -rf /tmp/src

# Add a user that will be used when shelling into this container and allow them to use devices
ARG USER_ID=1000
ARG GROUP_ID=1000
RUN set -ex \
&& groupadd -g ${USER_ID} microstrain \
&& useradd -N -m -u ${USER_ID} -g ${GROUP_ID} -G "dialout" microstrain

# Make the directory where we will mount all the files into
USER microstrain
RUN set -ex \
&& mkdir -p ${HOME}/src
82 changes: 82 additions & 0 deletions .devcontainer/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
.PHONY: all build build-shell clean

# These variables should be overridden in CI builds to configure this build
version ?= latest
docker ?= docker
arch ?= amd64
ros_version ?= noetic

# Just set some directory values to support out of tree builds
makefile_path := $(abspath $(lastword $(MAKEFILE_LIST)))
docker_dir := $(dir $(makefile_path))
project_dir := $(abspath $(docker_dir)/..)
project_name := $(shell echo $(notdir $(project_dir)) | tr A-Z a-z)
artifacts_dir := $(docker_dir)/.artifacts/$(arch)-$(ros_version)
build_dir := $(artifacts_dir)/build
devel_dir := $(artifacts_dir)/devel
docker_catkin_root := /home/microstrain
docker_catkin_src_dir := $(docker_catkin_root)/src
docker_catkin_build_dir := $(docker_catkin_root)/build
docker_catkin_devel_dir := $(docker_catkin_root)/devel

# All of these directories have to exist before we can run most tasks
dir_deps := $(artifacts_dir) $(build_dir) $(devel_dir)

# Grab the user and group ID so that the files we create can be deleted and managed from the base system
user_id := $(shell id -u)
group_id := $(shell id -g)

# Set up some variables for the docker build
dev_dockerfile := $(docker_dir)/Dockerfile.dev
deploy_dockerfile := $(docker_dir)/Dockerfile.deploy
build_args := --build-arg http_proxy --build-arg https_proxy --build-arg no_proxy --build-arg USER_ID=$(user_id) --build-arg GROUP_ID=$(group_id)
run_args := -e http_proxy -e https_proxy -e no_proxy
run_mounts := -v "$(project_dir)/ros_mscl:$(docker_catkin_src_dir)/ros_mscl" -v "$(project_dir)/mscl_msgs:$(docker_catkin_src_dir)/mscl_msgs" -v "$(build_dir):$(docker_catkin_build_dir)" -v "$(devel_dir):$(docker_catkin_devel_dir)"
dev_image_name := $(arch)/$(project_name)-dev:$(ros_version)
deploy_image_name := $(arch)/$(project_name):$(ros_version)
dev_image_artifact := $(artifacts_dir)/.image

all: image

image: $(dev_image_artifact) $(deploy_dockerfile)
@$(docker) build \
--build-arg DEV_IMAGE="$(dev_image_name)" \
-t $(deploy_image_name) \
-f $(deploy_dockerfile) \
$(build_args) \
$(project_dir)

$(dev_image_artifact): $(dev_dockerfile) | $(dir_deps)
@$(docker) build \
-t $(dev_image_name) \
-f $(dev_dockerfile) \
$(build_args) \
$(project_dir)
@echo $(dev_image_name) > $@

build-shell: $(dev_image_artifact)
@$(docker) run \
-it \
--rm \
-v /dev:/dev \
--user "microstrain" \
-w $(docker_catkin_root) \
--privileged \
$(run_args) \
$(run_mounts) \
$$(cat $<)

$(artifacts_dir):
@mkdir -p $@

$(build_dir):
@mkdir -p $@

$(devel_dir):
@mkdir -p $@

clean:
@rm -rf "$(build_dir)" "$(devel_dir)"
@rm -f "$(dev_image_artifact)"
@docker ps -a | grep "$(project_name)" | grep "$(arch)" | grep "$(ros_version)" | tr -s " " | cut -d' ' -f1 | xargs docker rm -f || echo "No containers to remove"
@docker images | grep "$(project_name)" | grep "$(arch)" | grep "$(ros_version)" | tr -s " " | cut -d' ' -f1 | xargs docker rmi -f || echo "No images to remove"
35 changes: 35 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"name": "amd64/ros-mscl-dev:noetic",
"context": "..",
"dockerFile": "Dockerfile.dev",
"extensions": [
"ms-iot.vscode-ros",
"ms-vscode.cpptools",
"ms-python.python",
"ms-vscode.cmake-tools"
],
"containerUser": "root",
"remoteUser": "microstrain",
"runArgs": [
"--privileged",
"--security-opt", "seccomp=unconfined"
],
"settings": {
"terminal.integrated.profiles.linux": {
"bash": {
"path": "/ros_entrypoint.sh",
"args": ["/bin/bash"]
}
},
"terminal.integrated.defaultProfile.windows": "bash"
},
"postCreateCommand": "/ros_entrypoint.sh roscore",
"mounts": [
"source=/dev,target=/dev,type=bind,consistency=cached",
"source=${localWorkspaceFolder}/ros_mscl,target=/home/microstrain/src/ros_mscl,type=bind,consistency=cached",
"source=${localWorkspaceFolder}/mscl_msgs,target=/home/microstrain/src/mscl_msgs,type=bind,consistency=cached",
"source=${localWorkspaceFolder}/.devcontainer/.vscode-docker,target=/home/microstrain/.vscode,type=bind,consistency=cached"
],
"workspaceMount": "",
"workspaceFolder": "/home/microstrain"
}
30 changes: 30 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,36 @@ This will launch two nodes that publish data to different namespaces:
An example subscriber node can be found here: [ROS-MSCL Examples](https://github.com/LORD-MicroStrain/ROS-MSCL/tree/master/Examples)


## Docker Integration

### VSCode

The easiest way to use docker while still using an IDE is to use VSCode as an IDE. Follow the steps below to develop on this repo in a docker container

1. Install the following dependencies:
1. [VSCode](https://code.visualstudio.com/)
1. [Docker](https://docs.docker.com/get-docker/)
1. Open VSCode and install the following [plugins](https://code.visualstudio.com/docs/editor/extension-marketplace):
1. [VSCode Docker plugin](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-docker)
1. [VSCode Remote Containers plugin](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers)
1. Open this directory in a container by following [this guide](https://code.visualstudio.com/docs/remote/containers#_quick-start-open-an-existing-folder-in-a-container)
1. Once the folder is open in VSCode, you can build the project by running `Ctrl+Shift+B` to trigger a build, or `Ctrl+p` to open quick open, then type `task build` and hit enter
1. Once the project is built, you can run the project by following [this guide](https://code.visualstudio.com/docs/editor/debugging)

### Make

If you are comfortable working from the command line, or want to produce runtime images, the [Makefile](./devcontainer/Makefile) in the [.devcontainer](./devcontainer) directory
can be used to build docker images, run a shell inside the docker images and produce a runtime image. Follow the steps below to setup your environment to use the `Makefile`

1. Install the following dependencies:
1. [Make](https://www.gnu.org/software/make/)
1. [Docker](https://docs.docker.com/get-docker/)

The `Makefile` exposes the following tasks. They can all be run from the `.devcontainer` directory:
* `make build-shell` - Builds the docker image and starts a shell session in the image allowing the user to develop and build the ROS project using common commands such as `catkin_make`
* `make image` - Builds the runtim image that contains only the required dependencies and the ROS node. The resulting image is names `ros-mscl`
* `make clean` - Cleans up after the above two tasks

## License
ROS-MSCL is released under the MIT License - see the `LICENSE` file in the source distribution.

Expand Down
4 changes: 0 additions & 4 deletions docker/.gitignore

This file was deleted.

60 changes: 0 additions & 60 deletions docker/Makefile

This file was deleted.

0 comments on commit 85e9557

Please sign in to comment.