NVIDIA / NVIDIA/cuda-python

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

Offen
#1,663 6 Kommentare 0 Reaktionen 2 zugewiesene Personen Auf GitHub ansehen

@mdboom arbeitet bereits daran.

Seit 29.6.2026.

cuda.bindings triage
Vorherrschende Sprache
Cython
Sterne
3.4k
Forks
329
Ø Merge
1 T. 23 Std.
Gemergte PRs (30 T.)
116

Beschreibung

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.

Beitragsleitfaden

Beitragsleitfaden öffnen

Erste Schritte

  1. Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
  3. Forke das Repository und arbeite in einem Branch.
  4. Öffne einen Pull Request, der die Issue-Nummer nennt.

Bewertung

Dieses Issue wurde noch nicht bewertet.

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.