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 摘要。