CUDA Dev Environment on NixOS
2024-07-23

Setting up CUDA development on NixOS has two high-level steps:

  1. Setting up your GPU and its drivers
  2. Setting up CUDA compilation and runtime

Drivers

Setting up your GPU is decently explained on the NixOS Cuda page. I'm using an eGPU (GTX 1070) connected to my laptop through a thunderbolt port. Therefore, my NixOS contains a module that looks like this:

{ config, pkgs, ... }: { services.xserver.videoDrivers = [ "nvidia" ]; # needed to enable cuda programming hardware.opengl.enable = true; hardware.nvidia.prime = { offload.enable = true; allowExternalGpu = true; intelBusId = "PCI:0:2:0"; nvidiaBusId = "PCI:6:0:0"; }; }

This will set up the drivers for the GPU, and (specific to my configuration) will identify the bus ids of the respective GPUs.

Runtime

Then, we can set up a shell.nix for local development. (Sorry flake.nix friends):

{ pkgs ? import <nixpkgs> { config = { allowUnfree = true; cudaSupport = true; }; }, }: pkgs.mkShell { nativeBuildInputs = with pkgs; [ cudaPackages.cuda_nvcc cudaPackages.cuda_cudart # this is because the CUDA driver being used requires gcc version <= 12 gcc12 ]; shellHook = '' export CUDA_PATH=${pkgs.cudatoolkit} export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/run/opengl-driver/lib ''; }

Now, you can use nvcc to compile CUDA applications. Additionally, LD_LIBRARY_PATH is properly set up to make the CUDA shared libraries discoverable at runtime.

LSP

Lastly, if you're using clangd as an LSP server, CUDA_PATH is taken care of you will have to create a .clangd file containing the --cuda-gpu-arch flag to identify the compute capability of your GPU:

CompileFlags: Add: [ '--cuda-gpu-arch=sm_61', ]