如何使用autotools与库同时构建Python接口 我现在有一个C++语言库,用GNU自动工具构建,我想给它添加一个Python接口。使用SWIG我已经开发了接口,但是我在弄清楚如何将Python模块的编译与流程的其余部分集成时遇到了一些问题
我已经研究了AM_PATH_PYTHON,但是这个宏似乎没有为PYTHON.h设置include路径,所以当我编译我的模块时,我会遇到一系列关于缺少include文件的错误。有没有办法从AM_path_Python中获取Python包含路径和ldflags 我不认为可以使用Python的distutils方法(setup.py),因为这需要库的位置来链接新模块。由于库尚未在编译时安装,因此我必须使用相对路径(例如../src/lib.so),一旦安装了Python模块,该路径当然会中断(因为库当时位于/usr/lib或/usr/local/lib中) 编辑: 现在它可以找到正在编译的.h文件,但是在安装它(在正确的位置)之后,Python无法加载模块。代码生成foo.so,当我“导入foo”时,我得到以下结果: ImportError: dynamic module does not define init function (initfoo) ImportError:动态模块未定义初始化函数(initfoo) 但是,如果我将它从foo.so重命名为_foo.so,那么它的加载和运行都很好,除非我必须“导入_foo”,我不希望这样做。当我按照SWIG指令在当前目录中生成_foo.so时,“import foo”起作用,因此我不确定在站点目录中安装库时它为什么会中断 编辑2:如何使用autotools与库同时构建Python接口 我现在有一个C++语言库,用GNU自动工具构建,我想给它添加一个Python接口。使用SWIG我已经开发了接口,但是我在弄清楚如何将Python模块的编译与流程的其余部分集成时遇到了一些问题,c++,python,swig,autotools,autoconf,C++,Python,Swig,Autotools,Autoconf,我已经研究了AM_PATH_PYTHON,但是这个宏似乎没有为PYTHON.h设置include路径,所以当我编译我的模块时,我会遇到一系列关于缺少include文件的错误。有没有办法从AM_path_Python中获取Python包含路径和ldflags 我不认为可以使用Python的distutils方法(setup.py),因为这需要库的位置来链接新模块。由于库尚未在编译时安装,因此我必须使用相对路径(例如../src/lib.so),一旦安装了Python模块,该路径当然会中断(因为库当
问题是我忘了将SWIG生成的foo.py与_foo.so一起复制到安装目录中。一旦我做到了这一点,一切都如期进行!现在,我只需要找出一些自动生成规则,将文件复制到安装目录…要找到包含路径,我将使用
python config
。诀窍是使用与安装在$python
中的python对应的python配置
AM_PATH_PYTHON
AC_ARG_VAR([PYTHON_INCLUDE], [Include flags for python, bypassing python-config])
AC_ARG_VAR([PYTHON_CONFIG], [Path to python-config])
AS_IF([test -z "$PYTHON_INCLUDE"], [
AS_IF([test -z "$PYTHON_CONFIG"], [
AC_PATH_PROGS([PYTHON_CONFIG],
[python$PYTHON_VERSION-config python-config],
[no],
[`dirname $PYTHON`])
AS_IF([test "$PYTHON_CONFIG" = no], [AC_MSG_ERROR([cannot find python-config for $PYTHON.])])
])
AC_MSG_CHECKING([python include flags])
PYTHON_INCLUDE=`$PYTHON_CONFIG --includes`
AC_MSG_RESULT([$PYTHON_INCLUDE])
])
另一种选择是查看distutils.sysconfig
模块(这与使用distutils构建代码无关)。运行python-c“import distutils.sysconfig;help(distutils.sysconfig)”
并查看一下。下面是我从我的`configure.ac
调用的autoconf宏,以查找python包含目录(PYTHONINC)和python安装目录(通过AM_PATH_python)
然后我的wrap/python/Makefile.am
使用Libtool构建两个Swig模块,如下所示:
SUBDIRS = . cgi-bin ajax tests
AM_CPPFLAGS = -I$(PYTHONINC) -I$(top_srcdir)/src $(BUDDY_CPPFLAGS) \
-DSWIG_TYPE_TABLE=spot
EXTRA_DIST = spot.i buddy.i
python_PYTHON = $(srcdir)/spot.py $(srcdir)/buddy.py
pyexec_LTLIBRARIES = _spot.la _buddy.la
MAINTAINERCLEANFILES = \
$(srcdir)/spot_wrap.cxx $(srcdir)/spot.py \
$(srcdir)/buddy_wrap.cxx $(srcdir)/buddy.py
## spot
_spot_la_SOURCES = $(srcdir)/spot_wrap.cxx $(srcdir)/spot_wrap.h
_spot_la_LDFLAGS = -avoid-version -module
_spot_la_LIBADD = $(top_builddir)/src/libspot.la
$(srcdir)/spot_wrap.cxx: $(srcdir)/spot.i
$(SWIG) -c++ -python -I$(srcdir) -I$(top_srcdir)/src $(srcdir)/spot.i
$(srcdir)/spot.py: $(srcdir)/spot.i
$(MAKE) $(AM_MAKEFLAGS) spot_wrap.cxx
## buddy
_buddy_la_SOURCES = $(srcdir)/buddy_wrap.cxx
_buddy_la_LDFLAGS = -avoid-version -module $(BUDDY_LDFLAGS)
$(srcdir)/buddy_wrap.cxx: $(srcdir)/buddy.i
$(SWIG) -c++ -python $(BUDDY_CPPFLAGS) $(srcdir)/buddy.i
$(srcdir)/buddy.py: $(srcdir)/buddy.i
$(MAKE) $(AM_MAKEFLAGS) buddy_wrap.cxx
上述规则使得Swig的结果被视为源文件(即分布在tarball中),其方式与Bison生成的解析器相同。这样,最终用户不需要安装Swig
运行make
时,Libtool会将*.so
文件隐藏在一些.libs/
目录中,但在make install
之后,它们会被复制到正确的位置
唯一的技巧是如何在运行makeinstall
之前从源目录中使用模块。例如,在运行时检查。对于这种情况,我(使用configure
)生成一个名为run
的脚本,在运行任何python
脚本之前设置PYTHONPATH
,并通过该run
脚本执行所有测试用例。以下是run的内容。在configure
替换任何值之前的中:
# Darwin needs some help in figuring out where non-installed libtool
# libraries are (on this platform libtool encodes the expected final
# path of dependent libraries in each library).
modpath='../.libs:@top_builddir@/src/.libs:@top_builddir@/buddy/src/.libs'
# .. is for the *.py files, and ../.libs for the *.so. We used to
# rely on a module called ltihooks.py to teach the import function how
# to load a Libtool library, but it started to cause issues with
# Python 2.6.
pypath='..:../.libs:@srcdir@/..:@srcdir@/../.libs:$PYTHONPATH'
test -z "$1" &&
PYTHONPATH=$pypath DYLD_LIBRARY_PATH=$modpath exec @PYTHON@
case $1 in
*.py)
PYTHONPATH=$pypath DYLD_LIBRARY_PATH=$modpath exec @PYTHON@ "$@";;
*.test)
exec sh -x "$@";;
*)
echo "Unknown extension" >&2
exit 2;;
esac
如果你想在一个真实的项目中看到这一切,你可以从中得到它。我知道这是一篇老文章,但因为我在这里登陆了:有一些m4宏使得使用swig编译python绑定非常容易:
和
在命令行上手动构建
无需将SWIG步骤添加到makefiles中,您就可以使用以下命令构建SWIG扩展名(如果您有source_file.cpp和_extension.i来创建python模块):
注意:在共享对象的名称前加下划线很重要,否则在执行导入扩展时Python将无法找到它
将SWIG添加到Autoconf
我在Python中编写了一个小程序,其中需要用C++编写的一个文件(如舍入法)。
您需要额外的Autoconf宏来启用SWIG支持。正如johanvdw所指出的,如果您使用这两个m4宏:ax_pck_swig和ax_swig_python,将会更加容易。我下载了它并将其放置在我的项目树的m4子目录中:
trunk
├── configure.ac
├── __init__.py
├── m4
│ ├── ax_pkg_swig.m4
│ ├── ax_swig_python.m4
│ ├── libtool.m4
│ ├── lt~obsolete.m4
│ ├── ltoptions.m4
│ ├── ltsugar.m4
│ └── ltversion.m4
├── Makefile.am
├── rounding_swig
│ ├── compile.txt
│ ├── __init__.py
│ ├── Makefile.am
│ ├── rnd_C.cpp
│ ├── rounding.i
│ ├── rounding_wrap.cpp
└── src
├── cadna_add.py
├── cadna_computedzero.py
├── cadna_convert.py
├── __init__.py
└── Makefile.am
将两个m4宏放入子目录时,需要将此行添加到trunk/Makefile.am:
ACLOCAL_AMFLAGS = -I m4
现在,让我们看看trunk/configure.ac:
AC_PREREQ([2.69]) # Check autoconf version
AC_INIT(CADNA_PY, 1.0.0, cadna-team@lip6.fr) # Name of your software
AC_CONFIG_SRCDIR([rounding_swig/rnd_C.cpp]) # Name of the c++ source
AC_CONFIG_MACRO_DIR(m4) # Indicate where are your m4 macro
AC_CONFIG_HEADERS(config.h)
AM_INIT_AUTOMAKE
AC_DISABLE_STATIC #enable shared libraries
# Checks for programs.
AC_PROG_LIBTOOL # check libtool
AC_PROG_CXX # check c++ compiler
AM_PATH_PYTHON(2.3) # check python version
AX_PKG_SWIG(1.3.21) # check swig version
AX_SWIG_ENABLE_CXX # fill some variable usefull later
AX_SWIG_PYTHON # same
# Checks for header files.
AC_CHECK_HEADERS([fenv.h stdlib.h string.h]) # any header needed by your c++ source
# Checks for typedefs, structures, and compiler characteristics.
AC_CHECK_HEADER_STDBOOL
AC_TYPE_SIZE_T
# Checks for library functions.
AC_FUNC_MALLOC
AC_CHECK_FUNCS([fesetround memset strstr])
AC_CONFIG_FILES([
Makefile
src/Makefile
rounding_swig/Makefile
])
LIBPYTHON="python$PYTHON_VERSION" # define the python interpreter
LDFLAGS="$LDFLAGS -l$LIBPYTHON"
AC_OUTPUT
将SWIG添加到Automake
在trunk/Makefile.am中,您需要执行以下操作:
ACLOCAL_AMFLAGS = -I m4
# Indicate the subdir of c++ file and python file
SUBDIRS = src rounding_swig
# Indicate a list of all the files that are part of the package, but
# are not installed by default and were not specified in any other way
EXTRA_DIST= \
rounding_swig/rounding.i \
rounding_swig/testrounding.py \
rounding_swig/testrounding.cpp
在trunk/src/Makefile.am中:
# Python source files that will be install in prefix/lib/name_of_your_python_interpreter/site-packages/name_of_your_project
pkgpython_PYTHON = cadna_add.py cadna_computedzero.py cadna_convert.py
困难的部分在trunk/rounding_swig/Makefile.am中。它创建一个library.la和一个_your_extension.so,并将其放置在项目的前缀/lib64/python2.7/site packages/name_中
# Name of the cpp source file
BUILT_SOURCES = rounding_wrap.cpp
# Name of the swig source file
SWIG_SOURCES = rounding.i
# Python source files that will be install in prefix/lib/name_of_your_python_interpreter/site-packages/name_of_your_project
pkgpython_PYTHON = rounding.py __init__.py
pkgpyexec_LTLIBRARIES = _rounding.la
_rounding_la_SOURCES = rounding_wrap.cpp $(SWIG_SOURCES) rnd_C.cpp
_rounding_la_CPPFLAGS = $(AX_SWIG_PYTHON_CPPFLAGS) -I$(top_srcdir)/rounding_swig -I/usr/include/python@PYTHON_VERSION@ -lpython@PYTHON_VERSION@
_rounding_la_LDFLAGS = -module
rounding_wrap.cpp: $(SWIG_SOURCES)
$(SWIG) $(AX_SWIG_PYTHON_OPT) -I$(top_srcdir)/rounding_swig -I/usr/include/python@PYTHON_VERSION@ -o $@ $<
最后,要安装项目,请执行以下操作:
libtoolize && aclocal && autoheader && autoconf && automake -a -c
./configure --prefix=<install prefix>
make
make install
libtoolize&&aclocal&&autoheader&&autoconf&&automake-a-c
/配置-前缀=
制作
安装
PS:是一个过时但简单的教程,对我有帮助(过时是因为它使用了ac_pkg_swig.m4,但新版本的swig失败)。谢谢-这很有效,但现在我在最后一个问题上遇到了麻烦。所以二进制,我更新了原始问题。要将不可执行文件复制到目录中,您可能需要类似于pkgpythondir\u DATA=foo.py
的东西。
# Name of the cpp source file
BUILT_SOURCES = rounding_wrap.cpp
# Name of the swig source file
SWIG_SOURCES = rounding.i
# Python source files that will be install in prefix/lib/name_of_your_python_interpreter/site-packages/name_of_your_project
pkgpython_PYTHON = rounding.py __init__.py
pkgpyexec_LTLIBRARIES = _rounding.la
_rounding_la_SOURCES = rounding_wrap.cpp $(SWIG_SOURCES) rnd_C.cpp
_rounding_la_CPPFLAGS = $(AX_SWIG_PYTHON_CPPFLAGS) -I$(top_srcdir)/rounding_swig -I/usr/include/python@PYTHON_VERSION@ -lpython@PYTHON_VERSION@
_rounding_la_LDFLAGS = -module
rounding_wrap.cpp: $(SWIG_SOURCES)
$(SWIG) $(AX_SWIG_PYTHON_OPT) -I$(top_srcdir)/rounding_swig -I/usr/include/python@PYTHON_VERSION@ -o $@ $<
autoreconf -i
libtoolize && aclocal && autoheader && autoconf && automake -a -c
./configure --prefix=<install prefix>
make
make install