ITADN

conda-file builds cannot install packages requiring __cuda virtual package

#1026Openpinin4fjords 创建于 2026-04-15
P
pinin4fjordscommented
conda-file builds cannot install packages requiring `__cuda` virtual package ### Summary Wave's conda-file builds cannot install any conda-forge package that depends on the `__cuda` virtual package, because Wave's build servers do not have GPUs and the templates provide no mechanism to set `CONDA_OVERRIDE_CUDA` during the conda solve step. This affects all GPU-enabled packages on conda-forge from mid-2022 onwards, including PyTorch >= 1.12.1, JAX, TensorFlow, and others. The standard conda/mamba workaround for building on CPU-only systems is setting `CONDA_OVERRIDE_CUDA=<version>` as an environment variable during the solve. Wave does not support this. This was previously reported in the community forum ([Problems with GPU-enabled wave images](https://community.seqera.io/t/problems-with-gpu-enabled-wave-images/1596), Jan 2025) by Nico_Trummer, who hit the same `__cuda` resolution failure building JAX GPU containers. That thread is unresolved - Paolo responded about the build timeout aspect ([#597](https://github.com/seqeralabs/wave/issues/597)) but the core `CONDA_OVERRIDE_CUDA` gap was not addressed. This issue documents the problem fully with reproduction steps, tested workarounds, and concrete fix proposals. ### Reproduction Given this `environment.gpu.yml`: ```yaml channels: - conda-forge - bioconda dependencies: - "bioconda::ribodetector=0.3.3" - "conda-forge::pytorch-gpu>=2.0" ``` ```bash wave --conda-file environment.gpu.yml --platform linux/amd64 --freeze --await ``` Fails with: ``` Could not solve for environment specs pytorch-gpu >=2.0 is not installable because it requires pytorch [...], which requires __cuda =* *, which is missing on the system. ``` Build log: https://wave.seqera.io/view/builds/bd-bbf66b1b68ac0df5_1 ### Why this matters The `__cuda` virtual package requirement was introduced in conda-forge's PyTorch builds starting at version 1.12.1. We verified this by testing every major version on a Linux x86_64 system without `CONDA_OVERRIDE_CUDA` set: | pytorch-gpu version | Resolves without `__cuda`? | CUDA packaging | |---|---|---| | 1.11.0 | Yes | Uses `cudatoolkit` (regular package) | | 1.12.1 | **No** | Requires `__cuda` virtual package | | 1.13.1 | **No** | Requires `__cuda` virtual package | | 2.0.0 | **No** | Requires `__cuda` virtual package | | 2.5.1 | **No** | Requires `__cuda` virtual package | This means Wave can only install `pytorch-gpu=1.11.0` (March 2022, CUDA 11.1) via `--conda-file`. All newer versions fail. This is a real problem in production: the nf-core/rnaseq pipeline's GPU ribodetector test [stalls for 2 hours under Singularity](https://github.com/nf-core/rnaseq/pull/1788) because the old PyTorch 1.11.0 container (CUDA 11.1 runtime) deadlocks on CUDA 12.x hosts. We need a container with modern PyTorch (CUDA 12.x), but Wave's `--conda-file` path cannot build one. ### What we tried **`--config-env 'CONDA_OVERRIDE_CUDA=12.6'`**: This sets the env var in the final container image, not during the build/solve step. The conda solver never sees it. ([Build log](https://wave.seqera.io/view/builds/bd-566e7b0788a824ff_1)) **`--conda-run-command`**: Per the Wave source (`TemplateUtils.java`, `addCommands` method), this appends Dockerfile `RUN` commands *after* the `micromamba install` step. It cannot influence the conda solve. **`--conda-base-image nvidia/cuda:12.6.3-base-ubuntu24.04`**: Fails because the NVIDIA base image does not have micromamba installed. ([Build log](https://wave.seqera.io/view/builds/bd-b587fdb7e4ed8bfc_1)) **Adding `__cuda>=12` as a dependency in the YAML**: The solver correctly identifies it as a virtual package that must be provided by the system and refuses to install it. ([Build log](https://wave.seqera.io/view/builds/bd-5a19be48d123eec7_1)) ### Workaround: custom Dockerfile (works, but no community freeze) A custom Dockerfile with `CONDA_OVERRIDE_CUDA` set inline works: ```dockerfile FROM mambaorg/micromamba:1.5.10-noble COPY conda.yml /tmp/conda.yml RUN CONDA_OVERRIDE_CUDA="12.6" micromamba install -y -n base -f /tmp/conda.yml && micromamba clean -a -y USER root ENV PATH="$MAMBA_ROOT_PREFIX/bin:$PATH" ``` ```bash wave -f Dockerfile --context . --platform linux/amd64 --await --tower-token $TOKEN # Returns: wave.seqera.io/wt/51f41f22dbb8/wave/build:96b4265a2148d918 ``` We pulled this container and verified it contains PyTorch 2.10.0 with CUDA 12.9 and ribodetector 0.3.3 works correctly: ``` $ docker run --rm <image> python -c "import torch; print(torch.__version__, torch.version.cuda)" 2.10.0 12.9 $ docker run --rm <image> ribodetector --version ribodetector 0.3.3 ``` However, the custom Dockerfile path requires `--build-repo` for `--freeze`, meaning it cannot be frozen to the community Wave registry (`community.wave.seqera.io/library/...`). This makes it unusable for nf-core modules, which rely on community-frozen container URLs. ### Proposed solutions There are several ways to address this, ranging from minimal to comprehensive: #### Option A: Add `{{conda_env_prefix}}` template placeholder (minimal, targeted) Add a new placeholder to the Dockerfile templates that injects environment variables before `micromamba install`: ```diff FROM {{mamba_image}} AS build COPY --chown=$MAMBA_USER:$MAMBA_USER conda.yml /tmp/conda.yml -RUN micromamba install -y -n base -f /tmp/conda.yml \ +RUN {{conda_env_prefix}}micromamba install -y -n base -f /tmp/conda.yml \ ``` Expose this via a new CLI flag (e.g., `--conda-solve-env KEY=VALUE`) and Nextflow config option. The placeholder would render as `CONDA_OVERRIDE_CUDA="12.6" ` when set, or empty string when not. This requires changes to: - All 8 conda templates (v1/v2, Docker/Singularity, file/packages) - `CondaOpts.java` (new field) - `TemplateUtils.java` (new binding) - Wave CLI (new flag) - Nextflow Wave config (new option) #### ~~Option B: Set `CONDA_OVERRIDE_CUDA` unconditionally in templates~~ *Ruled out: testing shows that for packages with both CPU and GPU variants (e.g. bare `pytorch` without the `-gpu`/`-cpu` suffix), the override causes the solver to prefer CUDA builds, silently pulling in hundreds of MB of CUDA toolkit into containers that never intended to use a GPU.* #### Option C: Detect GPU packages and set override automatically Wave could inspect the conda environment spec for known GPU metapackages (`pytorch-gpu`, `jaxlib`, `tensorflow-gpu`, etc.) or `__cuda` dependencies and automatically set `CONDA_OVERRIDE_CUDA` during the solve. This would be the most user-friendly option but requires more implementation effort. #### Option D: Two-pass solve with automatic retry Run the solve normally. If it fails and the error output contains `__cuda`, retry with `CONDA_OVERRIDE_CUDA` set. The template's `RUN` command would become something like: ```bash micromamba install -y -n base -f /tmp/conda.yml || \ (micromamba install --dry-run -y -n base -f /tmp/conda.yml 2>&1 | grep -q __cuda \ && CONDA_OVERRIDE_CUDA="12" micromamba install -y -n base -f /tmp/conda.yml) ``` This requires no new CLI flags, no package list, and no repodata inspection. The solver itself discovers whether `__cuda` is needed. The cost is one extra failed solve (~4s) for GPU environments only; non-GPU environments succeed on the first pass with zero overhead. This could be implemented entirely within the existing templates. ### Related - [Community thread: Problems with GPU-enabled wave images](https://community.seqera.io/t/problems-with-gpu-enabled-wave-images/1596) (Jan 2025, unresolved) - [conda-forge docs: CONDA_OVERRIDE_CUDA](https://conda-forge.org/docs/user/tipsandtricks/#installing-cuda-enabled-packages-like-tensorflow-and-pytorch)
11 条评论