Subject: bug#17811: closed (Re: bug#17811: RFE: build against multiple python stacks)

From: [email-masked] (GNU bug Tracking System)
Date: Mon, 24 Feb 2025 23:48:03 +0000

Your bug report

#17811: RFE: build against multiple python stacks

which was filed against the automake package, has been closed.

The explanation is attached below, along with your original report.
If you require more details, please reply to [email-masked].

-- 
17811: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=17811
GNU Bug Tracking System
Contact [email-masked] with problems

Subject: Re: bug#17811: RFE: build against multiple python stacks
From: Karl Berry <[email-masked]>
To: [email-masked]
Cc: [email-masked], [email-masked]
Date: Mon, 24 Feb 2025 16:46:30 -0700
List-Id: <debbugs-submit.debbugs.gnu.org>

Hi Pavel - back in 2014 (!), you suggested supporting python2 and python3
simultaneously: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=17811
Essentially by defining a new "python3" primary to sit alongside
"python".

Agreed that this is desirable in general. It's now being discussed in
  https://debbugs.gnu.org/cgi/bugreport.cgi?bug=71672
via a somewhat different approach. I'd worry about making python3 a new
primary, since 3 vs. 2 is not the only distinction needed, as has been
discussed.

I'm closing this one to reduce duplication in the bugdb, but feel free
to reply on 71762 or open a new issue if desired. --thanks, karl.

Subject: RFE: build against multiple python stacks
From: Pavel Raiskup <[email-masked]>
To: Automake Bugs <[email-masked]>
Date: Thu, 19 Jun 2014 14:37:52 +0200
List-Id: <debbugs-submit.debbugs.gnu.org>

Hello,

I have been playing a little with Python dual-stack build (as a PoC for
long-term filed issue against RH Bugzilla [1]).

Non-tl;dr version of task regarding this RFE:

  There is need to build python plugins against both python2 & python3
  with autotools easily.

Current status:

  Automake supports python_PYTHON/pkgpython_PYTHON variable definition
  which uses variables PYTHON/pythondir/pkgpythondir, etc.  It caches the
  results among multiple AM_PYTHON_PATH calls, etc.  Works as expected in
  usual cases.

  To workaround problems with ${task}, e.g. abrt package handles this its
  own way, see [2].

Proposed solution:

  Make the _PYTHON primary support namespaces.  PoC patch attached.  This
  allows us to work with python like:

  configure.ac:
    AM_PATH_PYTHON([2.7])
    AM_PATH_PYTHON([3.3],,,3)

  Makefile.am:
    both_versions = main.py
    python_PYTHON = $(both_versions)
    python3_PYTHON = $(both_versions) python3_stuff.py

  ./configure | grep PYTHON
    PYTHON      the Python interpreter
    PYTHON3     the Python3 interpreter

  The fourth parameter of AM_PATH_PYTHON is not arbitrarily limited to
  numbers or something like that (so we may use more than two python
  stacks).  The result of this macro is:

  $ cat src/Makefile | grep -i ^python
  PYTHON = /usr/bin/python
  PYTHON3 = /usr/bin/python3
  PYTHON3_EXEC_PREFIX = ${exec_prefix}
  PYTHON3_PLATFORM = linux
  PYTHON3_PREFIX = ${prefix}
  ...
  python_PYTHON = main.py
  python3_PYTHON = main2.py

What do you think about that?  Could this be way to go?  AM_PATH_PYTHON
would stay backward compatible, current testsuite is OK (log attached).

If that was OK, I would prepare more clean patch (not so much $4s in
python.m4 probably) with testsuite & documenation fixes.

[1] https://bugzilla.redhat.com/533920
[2] https://github.com/abrt/abrt/blob/master/configure.ac#L59

Pavel
diff --git a/lib/am/python.am b/lib/am/python.am
index 5c36a2c..036a68a 100644
--- a/lib/am/python.am
+++ b/lib/am/python.am
@@ -18,7 +18,7 @@ if %?INSTALL%
 include inst-vars.am
 endif %?INSTALL%
 
-?FIRST?am__py_compile = PYTHON=$(PYTHON) $(SHELL) $(py_compile)
+?FIRST?am__py_compile = $(SHELL) $(py_compile)
 
 ## ------------ ##
 ## Installing.  ##
@@ -57,7 +57,7 @@ if %?BASE%
 ## Byte-compile must be done at install time, since file times are
 ## encoded in the actual files.
 	if test -n "$$dlist"; then \
-	  $(am__py_compile) --destdir "$(DESTDIR)" \
+	  PYTHON=$(%NDIR%_exec) $(am__py_compile) --destdir "$(DESTDIR)" \
 	                    --basedir "$(%NDIR%dir)" $$dlist; \
 	else :; fi
 else !%?BASE%
@@ -83,7 +83,7 @@ else !%?BASE%
 ## Byte-compile must be done at install time, since file times are
 ## encoded in the actual files.
 	if test -n "$$dlist"; then \
-	  $(am__py_compile) --destdir "$(DESTDIR)" \
+	  PYTHON=$(%NDIR%_exec) $(am__py_compile) --destdir "$(DESTDIR)" \
 	                    --basedir "$(%NDIR%dir)" $$dlist; \
 	else :; fi; }
 endif !%?BASE%
diff --git a/m4/python.m4 b/m4/python.m4
index 5b2c695..0d97637 100644
--- a/m4/python.m4
+++ b/m4/python.m4
@@ -10,7 +10,8 @@
 # with or without modifications, as long as this notice is preserved.

-# AM_PATH_PYTHON([MINIMUM-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+# AM_PATH_PYTHON([MINIMUM-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND],
+#                [VSUFFIX])
 # ---------------------------------------------------------------------------
 # Adds support for distributing Python modules and packages.  To
 # install modules, copy them to $(pythondir), using the python_PYTHON
@@ -32,6 +33,15 @@
 # cause an error if the version of python installed on the system
 # doesn't meet the requirement.  MINIMUM-VERSION should consist of
 # numbers and dots only.
+#
+# When the string VSUFFIX (version suffix) is non-empty, it is used for
+# diverging subsequent variable generation among multiple calls to
+# AM_PATH_PYTHON.  This is to allow us defining multiple python
+# variable "name-spaces" for multiple python stacks installed on one
+# system and to build against.  E.g., when VSUFFIX == 3, PYTHON3,
+# python3dir, pkgpython3dir and pyexec3dir are generated & used.  As a
+# result to this, users will use {,pkg}python3_PYTHON variable definition
+# in Makefile.am.
 AC_DEFUN([AM_PATH_PYTHON],
  [
   dnl Find a Python interpreter.  Python versions prior to 2.0 are not
@@ -40,71 +50,76 @@ AC_DEFUN([AM_PATH_PYTHON],
 [python python2 python3 python3.3 python3.2 python3.1 python3.0 python2.7 dnl
  python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python2.0])
 
-  AC_ARG_VAR([PYTHON], [the Python interpreter])
+  AC_ARG_VAR([PYTHON$4], [the Python$4 interpreter])
 
   m4_if([$1],[],[
     dnl No version check is needed.
     # Find any Python interpreter.
-    if test -z "$PYTHON"; then
-      AC_PATH_PROGS([PYTHON], _AM_PYTHON_INTERPRETER_LIST, :)
+    if test -z "$PYTHON$4"; then
+      AC_PATH_PROGS([PYTHON$4], _AM_PYTHON_INTERPRETER_LIST, :)
     fi
     am_display_PYTHON=python
   ], [
     dnl A version check is needed.
-    if test -n "$PYTHON"; then
-      # If the user set $PYTHON, use it and don't search something else.
-      AC_MSG_CHECKING([whether $PYTHON version is >= $1])
-      AM_PYTHON_CHECK_VERSION([$PYTHON], [$1],
+    if test -n "$PYTHON$4"; then
+      # If the user set $PYTHON$4, use it and don't search something else.
+      AC_MSG_CHECKING([whether $PYTHON$4 version is >= $1])
+      AM_PYTHON_CHECK_VERSION([$PYTHON$4], [$1],
 			      [AC_MSG_RESULT([yes])],
 			      [AC_MSG_RESULT([no])
-			       AC_MSG_ERROR([Python interpreter is too old])])
-      am_display_PYTHON=$PYTHON
+			       AC_MSG_ERROR([Python$4 interpreter is too old])])
+      am_display_PYTHON=$PYTHON$4
     else
       # Otherwise, try each interpreter until we find one that satisfies
       # VERSION.
-      AC_CACHE_CHECK([for a Python interpreter with version >= $1],
-	[am_cv_pathless_PYTHON],[
-	for am_cv_pathless_PYTHON in _AM_PYTHON_INTERPRETER_LIST none; do
-	  test "$am_cv_pathless_PYTHON" = none && break
-	  AM_PYTHON_CHECK_VERSION([$am_cv_pathless_PYTHON], [$1], [break])
+      AC_CACHE_CHECK([for a Python$4 interpreter with version >= $1],
+	[am_cv_pathless_PYTHON$4],[
+	for am_cv_pathless_PYTHON$4 in _AM_PYTHON_INTERPRETER_LIST none; do
+	  test "$am_cv_pathless_PYTHON$4" = none && break
+	  AM_PYTHON_CHECK_VERSION([$am_cv_pathless_PYTHON$4], [$1], [break])
 	done])
-      # Set $PYTHON to the absolute path of $am_cv_pathless_PYTHON.
-      if test "$am_cv_pathless_PYTHON" = none; then
-	PYTHON=:
+      # Set $PYTHON$4 to the absolute path of $am_cv_pathless_PYTHON$4.
+      if test "$am_cv_pathless_PYTHON$4" = none; then
+	PYTHON$4=:
       else
-        AC_PATH_PROG([PYTHON], [$am_cv_pathless_PYTHON])
+        AC_PATH_PROG([PYTHON$4], [$am_cv_pathless_PYTHON$4])
       fi
-      am_display_PYTHON=$am_cv_pathless_PYTHON
+      am_display_PYTHON=$am_cv_pathless_PYTHON$4
     fi
   ])
 
-  if test "$PYTHON" = :; then
+  if test "$PYTHON$4" = :; then
   dnl Run any user-specified action, or abort.
-    m4_default([$3], [AC_MSG_ERROR([no suitable Python interpreter found])])
+    m4_default([$3], [AC_MSG_ERROR([no suitable Python$4 interpreter found])])
   else
 
+  AC_SUBST([python$4_exec], ['${PYTHON$4}'])
+
+  dnl The first PYTHON$4 wins here
+  test x$4 != x && test -z "$PYTHON" && AC_SUBST([PYTHON], ['${PYTHON$4}'])
+
   dnl Query Python for its version number.  Getting [:3] seems to be
   dnl the best way to do this; it's what "site.py" does in the standard
   dnl library.
 
-  AC_CACHE_CHECK([for $am_display_PYTHON version], [am_cv_python_version],
-    [am_cv_python_version=`$PYTHON -c "import sys; sys.stdout.write(sys.version[[:3]])"`])
-  AC_SUBST([PYTHON_VERSION], [$am_cv_python_version])
+  AC_CACHE_CHECK([for $am_display_PYTHON version], [am_cv_python$4_version],
+    [am_cv_python$4_version=`$PYTHON$4 -c "import sys; sys.stdout.write(sys.version[[:3]])"`])
+  AC_SUBST([PYTHON$4_VERSION], [$am_cv_python$4_version])
 
   dnl Use the values of $prefix and $exec_prefix for the corresponding
   dnl values of PYTHON_PREFIX and PYTHON_EXEC_PREFIX.  These are made
   dnl distinct variables so they can be overridden if need be.  However,
   dnl general consensus is that you shouldn't need this ability.
 
-  AC_SUBST([PYTHON_PREFIX], ['${prefix}'])
-  AC_SUBST([PYTHON_EXEC_PREFIX], ['${exec_prefix}'])
+  AC_SUBST([PYTHON$4_PREFIX], ['${prefix}'])
+  AC_SUBST([PYTHON$4_EXEC_PREFIX], ['${exec_prefix}'])
 
   dnl At times (like when building shared libraries) you may want
   dnl to know which OS platform Python thinks this is.
 
-  AC_CACHE_CHECK([for $am_display_PYTHON platform], [am_cv_python_platform],
-    [am_cv_python_platform=`$PYTHON -c "import sys; sys.stdout.write(sys.platform)"`])
-  AC_SUBST([PYTHON_PLATFORM], [$am_cv_python_platform])
+  AC_CACHE_CHECK([for $am_display_PYTHON platform], [am_cv_python$4_platform],
+    [am_cv_python$4_platform=`$PYTHON$4 -c "import sys; sys.stdout.write(sys.platform)"`])
+  AC_SUBST([PYTHON$4_PLATFORM], [$am_cv_python$4_platform])
 
   # Just factor out some code duplication.
   am_python_setup_sysconfig="\
@@ -128,20 +143,20 @@ except ImportError:
 
   dnl Set up 4 directories:
 
-  dnl pythondir -- where to install python scripts.  This is the
+  dnl python$4dir -- where to install python scripts.  This is the
   dnl   site-packages directory, not the python standard library
   dnl   directory like in previous automake betas.  This behavior
   dnl   is more consistent with lispdir.m4 for example.
   dnl Query distutils for this directory.
   AC_CACHE_CHECK([for $am_display_PYTHON script directory],
-    [am_cv_python_pythondir],
+    [am_cv_python$4_pythondir],
     [if test "x$prefix" = xNONE
      then
        am_py_prefix=$ac_default_prefix
      else
        am_py_prefix=$prefix
      fi
-     am_cv_python_pythondir=`$PYTHON -c "
+     am_cv_python$4_pythondir=`$PYTHON$4 -c "
 $am_python_setup_sysconfig
 if can_use_sysconfig:
     sitedir = sysconfig.get_path('purelib', vars={'base':'$am_py_prefix'})
@@ -149,41 +164,41 @@ else:
     from distutils import sysconfig
     sitedir = sysconfig.get_python_lib(0, 0, prefix='$am_py_prefix')
 sys.stdout.write(sitedir)"`
-     case $am_cv_python_pythondir in
+     case $am_cv_python$4_pythondir in
      $am_py_prefix*)
        am__strip_prefix=`echo "$am_py_prefix" | sed 's|.|.|g'`
-       am_cv_python_pythondir=`echo "$am_cv_python_pythondir" | sed "s,^$am__strip_prefix,$PYTHON_PREFIX,"`
+       am_cv_python$4_pythondir=`echo "$am_cv_python$4_pythondir" | sed "s,^$am__strip_prefix,$PYTHON$4_PREFIX,"`
        ;;
      *)
        case $am_py_prefix in
          /usr|/System*) ;;
          *)
-	  am_cv_python_pythondir=$PYTHON_PREFIX/lib/python$PYTHON_VERSION/site-packages
+	  am_cv_python$4_pythondir=$PYTHON$4_PREFIX/lib/python$PYTHON$4_VERSION/site-packages
 	  ;;
        esac
        ;;
      esac
     ])
-  AC_SUBST([pythondir], [$am_cv_python_pythondir])
+  AC_SUBST([python$4dir], [$am_cv_python$4_pythondir])
 
-  dnl pkgpythondir -- $PACKAGE directory under pythondir.  Was
+  dnl pkgpython$4dir -- $PACKAGE directory under pythondir.  Was
   dnl   PYTHON_SITE_PACKAGE in previous betas, but this naming is
   dnl   more consistent with the rest of automake.
 
-  AC_SUBST([pkgpythondir], [\${pythondir}/$PACKAGE])
+  AC_SUBST([pkgpython$4dir], [\${python$4dir}/$PACKAGE])
 
   dnl pyexecdir -- directory for installing python extension modules
   dnl   (shared libraries)
   dnl Query distutils for this directory.
   AC_CACHE_CHECK([for $am_display_PYTHON extension module directory],
-    [am_cv_python_pyexecdir],
+    [am_cv_python$4_pyexecdir],
     [if test "x$exec_prefix" = xNONE
      then
        am_py_exec_prefix=$am_py_prefix
      else
        am_py_exec_prefix=$exec_prefix
      fi
-     am_cv_python_pyexecdir=`$PYTHON -c "
+     am_cv_python$4_pyexecdir=`$PYTHON$4 -c "
 $am_python_setup_sysconfig
 if can_use_sysconfig:
     sitedir = sysconfig.get_path('platlib', vars={'platbase':'$am_py_prefix'})
@@ -191,31 +206,30 @@ else:
     from distutils import sysconfig
     sitedir = sysconfig.get_python_lib(1, 0, prefix='$am_py_prefix')
 sys.stdout.write(sitedir)"`
-     case $am_cv_python_pyexecdir in
+     case $am_cv_python$4_pyexecdir in
      $am_py_exec_prefix*)
        am__strip_prefix=`echo "$am_py_exec_prefix" | sed 's|.|.|g'`
-       am_cv_python_pyexecdir=`echo "$am_cv_python_pyexecdir" | sed "s,^$am__strip_prefix,$PYTHON_EXEC_PREFIX,"`
+       am_cv_python$4_pyexecdir=`echo "$am_cv_python$4_pyexecdir" | sed "s,^$am__strip_prefix,$PYTHON_EXEC_PREFIX,"`
        ;;
      *)
        case $am_py_exec_prefix in
          /usr|/System*) ;;
          *)
-	   am_cv_python_pyexecdir=$PYTHON_EXEC_PREFIX/lib/python$PYTHON_VERSION/site-packages
+	   am_cv_python$4_pyexecdir=$PYTHON_EXEC_PREFIX/lib/python$PYTHON_VERSION/site-packages
 	   ;;
        esac
        ;;
      esac
     ])
-  AC_SUBST([pyexecdir], [$am_cv_python_pyexecdir])
+  AC_SUBST([pyexec$4dir], [$am_cv_python$4_pyexecdir])
 
   dnl pkgpyexecdir -- $(pyexecdir)/$(PACKAGE)
 
-  AC_SUBST([pkgpyexecdir], [\${pyexecdir}/$PACKAGE])
+  AC_SUBST([pkgpyexec$4dir], [\${pyexec$4dir}/$PACKAGE])
 
   dnl Run any user-specified action.
   $2
   fi
-
 ])