Commit c216854607c2ed2ab0df90f2e2ea5c44dfcb85ad

Authored by Jay Berkenbilt
1 parent ad096b46

Add basic framework for QPDFJob code generation

generate_auto_job 0 โ†’ 100755
  1 +#!/usr/bin/env python3
  2 +import os
  3 +import sys
  4 +import argparse
  5 +import hashlib
  6 +import re
  7 +
  8 +whoami = os.path.basename(sys.argv[0])
  9 +BANNER = f'''//
  10 +// This file is automatically generated by {whoami}.
  11 +// Edits will be automatically overwritten if the build is
  12 +// run in maintainer mode.
  13 +//'''
  14 +
  15 +
  16 +def warn(*args, **kwargs):
  17 + print(*args, file=sys.stderr, **kwargs)
  18 +
  19 +
  20 +class Main:
  21 + SOURCES = [whoami, 'job.yml']
  22 + SUMS = 'job.sums'
  23 +
  24 + def main(self, args=sys.argv[1:], prog=whoami):
  25 + options = self.parse_args(args, prog)
  26 + self.top(options)
  27 +
  28 + def parse_args(self, args, prog):
  29 + parser = argparse.ArgumentParser(
  30 + prog=prog,
  31 + description='Generate files for QPDFJob',
  32 + )
  33 + mxg = parser.add_mutually_exclusive_group(required=True)
  34 + mxg.add_argument('--check',
  35 + help='update checksums if files are not up to date',
  36 + action='store_true', default=False)
  37 + mxg.add_argument('--generate',
  38 + help='generate files from sources',
  39 + action='store_true', default=False)
  40 + return parser.parse_args(args)
  41 +
  42 + def top(self, options):
  43 + if options.check:
  44 + self.check()
  45 + elif options.generate:
  46 + self.generate()
  47 + else:
  48 + exit(f'{whoami} unknown mode')
  49 +
  50 + def get_hashes(self):
  51 + hashes = {}
  52 + for i in sorted(self.SOURCES):
  53 + m = hashlib.sha256()
  54 + with open(i, 'rb') as f:
  55 + m.update(f.read())
  56 + hashes[i] = m.hexdigest()
  57 + return hashes
  58 +
  59 + def check(self):
  60 + hashes = self.get_hashes()
  61 + match = False
  62 + try:
  63 + old_hashes = {}
  64 + with open(self.SUMS, 'r') as f:
  65 + for line in f.readlines():
  66 + m = re.match(r'^(\S+) (\S+)\s*$', line)
  67 + if m:
  68 + old_hashes[m.group(1)] = m.group(2)
  69 + match = old_hashes == hashes
  70 + except Exception:
  71 + pass
  72 + if not match:
  73 + exit(f'{whoami}: auto job inputs have changed')
  74 +
  75 + def update_hashes(self):
  76 + hashes = self.get_hashes()
  77 + with open(self.SUMS, 'w') as f:
  78 + print(f'# Generated by {whoami}', file=f)
  79 + for k, v in hashes.items():
  80 + print(f'{k} {v}', file=f)
  81 +
  82 + def generate(self):
  83 + warn(f'{whoami}: regenerating auto job files')
  84 +
  85 + with open('libqpdf/qpdf/auto_job_decl.hh', 'w') as f:
  86 + print(BANNER, file=f)
  87 +
  88 + # Update hashes last to ensure that this will be rerun in the
  89 + # event of a failure.
  90 + self.update_hashes()
  91 +
  92 +
  93 +if __name__ == '__main__':
  94 + try:
  95 + os.chdir(os.path.dirname(os.path.realpath(__file__)))
  96 + Main().main()
  97 + except KeyboardInterrupt:
  98 + exit(130)
... ...
job.sums 0 โ†’ 100644
  1 +# Generated by generate_auto_job
  2 +generate_auto_job 3905985c383d33f9e8629414d1481724ea67d836749f6dff53859ca558325743
  3 +job.yml f52d711103d50a437830c6fbcd04fb4bab49a0f82f6d26d1c791c6e8488dd090
... ...
libqpdf/build.mk
1 1 TARGETS_libqpdf = libqpdf/$(OUTPUT_DIR)/$(call libname,qpdf)
2 2  
  3 +ifeq ($(MAINTAINER_MODE), 1)
  4 +ifeq ($(shell if ./generate_auto_job --check; then echo 0; else echo 1; fi), 1)
  5 +_ := $(shell ./generate_auto_job --generate)
  6 +endif
  7 +endif
  8 +
3 9 INCLUDES_libqpdf = include libqpdf
4 10 LDFLAGS_libqpdf = -Llibqpdf/$(OUTPUT_DIR)
5 11 LIBS_libqpdf = -lqpdf
... ...
libqpdf/qpdf/auto_job_decl.hh 0 โ†’ 100644
  1 +//
  2 +// This file is automatically generated by generate_auto_job.
  3 +// Edits will be automatically overwritten if the build is
  4 +// run in maintainer mode.
  5 +//
... ...