From a5d91fba6a8f20465f6a8884207f98b241d993fe Mon Sep 17 00:00:00 2001 From: Peter Johnson Date: Tue, 4 Apr 2006 06:07:32 +0000 Subject: [PATCH] Hook Python module into the build (even though it's pretty incomplete), enabled with --enable-python (defaults to auto-detect). Thanks to some magic in python-yasm/Makefile.inc and setup.py, this actually plays nicely with automake distcheck. * m4/pythonhead.m4: Script to find Python.h. * m4/Makefile.inc: Include it in distfiles. * configure.ac: Add --enable-python option and Python and Pyrex detection. * tools/Makefile.inc: Pull tools/python-yasm/Makefile.inc into build. * python-yasm/Makefile.inc: Add automake build magic for extension. * setup.py: Likewise. svn path=/trunk/yasm/; revision=1456 --- Makefile.am | 10 ++- configure.ac | 45 ++++++++++++++ m4/Makefile.inc | 1 + m4/pythonhead.m4 | 24 ++++++++ tools/Makefile.inc | 2 + tools/python-yasm/Makefile.inc | 49 +++++++++++++++ tools/python-yasm/setup.py | 109 ++++++++++++++++++++++++++------- 7 files changed, 216 insertions(+), 24 deletions(-) create mode 100644 m4/pythonhead.m4 create mode 100644 tools/python-yasm/Makefile.inc diff --git a/Makefile.am b/Makefile.am index 45e5dde3..d2921e1e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -93,8 +93,16 @@ ACLOCAL_AMFLAGS = -I m4 distclean-local: -rm -rf results +if HAVE_PYTHON + -rm -rf build +endif + +if HAVE_PYTHON +all-am: Makefile $(LIBRARIES) $(PROGRAMS) $(MANS) $(HEADERS) config.h python-build +install-hook: python-install +uninstall-hook: python-uninstall +endif if BUILD_MAN MAINTAINERCLEANFILES = $(dist_man_MANS) endif - diff --git a/configure.ac b/configure.ac index cdf977ee..95d47b9a 100644 --- a/configure.ac +++ b/configure.ac @@ -49,6 +49,14 @@ AC_HELP_STRING([--enable-gcov],[Enable gcov code coverage (requires GCC)]), *) AC_MSG_ERROR([bad value ${enableval} for --enable-gcov]) ;; esac]) +AC_ARG_ENABLE(python, +AC_HELP_STRING([--enable-python],[Build Python bindings]), +[case "${enableval}" in + yes) enable_python="yes" ;; + no) enable_python="no" ;; + *) AC_MSG_ERROR([bad value ${enableval} for --enable-python]) ;; +esac], enable_python="auto") + # # Checks for programs. # @@ -244,6 +252,43 @@ AC_SUBST(CCLD_FOR_BUILD) HOST_CC="$CC_FOR_BUILD" AC_SUBST(HOST_CC) +# Detect if we can build Python bindings +# (needs Python, Python headers, and Pyrex) +if test x$enable_python = xno; then + have_python=no +else + AC_MSG_NOTICE([Checking to see if we can build Python bindings]) + have_python=no + AM_PATH_PYTHON(2.4) + + if test -z "$PYTHON" ; then + AC_MSG_WARN([Python not found]) + else + AC_CHECK_PROGS(PYREX, pyrexc) + + if test -z "$PYREX" ; then + have_pyrex=no + else + have_pyrex=yes + fi + + AM_CHECK_PYTHON_HEADERS(have_python_headers=yes,have_python_headers=no) + + if test x$have_pyrex = xyes -a x$have_python_headers = xyes ; then + have_python=yes + fi + fi + + if test x$have_python = xno ; then + if test x$enable_python = xyes ; then + AC_MSG_ERROR([Building Python explicitly requested, but can't build Python bindings because either Pyrex, Python headers or a suitable Python version was not found]) + else + AC_MSG_WARN([Couldn't find either Pyrex, the Python headers or a suitable version of Python, not building Python bindings]) + fi + fi +fi + +AM_CONDITIONAL(HAVE_PYTHON, test x$have_python = xyes) AC_CONFIG_FILES([Makefile po/Makefile.in diff --git a/m4/Makefile.inc b/m4/Makefile.inc index 6cd21522..3df185a9 100644 --- a/m4/Makefile.inc +++ b/m4/Makefile.inc @@ -26,3 +26,4 @@ EXTRA_DIST += m4/longlong.m4 EXTRA_DIST += m4/progtest.m4 EXTRA_DIST += m4/stdint_h.m4 EXTRA_DIST += m4/uintmax_t.m4 +EXTRA_DIST += m4/pythonhead.m4 diff --git a/m4/pythonhead.m4 b/m4/pythonhead.m4 new file mode 100644 index 00000000..1e0f2b63 --- /dev/null +++ b/m4/pythonhead.m4 @@ -0,0 +1,24 @@ +dnl a macro to check for ability to create python extensions +dnl AM_CHECK_PYTHON_HEADERS([ACTION-IF-POSSIBLE], [ACTION-IF-NOT-POSSIBLE]) +dnl function also defines PYTHON_INCLUDES +AC_DEFUN([AM_CHECK_PYTHON_HEADERS], +[AC_REQUIRE([AM_PATH_PYTHON]) +AC_MSG_CHECKING(for headers required to compile python extensions) +dnl deduce PYTHON_INCLUDES +py_prefix=`$PYTHON -c "import sys; print sys.prefix"` +py_exec_prefix=`$PYTHON -c "import sys; print sys.exec_prefix"` +PYTHON_INCLUDES="-I${py_prefix}/include/python${PYTHON_VERSION}" +if test "$py_prefix" != "$py_exec_prefix"; then + PYTHON_INCLUDES="$PYTHON_INCLUDES -I${py_exec_prefix}/include/python${PYTHON_VERSION}" +fi +AC_SUBST(PYTHON_INCLUDES) +dnl check if the headers exist: +save_CPPFLAGS="$CPPFLAGS" +CPPFLAGS="$CPPFLAGS $PYTHON_INCLUDES" +AC_TRY_CPP([#include ],dnl +[AC_MSG_RESULT(found) +$1],dnl +[AC_MSG_RESULT(not found) +$2]) +CPPFLAGS="$save_CPPFLAGS" +]) diff --git a/tools/Makefile.inc b/tools/Makefile.inc index 264b8e16..56a4697f 100644 --- a/tools/Makefile.inc +++ b/tools/Makefile.inc @@ -2,6 +2,8 @@ EXTRA_DIST += tools/re2c/Makefile.inc EXTRA_DIST += tools/gap/Makefile.inc +EXTRA_DIST += tools/python-yasm/Makefile.inc include tools/re2c/Makefile.inc include tools/gap/Makefile.inc +include tools/python-yasm/Makefile.inc diff --git a/tools/python-yasm/Makefile.inc b/tools/python-yasm/Makefile.inc new file mode 100644 index 00000000..3f0f8f43 --- /dev/null +++ b/tools/python-yasm/Makefile.inc @@ -0,0 +1,49 @@ +# $Id$ +if HAVE_PYTHON + +PYBINDING_DEPS = tools/python-yasm/bytecode.pxi +PYBINDING_DEPS += tools/python-yasm/coretype.pxi +PYBINDING_DEPS += tools/python-yasm/expr.pxi +PYBINDING_DEPS += tools/python-yasm/floatnum.pxi +PYBINDING_DEPS += tools/python-yasm/intnum.pxi +PYBINDING_DEPS += tools/python-yasm/symrec.pxi +PYBINDING_DEPS += tools/python-yasm/value.pxi + +EXTRA_DIST += tools/python-yasm/setup.py +EXTRA_DIST += tools/python-yasm/yasm.pyx +EXTRA_DIST += $(PYBINDING_DEPS) + +yasm_python.c: $(srcdir)/tools/python-yasm/yasm.pyx $(PYBINDING_DEPS) + $(PYREX) -o $@ `test -f tools/python-yasm/yasm.pyx || echo '$(srcdir)/'`tools/python-yasm/yasm.pyx + +CLEANFILES += yasm_python.c + +# Now the Python build magic... +python-setup.txt: Makefile + echo "includes=${DEFAULT_INCLUDES} ${INCLUDES} ${DEFS}" > python-setup.txt + echo "sources=${libyasm_a_SOURCES}" >> python-setup.txt + echo "srcdir=${srcdir}" >> python-setup.txt + +CLEANFILES += python-setup.txt + +.python-build: python-setup.txt yasm_python.c + -rm -rf build + $(PYTHON) `test -f tools/python-yasm/setup.py || echo '$(srcdir)/'`tools/python-yasm/setup.py build + touch .python-build +python-build: .python-build + +CLEANFILES += .python-build + +python-install: .python-build + $(PYTHON) `test -f tools/python-yasm/setup.py || echo '$(srcdir)/'`tools/python-yasm/setup.py install "--install-lib=$(pythondir)" + +python-uninstall: + rm -f `$(PYTHON) -c "import sys;sys.path.insert(0, '${pythondir}'); import yasm; print yasm.__file__"` + +else + +python-build: +python-install: +python-uninstall: + +endif diff --git a/tools/python-yasm/setup.py b/tools/python-yasm/setup.py index 545a3cad..53be8082 100644 --- a/tools/python-yasm/setup.py +++ b/tools/python-yasm/setup.py @@ -3,27 +3,90 @@ from distutils.core import setup from distutils.extension import Extension from Pyrex.Distutils import build_ext +from os.path import basename, join, exists +import re + +def ReadSetup(filename): + """ReadSetup goes through filename and parses out the values stored + in the file. Values need to be stored in a + \"key=value format\"""" + + #return val + opts = {} + + fh = open(filename, 'r') + reobj = re.compile(r"([a-z]+)=(.+)") + for line in fh.readlines(): + matchobj = reobj.search(line) + + if matchobj is None: + raise "Error: syntaxt error in setup.txt line: %s"%line + + lab, val = matchobj.groups() + opts[lab] = val + return opts + +def ParseCPPFlags(str): + """parse the CPPFlags macro""" + incl_dir = [] + cppflags = [] + + tokens = str.split() + # go through the list of compile flags. treat search path args + # specially; otherwise just add to "extra_compile_args" + for tok in tokens: + if tok.startswith("-I"): + incl_dir.append(tok[2:]) + else: + cppflags.append(tok) + + return (incl_dir, cppflags) + +def ParseSources(str, srcdir): + """parse the Sources macro""" + sources = [] + + tokens = str.split() + # go through the list of source filenames + # do the dance of detecting if the source file is in the current + # directory, and if it's not, prepend srcdir + for tok in tokens: + fn = None + if tok.endswith(".c"): + fn = tok + elif tok.endswith(".y"): + fn = basename(tok)[:-2] + ".c" + else: + continue + if not exists(fn): + fn = join(srcdir, fn) + sources.append(fn) + + return sources + +def RunSetup(incldir, cppflags, sources): + setup( + name='yasm', + version='0.0', + description='Python bindings for Yasm', + author='Michael Urman', + url='http://www.tortall.net/projects/yasm', + ext_modules=[ + Extension('yasm', + sources=sources, + extra_compile_args=cppflags, + include_dirs=incldir, + library_dirs=['.'], + libraries=['yasm'], + ), + ], + cmdclass = dict(build_ext=build_ext), + ) + +if __name__ == "__main__": + opts = ReadSetup("python-setup.txt") + incldir, cppflags = ParseCPPFlags(opts["includes"]) + sources = ParseSources(opts["sources"], opts["srcdir"]) + sources.append('yasm_python.c') + RunSetup(incldir, cppflags, sources) -setup( - name='yasm', - version='0.0', - description='Python bindings for Yasm', - author='Michael Urman', - url='http://www.tortall.net/projects/yasm', - ext_modules=[ - Extension('yasm', ['yasm.pyx'], - depends=['bytecode.pxi', - 'coretype.pxi', - 'expr.pxi', - 'floatnum.pxi', - 'intnum.pxi', - 'symrec.pxi', - 'value.pxi'], - include_dirs=['../..'], - library_dirs=['../..'], - libraries=['yasm'], - ), - ], - cmdclass = dict(build_ext=build_ext), - ) - -- 2.40.0