Skip to content

build: drop the CUDA toolkit dependency - #1

Merged
richardkiene merged 1 commit into
mainfrom
build/drop-cuda-toolkit-dependency
Sep 1, 2026
Merged

build: drop the CUDA toolkit dependency#1
richardkiene merged 1 commit into
mainfrom
build/drop-cuda-toolkit-dependency

Conversation

@richardkiene

@richardkiene richardkiene commented Sep 1, 2026

Copy link
Copy Markdown

Why

nvfd only needs NVML, and NVML ships with every NVIDIA driver as libnvidia-ml.so.1. The only reason the CUDA toolkit was required was nvml.h — and installing the toolkit through a distribution package (apt-get install nvidia-cuda-toolkit in install.sh) can replace or pin the NVIDIA driver on the host. On Ubuntu 22.04 the packaged header is also CUDA 11.5, which predates nvmlDeviceSetFanControlPolicy, so the #ifdef in fan.c silently compiled the auto-restore path out.

What

  • include/nvml_api.h declares the 17 NVML entry points nvfd calls, with the enum values and struct layouts from nvml.h. These are part of the versioned ABI (_v2 suffixes) and do not change.
  • Link by SONAME (-l:libnvidia-ml.so.1) so no libnvidia-ml.so dev symlink is needed either.
  • -Werror=implicit-function-declaration, so an NVML call that is not declared is a build error rather than an implicit int.
  • nvmlDeviceSetFanControlPolicy is always compiled in and its result is checked. Minimum driver is R520 (first branch exporting every symbol; Set*FanSpeed_v2 are R515, SetFanControlPolicy is 520.61.05 / backported to 515.105.01).
  • install.sh: no longer installs nvidia-cuda-toolkit. Preflights libnvidia-ml.so.1 via ldconfig -p before installing anything, builds, probes NVML with the fresh build/nvfd list (which also runs the v1.x migration), and only then stops the old service, installs and starts — an NVML failure leaves the host untouched. The link directory is taken from the same ldconfig line.
  • CI: builds without the toolkit, and links against a stub libnvidia-ml.so.1 built from tests/nvml_stub.c, which defines every declared entry point with the same signature — so both the link line and the symbol set are exercised, and the stub fails to compile if nvml_api.h drifts.

Verified

All 17 symbols resolve in driver 595.84's libnvidia-ml.so.1 (nm -D /lib/x86_64-linux-gnu/libnvidia-ml.so.1, Ubuntu 22.04.5). Code review mechanically checked every prototype, enum value, struct layout and unversioned→_v2 macro against nvml.h from CUDA 12.0 and the current API-13 header (function-pointer _Static_assert equivalence), confirmed nvmlDeviceGetMemoryInfo is not auto-upgraded to _v2, and verified the -l: link with ld.lld against a .so.1-only directory.

nvfd only needs NVML, and NVML ships with every NVIDIA driver as
libnvidia-ml.so.1. The only reason the CUDA toolkit was required was
nvml.h, and installing the toolkit through a distribution package
(nvidia-cuda-toolkit on Debian/Ubuntu) can replace or pin the driver on
the host. On Ubuntu 22.04 the packaged header is also CUDA 11.5, which
predates nvmlDeviceSetFanControlPolicy, so the #ifdef in fan.c silently
compiled the auto-restore path out.

- Add include/nvml_api.h declaring the 17 NVML entry points nvfd calls,
  with the enum values and struct layouts from nvml.h. Signatures are
  part of the versioned ABI (_v2 suffixes), so this is stable.
- Link by SONAME (-l:libnvidia-ml.so.1) so no libnvidia-ml.so dev
  symlink is needed either. Compile with
  -Werror=implicit-function-declaration so an undeclared NVML call is a
  build error, not a silent implicit int.
- nvmlDeviceSetFanControlPolicy is always compiled in and its result
  checked. Minimum driver is R520: the first branch exporting every
  symbol (Set*FanSpeed_v2 are R515; SetFanControlPolicy is 520.61.05,
  backported to 515.105.01).
- install.sh: stop installing nvidia-cuda-toolkit. Preflight
  libnvidia-ml.so.1 via ldconfig before installing anything, build,
  probe NVML with the fresh build/nvfd list (which also runs the v1.x
  migration), and only then stop the old service, install and start, so
  an NVML failure leaves the host untouched instead of half-upgraded.
  The link directory comes from the same ldconfig line, so the linker
  searches where ld.so actually resolves the library.
- CI: build without the toolkit, and link against a stub
  libnvidia-ml.so.1 built from tests/nvml_stub.c, which defines every
  declared entry point with the same signature. This exercises the
  -l: link line and the symbol set, and fails to compile if nvml_api.h
  drifts.
@richardkiene
richardkiene force-pushed the build/drop-cuda-toolkit-dependency branch from ced66b6 to fa27c20 Compare September 1, 2026 16:30
@richardkiene
richardkiene merged commit 4db6ec8 into main Sep 1, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant