NVIDIA / NVIDIA/cuda-python

Non-externed Cython type definitions cause redefinition errors with transitive header includes

Abierto
#1,663 6 comentarios 0 reacciones 2 asignados Ver en GitHub

@mdboom ya está trabajando en esto.

Desde el 29/6/2026.

cuda.bindings triage
Lenguaje dominante
Cython
Estrellas
3.4k
Forks
329
Merge medio
1 d 23 h
PR fusionados (30 d)
116

Descripción

Summary

Several cuda.bindings Cython interfaces (cynvvm, cynvml, cynvjitlink, cynvfatbin) define types using Cython's quoted C name syntax without cdef extern from blocks. This causes C compilation errors when a user cimports these types in a module that also transitively includes the corresponding C header.

Problem

The externed interfaces (cynvrtc, cydriver, cyruntime) use cdef extern from "header.h" blocks, so Cython emits a #include directive and the header's include guards prevent duplicate definitions.

The non-externed interfaces instead define types inline:

# cynvvm.pxd (current)
ctypedef enum nvvmResult "nvvmResult":
    NVVM_SUCCESS "NVVM_SUCCESS" = 0
    NVVM_ERROR_OUT_OF_MEMORY "NVVM_ERROR_OUT_OF_MEMORY" = 1
    ...

When Cython compiles a .pyx that cimports these types, it generates its own enum/typedef definitions in the C output. If any cdef extern from block in the same module (directly or via its .pxd) includes a header that transitively includes nvvm.h, the C compiler sees duplicate enum constant definitions and fails.

Minimal Reproducer

nvvm.h (or the real one from the CUDA Toolkit):

#ifndef NVVM_H
#define NVVM_H

typedef enum {
    NVVM_SUCCESS = 0,
    NVVM_ERROR_OUT_OF_MEMORY = 1,
    NVVM_ERROR_PROGRAM_CREATION_FAILURE = 2,
    NVVM_ERROR_INVALID_INPUT = 4,
    NVVM_ERROR_INVALID_PROGRAM = 5,
} nvvmResult;

typedef void *nvvmProgram;

#endif

example.h — a user header that happens to transitively include nvvm.h:

#ifndef EXAMPLE_H
#define EXAMPLE_H

#include "nvvm.h"

int test_func(int a);

#endif

example.pxd — declares the user's C function:

cdef extern from "example.h":
    int test_func(int a)

example.pyx — cimports the nvvm types from cuda.bindings:

from cuda.bindings.cynvvm cimport nvvmResult

def call_test(int x):
    return test_func(x)
Build Output
example.c:1541:3: error: redeclaration of enumerator 'NVVM_SUCCESS'
 1541 |   NVVM_SUCCESS = 0,
      |   ^~~~~~~~~~~~
In file included from example.h:4,
                 from example.c:1138:
nvvm.h:5:5: note: previous definition of 'NVVM_SUCCESS' with type 'enum <anonymous>'
    5 |     NVVM_SUCCESS = 0,
      |     ^~~~~~~~~~~~
example.c:1542:3: error: redeclaration of enumerator 'NVVM_ERROR_OUT_OF_MEMORY'
...
example.c:1547:25: error: conflicting types for 'nvvmResult'; have 'enum nvvmResult'

The generated C file first emits #include "example.h" (which transitively includes nvvm.h), then later emits Cython's own enum nvvmResult { NVVM_SUCCESS = 0, ... } from the cimport. The duplicate enum constants are a hard C compilation error.

Impact

Any downstream Cython project that wants to:

  1. Use types from cynvvm, cynvml, cynvjitlink, or cynvfatbin via cimport, and
  2. Has any cdef extern from that transitively includes the corresponding C header

...will fail to compile. The user doesn't need to redeclare any types themselves — the mere transitive include is sufficient.

This does not affect the externed interfaces (cynvrtc, cydriver, cyruntime) since they use cdef extern from, which emits #include directives that are deduplicated by include guards.

Affected Interfaces

Interface Style Affected
cynvvm.pxd Non-externed (quoted names) Yes
cynvml.pxd Non-externed (quoted names) Yes
cynvjitlink.pxd Non-externed (quoted names) Yes
cynvfatbin.pxd Non-externed (quoted names) Yes
cynvrtc.pxd cdef extern from "nvrtc.h" No
cydriver.pxd cdef extern from "cuda.h" No
cyruntime.pxd cdef extern from "driver_types.h" No

Suggested Fix

Switch the non-externed interfaces to use cdef extern from blocks, consistent with cynvrtc.pxd, cydriver.pxd, and cyruntime.pxd. This causes Cython to emit #include directives instead of generating its own type definitions, allowing include guards to deduplicate.

Edit: On further analysis, this is not believed to be an ABI break. The .pxd file is purely a compile-time artifact — it is not referenced at runtime by already-compiled extensions. Since the quoted C names already produce the exact same C type identifiers and enum constant values as the header, the generated machine code is identical regardless of declaration style. Already-compiled downstream extensions would continue to work without recompilation against an updated cuda.bindings that makes this change.

Guía de contribución

Abrir la guía de contribución

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Evaluación

Este issue todavía no se ha evaluado.

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.