|
| 1 | +# Holohub Dev Containers |
| 2 | + |
| 3 | +Holohub uses [Development Containers](https://containers.dev/) to provide consistent and convenient development environments for [Holoscan](https://developer.nvidia.com/holoscan-sdk) and [Holohub](https://github.com/nvidia-holoscan/holohub). This guide covers using the Holohub Dev Container with [Visual Studio Code](https://code.visualstudio.com/). |
| 4 | + |
| 5 | +> 💡 Note: This guide is specific to the Linux development environment and is tested on Ubuntu 22.04 LTS. |
| 6 | +
|
| 7 | +> 💡 Note: This Dev Container does not support [Github Codespaces](https://github.com/features/codespaces) and does not support the *Open Folder in Dev Container* feature from VS Code. Please use the following guide to start the Holohub Dev Container. |
| 8 | +
|
| 9 | +## Prerequisites |
| 10 | + |
| 11 | +- [NVIDIA CUDA Toolkit](https://developer.nvidia.com/cuda-downloads) |
| 12 | +- [Docker](https://docs.docker.com/engine/install/) |
| 13 | +- [NVIDIA Container Toolkit](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html) |
| 14 | +- [VS Code](https://code.visualstudio.com/) with the [Dev Container Extension Pack](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) |
| 15 | + - Install [Dev Container Extension Pack](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) via the command line |
| 16 | + ```bash |
| 17 | + code --install-extension ms-vscode-remote.remote-containers |
| 18 | + ``` |
| 19 | + |
| 20 | +### Steps |
| 21 | + |
| 22 | +1. Clone the Repository |
| 23 | + ```bash |
| 24 | + git clone git@github.com:nvidia-holoscan/holohub.git |
| 25 | + ``` |
| 26 | +2. Open the cloned directory in the terminal. |
| 27 | + |
| 28 | +3. Launch a Dev Container with the `./dev_container` script as follows: |
| 29 | + |
| 30 | + ```bash |
| 31 | + ./dev_container vscode |
| 32 | + ``` |
| 33 | + |
| 34 | + The above command starts a new Dev Container for Holohub using the default [Dockerfile](../Dockerfile). |
| 35 | + |
| 36 | + |
| 37 | +4. VS Code will build and initialize the selected Dev Container. This can take a few minutes for the first time. |
| 38 | + |
| 39 | +5. Once initialized, a new VS Code window will open with the following prompts. Click **Yes** and **Trust Folder & Continue** to continue the Dev Container build process. |
| 40 | + |
| 41 | +   |
| 42 | + |
| 43 | +6. When ready, the Holohub directory is mirrored into the container under `/workspace/holohub` to preserve any changes. |
| 44 | + |
| 45 | +> 💡 Note: VS Code creates a new container image for each Dev Container instance. To clean up the container images, run the following command in the terminal: |
| 46 | +> ```bash |
| 47 | +> docker images --format '{{.Repository}}:{{.Tag}}' | grep '^vsc-holohub' | xargs -r docker rmi |
| 48 | +> ``` |
| 49 | +
|
| 50 | +
|
| 51 | +### Debugging Holohub Applications |
| 52 | +
|
| 53 | +Most Holohub applications are pre-configured with one or more launch profiles. Click the **Run & Debug** tab and select the application you want to run/debug from the dropdown. |
| 54 | +
|
| 55 | +> 💡 Note: Some applications requires special instructions for debugging. Please refer to the [Application-Specific Dockerfile](#application-specific-dockerfile) for more information. |
| 56 | +
|
| 57 | +#### Debugging Multi-Fragment Applications |
| 58 | +
|
| 59 | +To debug multi-fragment applications, find and locate launch profiles prefixed with `(compound)`. |
| 60 | +
|
| 61 | +For example, the [Distributed Endoscopy Tool Tracking](../applications/endoscopy_tool_tracking_distributed/) application is configured with `(compound) endoscopy_tool_tracking_distributed/cpp` and `(compound) endoscopy_tool_tracking_distributed/python` launch profiles. |
| 62 | +
|
| 63 | +Each of these compound launch profiles links to three pre-configured launch profiles, one for each fragment (`video_in`, `inference`, and `viz`): |
| 64 | +
|
| 65 | +- `(compound) endoscopy_tool_tracking_distributed/cpp` |
| 66 | + - `(gdb) endoscopy_tool_tracking_distributed/cpp - video_in fragment` |
| 67 | + - `(gdb) endoscopy_tool_tracking_distributed/cpp - inference fragment` |
| 68 | + - `(gdb) endoscopy_tool_tracking_distributed/cpp - viz fragment` |
| 69 | +- `(compound) endoscopy_tool_tracking_distributed/python` |
| 70 | + - `(gdb) endoscopy_tool_tracking_distributed/python - video_in fragment` |
| 71 | + - `(gdb) endoscopy_tool_tracking_distributed/python - inference fragment` |
| 72 | + - `(gdb) endoscopy_tool_tracking_distributed/python - viz fragment` |
| 73 | +
|
| 74 | +When you start debugging with one of these compound launch profiles, VS Code starts three terminals to build the application, one terminal per fragment. After each terminal completes the build process, VS Code launches another terminal to start the fragment. This compound task feature lets us launch and debug all three fragments simultaneously. |
| 75 | +
|
| 76 | +> 💡 Tip: If VS Code does not launch all three debugger terminals, close all terminals first, then start the compound launch profile again. If the problem persists, try adjusting the start-up delays in the [tasks.json](../.vscode/tasks.json) file. Refer to the [troubleshooting](#troubleshooting) section for more information. |
| 77 | +
|
| 78 | +
|
| 79 | +> 💡 Note: Launch profiles prefixed with `(compound)` for Python applications default to `debugpy` debugger, which only allows debugging of Python code. To debug both Python and C++ code, modify the compound launch profile in the [launch.json](../.vscode/launch.json) and change `(debugpy)` to `(pythoncpp)`. |
| 80 | +
|
| 81 | +
|
| 82 | +
|
| 83 | +
|
| 84 | +#### Step into Holoscan Source Code |
| 85 | +
|
| 86 | +The Holohub Dev Container derives from the [Holoscan NGC Container](https://catalog.ngc.nvidia.com/orgs/nvidia/teams/clara-holoscan/containers/holoscan), which supports debugging of Holoscan source code in C++ and Python. To simplify the process, add the Holoscan source code to the workspace by clicking the **Add Folder to Workspace** menu item from the **File** menu.. Enter `/workspace/holoscan-sdk/` in the **Add Folder to Workspace** dialog box. If VS Code prompts you to reload the window, please do so. Expect to see both the *holohub* and *holoscan-sdk* folders appear under the Explorer tab. |
| 87 | +
|
| 88 | + |
| 89 | +
|
| 90 | +**Let's give it a try:** |
| 91 | +
|
| 92 | +Expand the **holoscan-sdk** folder and open `application.cpp` file from `src/core/` directory. |
| 93 | +Please scroll down to find the `void Application::run()` function and set a breakpoint inside the function. |
| 94 | +
|
| 95 | +With any launch profile prefixed with `gdb` or `pythoncpp`, hit F5 to start a new debugging session. Expect the debugger to hit the breakpoint in the `Application::run()` function. |
| 96 | +
|
| 97 | +> 💡 Important: [Holoscan NGC Container](https://catalog.ngc.nvidia.com/orgs/nvidia/teams/clara-holoscan/containers/holoscan) version 2.3.0 or later version is required to enable debugging of Holoscan source code. |
| 98 | +
|
| 99 | +> ⚠️ Warning: Build error may occur when switching between building inside and outside the Dev Container. When this happens, execute the following command to clear the build cache: |
| 100 | +> |
| 101 | +> ```bash |
| 102 | +> ./run clear_cache |
| 103 | +> ``` |
| 104 | +
|
| 105 | +> ⚠️ Warning: Build error may occur if an application provides its own Dockerfile with additional dependencies. In this case, refer to the [Application-Specific Dockerfile](#application-specific-dockerfile) section to launch a new Dev Container session with the appropriate Docker image. |
| 106 | +
|
| 107 | +## Advanced Options |
| 108 | +
|
| 109 | +### Application-Specific Dockerfile |
| 110 | +
|
| 111 | +For Holohub applications that bundle with a Dockerfile with additional dependencies and tools, pass the application's name to the `./dev_container` script. |
| 112 | +
|
| 113 | +**Usage:** |
| 114 | +
|
| 115 | +```bash |
| 116 | +./dev_container vscode <application_name> [--language [cpp|python]] |
| 117 | +``` |
| 118 | +
|
| 119 | +Take the [endoscopy_depth_estimation](../applications/endoscopy_depth_estimation) application as an example. The command will launch a Dev Container using [applications/endoscopy_depth_estimation/Dockerfile](../applications/endoscopy_depth_estimation/Dockerfile) as the base image that builds `OpenCV`: |
| 120 | +
|
| 121 | +```bash |
| 122 | +./dev_container vscode endoscopy_depth_estimation |
| 123 | +``` |
| 124 | +
|
| 125 | +The `language` argument is optional with `cpp` as default. This argument allows you to use a language-specific Dockerfile when available. |
| 126 | +
|
| 127 | +
|
| 128 | +### Custom Base Image/Dockerfile |
| 129 | +
|
| 130 | +The `./dev_container vscode` script can launch a Dev Container using a custom base image and/or Dockerfile. |
| 131 | +
|
| 132 | +**Usage:** |
| 133 | +
|
| 134 | +```bash |
| 135 | +./dev_container vscode --base_img <image> |
| 136 | +``` |
| 137 | +
|
| 138 | +For example, if an application is designed for Holoscan 1.0 on NVIDIA IGX Orin with integrated GPU, you may want to use Holsocan 1.0.3 as the base image with iGPU support: |
| 139 | +
|
| 140 | +```bash |
| 141 | +./devcontainer vscode --base_img nvcr.io/nvidia/clara-holoscan/holoscan:v1.0.3-igpu |
| 142 | +``` |
| 143 | +
|
| 144 | +In addition, if you have a custom Dockerfile that you would like to use on top of the base image, you may pass it to the `./dev_container` script as follows: |
| 145 | +
|
| 146 | +
|
| 147 | +```bash |
| 148 | +./devcontainer vscode --base_img nvcr.io/nvidia/clara-holoscan/holoscan:v1.0.3-igpu --docker_file /path/to/my/Dockerfile |
| 149 | +``` |
| 150 | +
|
| 151 | +Refer to the [Add a Custom Dockerfile](#add-a-custom-dev-container) section if you have your own Dockerfile. |
| 152 | +
|
| 153 | +```Dockerfile |
| 154 | +ARG BASE_IMAGE |
| 155 | +
|
| 156 | +FROM ${BASE_IMAGE} AS base |
| 157 | +``` |
| 158 | +
|
| 159 | +### Additional Options |
| 160 | +
|
| 161 | +Use the `-h` or `--help` option to see all available options for the `./dev_container` script: |
| 162 | +
|
| 163 | +```bash |
| 164 | +$ ./dev_container vscode -h |
| 165 | +
|
| 166 | +Launch VSCode in DevContainer |
| 167 | +
|
| 168 | +Launch a VSCode instance in a Docker container with the development environment. |
| 169 | + Usage: ./dev_container vscode <application_name> [options] |
| 170 | +
|
| 171 | +Options: |
| 172 | + application_name: Name of an existing Holohub application found in the applications folder. |
| 173 | + If specified and exists: the application-provided DevContainer configuration is used. |
| 174 | + Otherwise, the top-level DevContainer configuration. |
| 175 | + --base_img: Fully qualified base image name, e.g. holoscan-sdk-dev:latest |
| 176 | + --docker_file: Path to Dockerfile to use for building container. |
| 177 | + Defaults to: |
| 178 | + - Application-provided "Dockerfile", if it exists; |
| 179 | + - Otherwise the top-level HoloHub "Dockerfile" |
| 180 | + --language : Specify the app language implementation to run. |
| 181 | + Some applications provide both `cpp` and `python` implementations. |
| 182 | + --docker_opts : Additional options to pass to the Docker launch |
| 183 | +``` |
| 184 | +
|
| 185 | +## Contributing |
| 186 | +
|
| 187 | +> 💡 Note: See [CONTRIBUTING.md](../CONTRIBUTING.md) for details on how to contribute to Holohub. This section describes adding a custom Dockerfile and Dev Container for a Holohub application. |
| 188 | +
|
| 189 | +### Add a Custom Dockerfile |
| 190 | +
|
| 191 | +The following steps allow the `./devcontainer vscode` script to find your custom `Dockerfile`: |
| 192 | +
|
| 193 | +- Create a new `Dockerfile` in your application's root directory or a language-specific directory: |
| 194 | +
|
| 195 | +```bash |
| 196 | +applications/my_application/ |
| 197 | +├── Dockerfile # option 1: put the Dockefile in the root of the application's directory |
| 198 | +├── cpp |
| 199 | +│ └── Dockerfile # option 2: put the Dockerfile in a language-specific directory |
| 200 | +└── python |
| 201 | + └── Dockerfile # option 2: same as above |
| 202 | +``` |
| 203 | +- Include the following at the top of your custom `Dockerfile`: |
| 204 | +
|
| 205 | +```Dockerfile |
| 206 | +ARG BASE_IMAGE |
| 207 | +FROM ${BASE_IMAGE} as base |
| 208 | +``` |
| 209 | +
|
| 210 | +### Add a Custom Dev Container |
| 211 | +
|
| 212 | +Using the following steps enables the `./devcontainer vscode` script to find your custom Dev Container: |
| 213 | +
|
| 214 | +- Create a new directory in the `.devcontainer/` directory (same directory as this README file) with a name that matches the name of your application. |
| 215 | +- Create `devcontainer.json` and `Dockerfile` in the new directory: |
| 216 | +
|
| 217 | +```bash |
| 218 | +.devcontainer/ |
| 219 | +│ └── my_application/ |
| 220 | +│ ├── devcontainer.json |
| 221 | +│ └── Dockerfile |
| 222 | +└── applications/ |
| 223 | + └── my_application/ |
| 224 | +
|
| 225 | +``` |
| 226 | +
|
| 227 | +## Troubleshooting |
| 228 | +
|
| 229 | +### Compound Launch Profile Issues |
| 230 | +
|
| 231 | +A compound launch profile may not launch all the linked launch profiles. For an example, look at the `(compound) endoscopy_tool_tracking_distributed/python` launch profile. |
| 232 | +
|
| 233 | +This profile links to three launch profiles, one for each fragment: `inference`, `inference`, and `viz`. |
| 234 | +
|
| 235 | +1. `(debugpy) endoscopy_tool_tracking_distributed/python - video_in fragment` |
| 236 | +2. `(debugpy) endoscopy_tool_tracking_distributed/python - inference fragment` |
| 237 | +3. `(debugpy) endoscopy_tool_tracking_distributed/python - viz fragment` |
| 238 | +
|
| 239 | +The second launch profile, the `inference` fragment, has `preLaunchTask` configured with the `Build endoscopy_tool_tracking_distributed (delay 3s)` task, which can be found in the [tasks.json](../.vscode/tasks.json) file. This task depends on another task called `Delay Task (3s)` with a bash command `sleep 3` via the `dependsOn` property. This delay task allows the `Build endoscopy_tool_tracking_distributed (delay 3s)` task to put a delay before building the application and enable VS Code to start a terminal session properly. Similarly, the `viz` fragment has a delay of 5 seconds configured. These default values may not work in all scenarios; adjust the sleep value to match your needs. |
| 240 | +
|
| 241 | +### Build Errors |
| 242 | +
|
| 243 | +When switching between Dev Container and other build environments, the build may fail with the following error: |
| 244 | +
|
| 245 | +```bash |
| 246 | +CMake Error: The current CMakeCache.txt directory /workspace/holohub/build/endoscopy_tool_tracking_distributed/CMakeCache.txt is different than the directory /home/host/github/holohub/build/endoscopy_tool_tracking_distributed where CMakeCache.txt was created. |
| 247 | +``` |
| 248 | +
|
| 249 | +When this error occurs, run the clear cache command in the terminal or from VS Code Command Palette: |
| 250 | +
|
| 251 | +Terminal: `./run clear_cache` |
| 252 | +VS Code Command Pallette (`CTRL+SHIFT+P`): `Tasks: Run Task` -> `Clear Build Cache`. |
| 253 | +
|
| 254 | +
|
| 255 | +## Resources |
| 256 | +
|
| 257 | +- [Developing inside a Container](https://code.visualstudio.com/docs/devcontainers/containers) |
| 258 | +- [containers.dev](https://containers.dev/) |
| 259 | +- [NVIDIA Holoscan Containers](https://catalog.ngc.nvidia.com/orgs/nvidia/teams/clara-holoscan/containers/holoscan) |
| 260 | +- [Debugging in Visual Studio Code](https://code.visualstudio.com/docs/editor/debugging) |
0 commit comments