如何在构建Cython模块时覆盖-DNDEBUG编译标志

10 投票
2 回答
2376 浏览
提问于 2025-04-18 10:09

我有一个Cython模块,它通过cdef extern调用一个C++函数。这个C++函数里面有assert()语句,我想检查这些断言。但是,当我通过运行python setup.py build_ext --inplace来创建模块时,GCC总是带着-DNDEBUG这个选项。每次运行代码时,断言都不会被检查。

我找不到办法在setup.py中覆盖-DNDEBUG这个选项。这可能吗?

目前我找到的唯一解决办法是手动调用Cython、GCC和g++,并使用python setup.py时用的选项,但把-DNDEBUG去掉。不过肯定有更简单的方法。

2 个回答

12

你可以在你的 setup.py 文件中取消定义 NDEBUG。只需要在定义扩展时使用 undef_macros 这个选项就可以了:

extensions = [ Extension ( "myprog", [ mysrc.c ], undef_macros = [ "NDEBUG" ] ) ]

在构建输出中,你会看到 -DNDEBUG 后面跟着 -UNDEBUG,这样就会覆盖掉前面的设置。想了解更多关于扩展选项的信息,可以查看 distutils 文档

不过要注意,如果在扩展模块中触发了 assert,那么 Python 或者 IPython 解释器会直接退出。

1

如果你在代码中定义了 NDEBUG,可以手动取消这个定义,然后再包含 <cassert>。你只需要在包含这些断言语句的 cpp 文件的最上面加上以下几行代码。记得这些代码要放在文件的第一行。

#ifdef NDEBUG
# define NDEBUG_DISABLED
# undef NDEBUG
#endif
#include <cassert>

#ifdef NDEBUG_DISABLED
# define NDEBUG        // re-enable NDEBUG if it was originally enabled
#endif

// rest of the file

这样做可以确保在处理器包含 <cassert> 时,NDEBUG 是没有定义的,这样断言检查就会被编译进你的代码里。

撰写回答