从 Makefile 传递复杂的链接标志到 setup.py

82 阅读2分钟

准备使用 Python 2.7 开发一个 C++ 扩展库,该库需要调用 Kaldi 的一部分 C++ 库。

之前,通过创建共享库并将共享库与 Python 扩展库一起分发的方式进行开发,但当时需要设置 LD_LIBRARY_PATH。

现在想改为静态编译扩展库。Kaldi 库可以通过 --fPIC 标志进行静态编译。然而,编译过程仍需要依赖其他库,这些库的标志由 configure 脚本生成。

希望可以使用 setup.py 编译扩展库,并将 Makefile 中的编译设置“窃取”过来。

huake_00152_.jpg

2、解决方案

2.1 从 Makefile 中提取链接参数

首先,需要从 Makefile 中提取链接参数。

可以首先将 Makefile 中用于链接共享库的命令复制到 .txt 文件中,然后从 .txt 文件中提取出所需的链接参数。

在 Makefile 中,用于链接共享库的命令一般类似于:

$(CXX) -shared -DPIC -o $@ -Wl,-soname=$@,--whole-archive $^ -Wl,--no-whole-archive $(EXTRA_LDLIBS) $(LDFLAGS) $(LDLIBS)

其中,

  • $(CXX) 是 C++ 编译器,
  • -shared 表示生成共享库,
  • -DPIC 表示生成位置无关代码,
  • -o $@ 表示输出文件,
  • -Wl,-soname=$@ 表示设置共享库的文件名,
  • --whole-archive 和 --no-whole-archive 表示对所有目标库进行链接,
  • $(EXTRA_LDLIBS) 是额外的链接器标志,
  • $(LDFLAGS) 是链接器标志,
  • $(LDLIBS) 是库文件。

从中提取出所需的链接参数,包括 (EXTRALDLIBS)(EXTRA_LDLIBS)、(LDFLAGS) 和 (LDLIBS)。其中,(LDLIBS)。其中,(EXTRA_LDLIBS) 是一个列表,(LDFLAGS)(LDFLAGS) 和 (LDLIBS) 是字符串。

2.2 在 setup.py 中应用链接参数

接下来,在 setup.py 中应用这些链接参数。

在 setup.py 中,可以设置 library_dirs 参数来指定库文件的目录,还可以设置 libraries 参数来指定需要链接的库。

ext_modules = [
    Extension('pykaldi.decoders',
             language='c++',
             include_dirs=['..', 'fst'],
             library_dirs=['.'],
             libraries=['pykaldi'],
             sources=['pykaldi/decoders.pyx'],
             extra_objects=['pykaldi.a', ]
             )
]

其中,

  • ext_modules 是一个列表,用于存储所有扩展模块,
  • Extension() 函数用于创建扩展模块,
  • pykaldi.decoders 是扩展模块的名称,
  • language='c++' 表示该扩展模块是用 C++ 编写的,
  • include_dirs=['..', 'fst'] 是包含头文件的目录,
  • library_dirs=['.'] 是包含库文件的目录,
  • libraries=['pykaldi'] 是需要链接的库,
  • sources=['pykaldi/decoders.pyx'] 是源文件,
  • extra_objects=['pykaldi.a', ] 是额外的对象文件。

通过设置 library_dirs 参数来指定库文件的目录,通过设置 libraries 参数来指定需要链接的库,就可以在 setup.py 中应用从 Makefile 中提取出的链接参数。

2.3 编译扩展模块

最后,运行 setup.py 来编译扩展模块。

python setup.py build_ext --inplace

其中,

  • python 是 Python 解释器,
  • setup.py 是 setup.py 脚本,
  • build_ext 是命令,用于编译扩展模块,
  • --inplace 是选项,表示在当前目录中编译扩展模块。

运行该命令后,就可以在当前目录中找到编译好的扩展模块。