Skip to content

Commit c358366

Browse files
sayakpauldanieldk
andauthored
[docs] add a guide on developing with an ide (#574)
* start working on ide-setup.md * Apply suggestions from code review Co-authored-by: Daniël de Kok <me@danieldk.eu> * address venv comments. * address CMake discovery. * mkhl.direnv --------- Co-authored-by: Daniël de Kok <me@danieldk.eu>
1 parent b45883d commit c358366

4 files changed

Lines changed: 215 additions & 0 deletions

File tree

docs/source/_toctree.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
title: Building kernels
3232
- local: builder/local-dev
3333
title: Local Development
34+
- local: builder/ide-setup
35+
title: IDE Setup
3436
- local: kernel-requirements
3537
title: Kernel Requirements
3638
- local: builder/security

docs/source/builder/build.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,9 @@ $ rm -rf .venv # Remove existing venv if any.
9999
$ kernel-builder devshell --variant torch211-cxx11-rocm71-x86_64-linux
100100
```
101101

102+
For an editor-driven workflow with `direnv` activating the devshell on
103+
`cd`, see [IDE Setup](./ide-setup.md).
104+
102105
You can list the variants that the kernel supports with the `list-variants`
103106
subcommand:
104107

docs/source/builder/ide-setup.md

Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
# IDE setup with direnv and the kernel devshell
2+
3+
## Introduction
4+
5+
Language servers do not interpret `build.toml`, so IDE completion for
6+
CUDA, ROCm, framework headers, and the kernel's Python wrapper does not
7+
work out of the box. This guide shows how to configure VS Code so that
8+
completion resolves against the same toolchain `kernel-builder`
9+
uses.
10+
11+
The setup has three pieces:
12+
13+
- `kernel-builder create-pyproject` to emit CMake and setuptools files
14+
the IDE can read (see [Local Development](./local-dev.md)).
15+
- The kernel-builder devshell, which provides the toolchain (CUDA, ROCm,
16+
Torch headers, etc.) from the Nix store.
17+
- `direnv` to activate the devshell on `cd`, so VS Code inherits the
18+
environment through the shell.
19+
20+
Pinning the toolchain through Nix keeps IDE completion aligned with
21+
the build. It also makes switching between CUDA, ROCm, or XPU a
22+
one-line change in `.envrc`.
23+
24+
## Installing direnv and nix-direnv
25+
26+
On non-NixOS systems, install both via `nix profile`:
27+
28+
```bash
29+
$ nix profile install nixpkgs#nix-direnv
30+
```
31+
32+
Add the direnv hook to your shell rc (`~/.bashrc` or
33+
`~/.zshrc`, for example):
34+
35+
```bash
36+
eval "$(direnv hook bash)" # or: direnv hook zsh
37+
```
38+
39+
Source the rc file (or open a new shell) so the hook is
40+
active in the current session:
41+
42+
```bash
43+
$ source ~/.bashrc # or: source ~/.zshrc
44+
```
45+
46+
Wire `nix-direnv` into direnv:
47+
48+
```bash
49+
$ mkdir -p ~/.config/direnv
50+
$ echo 'source $HOME/.nix-profile/share/nix-direnv/direnvrc' \
51+
>> ~/.config/direnv/direnvrc
52+
```
53+
54+
On [NixOS](https://github.com/nix-community/nix-direnv#via-system-configuration-on-nixos)
55+
or with [home-manager](https://github.com/nix-community/nix-direnv#via-home-manager),
56+
enable `programs.direnv` with
57+
`nix-direnv` instead. See
58+
[`terraform/nixos-configuration.nix`](https://github.com/huggingface/kernels/tree/main/terraform/nixos-configuration.nix)
59+
for a working example.
60+
61+
## Activating the devshell with direnv
62+
63+
From the kernel root directory (the one containing `flake.nix` and
64+
`build.toml`), tell direnv to use the flake's default devshell:
65+
66+
```bash
67+
$ echo 'use flake' > .envrc
68+
$ direnv allow
69+
```
70+
71+
`direnv` now activates the default devshell whenever you `cd` into the
72+
project. The devshell's `shellHook` creates and activates a `.venv` on
73+
first entry. Confirm it picked up the toolchain and venv:
74+
75+
```bash
76+
$ which nvcc
77+
/nix/store/.../bin/nvcc
78+
$ ls -ld .venv
79+
drwxr-xr-x ... .venv
80+
$ which python
81+
/path/to/kernel/.venv/bin/python
82+
```
83+
84+
If `.venv` is missing, re-run `direnv reload` and check the output for
85+
the `Creating new venv environment in path: './.venv'` line from the
86+
`shellHook`.
87+
88+
To pin a non-default build variant, name it explicitly:
89+
90+
```bash
91+
$ echo 'use flake .#devShells.torch211-cxx11-rocm71-x86_64-linux' > .envrc
92+
$ direnv allow
93+
```
94+
95+
See [Build Variants](./build-variants.md) for the variant list.
96+
97+
## Generating IDE-facing project files
98+
99+
direnv puts the toolchain on `PATH`, but the C++ language server still
100+
needs a CMake-derived `compile_commands.json` to resolve per-file
101+
include paths. Generate the CMake/setuptools project and the file:
102+
103+
```bash
104+
$ kernel-builder create-pyproject -f
105+
$ cmake -B build-ext -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
106+
$ ln -sf build-ext/compile_commands.json compile_commands.json
107+
```
108+
109+
`-DCMAKE_EXPORT_COMPILE_COMMANDS=ON` is required: the generated CMake
110+
does not set it. The symlink lets the language server find the file
111+
at the project root.
112+
113+
As noted in [Local Development](./local-dev.md), do not commit the
114+
generated files.
115+
116+
## Configuring VS Code
117+
118+
Install the [`mkhl.direnv`](https://github.com/direnv/direnv-vscode)
119+
extension. It activates the project's `.envrc` when VS Code opens
120+
the workspace, so language servers and the integrated terminal see
121+
the devshell environment without launching `code` from a shell.
122+
123+
Alternatively, skip the extension and open the project from a
124+
direnv-activated shell — VS Code inherits the environment that way
125+
too:
126+
127+
```bash
128+
$ cd path/to/kernel
129+
$ code .
130+
```
131+
132+
Install one of the following first-party extensions for C++/CUDA
133+
completion:
134+
135+
- `llvm-vs-code-extensions.vscode-clangd` (recommended for CUDA).
136+
- `ms-vscode.cpptools` (Microsoft C/C++).
137+
138+
Add `.vscode/settings.json` (do not commit):
139+
140+
```jsonc
141+
{
142+
"python.defaultInterpreterPath": "${workspaceFolder}/.venv/bin/python",
143+
144+
// clangd
145+
"clangd.arguments": ["--compile-commands-dir=${workspaceFolder}"],
146+
147+
// Microsoft C/C++ extension
148+
"C_Cpp.default.compileCommands": "${workspaceFolder}/compile_commands.json"
149+
}
150+
```
151+
152+
Depending on the extension being used, the configuration above behaves
153+
differently:
154+
155+
- With `clangd`, the `clangd.arguments` line is optional. clangd already
156+
looks in the parent directories of each source file for
157+
`compile_commands.json` and will find the workspace-root symlink on its
158+
own ([clangd docs](https://clangd.llvm.org/installation#project-setup)).
159+
Setting it explicitly does no harm.
160+
- With the Microsoft C/C++ extension, the `C_Cpp.default.compileCommands`
161+
line is required. The extension does not pick up
162+
`compile_commands.json` from the workspace root on its own, unless
163+
another extension (such as CMake Tools) tells it where to look.
164+
165+
To verify, open `torch-ext/torch_binding.cpp` and hover an
166+
`#include <torch/torch.h>` directive. The resolved path should point
167+
into `/nix/store/...`, not a system path.
168+
169+
## Remote development
170+
171+
Use the VS Code Remote-SSH extension and put the direnv hook in the
172+
remote shell's rc. The remote integrated terminal activates the
173+
devshell on `cd`, and VS Code's language servers — which run on the
174+
remote — inherit that environment. The
175+
[`terraform/`](https://github.com/huggingface/kernels/tree/main/terraform)
176+
setup is already configured this way.
177+
178+
## Switching toolchains
179+
180+
Change the `use flake` line in `.envrc` to point at a different
181+
variant. For example:
182+
183+
```bash
184+
# CUDA 13.0
185+
use flake .#devShells.torch211-cxx11-cu130-x86_64-linux
186+
187+
# ROCm 7.1
188+
use flake .#devShells.torch211-cxx11-rocm71-x86_64-linux
189+
190+
# XPU
191+
use flake .#devShells.torch211-cxx11-xpu20253-x86_64-linux
192+
```
193+
194+
Remove `.venv/` first if it was created against a different variant,
195+
then reload direnv to recreate it via the new devshell's `shellHook`:
196+
197+
```bash
198+
$ rm -rf .venv
199+
$ direnv reload
200+
```
201+
202+
## noarch kernels
203+
204+
For Python-only (noarch) kernels, skip the CMake step in "Generating
205+
IDE-facing project files" and the C++ portions of the VS Code
206+
configuration. The `direnv` setup and `python.defaultInterpreterPath`
207+
are all that is needed.

docs/source/builder/local-dev.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ $ kernel-builder create-pyproject -f path/to/kernel
4848
- Do not add the generated files to Git. `kernel-builder` has regular updates
4949
and you generally want to use files generated by the latest version.
5050

51+
See [IDE Setup](./ide-setup.md) for wiring the generated project into
52+
VS Code with direnv.
53+
5154
## Testing kernel builds before publishing
5255

5356
Once you have built a kernel with kernel builder, you may want to test it

0 commit comments

Comments
 (0)