0027-gh-115382-Fix-cross-compiles-when-host-and-target-us.patch 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. From ffe5a060a1b24bedc2aac5d60d6b3b7e40f55adc Mon Sep 17 00:00:00 2001
  2. From: Vincent Fazio <5265893+vfazio@users.noreply.github.com>
  3. Date: Wed, 28 Feb 2024 13:55:04 -0600
  4. Subject: [PATCH] gh-115382: Fix cross compiles when host and target use same
  5. SOABI
  6. Previously, when a build was configured to use a host interpreter via
  7. --with-build-python, the PYTHON_FOR_BUILD config value included a path
  8. in PYTHONPATH that pointed to the target's built external modules.
  9. For "normal" foreign architecture cross compiles, when loading compiled
  10. external libraries, the target libraries were processed first due to
  11. their precedence in sys.path. These libraries were then ruled out due to
  12. a mismatch in the SOABI so the import mechanism continued searching
  13. until it found the host's native modules.
  14. However, if the host interpreter and the target python were on the same
  15. version + SOABI combination, the host interpreter would attempt to load
  16. the target's external modules due to their precedence in sys.path.
  17. Despite the "match", the target build may have been linked against a
  18. different libc or may include unsupported instructions so loading or
  19. executing the target's external modules can lead to crashes.
  20. Now, the path to the target's external modules is no longer defined in
  21. PYTHONPATH to prevent accidentally loading these foreign modules.
  22. One caveat is that during certain build stages, the target's sysconfig
  23. module requires higher precedence than the host's version in order to
  24. accurately query the target build's configuration.
  25. This worked previously due to the target's sysconfig data module having
  26. precedence over the host's (see above). In order to keep this desired
  27. behavior, a new environment variable, _PYTHON_SYSCONFIGDATA_PATH, has
  28. been defined so sysconfig can search this directory for the target's
  29. sysconfig data.
  30. Signed-off-by: Vincent Fazio <vfazio@gmail.com>
  31. Upstream-issue: https://github.com/python/cpython/issues/115382
  32. Upstream: https://github.com/python/cpython/pull/116294
  33. ---
  34. Lib/sysconfig.py | 15 ++++++++++++++-
  35. Lib/test/libregrtest/main.py | 1 +
  36. Lib/test/pythoninfo.py | 1 +
  37. Tools/scripts/run_tests.py | 1 +
  38. configure | 2 +-
  39. configure.ac | 2 +-
  40. 6 files changed, 19 insertions(+), 3 deletions(-)
  41. diff --git a/Lib/sysconfig.py b/Lib/sysconfig.py
  42. index ebe37118274..ba424236e11 100644
  43. --- a/Lib/sysconfig.py
  44. +++ b/Lib/sysconfig.py
  45. @@ -528,7 +528,20 @@ def _init_posix(vars):
  46. """Initialize the module as appropriate for POSIX systems."""
  47. # _sysconfigdata is generated at build time, see _generate_posix_vars()
  48. name = _get_sysconfigdata_name()
  49. - _temp = __import__(name, globals(), locals(), ['build_time_vars'], 0)
  50. +
  51. + # For cross builds, the path to the target's sysconfigdata must be specified
  52. + # so it can be imported. It cannot be in PYTHONPATH, as foreign modules in
  53. + # sys.path can cause crashes when loaded by the host interpreter.
  54. + # Rely on truthiness as a valueless env variable is still an empty string.
  55. + # See OS X note in _generate_posix_vars re _sysconfigdata.
  56. + if (path := os.environ.get('_PYTHON_SYSCONFIGDATA_PATH')):
  57. + from importlib.machinery import FileFinder, SourceFileLoader, SOURCE_SUFFIXES
  58. + from importlib.util import module_from_spec
  59. + spec = FileFinder(path, (SourceFileLoader, SOURCE_SUFFIXES)).find_spec(name)
  60. + _temp = module_from_spec(spec)
  61. + spec.loader.exec_module(_temp)
  62. + else:
  63. + _temp = __import__(name, globals(), locals(), ['build_time_vars'], 0)
  64. build_time_vars = _temp.build_time_vars
  65. vars.update(build_time_vars)
  66. diff --git a/Lib/test/libregrtest/main.py b/Lib/test/libregrtest/main.py
  67. index a9725fa9673..121e2e73938 100644
  68. --- a/Lib/test/libregrtest/main.py
  69. +++ b/Lib/test/libregrtest/main.py
  70. @@ -519,6 +519,7 @@ def _add_cross_compile_opts(self, regrtest_opts):
  71. '_PYTHON_PROJECT_BASE',
  72. '_PYTHON_HOST_PLATFORM',
  73. '_PYTHON_SYSCONFIGDATA_NAME',
  74. + "_PYTHON_SYSCONFIGDATA_PATH",
  75. 'PYTHONPATH'
  76. }
  77. old_environ = os.environ
  78. diff --git a/Lib/test/pythoninfo.py b/Lib/test/pythoninfo.py
  79. index 74ebb5e5b8a..fa7fbca34e1 100644
  80. --- a/Lib/test/pythoninfo.py
  81. +++ b/Lib/test/pythoninfo.py
  82. @@ -326,6 +326,7 @@ def format_groups(groups):
  83. "_PYTHON_HOST_PLATFORM",
  84. "_PYTHON_PROJECT_BASE",
  85. "_PYTHON_SYSCONFIGDATA_NAME",
  86. + "_PYTHON_SYSCONFIGDATA_PATH",
  87. "__PYVENV_LAUNCHER__",
  88. # Sanitizer options
  89. diff --git a/Tools/scripts/run_tests.py b/Tools/scripts/run_tests.py
  90. index 445a34ae3e8..4077a834245 100644
  91. --- a/Tools/scripts/run_tests.py
  92. +++ b/Tools/scripts/run_tests.py
  93. @@ -42,6 +42,7 @@ def main(regrtest_args):
  94. '_PYTHON_PROJECT_BASE',
  95. '_PYTHON_HOST_PLATFORM',
  96. '_PYTHON_SYSCONFIGDATA_NAME',
  97. + "_PYTHON_SYSCONFIGDATA_PATH",
  98. 'PYTHONPATH'
  99. }
  100. environ = {
  101. diff --git a/configure b/configure
  102. index cb3db60f9c2..5fc0cffa977 100755
  103. --- a/configure
  104. +++ b/configure
  105. @@ -3262,7 +3262,7 @@ fi
  106. fi
  107. ac_cv_prog_PYTHON_FOR_REGEN=$with_build_python
  108. PYTHON_FOR_FREEZE="$with_build_python"
  109. - PYTHON_FOR_BUILD='_PYTHON_PROJECT_BASE=$(abs_builddir) _PYTHON_HOST_PLATFORM=$(_PYTHON_HOST_PLATFORM) PYTHONPATH=$(shell test -f pybuilddir.txt && echo $(abs_builddir)/`cat pybuilddir.txt`:)$(srcdir)/Lib _PYTHON_SYSCONFIGDATA_NAME=_sysconfigdata_$(ABIFLAGS)_$(MACHDEP)_$(MULTIARCH) '$with_build_python
  110. + PYTHON_FOR_BUILD='_PYTHON_PROJECT_BASE=$(abs_builddir) _PYTHON_HOST_PLATFORM=$(_PYTHON_HOST_PLATFORM) PYTHONPATH=$(srcdir)/Lib _PYTHON_SYSCONFIGDATA_NAME=_sysconfigdata_$(ABIFLAGS)_$(MACHDEP)_$(MULTIARCH) _PYTHON_SYSCONFIGDATA_PATH=$(shell test -f pybuilddir.txt && echo $(abs_builddir)/`cat pybuilddir.txt`) '$with_build_python
  111. { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_build_python" >&5
  112. $as_echo "$with_build_python" >&6; }
  113. diff --git a/configure.ac b/configure.ac
  114. index 852cbaa6e4c..5ca316a948b 100644
  115. --- a/configure.ac
  116. +++ b/configure.ac
  117. @@ -162,7 +162,7 @@ AC_ARG_WITH(
  118. dnl Build Python interpreter is used for regeneration and freezing.
  119. ac_cv_prog_PYTHON_FOR_REGEN=$with_build_python
  120. PYTHON_FOR_FREEZE="$with_build_python"
  121. - PYTHON_FOR_BUILD='_PYTHON_PROJECT_BASE=$(abs_builddir) _PYTHON_HOST_PLATFORM=$(_PYTHON_HOST_PLATFORM) PYTHONPATH=$(shell test -f pybuilddir.txt && echo $(abs_builddir)/`cat pybuilddir.txt`:)$(srcdir)/Lib _PYTHON_SYSCONFIGDATA_NAME=_sysconfigdata_$(ABIFLAGS)_$(MACHDEP)_$(MULTIARCH) '$with_build_python
  122. + PYTHON_FOR_BUILD='_PYTHON_PROJECT_BASE=$(abs_builddir) _PYTHON_HOST_PLATFORM=$(_PYTHON_HOST_PLATFORM) PYTHONPATH=$(srcdir)/Lib _PYTHON_SYSCONFIGDATA_NAME=_sysconfigdata_$(ABIFLAGS)_$(MACHDEP)_$(MULTIARCH) _PYTHON_SYSCONFIGDATA_PATH=$(shell test -f pybuilddir.txt && echo $(abs_builddir)/`cat pybuilddir.txt`) '$with_build_python
  123. AC_MSG_RESULT([$with_build_python])
  124. ], [
  125. AS_VAR_IF([cross_compiling], [yes],
  126. --
  127. 2.44.0