1dnl Probe for Python properties and, optionally, flags for embedding Python.
2dnl $Id: python.m4 10521 2021-01-17 21:48:51Z iulius $
3dnl
4dnl Provides the following macros:
5dnl
6dnl INN_PROG_PYTHON
7dnl     Checks for a specific Python version and sets the PYTHON environment
8dnl     variable to the full path, or aborts the configure run if the version
9dnl     of Python is not new enough or couldn't be found.  Marks PYTHON as a
10dnl     substitution variable.
11dnl
12dnl     The first argument is a Python version related to the 2.x series (if
13dnl     empty, it means that Python 2 is not supported).  The second argument
14dnl     is a Python version related to at least the 3.x series (if empty,
15dnl     it means that Python 3 or later is not supported).
16dnl
17dnl INN_PYTHON_CHECK_MODULE
18dnl     Checks for the existence of a Python module.  Runs the second argument
19dnl     if it is present and the third argument if it is not.
20dnl
21dnl INN_LIB_PYTHON
22dnl     Determines the flags required for embedding Python and sets
23dnl     PYTHON_CPPFLAGS and PYTHON_LIBS.
24dnl
25dnl INN_PROG_PYTHON should generally be called before the other two macros.
26dnl If it isn't, the PYTHON environment variable must be set in some other
27dnl way.  (It cannot be run automatically via dependencies because it takes a
28dnl mandatory minimum version argument, which should be provided by the
29dnl calling configure script.)
30dnl
31dnl This macro uses the distutils.sysconfig module shipped with Python 2.2.0
32dnl and later to find the compiler and linker flags to use to embed Python.
33dnl It also expects libpython to be in the main library location, which it is
34dnl since Python 2.3.0.
35dnl
36dnl The canonical version of this file is maintained in the rra-c-util
37dnl package, available at <https://www.eyrie.org/~eagle/software/rra-c-util/>.
38dnl
39dnl Copyright 2018 Russ Allbery <eagle@eyrie.org>
40dnl Copyright 2009, 2011, 2015, 2018 Julien ÉLIE <julien@trigofacile.com>
41dnl Copyright 1998-2003 The Internet Software Consortium
42dnl
43dnl Permission to use, copy, modify, and distribute this software for any
44dnl purpose with or without fee is hereby granted, provided that the above
45dnl copyright notice and this permission notice appear in all copies.
46dnl
47dnl THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
48dnl REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
49dnl MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY
50dnl SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
51dnl WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
52dnl ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
53dnl IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
54dnl
55dnl SPDX-License-Identifier: ISC
56
57dnl Command used to probe the Python version.
58AC_DEFUN([_INN_PROG_PYTHON_CMD], [[
59import sys
60two_okay = False
61three_okay = False
62if len(sys.argv) > 1 and sys.argv[1]:
63    two_tuple = tuple(map(int, sys.argv[1].split(".")))
64    if sys.version_info[0] == 2 and sys.version_info >= two_tuple:
65        two_okay = True
66if len(sys.argv) > 2 and sys.argv[2]:
67    three_tuple = tuple(map(int, sys.argv[2].split(".")))
68    if sys.version_info[0] > 2 and sys.version_info >= three_tuple:
69        three_okay = True
70assert(two_okay or three_okay)
71]])
72
73dnl Check for the path to Python and ensure it meets our minimum version
74dnl requirement.  The first argument specifies the minimum Python 2 version
75dnl and the second argument specifies the minimum Python 3 (or later) version.
76dnl At least one constraint must be met.  Honor the $PYTHON environment
77dnl variable, if set.
78AC_DEFUN([INN_PROG_PYTHON],
79[AC_ARG_VAR([PYTHON], [Location of Python interpreter])
80 AS_IF([test x"$1" != x],
81    [inn_py_expected_ver="$1 (2.x series)"],
82    [inn_py_expected_ver=""])
83 AS_IF([test x"$2" != x],
84    [AS_IF([test x"$1" != x],
85        [inn_py_expected_ver="$inn_py_expected_ver or "])
86     inn_py_expected_ver="${inn_py_expected_ver}$2"])
87 AS_IF([test x"$PYTHON" != x],
88    [AS_IF([! test -x "$PYTHON"],
89        [AC_MSG_ERROR([Python binary $PYTHON not found])])
90     AS_IF([! "$PYTHON" -c '_INN_PROG_PYTHON_CMD()' '$1' '$2' >/dev/null 2>&1],
91        [AC_MSG_ERROR([Python $inn_py_expected_ver or greater is required])])],
92    [AC_CACHE_CHECK([for Python version $inn_py_expected_ver or later],
93        [ac_cv_path_PYTHON],
94        [AC_PATH_PROGS_FEATURE_CHECK([PYTHON], [python python3 python2],
95            [AS_IF(["$ac_path_PYTHON" -c '_INN_PROG_PYTHON_CMD()' \
96                    '$1' '$2' >/dev/null 2>&1],
97                [ac_cv_path_PYTHON="$ac_path_PYTHON"
98                 ac_path_PYTHON_found=:])])])
99     AS_IF([test x"$ac_cv_path_PYTHON" = x],
100         [AC_MSG_ERROR([Python $inn_py_expected_ver or greater is required])])
101     PYTHON="$ac_cv_path_PYTHON"
102     AC_SUBST([PYTHON])])])
103
104dnl Check whether a given Python module can be loaded.  Runs the second
105dnl argument if it can, and the third argument if it cannot.
106AC_DEFUN([INN_PYTHON_CHECK_MODULE],
107[AS_LITERAL_IF([$1], [], [m4_fatal([$0: requires literal arguments])])dnl
108 AS_VAR_PUSHDEF([ac_Module], [inn_cv_python_module_$1])dnl
109 AC_CACHE_CHECK([for Python module $1], [ac_Module],
110    [AS_IF(["$PYTHON" -c 'import $1' >/dev/null 2>&1],
111        [AS_VAR_SET([ac_Module], [yes])],
112        [AS_VAR_SET([ac_Module], [no])])])
113 AS_VAR_IF([ac_Module], [yes], [$2], [$3])
114 AS_VAR_POPDEF([ac_Module])])
115
116dnl Determine the flags used for embedding Python.
117AC_DEFUN([INN_LIB_PYTHON],
118[AC_SUBST([PYTHON_CPPFLAGS])
119 AC_SUBST([PYTHON_LIBS])
120 AC_MSG_CHECKING([for flags to link with Python])
121 py_include=`$PYTHON -c 'import distutils.sysconfig; \
122     print(distutils.sysconfig.get_python_inc())'`
123 PYTHON_CPPFLAGS="-I$py_include"
124 py_libdir=`$PYTHON -c 'import distutils.sysconfig; \
125     print(" -L".join(distutils.sysconfig.get_config_vars("LIBDIR")))'`
126 py_ldlibrary=`$PYTHON -c 'import distutils.sysconfig; \
127     print(distutils.sysconfig.get_config_vars("LDLIBRARY")@<:@0@:>@)'`
128 py_linkage=`$PYTHON -c 'import distutils.sysconfig;            \
129     print(" ".join(distutils.sysconfig.get_config_vars(        \
130         "LIBS", "LIBC", "LIBM", "LOCALMODLIBS", "BASEMODLIBS", \
131         "LINKFORSHARED", "LDFLAGS")))'`
132 py_libpython=`AS_ECHO(["$py_ldlibrary"]) | sed "s/^lib//" | sed "s/\.@<:@a-z@:>@*$//"`
133 PYTHON_LIBS="-L$py_libdir -l$py_libpython $py_linkage"
134 PYTHON_LIBS=`AS_ECHO(["$PYTHON_LIBS"]) | sed -e 's/[ \\t]*/ /g'`
135 AC_MSG_RESULT([$PYTHON_LIBS])
136 inn_python_save_CPPFLAGS="$CPPFLAGS"
137 inn_python_save_LIBS="$LIBS"
138 CPPFLAGS="$PYTHON_CPPFLAGS $CPPFLAGS"
139 LIBS="$PYTHON_LIBS $LIBS"
140 AC_CHECK_HEADER([Python.h], [],
141    [AC_MSG_FAILURE([unable to compile with Python.h])])
142 AC_CHECK_FUNC([Py_Initialize], [],
143    [AC_MSG_FAILURE([unable to link with Python library])])
144 CPPFLAGS="$inn_python_save_CPPFLAGS"
145 LIBS="$inn_python_save_LIBS"])
146