diff --git a/gh138498-llvm-version-config.patch b/gh138498-llvm-version-config.patch new file mode 100644 index 0000000..3a68a37 --- /dev/null +++ b/gh138498-llvm-version-config.patch @@ -0,0 +1,212 @@ +Index: Python-3.14.0/Tools/jit/README.md +=================================================================== +--- Python-3.14.0.orig/Tools/jit/README.md ++++ Python-3.14.0/Tools/jit/README.md +@@ -9,7 +9,7 @@ Python 3.11 or newer is required to buil + + The JIT compiler does not require end users to install any third-party dependencies, but part of it must be *built* using LLVM[^why-llvm]. You are *not* required to build the rest of CPython using LLVM, or even the same version of LLVM (in fact, this is uncommon). + +-LLVM version 19 is required. Both `clang` and `llvm-readobj` need to be installed and discoverable (version suffixes, like `clang-19`, are okay). It's highly recommended that you also have `llvm-objdump` available, since this allows the build script to dump human-readable assembly for the generated code. ++LLVM version 19 is the officially supported version. You can modify if needed using the `LLVM_VERSION` env var during configure. Both `clang` and `llvm-readobj` need to be installed and discoverable (version suffixes, like `clang-19`, are okay). It's highly recommended that you also have `llvm-objdump` available, since this allows the build script to dump human-readable assembly for the generated code. + + It's easy to install all of the required tools: + +Index: Python-3.14.0/Tools/jit/_llvm.py +=================================================================== +--- Python-3.14.0.orig/Tools/jit/_llvm.py ++++ Python-3.14.0/Tools/jit/_llvm.py +@@ -10,8 +10,8 @@ import typing + + import _targets + +-_LLVM_VERSION = 19 +-_LLVM_VERSION_PATTERN = re.compile(rf"version\s+{_LLVM_VERSION}\.\d+\.\d+\S*\s+") ++ ++_LLVM_VERSION = "19" + _EXTERNALS_LLVM_TAG = "llvm-19.1.7.0" + + _P = typing.ParamSpec("_P") +@@ -56,53 +56,66 @@ async def _run(tool: str, args: typing.I + + + @_async_cache +-async def _check_tool_version(name: str, *, echo: bool = False) -> bool: ++async def _check_tool_version( ++ name: str, llvm_version: str, *, echo: bool = False ++) -> bool: + output = await _run(name, ["--version"], echo=echo) +- return bool(output and _LLVM_VERSION_PATTERN.search(output)) ++ _llvm_version_pattern = re.compile(rf"version\s+{llvm_version}\.\d+\.\d+\S*\s+") ++ return bool(output and _llvm_version_pattern.search(output)) + + + @_async_cache +-async def _get_brew_llvm_prefix(*, echo: bool = False) -> str | None: +- output = await _run("brew", ["--prefix", f"llvm@{_LLVM_VERSION}"], echo=echo) ++async def _get_brew_llvm_prefix(llvm_version: str, *, echo: bool = False) -> str | None: ++ output = await _run("brew", ["--prefix", f"llvm@{llvm_version}"], echo=echo) + return output and output.removesuffix("\n") + + + @_async_cache +-async def _find_tool(tool: str, *, echo: bool = False) -> str | None: ++async def _find_tool(tool: str, llvm_version: str, *, echo: bool = False) -> str | None: + # Unversioned executables: + path = tool +- if await _check_tool_version(path, echo=echo): ++ if await _check_tool_version(path, llvm_version, echo=echo): + return path + # Versioned executables: +- path = f"{tool}-{_LLVM_VERSION}" +- if await _check_tool_version(path, echo=echo): ++ path = f"{tool}-{llvm_version}" ++ if await _check_tool_version(path, llvm_version, echo=echo): + return path + # PCbuild externals: + externals = os.environ.get("EXTERNALS_DIR", _targets.EXTERNALS) + path = os.path.join(externals, _EXTERNALS_LLVM_TAG, "bin", tool) +- if await _check_tool_version(path, echo=echo): ++ if await _check_tool_version(path, llvm_version, echo=echo): + return path + # Homebrew-installed executables: +- prefix = await _get_brew_llvm_prefix(echo=echo) ++ prefix = await _get_brew_llvm_prefix(llvm_version, echo=echo) + if prefix is not None: + path = os.path.join(prefix, "bin", tool) +- if await _check_tool_version(path, echo=echo): ++ if await _check_tool_version(path, llvm_version, echo=echo): + return path + # Nothing found: + return None + + + async def maybe_run( +- tool: str, args: typing.Iterable[str], echo: bool = False ++ tool: str, ++ args: typing.Iterable[str], ++ echo: bool = False, ++ llvm_version: str = _LLVM_VERSION, + ) -> str | None: + """Run an LLVM tool if it can be found. Otherwise, return None.""" +- path = await _find_tool(tool, echo=echo) ++ ++ path = await _find_tool(tool, llvm_version, echo=echo) + return path and await _run(path, args, echo=echo) + + +-async def run(tool: str, args: typing.Iterable[str], echo: bool = False) -> str: ++async def run( ++ tool: str, ++ args: typing.Iterable[str], ++ echo: bool = False, ++ llvm_version: str = _LLVM_VERSION, ++) -> str: + """Run an LLVM tool if it can be found. Otherwise, raise RuntimeError.""" +- output = await maybe_run(tool, args, echo=echo) ++ ++ output = await maybe_run(tool, args, echo=echo, llvm_version=llvm_version) + if output is None: +- raise RuntimeError(f"Can't find {tool}-{_LLVM_VERSION}!") ++ raise RuntimeError(f"Can't find {tool}-{llvm_version}!") + return output +Index: Python-3.14.0/Tools/jit/_targets.py +=================================================================== +--- Python-3.14.0.orig/Tools/jit/_targets.py ++++ Python-3.14.0/Tools/jit/_targets.py +@@ -48,6 +48,7 @@ class _Target(typing.Generic[_S, _R]): + debug: bool = False + verbose: bool = False + cflags: str = "" ++ llvm_version: str = _llvm._LLVM_VERSION + known_symbols: dict[str, int] = dataclasses.field(default_factory=dict) + pyconfig_dir: pathlib.Path = pathlib.Path.cwd().resolve() + +@@ -79,7 +80,9 @@ class _Target(typing.Generic[_S, _R]): + async def _parse(self, path: pathlib.Path) -> _stencils.StencilGroup: + group = _stencils.StencilGroup() + args = ["--disassemble", "--reloc", f"{path}"] +- output = await _llvm.maybe_run("llvm-objdump", args, echo=self.verbose) ++ output = await _llvm.maybe_run( ++ "llvm-objdump", args, echo=self.verbose, llvm_version=self.llvm_version ++ ) + if output is not None: + # Make sure that full paths don't leak out (for reproducibility): + long, short = str(path), str(path.name) +@@ -97,7 +100,9 @@ class _Target(typing.Generic[_S, _R]): + "--sections", + f"{path}", + ] +- output = await _llvm.run("llvm-readobj", args, echo=self.verbose) ++ output = await _llvm.run( ++ "llvm-readobj", args, echo=self.verbose, llvm_version=self.llvm_version ++ ) + # --elf-output-style=JSON is only *slightly* broken on Mach-O... + output = output.replace("PrivateExtern\n", "\n") + output = output.replace("Extern\n", "\n") +@@ -164,7 +169,9 @@ class _Target(typing.Generic[_S, _R]): + # Allow user-provided CFLAGS to override any defaults + *shlex.split(self.cflags), + ] +- await _llvm.run("clang", args, echo=self.verbose) ++ await _llvm.run( ++ "clang", args, echo=self.verbose, llvm_version=self.llvm_version ++ ) + return await self._parse(o) + + async def _build_stencils(self) -> dict[str, _stencils.StencilGroup]: +@@ -212,6 +219,8 @@ class _Target(typing.Generic[_S, _R]): + if not self.stable: + warning = f"JIT support for {self.triple} is still experimental!" + request = "Please report any issues you encounter.".center(len(warning)) ++ if self.llvm_version != _llvm._LLVM_VERSION: ++ request = f"Warning! Building with an LLVM version other than {_llvm._LLVM_VERSION} is not supported." + outline = "=" * len(warning) + print("\n".join(["", outline, warning, request, outline, ""])) + digest = f"// {self._compute_digest()}\n" +Index: Python-3.14.0/Tools/jit/build.py +=================================================================== +--- Python-3.14.0.orig/Tools/jit/build.py ++++ Python-3.14.0/Tools/jit/build.py +@@ -42,6 +42,7 @@ if __name__ == "__main__": + parser.add_argument( + "--cflags", help="additional flags to pass to the compiler", default="" + ) ++ parser.add_argument("--llvm-version", help="LLVM version to use") + args = parser.parse_args() + for target in args.target: + target.debug = args.debug +@@ -49,6 +50,8 @@ if __name__ == "__main__": + target.verbose = args.verbose + target.cflags = args.cflags + target.pyconfig_dir = args.pyconfig_dir ++ if args.llvm_version: ++ target.llvm_version = args.llvm_version + target.build( + comment=comment, + force=args.force, +Index: Python-3.14.0/configure +=================================================================== +--- Python-3.14.0.orig/configure ++++ Python-3.14.0/configure +@@ -10866,7 +10866,7 @@ then : + + else case e in #( + e) as_fn_append CFLAGS_NODIST " $jit_flags" +- REGEN_JIT_COMMAND="\$(PYTHON_FOR_REGEN) \$(srcdir)/Tools/jit/build.py ${ARCH_TRIPLES:-$host} --output-dir . --pyconfig-dir . --cflags=\"$CFLAGS_JIT\"" ++ REGEN_JIT_COMMAND="\$(PYTHON_FOR_REGEN) \$(srcdir)/Tools/jit/build.py ${ARCH_TRIPLES:-$host} --output-dir . --pyconfig-dir . --cflags=\"$CFLAGS_JIT\" --llvm-version=\"$LLVM_VERSION\"" + JIT_STENCILS_H="jit_stencils.h" + if test "x$Py_DEBUG" = xtrue + then : +Index: Python-3.14.0/configure.ac +=================================================================== +--- Python-3.14.0.orig/configure.ac ++++ Python-3.14.0/configure.ac +@@ -2779,7 +2779,7 @@ AS_VAR_IF([jit_flags], + [], + [AS_VAR_APPEND([CFLAGS_NODIST], [" $jit_flags"]) + AS_VAR_SET([REGEN_JIT_COMMAND], +- ["\$(PYTHON_FOR_REGEN) \$(srcdir)/Tools/jit/build.py ${ARCH_TRIPLES:-$host} --output-dir . --pyconfig-dir . --cflags=\"$CFLAGS_JIT\""]) ++ ["\$(PYTHON_FOR_REGEN) \$(srcdir)/Tools/jit/build.py ${ARCH_TRIPLES:-$host} --output-dir . --pyconfig-dir . --cflags=\"$CFLAGS_JIT\" --llvm-version=\"$LLVM_VERSION\""]) + AS_VAR_SET([JIT_STENCILS_H], ["jit_stencils.h"]) + AS_VAR_IF([Py_DEBUG], + [true], diff --git a/python314.changes b/python314.changes index e85b69d..9d3fa20 100644 --- a/python314.changes +++ b/python314.changes @@ -1,3 +1,10 @@ +------------------------------------------------------------------- +Thu Dec 11 12:47:12 UTC 2025 - Daniel Garcia + +- Use LLVM21 to build python314, add patch + gh138498-llvm-version-config.patch + bsc#1254826, gh#python/cpython#138498 + ------------------------------------------------------------------- Thu Nov 13 17:13:03 UTC 2025 - Matej Cepl diff --git a/python314.spec b/python314.spec index 791eede..4aa0914 100644 --- a/python314.spec +++ b/python314.spec @@ -54,6 +54,8 @@ %bcond_with GIL %endif +%define llvm_version 21 + %if 0%{?do_profiling} && !0%{?want_reproducible_builds} %bcond_without profileopt %else @@ -209,6 +211,8 @@ Patch07: bpo-31046_ensurepip_honours_prefix.patch # PATCH-FIX-SLE skip-test_pyobject_freed_is_freed.patch mcepl@suse.com # skip a test failing on SLE-15 Patch09: skip-test_pyobject_freed_is_freed.patch +# PATCH-FIX-UPSTREAM gh138498-llvm-version-config gh#python/cpython#138498 daniel.garcia@suse.com +Patch10: gh138498-llvm-version-config.patch # PATCH-FIX-OPENSUSE CVE-2023-52425-libexpat-2.6.0-backport-15.6.patch # This problem on libexpat is patched on 15.6 without version # update, this patch changes the tests to match the libexpat provided @@ -275,7 +279,7 @@ BuildRequires: python3-python-docs-theme >= 2022.1 %if %{with experimental_jit} # needed for experimental_jit -BuildRequires: clang19 llvm19 +BuildRequires: clang%{llvm_version} llvm%{llvm_version} BuildRequires: llvm %endif @@ -581,6 +585,7 @@ sed -e 's/-fprofile-correction//' -i Makefile.pre.in %endif export CFLAGS="%{optflags} -IVendor/" +export LLVM_VERSION=%{llvm_version} %configure \ --with-platlibdir=%{_lib} \