【问题标题】:Issue while compiling Cython code with distutils使用 distutils 编译 Cython 代码时出现问题
【发布时间】:2017-09-19 11:32:31
【问题描述】:

我正在尝试编译 Cython 代码并将其用作 Python 模块。我关注了Cython's basic tutorial。我已经制作了文件helloolrd.pyx:

print "Hello World"

我已经做了 setup.py:

from distutils.core import setup
from Cython.Build import cythonize

setup(
    ext_modules = cythonize("helloworld.pyx")
)

然后运行:

python setup.py build_ext --inplace

但不幸的是发生了错误:

running build_ext
building 'helloworld' extension
gcc -pthread -Wno-unused-result -Wsign-compare -DDYNAMIC_ANNOTATIONS_ENABLED=1 -DNDEBUG -O2 -g -pipe -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fstack-protector --param=ssp-buffer-size=4 -g -O2 -g -pipe -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fstack-protector --param=ssp-buffer-size=4 -I/usr/include/ncursesw -fPIC -I/usr/include/python3.5m -c helloworld.c -o build/temp.linux-x86_64-3.5/helloworld.o
gcc -pthread -shared -Wl,--as-needed -Wl,-z,relro -Wl,-O1 -Wl,--build-id -Wl,--enable-new-dtags build/temp.linux-x86_64-3.5/helloworld.o -L/usr/lib64 -lpython3.5m -o /home/dima/Projects/AntennaModeling/test/helloworld.cpython-35m-x86_64-linux-gnu.so
/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-mageia-linux-gnu/5.4.0/../../../libpython3.5m.so when searching for -lpython3.5m
/bin/ld: skipping incompatible /lib/libpython3.5m.so when searching for -lpython3.5m
/bin/ld: skipping incompatible /usr/lib/libpython3.5m.so when searching for -lpython3.5m
/bin/ld: cannot find -lpython3.5m
collect2: error: command ld failed with exit status 1
error: command 'gcc' failed with exit status 1

似乎 gcc 对 python3.5 库不满意。我尝试在没有 distutils 的情况下使用以下命令进行编译:

cython -a helloworld.pyx
gcc -shared -pthread -fPIC -fwrapv -O2 -Wall -fno-strict-aliasing -I/usr/include/python3.5m -o helloworld.so helloworld.c

它奏效了。从知道我可以从 Python 解释器导入 helloworld。但我不知道如何使用 distutils 编译 Cython 代码。我尝试使用 extra_compile_args 传递相同的标志,但没有奏效。

更新: 发现gcc找不到python的64位库,所以尝试显式显示库目录。所以我改变了 setup.py

from distutils.core import setup
from distutils.extension import Extension
from Cython.Build import cythonize

extensions = [
        Extension("helloworld", ["helloworld.pyx"],
        library_dirs = ['/usr/lib64']),
        ]
setup(
    name = 'Hello world app',
    ext_modules = cythonize(extensions),
)

还是一样的输出

running build_ext
building 'helloworld' extension
gcc -pthread -Wno-unused-result -Wsign-compare -DDYNAMIC_ANNOTATIONS_ENABLED=1 -DNDEBUG -O2 -g -pipe -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fstack-protector --param=ssp-buffer-size=4 -g -O2 -g -pipe -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fstack-protector --param=ssp-buffer-size=4 -I/usr/include/ncursesw -fPIC -I/usr/include/python3.5m -c helloworld.c -o build/temp.linux-x86_64-3.5/helloworld.o
gcc -pthread -shared -Wl,--as-needed -Wl,-z,relro -Wl,-O1 -Wl,--build-id -Wl,--enable-new-dtags build/temp.linux-x86_64-3.5/helloworld.o -L/usr/lib64 -L/usr/lib64 -lpython3.5m -o /home/dima/Projects/AntennaModeling/test/helloworld.cpython-35m-x86_64-linux-gnu.so
/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-mageia-linux-gnu/5.4.0/../../../libpython3.5m.so when searching for -lpython3.5m
/bin/ld: skipping incompatible /lib/libpython3.5m.so when searching for -lpython3.5m
/bin/ld: skipping incompatible /usr/lib/libpython3.5m.so when searching for -lpython3.5m
/bin/ld: cannot find -lpython3.5m
collect2: error: command ld failed with exit status 1
error: command 'gcc' failed with exit status 1

【问题讨论】:

  • 问题是链接(第二个gcc -pthread..)而不是编译(在你正在编译的命令行上,没有链接)看起来你有错误类型的库(32位,错误的架构?)
  • @ead,哦,天哪,我以为我检查过这个,但我弄错了。看来我的系统有两个用于 32 位架构和 64 位架构的 python 库。默认情况下,它会检查 32 位库。我将尝试在 distutils 中更改 lib 的路径。谢谢!
  • @ead。有 64 位库的路径,但链接器在输出中没有说明任何内容。
  • 我认为 cython 使用类似 /usr/bin/python-config --ldflags 的东西,这可能会返回错误的路径
  • @ead,在上面的输出中有 gcc 标志“-L/usr/lib64 -lpython3.5m”,它正是库所在的位置。

标签: python gcc cython cythonize


【解决方案1】:

通常,链接器会搜索名称为 libXXX.so 而不是 libXXX.so.1.0 的库(如果不成功,则搜索名称为 libXXX.a 的库)。通常libXXX.so 是指向libXXX.so.Y.0 的符号链接,libXXX.so.Y.0 是真正的库。

您可以通过使用-Wl,--verbose 调用链接命令来观察链接器的工作情况,例如:

gcc -Wl,--verbose -pthread -shared -Wl,--as-needed -Wl,-z,relro -Wl,-O1 -Wl,--build-id -Wl,--enable-new-dtags build/temp.linux-x86_64-3.5/helloworld.o -L/usr/lib64 -lpython3.5m -o /home/dima/Projects/AntennaModeling/test/helloworld.cpython-35m-x86_64-linux-gnu.so

你会看到类似的东西:

...
attempt to open /usr/lib64/libpython3.5m.so failed
...

所以有两种选择:

A:在你的系统上引入符号链接/usr/lib64/libpython3.5m.so。

或者较少干扰的 B:将 libraries=[':libpython3.5m.so.1.0'] 添加到您的扩展定义中:

extensions = [
        Extension("helloworld", ["helloworld.pyx"],
        library_dirs = ['/usr/lib64']),
        libraries=[':libpython3.5m.so.1.0']
        ]

现在链接命令应该看起来有点不同:

 gcc ... -L/usr/lib64 -l:libpython3.5m.so.1.0 ...

链接器将寻找libpython3.5m.so.1.0,而不仅仅是distutils 提供的libpython3.5m.so。

【讨论】:

  • 是的!这有帮助!谢谢!
猜你喜欢
  • 2013-09-22
  • 1970-01-01
  • 1970-01-01
  • 2019-04-09
  • 2010-10-26
  • 2016-06-23
  • 1970-01-01
  • 2014-08-11
  • 2017-01-16
相关资源
最近更新 更多