swayfx-mosaic/tooling/probes/step20c-optimized-blur-edge/prepare.py

109 lines
5.8 KiB
Python

#!/usr/bin/env python3
"""Build-only reconstruction from fixed archives and immutable source patches.
CONTRACT: no compositor launch, system install or write to older fixtures.
INVARIANT: consumed LABs cannot be rebuilt, and prepared identities are hashed.
"""
import hashlib
import io
import json
import os
import subprocess
import sys
import tarfile
import tempfile
from pathlib import Path
fixture = Path(__file__).resolve().parent
repo = fixture.parents[2]
lab = Path(sys.argv[1]).resolve() if len(sys.argv) == 2 else Path(
tempfile.mkdtemp(prefix='swayfx-mosaic-optimized-edge-', dir=Path.home()))
if (lab / 'runs').exists() and any((lab / 'runs').iterdir()):
raise RuntimeError('never rebuild a consumed LAB')
(lab / 'results').mkdir(parents=True, exist_ok=True)
(lab / 'runs').mkdir(exist_ok=True)
print('LAB=' + str(lab), flush=True)
def run(args, **kwargs):
with (lab / 'build.log').open('ab') as out:
subprocess.run(args, check=True, stdout=out, stderr=subprocess.STDOUT, **kwargs)
def sha(path):
return hashlib.sha256(path.read_bytes()).hexdigest()
def archive(git, revision, name):
target = lab / name
if target.exists():
raise RuntimeError('existing source tree; continue Meson explicitly, never overwrite')
target.mkdir()
data = subprocess.check_output(['git', '-C', str(git), 'archive', revision])
tarfile.open(fileobj=io.BytesIO(data)).extractall(target, filter='data')
scene_revision = '37ccd723bef49e6891156ffafce8f549f01446cc'
mosaic_revision = 'cd550382b311efdbfe3ed892f4e1d281d852e754'
pristine_revision = 'fd71a6bdc061bd633b488ae7b83e8a6981d22f86'
run(['git', 'clone', '--quiet', '--no-checkout', 'https://github.com/wlrfx/scenefx.git', str(lab / 'scenefx-git')])
for name in ('scene0', 'scenefx'):
archive(lab / 'scenefx-git', scene_revision, name)
archive(repo, pristine_revision, 'pristine')
archive(repo, mosaic_revision, 'mosaic')
chains = {
'scenefx': ['step20c-valid-grab/scenefx-popup-plus-base.patch',
'step20c-temporal-damage/scenefx-timing.patch',
'step20c-optimized-blur-cache/scenefx-cache-trace.patch'],
'mosaic': ['step20c-valid-grab/mosaic-popup-plus-base.patch',
'step20c-valid-grab/hidden-guard.patch',
'step20c-temporal-damage/mosaic-output-timing.patch',
'step20c-presentation-identity/presentation-events.patch',
'step20c-optimized-blur-cache/sway-source-trace.patch']}
patches = []
(lab / 'patches').mkdir()
for tree, chain in chains.items():
for name in chain:
source = repo / 'tooling/probes' / name
target = lab / 'patches' / source.name
target.write_bytes(source.read_bytes())
patches.append({'path': name, 'sha256': sha(target), 'target': tree})
run(['git', 'apply', '--check', str(target)], cwd=lab / tree)
run(['git', 'apply', str(target)], cwd=lab / tree)
for source, build in [('scene0', 'scene0-build'), ('scenefx', 'scenefx-build')]:
run(['meson', 'setup', str(lab / build), str(lab / source), '-Dexamples=false', '-Dwerror=false'])
run(['meson', 'compile', '-C', str(lab / build), '-j', '8'])
for source, build, scene in [('pristine', 'pristine-build', 'scene0-build'),
('mosaic', 'mosaic-build', 'scenefx-build')]:
env = {**os.environ, 'PKG_CONFIG_PATH': str(lab / scene / 'meson-uninstalled')}
args = ['meson', 'setup', str(lab / build), str(lab / source),
'-Ddefault-wallpaper=false', '-Dswaybar=false', '-Dswaynag=false',
'-Dman-pages=disabled', '-Dsd-bus-provider=libsystemd', '-Dwerror=false']
if source == 'mosaic':
args.append('-Dmosaic-package=true')
run(args, env=env)
run(['meson', 'compile', '-C', str(lab / build), '-j', '8'], env=env)
protocols = repo / 'tooling/probes/step20c-optimized-blur-cache'
for stem, name, digest in [
('layer-shell', 'wlr-layer-shell-unstable-v1.xml', '996b8c66e1c2276c443336d4cb174634e8e5948823779042f244930525b79cc2'),
('xdg-shell', 'xdg-shell.xml', '7ba7f9c8473deee674cb1f154a18abd0bb0cc072604fc055b0c15e459fc4c7df')]:
xml = protocols / name
assert sha(xml) == digest
target = lab / name
target.write_bytes(xml.read_bytes())
run(['wayland-scanner', 'client-header', str(target), str(lab / (stem + '-client.h'))])
run(['wayland-scanner', 'private-code', str(target), str(lab / (stem + '-protocol.c'))])
(lab / 'client-source.c').write_bytes((fixture / 'clients.c').read_bytes())
flags = subprocess.check_output(['pkg-config', '--cflags', '--libs', 'wayland-client'], text=True).split()
run(['cc', '-std=c17', '-Wall', '-Wextra', '-Werror', '-Wno-unused-parameter',
'-I' + str(lab), str(lab / 'client-source.c'), str(lab / 'xdg-shell-protocol.c'),
str(lab / 'layer-shell-protocol.c'), '-o', str(lab / 'clients'), *flags])
run(['meson', 'test', '-C', str(lab / 'mosaic-build'), 'mosaic-model', '--print-errorlogs'])
versions = {package: subprocess.check_output(['pkg-config', '--modversion', package], text=True).strip()
for package in ('wlroots-0.20', 'scenefx-0.5', 'wayland-client', 'wayland-protocols')}
binaries = {str(p.relative_to(lab)): sha(p) for p in [
lab / 'clients', lab / 'mosaic-build/sway/swayfx-mosaic', lab / 'pristine-build/sway/sway',
lab / 'scenefx-build/libscenefx-0.5.so', lab / 'scene0-build/libscenefx-0.5.so']}
for rel in ('mosaic-build/sway/swayfx-mosaic', 'pristine-build/sway/sway'):
run(['ldd', str(lab / rel)])
(lab / 'results/build-identities.json').write_text(json.dumps({
'revisions': {'SceneFX': scene_revision, 'Mosaic': mosaic_revision, 'pristine': pristine_revision},
'packages': versions, 'patches': patches, 'binaries': binaries,
'R2_R3': 'identical binary/library/client/config; only OPT_TRACE presence differs'}, indent=2) + '\n')
print('BUILD_PASS LAB=' + str(lab), flush=True)