Skip to content

Commit 4880d00

Browse files
DEKHTIARJonathanScottToddGMNGeoffrey
authored
[Dev Container] - Adding VSCode Dev Container Capability (iree-org#12921)
This PR aims to add support for VS Code development container - iree-org#12907 Full Documentation: .devcontainer/README.md --------- Co-authored-by: Scott Todd <[email protected]> Co-authored-by: Geoffrey Martin-Noble <[email protected]>
1 parent 8548216 commit 4880d00

File tree

10 files changed

+450
-11
lines changed

10 files changed

+450
-11
lines changed

.devcontainer/README.md

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
# Getting Started with IREE Development Containers
2+
3+
VS Code Development Container is a feature of Visual Studio Code that allows
4+
developers to create a consistent and isolated development environment for their
5+
projects. It leverages Docker containers to provide an environment that is
6+
identical to the production environment, which means developers can develop and
7+
test their code in an environment that closely mimics the production
8+
environment.
9+
10+
With VS Code Development Container, developers can avoid the hassle of setting
11+
up a local development environment, installing dependencies, and managing
12+
different versions of software packages. Instead, they can use a pre-configured
13+
container that contains all the required dependencies and tools to develop their
14+
project. This makes it easier to share the development environment with other
15+
team members and ensures that everyone is using the same environment.
16+
17+
In addition, VS Code Development Container provides a seamless development
18+
experience by allowing developers to work directly within the container using
19+
Visual Studio Code. They can edit code, run tests, and debug their applications
20+
as if they were working on their local machine.
21+
22+
Overall, VS Code Development Container is a powerful tool for developers who
23+
want to streamline their development process and ensure consistency across their
24+
team's development environment.
25+
26+
## A. Prerequisites
27+
28+
Please follow the following steps to prepare your working environment:
29+
30+
1. **Install Docker:** Before you can use VS Code Development Containers, you
31+
need to have Docker installed on your machine. You can download and install
32+
Docker for your operating system from the official Docker website.
33+
34+
2. **[Optional] Install the NVIDIA-Docker runtime:** If you have an NVIDIA GPU
35+
and want to use it for accelerated computing in your container, you can
36+
install the NVIDIA-Docker runtime. Follow the instructions on the
37+
[NVIDIA-Docker GitHub page](https://github.com/NVIDIA/nvidia-docker) or on
38+
[NVIDIA Developer Documentation](https://developer.nvidia.com/nvidia-container-runtime)
39+
to install the runtime for your operating system.
40+
41+
3. **Install VS Code:** Naturally you will need VS Code to be installed on your
42+
machine: https://code.visualstudio.com/download
43+
44+
4. **Install Dev Container VS Code Extension:** Once VS Code installed, you will
45+
need *Microsoft's Dev Containers extension:*
46+
[ms-vscode-remote.remote-containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers).
47+
48+
5. **[Optional] Install Remote Development VS Code Extension Pack:** If you wish
49+
to setup the `Dev Container` on a remote machine over SSH, we recommend
50+
installing *Microsoft's Remote Development extension pack:* :
51+
[ms-vscode-remote.vscode-remote-extensionpack](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.vscode-remote-extensionpack).
52+
53+
54+
## B. Configuring your Development Container.
55+
56+
IREE Project provides multiple possible development containers which corresponds
57+
to different usecases (e.g CPU, NVIDIA GPUs, etc.).
58+
59+
More containers will be integrated in the future, contributions are welcome.
60+
61+
In order to setup the environment, please execute this script:
62+
63+
```sh
64+
python3 .devcontainer/configure.py
65+
66+
# This question is optional and will only appear if your environment was
67+
# previously configured. It aims to avoid overriding an existing configuration
68+
# inadvertently.
69+
>>> A `docker-compose.yml` already exists. Are you certain you want to overwrite it [y/N]?
70+
71+
# Google provides prebuilt container images hosted on `gcr.io`. We invite you
72+
# and recommend using them. However, for expert users you can use locally built
73+
# containers by answering `N`.
74+
>>> Do you wish to use the official prebuild development containers [Y/n]?
75+
76+
# We offer the option to mount a host directory to use as persistant local
77+
# CCache cache. The directory needs to exist in order to be mounted.
78+
>>> [OPTIONAL] Enter the the directory path to mount as CCache Cache.
79+
It will be mounted in the container under: `/home/iree/.cache/ccache`. [Default: None]:
80+
81+
# We offer the option to mount a host directory to use as persistant local
82+
# build directory. The directory needs to exist in order to be mounted.
83+
>>> [OPTIONAL] Enter the the directory path to mount as Build Directory.
84+
It will mounted in the container under: `/home/iree/build` [Default: None]:
85+
86+
# If your environment has any NVIDIA GPU with properly installed drivers and
87+
# NVIDIA Docker Runtime, you will be asked if you wish to use an NVIDIA GPU
88+
# ready container.
89+
>>> [OPTIONAL] Do you wish to use NVIDIA GPU [y/N]?
90+
91+
# Finally a success message will be printed.
92+
>>> ================================================================================
93+
>>>
94+
>>> Success! Wrote Docker Compose file to `/path/to/iree/.devcontainer/docker-compose.yml`.
95+
```
96+
97+
## C. (Building and) Launching the Development
98+
99+
We can now build or download, if necessary, and launch the development
100+
container. In order to do so, we need to open the VS Code "Command Palette" with
101+
the shortcut: `Ctrl + Shift + P`.
102+
103+
We need to select and click `Dev Containers: Rebuild and Reopen in Container`.
104+
105+
![command palette](docs_data/command_palette.png)
106+
107+
A message will appear signifying that the environment is being setup (this step
108+
might take some time if you need to download or build the container, you can
109+
click on `show log` to see the details and watch the progress):
110+
111+
![dev container setup](docs_data/dev_container_setup.png)
112+
113+
The window will refresh once the environment is ready, and the container will be
114+
started (You can click on `show log` to watch the progress, this might take a
115+
few minutes).
116+
117+
![dev container start](docs_data/dev_container_start.png)
118+
119+
Once the container is started, you will be greeted by the container terminal
120+
(notice the username `iree`):
121+
122+
![dev container terminal](docs_data/dev_container_terminal.png)
123+
124+
**Once done, you are ready to start developing, building and contributing to
125+
IREE 🎉🎉🎉.**

.devcontainer/configure.py

Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
#!/usr/bin/env python3
2+
3+
# Copyright 2023 The IREE Authors
4+
#
5+
# Licensed under the Apache License v2.0 with LLVM Exceptions.
6+
# See https://llvm.org/LICENSE.txt for license information.
7+
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8+
"""Configure script to setup VSCode DevContainer Environment."""
9+
10+
import json
11+
import os
12+
import pathlib
13+
import shlex
14+
import subprocess
15+
import sys
16+
17+
from importlib.machinery import SourceFileLoader
18+
from shutil import which
19+
20+
CURRENT_DIR = pathlib.Path(__file__).resolve().parent
21+
22+
DOCKER_IMAGE_SHORTNAME_DICT = {
23+
"base": "base-bleeding-edge",
24+
"nvidia": "nvidia-bleeding-edge",
25+
}
26+
27+
28+
def run_shell(cmd):
29+
cmd = shlex.split(cmd)
30+
return subprocess.run(cmd, check=True, text=True,
31+
stdout=subprocess.PIPE).stdout
32+
33+
34+
def is_nvidia_gpu_available():
35+
"""This function verifies NVIDIA Docker runtime is installed and
36+
available. It also checks NVIDIA GPU are available and the driver
37+
is installed."""
38+
39+
command_str = f"'{which('docker')}' info --format '{{{{json .}}}}'"
40+
data = json.loads(run_shell(command_str))
41+
42+
if "nvidia" not in data["Runtimes"].keys():
43+
return (
44+
False, "NVIDIA Docker Runtime is not available. Please see: "
45+
"https://developer.nvidia.com/nvidia-container-runtime for additional "
46+
"information.")
47+
48+
nvidia_smi_executable = which('nvidia-smi')
49+
if nvidia_smi_executable is None:
50+
return False, "NVIDIA Driver is not installed or not in the user path."
51+
52+
command_str = f"{nvidia_smi_executable} --query-gpu=gpu_name --format=csv"
53+
54+
if run_shell(command_str).splitlines()[1:]: # Skip header
55+
return True, None
56+
else:
57+
return False, "No NVIDIA GPU was found on this system."
58+
59+
60+
def _get_input(question, default_answer):
61+
try:
62+
answer = input(f"\n- {question} ")
63+
except EOFError:
64+
answer = default_answer
65+
66+
return (answer or default_answer).strip().lower()
67+
68+
69+
def get_input(question, default_answer='', accepted_answers=None):
70+
if accepted_answers is None:
71+
raise RuntimeError("Argument `accepted_answers` is None.")
72+
73+
accepted_answers = [x.strip().lower() for x in accepted_answers]
74+
75+
while True:
76+
answer = _get_input(question, default_answer)
77+
if answer not in accepted_answers:
78+
print(f"\tERROR: Unsupported answer received: {answer}."
79+
f"Expected: {accepted_answers}")
80+
continue
81+
break
82+
83+
return answer
84+
85+
86+
def get_input_path(question):
87+
88+
while True:
89+
answer = _get_input(question, default_answer="")
90+
if answer != "" and not os.path.isdir(answer):
91+
print(f"\tERROR: Received path does not exist: `{answer}`")
92+
continue
93+
break
94+
95+
return answer
96+
97+
98+
if __name__ == "__main__":
99+
100+
# ------------------------------------------------------------------------- #
101+
# Environment Verifications #
102+
# ------------------------------------------------------------------------- #
103+
104+
docker_executable = which('docker')
105+
if docker_executable is None:
106+
raise RuntimeError(
107+
"Docker is not installed or in the user path. Please refer to: "
108+
"https://docs.docker.com/desktop/")
109+
110+
try:
111+
run_shell(f"'{docker_executable}' compose version")
112+
except subprocess.CalledProcessError as e:
113+
raise RuntimeError(
114+
"Docker Compose must be installed in order to use IREE VS Code "
115+
"Development Container. Please refer to: "
116+
"https://docs.docker.com/compose/") from e
117+
118+
docker_image_key = "base"
119+
120+
# ------------------------------------------------------------------------- #
121+
# Mandatory Steps #
122+
# ------------------------------------------------------------------------- #
123+
124+
# STEP 1: Verify the user doesn't have a pre-existing `docker-compose.yml`.
125+
# If yes, confirm they want to overwrite it.
126+
if os.path.isfile(CURRENT_DIR / "docker-compose.yml"):
127+
if get_input(
128+
"A `docker-compose.yml` already exists. Are you certain you want to overwrite it [y/N]?",
129+
default_answer="n",
130+
accepted_answers=["y", "n"]) == "n":
131+
sys.exit(1)
132+
133+
# STEP 2: Read the template configuration file
134+
with open(CURRENT_DIR / "docker-compose.base.yml") as f:
135+
docker_config = json.load(f)
136+
137+
# STEP 3: Prebuilt vs Locally Built Containers
138+
use_official_img = get_input(
139+
"Do you wish to use the official prebuild development containers [Y/n]?",
140+
default_answer="y",
141+
accepted_answers=["y", "n"]) == "y"
142+
143+
# ------------------------------------------------------------------------- #
144+
# Optional Mounting Points - Build & Cache #
145+
# ------------------------------------------------------------------------- #
146+
147+
# STEP 4 [OPTIONAL]: Does the user want to mount a directory for CCACHE ?
148+
ccache_mount_cache = get_input_path(
149+
"[OPTIONAL] Enter the the directory path to mount as CCache Cache.\n"
150+
" It will be mounted in the container under: `/home/iree/.cache/ccache` [Default: None]:"
151+
)
152+
if ccache_mount_cache:
153+
docker_config["services"]["iree-dev"]["volumes"].append(
154+
f"{ccache_mount_cache}:/home/iree/.cache/ccache:cached")
155+
156+
# STEP 5 [OPTIONAL]: Does the user want to mount a directory for BUILD ?
157+
build_mount_cache = get_input_path(
158+
"[OPTIONAL] Enter the the directory path to mount as Build Directory.\n"
159+
" It will mounted in the container under: `/home/iree/build` [Default: None]:"
160+
)
161+
if build_mount_cache:
162+
docker_config["services"]["iree-dev"]["volumes"].append(
163+
f"{build_mount_cache}:/home/iree/build:cached")
164+
165+
# ------------------------------------------------------------------------- #
166+
# Optional Deep Learning Accelerator Support #
167+
# ------------------------------------------------------------------------- #
168+
169+
# STEP 6 [OPTIONAL]: Does the user want to use NVIDIA GPUs ?
170+
nvidia_gpu_available, err_msg = is_nvidia_gpu_available()
171+
172+
if nvidia_gpu_available:
173+
if get_input("[OPTIONAL] Do you wish to use NVIDIA GPU [y/N]?",
174+
default_answer="n",
175+
accepted_answers=["y", "n"]) == "y":
176+
docker_image_key = "nvidia"
177+
178+
else:
179+
print(f"[INFO] NVIDIA GPUs are not available for use: {err_msg}")
180+
181+
if docker_image_key != "nvidia":
182+
del docker_config["services"]["iree-dev"]["deploy"]
183+
184+
# ------------------------------------------------------------------------- #
185+
# Setting the right docker image / container to build #
186+
# ------------------------------------------------------------------------- #
187+
188+
docker_img_shortname = DOCKER_IMAGE_SHORTNAME_DICT[docker_image_key]
189+
190+
if use_official_img:
191+
del docker_config["services"]["iree-dev"]["build"]
192+
193+
docker_iree_registry = SourceFileLoader(
194+
"docker_iree_registry",
195+
str(CURRENT_DIR /
196+
"../build_tools/docker/get_image_name.py")).load_module()
197+
198+
image_name = docker_iree_registry.find_image_by_name(docker_img_shortname)
199+
docker_config["services"]["iree-dev"]["image"] = image_name
200+
201+
else:
202+
del docker_config["services"]["iree-dev"]["image"]
203+
204+
dockerfile = f"build_tools/docker/dockerfiles/{docker_img_shortname}.Dockerfile"
205+
docker_config["services"]["iree-dev"]["build"]["dockerfile"] = dockerfile
206+
207+
if (not os.path.isfile(CURRENT_DIR / ".." / dockerfile)):
208+
raise FileNotFoundError(f"The file `{dockerfile}` does not exist.")
209+
210+
docker_compose_filepath = os.path.join(CURRENT_DIR, "docker-compose.yml")
211+
with open(docker_compose_filepath, "w") as f:
212+
json.dump(docker_config, f, indent=2)
213+
214+
# ------------------------------------------------------------------------- #
215+
# SUCCESS #
216+
# ------------------------------------------------------------------------- #
217+
218+
print("\n" + "=" * 80)
219+
print(f"\nSuccess! Wrote Docker Compose file to `{docker_compose_filepath}`.")

.devcontainer/devcontainer.json

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
2+
// https://github.com/microsoft/vscode-dev-containers/tree/v0.245.2/containers/docker-existing-dockerfile
3+
{
4+
"name": "IREE Development Container",
5+
"dockerComposeFile": [
6+
"docker-compose.yml"
7+
],
8+
"service": "iree-dev",
9+
"remoteUser": "iree",
10+
"workspaceFolder": "/workspaces/iree",
11+
"customizations": {
12+
"vscode": {
13+
"extensions": [
14+
// LLVM & MLIR
15+
"llvm-vs-code-extensions.vscode-clangd",
16+
"llvm-vs-code-extensions.vscode-mlir",
17+
"jakob-erzar.llvm-tablegen",
18+
// CPP
19+
"ms-vscode.cpptools-extension-pack",
20+
// Python
21+
"ms-python.python",
22+
// Build Tools
23+
"ms-azuretools.vscode-docker",
24+
"ms-vscode.makefile-tools",
25+
"ms-vscode.cmake-tools",
26+
// Git & Github
27+
"GitHub.vscode-pull-request-github"
28+
]
29+
}
30+
},
31+
"features": {
32+
"ghcr.io/devcontainers/features/common-utils:2": {
33+
"username": "iree",
34+
"uid": "automatic",
35+
"gid": "automatic",
36+
"installZsh": true,
37+
"installOhMyZsh": true,
38+
"configureZshAsDefaultShell": false,
39+
"upgradePackages": true
40+
},
41+
"ghcr.io/devcontainers/features/git:1": {
42+
"version": "latest"
43+
}
44+
}
45+
}

0 commit comments

Comments
 (0)