mirror of
https://github.com/python/cpython.git
synced 2025-11-24 20:30:18 +00:00
gh-138497: Support LLVM_VERSION configuration via env (#138498)
Some checks failed
mypy / Run mypy on Tools/jit (push) Waiting to run
Tests / Check if generated files are up to date (push) Blocked by required conditions
Tests / Ubuntu SSL tests with AWS-LC (push) Blocked by required conditions
Tests / WASI (push) Blocked by required conditions
Tests / Hypothesis tests on Ubuntu (push) Blocked by required conditions
Tests / Cross build Linux (push) Blocked by required conditions
Tests / CIFuzz (push) Blocked by required conditions
Tests / All required checks pass (push) Blocked by required conditions
mypy / Run mypy on Lib/test/libregrtest (push) Waiting to run
mypy / Run mypy on Lib/tomllib (push) Waiting to run
Tests / (push) Blocked by required conditions
Tests / Windows MSI (push) Blocked by required conditions
Tests / Change detection (push) Waiting to run
Tests / Docs (push) Blocked by required conditions
Tests / Check if Autoconf files are up to date (push) Blocked by required conditions
Tests / Ubuntu SSL tests with OpenSSL (push) Blocked by required conditions
Tests / Android (aarch64) (push) Blocked by required conditions
Tests / Android (x86_64) (push) Blocked by required conditions
Tests / Address sanitizer (push) Blocked by required conditions
Tests / Sanitizers (push) Blocked by required conditions
Lint / lint (push) Waiting to run
mypy / Run mypy on Lib/_pyrepl (push) Waiting to run
mypy / Run mypy on Tools/build (push) Waiting to run
mypy / Run mypy on Tools/cases_generator (push) Waiting to run
mypy / Run mypy on Tools/clinic (push) Waiting to run
mypy / Run mypy on Tools/peg_generator (push) Waiting to run
JIT / Interpreter (Debug) (push) Has been cancelled
Tail calling interpreter / aarch64-apple-darwin/clang (push) Has been cancelled
Tail calling interpreter / aarch64-unknown-linux-gnu/gcc (push) Has been cancelled
Tail calling interpreter / x86_64-pc-windows-msvc/msvc (push) Has been cancelled
Tail calling interpreter / x86_64-apple-darwin/clang (push) Has been cancelled
Tail calling interpreter / free-threading (push) Has been cancelled
Tail calling interpreter / x86_64-unknown-linux-gnu/gcc (push) Has been cancelled
JIT / aarch64-pc-windows-msvc/msvc (Release) (push) Has been cancelled
JIT / aarch64-pc-windows-msvc/msvc (Debug) (push) Has been cancelled
JIT / i686-pc-windows-msvc/msvc (Release) (push) Has been cancelled
JIT / i686-pc-windows-msvc/msvc (Debug) (push) Has been cancelled
JIT / aarch64-apple-darwin/clang (Release) (push) Has been cancelled
JIT / aarch64-unknown-linux-gnu/gcc (Release) (push) Has been cancelled
JIT / aarch64-apple-darwin/clang (Debug) (push) Has been cancelled
JIT / aarch64-unknown-linux-gnu/gcc (Debug) (push) Has been cancelled
JIT / x86_64-pc-windows-msvc/msvc (Release) (push) Has been cancelled
JIT / x86_64-pc-windows-msvc/msvc (Debug) (push) Has been cancelled
JIT / x86_64-apple-darwin/clang (Release) (push) Has been cancelled
JIT / x86_64-unknown-linux-gnu/gcc (Release) (push) Has been cancelled
JIT / x86_64-apple-darwin/clang (Debug) (push) Has been cancelled
JIT / x86_64-unknown-linux-gnu/gcc (Debug) (push) Has been cancelled
JIT / Free-Threaded (Debug) (push) Has been cancelled
JIT / JIT without optimizations (Debug) (push) Has been cancelled
Some checks failed
mypy / Run mypy on Tools/jit (push) Waiting to run
Tests / Check if generated files are up to date (push) Blocked by required conditions
Tests / Ubuntu SSL tests with AWS-LC (push) Blocked by required conditions
Tests / WASI (push) Blocked by required conditions
Tests / Hypothesis tests on Ubuntu (push) Blocked by required conditions
Tests / Cross build Linux (push) Blocked by required conditions
Tests / CIFuzz (push) Blocked by required conditions
Tests / All required checks pass (push) Blocked by required conditions
mypy / Run mypy on Lib/test/libregrtest (push) Waiting to run
mypy / Run mypy on Lib/tomllib (push) Waiting to run
Tests / (push) Blocked by required conditions
Tests / Windows MSI (push) Blocked by required conditions
Tests / Change detection (push) Waiting to run
Tests / Docs (push) Blocked by required conditions
Tests / Check if Autoconf files are up to date (push) Blocked by required conditions
Tests / Ubuntu SSL tests with OpenSSL (push) Blocked by required conditions
Tests / Android (aarch64) (push) Blocked by required conditions
Tests / Android (x86_64) (push) Blocked by required conditions
Tests / Address sanitizer (push) Blocked by required conditions
Tests / Sanitizers (push) Blocked by required conditions
Lint / lint (push) Waiting to run
mypy / Run mypy on Lib/_pyrepl (push) Waiting to run
mypy / Run mypy on Tools/build (push) Waiting to run
mypy / Run mypy on Tools/cases_generator (push) Waiting to run
mypy / Run mypy on Tools/clinic (push) Waiting to run
mypy / Run mypy on Tools/peg_generator (push) Waiting to run
JIT / Interpreter (Debug) (push) Has been cancelled
Tail calling interpreter / aarch64-apple-darwin/clang (push) Has been cancelled
Tail calling interpreter / aarch64-unknown-linux-gnu/gcc (push) Has been cancelled
Tail calling interpreter / x86_64-pc-windows-msvc/msvc (push) Has been cancelled
Tail calling interpreter / x86_64-apple-darwin/clang (push) Has been cancelled
Tail calling interpreter / free-threading (push) Has been cancelled
Tail calling interpreter / x86_64-unknown-linux-gnu/gcc (push) Has been cancelled
JIT / aarch64-pc-windows-msvc/msvc (Release) (push) Has been cancelled
JIT / aarch64-pc-windows-msvc/msvc (Debug) (push) Has been cancelled
JIT / i686-pc-windows-msvc/msvc (Release) (push) Has been cancelled
JIT / i686-pc-windows-msvc/msvc (Debug) (push) Has been cancelled
JIT / aarch64-apple-darwin/clang (Release) (push) Has been cancelled
JIT / aarch64-unknown-linux-gnu/gcc (Release) (push) Has been cancelled
JIT / aarch64-apple-darwin/clang (Debug) (push) Has been cancelled
JIT / aarch64-unknown-linux-gnu/gcc (Debug) (push) Has been cancelled
JIT / x86_64-pc-windows-msvc/msvc (Release) (push) Has been cancelled
JIT / x86_64-pc-windows-msvc/msvc (Debug) (push) Has been cancelled
JIT / x86_64-apple-darwin/clang (Release) (push) Has been cancelled
JIT / x86_64-unknown-linux-gnu/gcc (Release) (push) Has been cancelled
JIT / x86_64-apple-darwin/clang (Debug) (push) Has been cancelled
JIT / x86_64-unknown-linux-gnu/gcc (Debug) (push) Has been cancelled
JIT / Free-Threaded (Debug) (push) Has been cancelled
JIT / JIT without optimizations (Debug) (push) Has been cancelled
Co-authored-by: Savannah Ostrowski <savannah@python.org>
This commit is contained in:
parent
7094f09f54
commit
96c59a6e42
7 changed files with 56 additions and 25 deletions
|
|
@ -0,0 +1,4 @@
|
|||
The LLVM version used by the JIT at build time can now be modified using
|
||||
the ``LLVM_VERSION`` environment variable. Use this at your own risk, as
|
||||
there is only one officially supported LLVM version. For more information,
|
||||
please check ``Tools/jit/README.md``.
|
||||
|
|
@ -9,7 +9,7 @@ Python 3.11 or newer is required to build the JIT.
|
|||
|
||||
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:
|
||||
|
||||
|
|
|
|||
|
|
@ -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.Iterable[str], echo: bool = False) -> str
|
|||
|
||||
|
||||
@_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
|
||||
|
|
|
|||
|
|
@ -50,6 +50,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()
|
||||
|
||||
|
|
@ -81,7 +82,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)
|
||||
|
|
@ -99,7 +102,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")
|
||||
|
|
@ -175,12 +180,16 @@ class _Target(typing.Generic[_S, _R]):
|
|||
# Allow user-provided CFLAGS to override any defaults
|
||||
*shlex.split(self.cflags),
|
||||
]
|
||||
await _llvm.run("clang", args_s, echo=self.verbose)
|
||||
await _llvm.run(
|
||||
"clang", args_s, echo=self.verbose, llvm_version=self.llvm_version
|
||||
)
|
||||
self.optimizer(
|
||||
s, label_prefix=self.label_prefix, symbol_prefix=self.symbol_prefix
|
||||
).run()
|
||||
args_o = [f"--target={self.triple}", "-c", "-o", f"{o}", f"{s}"]
|
||||
await _llvm.run("clang", args_o, echo=self.verbose)
|
||||
await _llvm.run(
|
||||
"clang", args_o, echo=self.verbose, llvm_version=self.llvm_version
|
||||
)
|
||||
return await self._parse(o)
|
||||
|
||||
async def _build_stencils(self) -> dict[str, _stencils.StencilGroup]:
|
||||
|
|
@ -224,6 +233,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"
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
2
configure
generated
vendored
2
configure
generated
vendored
|
|
@ -10875,7 +10875,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\""
|
||||
if test "x$Py_DEBUG" = xtrue
|
||||
then :
|
||||
as_fn_append REGEN_JIT_COMMAND " --debug"
|
||||
|
|
|
|||
|
|
@ -2786,7 +2786,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_IF([Py_DEBUG],
|
||||
[true],
|
||||
[AS_VAR_APPEND([REGEN_JIT_COMMAND], [" --debug"])],
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue