From 56b45289b938fbac1e4e3edec0df1ca2d1f8f50e Mon Sep 17 00:00:00 2001 From: Simon Howard Date: Wed, 4 Sep 2024 18:38:02 -0400 Subject: [PATCH] Generate rules instead of dependencies. This allows the testrunner script to be eliminated, and on one of my lower-spec machines this makes a significant difference because Python startup can be slow, and it's now not necessary to invoke it for every run. --- .gitignore | 2 +- GNUmakefile | 8 ++--- common.py | 27 ---------------- makedepends | 41 ------------------------ makerules | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++++ testrunner | 40 ------------------------ 6 files changed, 94 insertions(+), 113 deletions(-) delete mode 100644 common.py delete mode 100755 makedepends create mode 100755 makerules delete mode 100755 testrunner diff --git a/.gitignore b/.gitignore index e7b97c5bd..8663ed51f 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -.depends +.rules diff --git a/GNUmakefile b/GNUmakefile index e4872a4f7..ee99d9cec 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -28,8 +28,8 @@ output/%.txt: demos/%.lmp $(SOURCE_PORT) @mkdir -p $(dir $@) @./testrunner $< $@ -.depends: makedepends - ./makedepends $@ +.rules: makerules + ./makerules $@ extract/%: unzip $(UNZIPOPTS) -d extract $< $(notdir $@) @@ -45,6 +45,6 @@ extract/class_ep.wad: pwads/class_ep.zip clean: rm -f extract/*.wad rm -rf output/* - rm -f .depends + rm -f .rules -include .depends +include .rules diff --git a/common.py b/common.py deleted file mode 100644 index edf441b20..000000000 --- a/common.py +++ /dev/null @@ -1,27 +0,0 @@ -# -# Copyright (C) 2024 Simon Howard -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation; either version 2 of the License, or (at your -# option) any later version. This program is distributed in the hope that -# it will be useful, but WITHOUT ANY WARRANTY; without even the implied -# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -# - -from os.path import dirname, join, exists -import yaml - -def read_config(path): - if path == '': - return {} - - # Config deeper in the hierarchy can override config files from - # higher up in the hierarchy: - result = read_config(dirname(path)) - config_file = join(path, ".democonfig") - if exists(config_file): - with open(config_file) as f: - result.update(yaml.safe_load(f)) - - return result diff --git a/makedepends b/makedepends deleted file mode 100755 index 15e7f9676..000000000 --- a/makedepends +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright (C) 2024 Simon Howard -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation; either version 2 of the License, or (at your -# option) any later version. This program is distributed in the hope that -# it will be useful, but WITHOUT ANY WARRANTY; without even the implied -# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -# - -from glob import glob -import os -from os.path import exists, join -import sys - -from common import * - -depends_file = sys.argv[1] -dependencies = {} - -for filename in glob("expected/**/*.txt", recursive=True): - lmp_file = filename.replace("expected/", "demos/").replace(".txt", ".lmp") - cfg = read_config(lmp_file) - - depends = [join("iwads", cfg["iwad"])] - - pwad = cfg.get("pwad") - if pwad is not None: - depends.append(os.path.join("extract", pwad)) - - out_file = filename.replace("expected/", "output/") - dependencies[out_file] = depends - -with open(depends_file, "w") as f: - for out_file, depends in sorted(dependencies.items()): - out_file = out_file.replace("#", "\\#") - f.write("%s: %s\n" % ( - out_file, " ".join(depends), - )) diff --git a/makerules b/makerules new file mode 100755 index 000000000..79326295e --- /dev/null +++ b/makerules @@ -0,0 +1,89 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2024 Simon Howard +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. This program is distributed in the hope that +# it will be useful, but WITHOUT ANY WARRANTY; without even the implied +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# + +from glob import glob +import os +from os.path import dirname, basename, exists, join +import shlex +import sys +import yaml + +def escape_filename(filename): + return filename.replace("#", "\\#") + +def read_config(path): + if path == '': + return {} + + # Config deeper in the hierarchy can override config files from + # higher up in the hierarchy: + result = read_config(dirname(path)) + config_file = join(path, ".democonfig") + if exists(config_file): + with open(config_file) as f: + result.update(yaml.safe_load(f)) + + return result + +class Rule: + def __init__(self, expect_file): + self.out_file = expect_file.replace("expected/", "output/") + self.lmp_file = ( + expect_file.replace("expected/", "demos/") + .replace(".txt", ".lmp")) + self.cfg = read_config(self.lmp_file) + + def dependencies(self): + yield self.lmp_file + yield "$(SOURCE_PORT)" + yield join("iwads", self.cfg["iwad"]) + + pwad = self.cfg.get("pwad") + if pwad is not None: + yield join("extract", pwad) + + def game_arguments(self): + result = [ + "$(DOOMOPTS)", + "-statdump", "$@", + "-iwad", join("iwads", self.cfg["iwad"]), + "-timedemo", "$<" + ] + + if "gameversion" in self.cfg: + result.extend(("-gameversion", self.cfg["gameversion"])) + + if "pwad" in self.cfg: + result.extend(("-file", join("extract", self.cfg["pwad"]))) + + return result + + def command(self): + args = self.game_arguments() + return "$(SOURCE_PORT) " + " ".join(args) + " >/dev/null 2>&1" + + def rule_output(self): + result = "%s: %s\n" % ( + escape_filename(self.out_file), " ".join( + escape_filename(f) for f in self.dependencies()), + ) + result += "\t@mkdir -p %s\n" % (shlex.quote(dirname(self.out_file))) + result += "\t%s || true\n\n" % self.command() + return result + +depends_file = sys.argv[1] +rules = [] + +with open(depends_file, "w") as f: + for filename in sorted(glob("expected/**/*.txt", recursive=True)): + r = Rule(filename) + f.write(r.rule_output()) diff --git a/testrunner b/testrunner deleted file mode 100755 index 3c498fd02..000000000 --- a/testrunner +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright (C) 2024 Simon Howard -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation; either version 2 of the License, or (at your -# option) any later version. This program is distributed in the hope that -# it will be useful, but WITHOUT ANY WARRANTY; without even the implied -# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -# - -import os -from os.path import join -import shlex -import sys - -from common import * - -source_port = os.getenv("SOURCE_PORT") -assert source_port != "", "SOURCE_PORT environment variable not set." -lmp_file, out_file = sys.argv[1:] -cfg = read_config(lmp_file) - -args = [ - source_port, - "-iwad", join("iwads", cfg["iwad"]), - "-statdump", out_file, - "-timedemo", lmp_file, -] + shlex.split(os.getenv("DOOMOPTS", "")) - -if "gameversion" in cfg: - args.extend(("-gameversion", cfg["gameversion"])) - -if "pwad" in cfg: - args.extend(("-file", join("extract", cfg["pwad"]))) - -command = shlex.join(args) + " >/dev/null 2>&1" -print(command) -os.system(command)