181 lines
5.5 KiB
Python
181 lines
5.5 KiB
Python
# A cross `llvm-config`. The target llvm-config is a glibc binary that can't run
|
|
# on the (musl) build host, so instead of executing it we emulate the queries
|
|
# meson/mesa make, reporting paths inside the sysroot. Self-configuring: it reads
|
|
# the LLVM version, library soname, and built targets from the installed sysroot,
|
|
# so it works for any LLVM consumer (mesa now, rust/etc. later) with no hardcoding.
|
|
_LLVM_CONFIG_EMULATOR = r'''#!/usr/bin/env python3
|
|
import glob, re, sys
|
|
|
|
SYSROOT = "/sysroot"
|
|
LIBDIR = SYSROOT + "/usr/lib"
|
|
INCDIR = SYSROOT + "/usr/include"
|
|
|
|
_major = ""
|
|
for _p in sorted(glob.glob(LIBDIR + "/libLLVM-*.so*")):
|
|
_m = re.search(r"libLLVM-(\d+)", _p)
|
|
if _m:
|
|
_major = _m.group(1)
|
|
break
|
|
|
|
_version = (_major + ".0.0") if _major else "0.0.0"
|
|
try:
|
|
with open(INCDIR + "/llvm/Config/llvm-config.h") as _f:
|
|
_m = re.search(r'LLVM_VERSION_STRING\s+"([^"]+)"', _f.read())
|
|
if _m:
|
|
_version = _m.group(1)
|
|
except OSError:
|
|
pass
|
|
|
|
_targets = []
|
|
try:
|
|
with open(INCDIR + "/llvm/Config/Targets.def") as _f:
|
|
_targets = re.findall(r"LLVM_TARGET\((\w+)\)", _f.read())
|
|
except OSError:
|
|
pass
|
|
if not _targets:
|
|
_targets = ["X86", "AMDGPU"]
|
|
|
|
_GENERIC = (
|
|
"aggressiveinstcombine all all-targets analysis asmparser asmprinter "
|
|
"binaryformat bitreader bitstreamreader bitwriter cfguard codegen "
|
|
"codegentypes core coroutines coverage debuginfocodeview debuginfodwarf "
|
|
"debuginfomsf debuginfopdb demangle dlltooldriver engine executionengine "
|
|
"extensions frontenddriver frontendhlsl frontendoffloading frontendopenmp "
|
|
"fuzzmutate globalisel instcombine instrumentation interpreter ipo irreader "
|
|
"irprinter jitlink libdriver lineeditor linker lto mc mca mcdisassembler "
|
|
"mcjit mcparser native nativecodegen object objectyaml option orcjit "
|
|
"orcshared orctargetprocess passes profiledata remarks runtimedyld "
|
|
"scalaropts selectiondag support symbolize target targetparser textapi "
|
|
"transformutils vectorize windowsdriver windowsmanifest"
|
|
).split()
|
|
|
|
|
|
def _components():
|
|
comps = list(_GENERIC)
|
|
for t in _targets:
|
|
tl = t.lower()
|
|
comps += [tl, tl + "asmparser", tl + "codegen", tl + "desc",
|
|
tl + "disassembler", tl + "info", tl + "targetmca", tl + "utils"]
|
|
return " ".join(sorted(set(comps)))
|
|
|
|
|
|
_H = {
|
|
"--version": lambda: _version,
|
|
"--components": _components,
|
|
"--targets-built": lambda: " ".join(_targets),
|
|
"--prefix": lambda: SYSROOT + "/usr",
|
|
"--bindir": lambda: SYSROOT + "/usr/bin",
|
|
"--includedir": lambda: INCDIR,
|
|
"--libdir": lambda: LIBDIR,
|
|
"--cmakedir": lambda: LIBDIR + "/cmake/llvm",
|
|
"--has-rtti": lambda: "YES",
|
|
"--shared-mode": lambda: "shared",
|
|
"--libs": lambda: "-lLLVM-" + _major,
|
|
"--system-libs": lambda: "",
|
|
"--cflags": lambda: "-I" + INCDIR,
|
|
"--cppflags": lambda: ("-I" + INCDIR
|
|
+ " -D__STDC_CONSTANT_MACROS"
|
|
+ " -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS"),
|
|
"--cxxflags": lambda: ("-I" + INCDIR
|
|
+ " -D__STDC_CONSTANT_MACROS"
|
|
+ " -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS"),
|
|
"--ldflags": lambda: "-L" + LIBDIR,
|
|
}
|
|
|
|
for _a in sys.argv[1:]:
|
|
if _a in _H:
|
|
print(_H[_a]())
|
|
'''
|
|
|
|
|
|
def meson_cross_file(self):
|
|
cross = self.build_dir / "meson-cross.ini"
|
|
llvm_config = self.build_dir / "llvm-config"
|
|
self.write_text(llvm_config, _LLVM_CONFIG_EMULATOR)
|
|
self.run("chmod", "+x", llvm_config)
|
|
self.write_text(
|
|
cross,
|
|
f"""\
|
|
[binaries]
|
|
c = '{self.triple}-gcc'
|
|
cpp = '{self.triple}-g++'
|
|
ar = '{self.triple}-gcc-ar'
|
|
nm = '{self.triple}-nm'
|
|
objcopy = '{self.triple}-objcopy'
|
|
ranlib = '{self.triple}-ranlib'
|
|
strip = '{self.triple}-strip'
|
|
pkg-config = '{self.triple}-pkg-config'
|
|
cmake = '/usr/bin/cmake'
|
|
llvm-config = '{llvm_config}'
|
|
|
|
[host_machine]
|
|
system = 'linux'
|
|
cpu_family = '{self.arch}'
|
|
cpu = '{self.arch}'
|
|
endian = 'little'
|
|
""",
|
|
)
|
|
return cross
|
|
|
|
|
|
def meson_configure(
|
|
self, extra_args=(), extra_env=None, *, source_dir=None, flags=True, host=False
|
|
):
|
|
p = self.options
|
|
env = {}
|
|
if flags:
|
|
env.update(
|
|
{
|
|
"CFLAGS": p.get("cflags", ""),
|
|
"CXXFLAGS": p.get("cxxflags", ""),
|
|
"LDFLAGS": p.get("ldflags", ""),
|
|
}
|
|
)
|
|
if extra_env:
|
|
env.update(extra_env)
|
|
cross_args = [] if host else ["--cross-file", meson_cross_file(self)]
|
|
self.run(
|
|
"meson",
|
|
"setup",
|
|
source_dir or self.source_dir,
|
|
*cross_args,
|
|
f"--prefix={p.get('prefix', '/usr')}",
|
|
f"--sysconfdir={p.get('sysconfdir', '/etc')}",
|
|
f"--localstatedir={p.get('localstatedir', '/var')}",
|
|
"--libdir=lib",
|
|
"--sbindir=bin",
|
|
"--bindir=bin",
|
|
"--datadir=share",
|
|
"--buildtype=release",
|
|
"-Ddefault_library=shared",
|
|
*extra_args,
|
|
env=env,
|
|
)
|
|
|
|
|
|
def meson_build(self, extra_args=()):
|
|
self.run("meson", "compile", f"-j{self.jobs}", *extra_args)
|
|
|
|
|
|
def meson_install(self, extra_args=()):
|
|
self.run(
|
|
"meson",
|
|
"install",
|
|
"--no-rebuild",
|
|
*extra_args,
|
|
env={"DESTDIR": str(self.dest_dir)},
|
|
)
|
|
|
|
|
|
def meson(*, configure_args=(), configure_env=None, build_args=(), install_args=()):
|
|
def _configure(self):
|
|
meson_configure(self, configure_args, configure_env)
|
|
|
|
def _build(self):
|
|
meson_build(self, build_args)
|
|
|
|
def _install(self):
|
|
meson_install(self, install_args)
|
|
|
|
return _configure, _build, _install
|