# SAGE_CHECK_PYTHON_FOR_VENV(PYTHON_EXE, MIN_VERSION, LT_VERSION, REQUIRED_MODULES, COMMANDS_IF_GOOD) AC_DEFUN([SAGE_CHECK_PYTHON_FOR_VENV], [ m4_pushdef([PYTHON_EXE], [$1]) m4_pushdef([MIN_VERSION], [$2]) m4_pushdef([LT_VERSION], [$3]) m4_pushdef([REQUIRED_MODULES], [$4]) m4_pushdef([COMMANDS_IF_GOOD], [$5]) AC_SUBST([SAGE_ARCHFLAGS]) AC_MSG_CHECKING([... whether ]PYTHON_EXE[ is good]) python3_version=`"PYTHON_EXE" --version 2>&1 \ | $SED -n -e 's/\([[0-9]]*\.[[0-9]]*\.[[0-9]]*\).*/\1/p'` AS_IF([test -n "$python3_version"], [ AX_COMPARE_VERSION([$python3_version], [ge], MIN_VERSION, [ AX_COMPARE_VERSION([$python3_version], [lt], LT_VERSION, [ dnl Because the system python is not used directly but rather in a venv without site-packages, dnl we should test whether the module will be available in a venv. dnl Otherwise, some system site-package may be providing this module to the system python. dnl However, on Python >= 3.12, we need setuptools to run our extension compilation tests dnl because distutils has been removed from the standard library. AX_COMPARE_VERSION([$python3_version], [ge], [3.12.0], [ conftest_venv_options="--system-site-packages" distutils_core="setuptools" distutils_extension="setuptools.extension" ], [ conftest_venv_options= distutils_core="distutils.core" distutils_extension="distutils.extension" ]) all_required_modules="]REQUIRED_MODULES[, $distutils_core, $distutils_extension" dnl m4_define([conftest_venv], [config-venv]) .... for debugging only rm -rf conftest_venv AS_IF(["]PYTHON_EXE[" build/bin/sage-venv $conftest_venv_options conftest_venv && conftest_venv/bin/python3 -c "import $all_required_modules" 2>& ]AS_MESSAGE_LOG_FD, [ AS_VAR_SET([python3_result], [yes]) SAGE_PYTHON_CHECK_DISTUTILS([CC="$CC" CXX="$CXX" conftest_venv/bin/python3], [ SAGE_ARCHFLAGS="unset" ], [ AS_CASE([$host], [*-*-darwin*], [ dnl #31227: Try if setting ARCHFLAGS to empty fixes it SAGE_PYTHON_CHECK_DISTUTILS([CC="$CC" CXX="$CXX" ARCHFLAGS="" conftest_venv/bin/python3], [ SAGE_ARCHFLAGS="" ], [ AS_VAR_SET([python3_result], ["no, the version is in the supported range, and the modules can be imported, but $reason (even with ARCHFLAGS set to empty)"]) ]) ], [ AS_VAR_SET([python3_result], ["no, the version is in the supported range, and the modules can be imported, but $reason"]) ]) ]) AS_VAR_IF([python3_result], [yes], [ dnl these commands are expected to call AC_MSG_RESULT COMMANDS_IF_GOOD ], [ AC_MSG_RESULT([$python3_result]) ]) ], [ AC_MSG_RESULT([no, the version is in the supported range but cannot import one of the required modules: $all_required_modules]) ]) ], [ AC_MSG_RESULT([no, $python3_version is too recent]) ]) ], [ AC_MSG_RESULT([no, $python3_version is too old]) ]) ], [ AC_MSG_RESULT([no, "]PYTHON_EXE[ --version" does not work]) ]) m4_popdef([PYTHON_EXE]) m4_popdef([MIN_VERSION]) m4_popdef([LT_VERSION]) m4_popdef([REQUIRED_MODULES]) m4_popdef([COMMANDS_IF_GOOD]) ]) dnl distutils test AC_DEFUN([SAGE_PYTHON_CHECK_DISTUTILS], [ m4_pushdef([PYTHON_EXE], [$1]) m4_pushdef([COMMANDS_IF_DISTUTILS_GOOD], [$2]) m4_pushdef([COMMANDS_IF_DISTUTILS_NOT_GOOD], [$3]) SAGE_PYTHON_DISTUTILS_C_CONFTEST dnl (echo "***ENV***:"; env; echo "***SYSCONFIG***"; conftest_venv/bin/python3 -m sysconfig) >& AS_MESSAGE_LOG_FD echo PYTHON_EXE conftest.py --verbose build --build-base=conftest.dir >& AS_MESSAGE_LOG_FD AS_IF([PYTHON_EXE conftest.py --verbose build --build-base=conftest.dir >& AS_MESSAGE_LOG_FD 2>&1 ], [ SAGE_PYTHON_DISTUTILS_CXX_CONFTEST echo PYTHON_EXE conftest.py --verbose build --build-base=conftest.dir >& AS_MESSAGE_LOG_FD 2>&1 AS_IF([PYTHON_EXE conftest.py --verbose build --build-base=conftest.dir >& AS_MESSAGE_LOG_FD 2>&1 ], [ COMMANDS_IF_DISTUTILS_GOOD], [ reason="distutils cannot build a C++ 11 extension" COMMANDS_IF_DISTUTILS_NOT_GOOD ]) ], [ reason="distutils cannot build a C extension" COMMANDS_IF_DISTUTILS_NOT_GOOD ]) m4_popdef([PYTHON_EXE]) m4_popdef([COMMANDS_IF_DISTUTILS_GOOD]) m4_popdef([COMMANDS_IF_DISTUTILS_NOT_GOOD]) ]) dnl Write conftest.py and conftest.c AC_DEFUN([SAGE_PYTHON_DISTUTILS_C_CONFTEST], [ rm -rf conftest.* AC_LANG_PUSH([C]) AC_LANG_CONFTEST([ AC_LANG_SOURCE([[ #define PY_SSIZE_T_CLEAN #include <Python.h> static PyMethodDef SpamMethods[] = { {NULL, NULL, 0, NULL} /* Sentinel */ }; static struct PyModuleDef spammodule = { PyModuleDef_HEAD_INIT, "spam", /* name of module */ NULL, /* module documentation, may be NULL */ -1, /* size of per-interpreter state of the module, or -1 if the module keeps state in global variables. */ SpamMethods }; PyMODINIT_FUNC PyInit_spam(void) { PyObject *m; m = PyModule_Create(&spammodule); return m; } ]]) ]) AC_LANG_POP([C]) cat > conftest.py <<EOF from $distutils_core import setup from $distutils_extension import Extension from sys import exit modules = list((Extension("config_check_distutils", list(("conftest.c",))),)) setup(name="config_check_distutils", ext_modules=modules) exit(0) EOF ]) dnl Write conftest.py and conftest.cpp AC_DEFUN([SAGE_PYTHON_DISTUTILS_CXX_CONFTEST], [ rm -rf conftest.* AC_LANG_PUSH([C++]) AC_LANG_CONFTEST([ AC_LANG_SOURCE([[ #define PY_SSIZE_T_CLEAN #include <Python.h> static PyMethodDef SpamMethods[] = { {NULL, NULL, 0, NULL} /* Sentinel */ }; static struct PyModuleDef spammodule = { PyModuleDef_HEAD_INIT, "spam", /* name of module */ NULL, /* module documentation, may be NULL */ -1, /* size of per-interpreter state of the module, or -1 if the module keeps state in global variables. */ SpamMethods }; PyMODINIT_FUNC PyInit_spam(void) { PyObject *m; m = PyModule_Create(&spammodule); return m; } // Partial C++11 test, from ax_cxx_compile_stdcxx.m4 namespace test_noexcept { int f() { return 0; } int g() noexcept { return 0; } static_assert(noexcept(f()) == false, ""); static_assert(noexcept(g()) == true, ""); } ]]) ]) AC_LANG_POP([C++]) cat > conftest.py <<EOF from $distutils_core import setup from $distutils_extension import Extension from sys import exit modules = list((Extension("config_check_distutils_cxx", list(("conftest.cpp",)), extra_compile_args=list(("-std=c++11",)), language="c++"),)) setup(name="config_check_distutils_cxx", ext_modules=modules) exit(0) EOF ])