NVIDIA / NVIDIA/cuda-python

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

未關閉
#1,663 6 則留言 0 個 reaction 已指派 2 人 在 GitHub 檢視

@mdboom 已經在處理了。

開始於 2026年6月29日。

cuda.bindings triage
主要語言
Cython
星號
3.4k
分支
329
平均合併
1 天 23 小時
30 天內合併 PR
116

描述

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.

貢獻指南

開啟貢獻指南

從這裡開始

  1. 先讀完整個 Issue,再讀專案的貢獻指南。
  2. 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
  3. Fork 儲存庫,在一個分支上完成修改。
  4. 送出 Pull Request,並在描述裡引用這個 Issue 編號。

評估

這個 Issue 還沒有評估資料。

把新 issue 寄到你的電子郵件信箱

精選適合新手參與的 GitHub issue 摘要。