diff options
-rw-r--r-- | config/report/license-compliance/body.tex | 11 | ||||
-rw-r--r-- | config/report/license-compliance/footer.tex | 2 | ||||
-rw-r--r-- | config/report/license-compliance/generator | 1 | ||||
-rw-r--r-- | config/report/license-compliance/header.tex | 52 | ||||
l--------- | config/report/license-compliance/logo.png | 1 | ||||
-rw-r--r-- | config/report/license-compliance/package.tex | 23 | ||||
-rw-r--r-- | config/report/license-report/body.tex | 12 | ||||
-rw-r--r-- | config/report/license-report/footer.tex | 37 | ||||
-rw-r--r-- | config/report/license-report/generator | 1 | ||||
-rw-r--r-- | config/report/license-report/header.tex | 57 | ||||
l--------- | config/report/license-report/logo.png | 1 | ||||
-rw-r--r-- | config/report/license-report/package.tex | 40 | ||||
-rw-r--r-- | rules/post/ptxd_make_image_common.make | 3 | ||||
-rw-r--r-- | rules/post/ptxd_make_world_report.make | 44 | ||||
-rw-r--r-- | rules/project-name.in | 9 | ||||
-rwxr-xr-x | scripts/generate-report.py | 275 | ||||
-rw-r--r-- | scripts/lib/ptxd_lib_dgen.awk | 6 | ||||
-rw-r--r-- | scripts/lib/ptxd_make_world_report.sh | 29 |
18 files changed, 603 insertions, 1 deletions
diff --git a/config/report/license-compliance/body.tex b/config/report/license-compliance/body.tex new file mode 100644 index 000000000..ce9eb4860 --- /dev/null +++ b/config/report/license-compliance/body.tex @@ -0,0 +1,11 @@ +{% from "package.tex" import package %} +{{ raise("Invalid image name '" + target + "'!") if not target in images }} +{{ raise("Image '" + target + "' has no packages!") if not images.get(target).pkgs }} +{% if target %} +{% set pkgs = images.get(target).pkgs|sort %} +{% else %} +{% set pkgs = packages.keys()|sort %} +{% endif %} +{%- for pkg in pkgs if not packages.get(pkg).licenses in ('ignore', 'proprietary') +%} +{{- package(packages.get(pkg)) }} +{%- endfor %} diff --git a/config/report/license-compliance/footer.tex b/config/report/license-compliance/footer.tex new file mode 100644 index 000000000..d4bf52671 --- /dev/null +++ b/config/report/license-compliance/footer.tex @@ -0,0 +1,2 @@ +\end{document} + diff --git a/config/report/license-compliance/generator b/config/report/license-compliance/generator new file mode 100644 index 000000000..dba411b45 --- /dev/null +++ b/config/report/license-compliance/generator @@ -0,0 +1 @@ +latex diff --git a/config/report/license-compliance/header.tex b/config/report/license-compliance/header.tex new file mode 100644 index 000000000..cac7c0dd6 --- /dev/null +++ b/config/report/license-compliance/header.tex @@ -0,0 +1,52 @@ +\documentclass[pointlessnumbers,bibtotocnumbered,openany,DIV14,paper=a4,twoside=false,listof=totoc]{scrbook} + +\usepackage{graphicx} +\usepackage[xetex]{hyperref} +\usepackage{scrtime} +\usepackage{tikz} +\usepackage{adjustbox} +\usepackage{spverbatim} +\usepackage{pdfpages} +\usepackage{tocloft} +\hypersetup{colorlinks=true,linkcolor=blue,urlcolor=blue} + +%% Something like this may be needed depending on the package list +%\usepackage[CJK]{ucharclasses} +%\usepackage{fontspec} +%\newfontfamily\mycjk{VL-Gothic-Regular} +%\setTransitionsForCJK{\mycjk}{} + +\begin{document} + +\thispagestyle{empty} +\begin{titlepage} +\null +\vfill +\begin{center} + +\includegraphics[width=4cm]{ {{- find_file("logo.png") }} } +\vskip 1cm +{\Huge \textbf{Open Source Software Licenses}} +{\huge \vfill for project \vfill {{ bsp.vendor }}-{{ bsp.project }}{{ bsp.get('project-version') }}} +{\LARGE \vfill created \today, \thistime} + +\vskip 5cm + +{\huge !Attention!} +\end{center} +\vskip 0.5cm + +This list of licenses is automatically generated and asserts no claims to +completeness or correctness. It is not legally binding, and comes without +warranty of any kind. We advise a manual counter-check before +publication or legal use. +\vfill +\vfill +\end{titlepage} + +\phantomsection +\pdfbookmark[1]{Contents}{toc} +\setlength{\cftchapnumwidth}{\widthof{\large\bfseries{}888}} +\tableofcontents + + diff --git a/config/report/license-compliance/logo.png b/config/report/license-compliance/logo.png new file mode 120000 index 000000000..a7e99e642 --- /dev/null +++ b/config/report/license-compliance/logo.png @@ -0,0 +1 @@ +../../../doc/_static/logo.png
\ No newline at end of file diff --git a/config/report/license-compliance/package.tex b/config/report/license-compliance/package.tex new file mode 100644 index 000000000..691a6db6a --- /dev/null +++ b/config/report/license-compliance/package.tex @@ -0,0 +1,23 @@ +{% macro package(pkg) %} +\chapter{ {{- build_chapter(pkg) }} \label{ {{- pkg.name }}}} + +\begin{description} +\item[Package:] {{ escape(pkg.name) }} {{ escape(pkg.get('version', '')) }} +\item[License:] {{ escape(pkg.licenses) }} +\end{description} + +{%- if pkg.get('license-files') %} +{%- for name, license in pkg.get('license-files').items() %} +\section{ {{- escape(name)}}} +{%- if name.endswith('.pdf') %} +\includepdf[pages=-]{ {{- license.file}}} +{% else %} +\begin{small} +\begin{spverbatim} +{{ source_file(license.file) }} +\end{spverbatim} +\end{small} +{% endif %} +{%- endfor %} +{% endif %} +{% endmacro %} diff --git a/config/report/license-report/body.tex b/config/report/license-report/body.tex new file mode 100644 index 000000000..7b03f7cfa --- /dev/null +++ b/config/report/license-report/body.tex @@ -0,0 +1,12 @@ +{% from "package.tex" import package %} +{{ raise("Invalid image name '" + target + "'!") if not target in images }} +{{ raise("Image '" + target + "' has no packages!") if not images.get(target).pkgs }} +{% if target %} +{% set pkgs = images.get(target).pkgs|sort %} +{% else %} +{% set pkgs = packages.keys()|sort %} +{% endif %} +{{ init_dot(packages, pkgs) }} +{%- for pkg in pkgs if not packages.get(pkg).licenses in ('ignore') +%} +{{- package(packages.get(pkg)) }} +{%- endfor %} diff --git a/config/report/license-report/footer.tex b/config/report/license-report/footer.tex new file mode 100644 index 000000000..106911b42 --- /dev/null +++ b/config/report/license-report/footer.tex @@ -0,0 +1,37 @@ +\appendix +\chapter{Flags\label{Flags}} +Note: This list of tags and the packages marked with them is meant +as a starting point for further work. It is by no means complete. +There are most likely packages that e.g. require attribution but +are missing the corresponding flag. + +For individual packages, adding the flag name to +\textless{}PKG\textgreater\_LICENSE +sets the corresponding flag. To add flags to groups of packages, +e.g. based on the package license, +\emph{ptxd\_make\_world\_license\_expand()} can be overwritten and +expanded. +\section{nosource\label{nosource}} +For packages marked with the {\it nosource} flag, the source +archive(s) will not be part of the license compliance package. +\section{nopatches\label{nopatches}} +For packages marked with the {\it nopatches} flag, the patches +for this package will not be part of the license compliance +package. +\section{attribution\label{attribution}} +Packages marked with the {\it attribution} flag require some sort +of attribution. Please refer to the package license for further +details. +\section{choice\label{choice}} +Packages marked with the {\it choice} flag require the licensee to +make some kind of license choice. Please refer to the package +license for further details. + +\printindex[attribution] +\printindex[choice] +\printindex[nosource] +\printindex[nopatches] + +\listoffigures + +\end{document} diff --git a/config/report/license-report/generator b/config/report/license-report/generator new file mode 100644 index 000000000..dba411b45 --- /dev/null +++ b/config/report/license-report/generator @@ -0,0 +1 @@ +latex diff --git a/config/report/license-report/header.tex b/config/report/license-report/header.tex new file mode 100644 index 000000000..8b271cbe4 --- /dev/null +++ b/config/report/license-report/header.tex @@ -0,0 +1,57 @@ +\documentclass[pointlessnumbers,bibtotocnumbered,openany,DIV14,paper=a4,twoside=false,listof=totoc]{scrbook} + +\usepackage{graphicx} +\usepackage{imakeidx} +\usepackage[xetex]{hyperref} +\usepackage{scrtime} +\usepackage{tikz} +\usepackage{adjustbox} +\usepackage{spverbatim} +\usepackage{pdfpages} +\usepackage{tocloft} +\usepackage{placeins} +\hypersetup{colorlinks=true,linkcolor=blue,urlcolor=blue} + +%% Something like this may be needed depending on the package list +%\usepackage[CJK]{ucharclasses} +%\usepackage{fontspec} +%\newfontfamily\mycjk{VL-Gothic-Regular} +%\setTransitionsForCJK{\mycjk}{} + +\makeindex[name=attribution,intoc,title=attribution Package Index] +\makeindex[name=choice,intoc,title=choice Package Index] +\makeindex[name=nosource,intoc,title=nosource Package Index] +\makeindex[name=nopatches,intoc,title=nopatches Package Index] + +\begin{document} + +\thispagestyle{empty} +\begin{titlepage} +\null +\vfill +\begin{center} + +\includegraphics[width=4cm]{ {{- find_file("logo.png") }} } +\vskip 1cm +{\Huge \textbf{License Report}} +{\huge \vfill for project \vfill {{ bsp.vendor }}-{{ bsp.project }}{{ bsp.get('project-version') }}} +{\LARGE \vfill created \today, \thistime} + +\vskip 5cm + +{\huge !Attention!} +\end{center} +\vskip 0.5cm + +This list of licenses is automatically generated and asserts no claims to +completeness or correctness. It is not legally binding, and comes without +warranty of any kind. We advise a manual counter-check before +publication or legal use. +\vfill +\vfill +\end{titlepage} + +\phantomsection +\pdfbookmark[1]{Contents}{toc} +\setlength{\cftchapnumwidth}{\widthof{\large\bfseries{}888}} +\tableofcontents diff --git a/config/report/license-report/logo.png b/config/report/license-report/logo.png new file mode 120000 index 000000000..a7e99e642 --- /dev/null +++ b/config/report/license-report/logo.png @@ -0,0 +1 @@ +../../../doc/_static/logo.png
\ No newline at end of file diff --git a/config/report/license-report/package.tex b/config/report/license-report/package.tex new file mode 100644 index 000000000..3f2f94e8a --- /dev/null +++ b/config/report/license-report/package.tex @@ -0,0 +1,40 @@ +{% macro package(pkg) %} +\chapter{ {{- build_chapter(pkg) }} \label{ {{- pkg.name }}}} + +\begin{description} +\item[Package:] {{ escape(pkg.name) }} {{ escape(pkg.get('version', '')) }} +\item[License:] {{ escape(pkg.licenses) }} +{% for flag in pkg.get('license-flags') or [] %} +\index[{{ flag }}]{ {{- pkg.name }}} +{%- endfor %} +\item[Flags:]{% for flag in pkg.get('license-flags') or [] %} \nameref{ {{- escape(flag) }}}{% endfor %} +\item[URL:]\begin{flushleft}{% for url in pkg.url %}{{ escape(url)}}\\ {% endfor %}\end{flushleft} +\item[MD5:] {\ttfamily {{ escape(pkg.get('md5', ''))}}} +\end{description} +{% if dot(pkg.name) %} +\begin{figure}[!ht] +\centering +\hspace*{-0.5in}\maxsizebox{0.9\paperwidth}{!}{ +{{ dot(pkg.name) }} +} +\caption{Dependency tree for {{ escape(pkg.name)}}} +\label{ {{- pkg.name }}-deps} +\end{figure} +\FloatBarrier +{% endif %} + +{%- if pkg.get('license-files') %} +{%- for name, license in pkg.get('license-files').items() %} +\section{ {{- escape(name) }}{% if license.guessed %} [automatically found]{% endif %}} +{%- if name.endswith('.pdf') %} +\includepdf[pages=-]{ {{- license.file}}} +{% else %} +\begin{small} +\begin{spverbatim} +{{ source_file(license.file) }} +\end{spverbatim} +\end{small} +{% endif %} +{%- endfor %} +{% endif %} +{% endmacro %} diff --git a/rules/post/ptxd_make_image_common.make b/rules/post/ptxd_make_image_common.make index 3ad573700..aefff54e9 100644 --- a/rules/post/ptxd_make_image_common.make +++ b/rules/post/ptxd_make_image_common.make @@ -19,7 +19,8 @@ world/image/env/impl = \ image_pkgs="$(call ptx/escape,$($(1)_PKGS))" \ image_files="$(call ptx/escape,$($(1)_FILES))" \ image_image="$(call ptx/escape,$($(1)_IMAGE))" \ - image_label="$(call ptx/escape,$($(1)_LABEL))" + image_label="$(call ptx/escape,$($(1)_LABEL))" \ + image_reports="$(call ptx/escape,$($(1)_REPORTS))" world/image/env = \ $(call world/image/env/impl,$(strip $(1))) diff --git a/rules/post/ptxd_make_world_report.make b/rules/post/ptxd_make_world_report.make new file mode 100644 index 000000000..b939a22c5 --- /dev/null +++ b/rules/post/ptxd_make_world_report.make @@ -0,0 +1,44 @@ +# -*-makefile-*- +# +# Copyright (C) 2023 by Michael Olbrich <m.olbrich@pengutronix.de> +# +# For further information about the PTXdist project and license conditions +# see the README file. +# + +# +# image/reports +# +image/reports = \ + $(call world/image/env,$(1)) \ + ptxd_make_image_reports + +$(STATEDIR)/image-%.reports: $(RELEASEDIR)/full-bsp-report.yaml + @$(call targetinfo) + @$(call image/reports, $(PTX_MAP_TO_PACKAGE_image-$(*))) + @$(call touch) + +define _generate_report_impl +$(strip $(if $($(1)_PKGS),$(if $(filter NO,$($(1)_REPORTS)),,y))) +endef + +define _generate_report +$(strip $(call _generate_report_impl,$(PTX_MAP_TO_PACKAGE_$(strip $(1))))) +endef + +PTX_IMAGES_REPORT += $(strip $(foreach image,$(IMAGE_PACKAGES),$(if $(call _generate_report,$(image)),$(image)))) + +$(if $(PTXDIST_OVERRIDE_REPORTS), \ +$(foreach image,$(PTX_IMAGES_REPORT), \ +$(eval $(PTX_MAP_TO_PACKAGE_$(image))_REPORTS := $(PTXDIST_OVERRIDE_REPORTS)) \ +)) + +PTXDIST_DEFAULT_REPORTS ?= license-compliance + +$(foreach image,$(PTX_IMAGES_REPORT), \ +$(eval $(PTX_MAP_TO_PACKAGE_$(image))_REPORTS ?= $(PTXDIST_DEFAULT_REPORTS)) \ +) + +image-reports: $(addprefix $(STATEDIR)/,$(addsuffix .reports,$(PTX_IMAGES_REPORT))) + +# vim: syntax=make diff --git a/rules/project-name.in b/rules/project-name.in index 6566c3257..977bb9779 100644 --- a/rules/project-name.in +++ b/rules/project-name.in @@ -81,6 +81,15 @@ config PROJECT_CHECK_LICENSES process. As a result all specified md5 sums for license files are verified. +config PROJECT_GENERATE_REPORTS + bool + prompt "generate reports with all relevant images" + help + If this es enabled <image>.reports is build before the + coresponding image. This is only relevant for images that are + build from packages since the document covers all packages that + are part of the image. + comment "------------------------------------" comment "reproducible builds" comment "------------------------------------" diff --git a/scripts/generate-report.py b/scripts/generate-report.py new file mode 100755 index 000000000..1fe19cd9d --- /dev/null +++ b/scripts/generate-report.py @@ -0,0 +1,275 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2023 by Michael Olbrich <m.olbrich@pengutronix.de> +# +# For further information about the PTXdist project and license conditions +# see the README file. +# + + +from os import path, environ, makedirs +from chardet.universaldetector import UniversalDetector +from multiprocessing import Pool +from dot2tex import dot2tex +import argparse +import jinja2 +import yaml +import subprocess +import hashlib + + +class ReportException(BaseException): + pass + +def find_file(search_path, name): + for file in [path.join(d, name) for d in search_path]: + if path.exists(file): + return file + return None + + +class Generator: + def __init__(self, args): + self.input_suffix = '.txt' + self.output_suffix = '.txt' + self.__template = args.template + self.__data = args.input + self.__output = args.output + self.__env = args.env or [] + self.verbose = args.verbose + self.detector = UniversalDetector() + self.path = args.path + + def create_loader(self): + return jinja2.ChoiceLoader([jinja2.FileSystemLoader(d) for d in self.path]) + + def escape(self, text): + return text + + def raise_exception(self, message): + raise ReportException(message) + + def build_chapter(self, pkg): + chapter = self.escape(pkg.get('name')) + chapter = chapter.removeprefix('host-').removeprefix('cross-') + if pkg.get('licenses', '').find('proprietary') >= 0: + chapter += ' *** Proprietary License!' + if pkg.get('licenses', '').find('unknown') >= 0: + chapter += ' *** Unknown License!' + return chapter + + def source_file(self, name): + raw = True + if path.exists(name + '.utf-8'): + name = name + '.utf-8' + raw = False + if self.verbose: + print(f'Reading "{name}" ...') + if raw: + raw_data = open(name, 'rb').read() + try: + data = raw_data.decode('UTF-8') + except UnicodeDecodeError: + self.detector.reset() + self.detector.feed(raw_data) + self.detector.close() + encoding = self.detector.result['encoding'] + if self.verbose: + print(f'Assuming encoding {encoding}.') + data = raw_data.decode(encoding) + else: + data = open(name, encoding='utf-8').read() + return data.replace('\f', '\n') + + def create_dot_recurse(self, pkgs, pkg, level, hit_deps): + if level > 3: + return '' + + display_name = self.escape( + pkg['name'].removeprefix('host-').removeprefix('cross-')) + licenses = self.escape(pkg['licenses']).split() + licenses = ' '.join(i + '\\\\' * (w % 3 == 2) + for w, i in enumerate(licenses)) + + data = """"%s" [ shape=box style="rounded corners" fixedsize=false texlbl="\\small\\begin{tabular}{c}{\\Large\\hyperref[%s]{%s}}\\\\%s\\end{tabular}" ]; +""" % (pkg['name'], pkg['name'], self.escape(pkg['name']), licenses) + + if not 'builddeps' in pkg: + return data + + for dep in pkg['builddeps']: + if f'{pkg["name"]} {dep}' in hit_deps: + continue + if not dep in pkgs: + continue + hit_deps.add(f'{pkg["name"]} {dep}') + data += """"%s" -> "%s"[dir=back]; +""" % (pkg['name'], dep) + data += self.create_dot_recurse(pkgs, + pkgs[dep], level + 1, hit_deps) + return data + + def create_dot(self, pkgs, pkg): + dot = """ +digraph "%s" { +rankdir=LR; +ratio=compress; +nodesep=0.1; +ranksep=0.1; +node [ shape=point fixedsize=true width=0.1 ]; +""" % pkg['name'] + dot += self.create_dot_recurse(pkgs, pkg, 0, set()) + dot += """} +""" + return dot + + def load(self, data): + return yaml.load(open(data).read(), Loader=yaml.SafeLoader) + + def setup_env(self, loader): + env = jinja2.Environment( + loader=loader, autoescape=jinja2.select_autoescape()) + + def _find_file(name): + return find_file(self.path, name) + + env.globals['find_file'] = _find_file + env.globals['source_file'] = self.source_file + env.globals['escape'] = self.escape + env.globals['raise'] = self.raise_exception + env.globals['build_chapter'] = self.build_chapter + for tmp in self.__env: + tmp = tmp.split('=', 2) + env.globals[tmp[0]] = tmp[1] + return env + + def build(self, data, loader): + env = self.setup_env(loader) + header = env.get_template("header" + self.input_suffix) + body = env.get_template("body" + self.input_suffix) + footer = env.get_template("footer" + self.input_suffix) + return header.render(**data) + body.render(**data) + footer.render(**data) + + def finalize(self, document, output): + makedirs(path.dirname(output), exist_ok=True) + with open(output, mode='w') as f: + f.write(document) + return output + + def run(self): + data = self.load(self.__data) + try: + document = self.build(data, self.create_loader()) + except jinja2.exceptions.TemplateNotFound: + raise ReportException(f'Invalid template "{self.__template}"!') + if self.__output: + output = self.__output + if not output.endswith(self.output_suffix): + output += self.output_suffix + else: + output = self.__template + self.output_suffix + return self.finalize(document, output) + + +class LatexGenerator(Generator): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.input_suffix = '.tex' + self.output_suffix = '.pdf' + + def escape(self, text): + return text.replace('_', '\\_').replace('&', '\\&') + + def dot(self, pkg): + return self.__dot.get(pkg, None) + + def format_dot(self, args): + dot = self.create_dot(args[0], args[1]) + return (args[1]['name'], dot2tex(dot, docpreamble='\\usepackage[xetex]{hyperref}', figonly=True, + format='pgf', autosize=True)) + + def init_dot(self, pkgs, limit): + from dot2tex import dot2tex + + if limit: + packages = {pkg: pkgs[pkg] for pkg in limit} + else: + packages = pkgs + + with Pool() as pool: + dots = pool.map(self.format_dot, [ + (packages, pkg) for pkg in packages.values()]) + self.__dot = {} + for pkg, dot in dots: + self.__dot[pkg] = dot + + def setup_env(self, loader): + env = super().setup_env(loader) + env.globals['init_dot'] = self.init_dot + env.globals['dot'] = self.dot + return env + + def finalize(self, document, output): + base = output.removesuffix(self.output_suffix) + tmp = super().finalize(document, base + self.input_suffix) + env = environ.copy() + env['max_print_line'] = '1000' + output_directory = path.dirname(tmp) or '.' + aux_hash = None + print(f'generating {output}...') + while True: + ret = subprocess.run(['xelatex', '-halt-on-error', path.basename(tmp)], env=env, + capture_output=not self.verbose, text=True, cwd=path.realpath(output_directory)) + if ret.returncode != 0: + if not self.verbose: + print(ret.stdout + ret.stderr) + raise ReportException('Failed to execute xelatex') + + new_aux_hash = hashlib.sha256( + open(base + '.aux', 'rb').read()).hexdigest() + if aux_hash == new_aux_hash: + break + aux_hash = new_aux_hash + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('-t', '--template', help='Template to use') + parser.add_argument( + '-p', '--path', help='Colon separated search path that contain the templates') + parser.add_argument('-o', '--output', help='Output file name') + parser.add_argument('-i', '--input', help='Input file name') + parser.add_argument( + '-e', '--env', help='Extra variables for the jinja2 env', action='append') + parser.add_argument('-g', '--generator', + help='Generator to use (plain, latex)') + parser.add_argument('-v', '--verbose', action='store_true') + + args = parser.parse_args() + + args.path = [path.abspath(path.join(d, args.template)) + for d in args.path.split(':')] if args.path else [''] + + if not args.generator: + file = find_file(args.path, 'generator') + if file: + args.generator = open(file).read().strip() + else: + args.generator = 'latex' + + if args.generator == 'plain': + generator = Generator(args) + elif args.generator == 'latex': + generator = LatexGenerator(args) + else: + raise ReportException(f'Invalid generator type: "{args.generator}"') + + generator.run() + + +if __name__ == "__main__": + try: + main() + except ReportException as e: + print(f'Report Generation failed: {e.args[0]}') + exit(1) diff --git a/scripts/lib/ptxd_lib_dgen.awk b/scripts/lib/ptxd_lib_dgen.awk index f1ad577e7..a172ebfe9 100644 --- a/scripts/lib/ptxd_lib_dgen.awk +++ b/scripts/lib/ptxd_lib_dgen.awk @@ -26,6 +26,7 @@ BEGIN { DEP = DIRTY == "true" ? "|" : "" PTXDIST_HASHLIST = PTXDIST_TEMPDIR "/pkghash.list" CHECK_LICENSES = 0 + GENERATE_REPORTS = 0 } # @@ -253,6 +254,9 @@ $1 ~ /^PTXCONF_/ { if (this_PKG == "PROJECT_CHECK_LICENSES") CHECK_LICENSES = 1; + if (this_PKG == "PROJECT_GENERATE_REPORTS") + GENERATE_REPORTS = 1; + do { if (this_PKG in PKG_to_pkg || this_PKG in virtual_pkg) { PKG_HASHFILE = PTXDIST_TEMPDIR "/pkghash-" this_PKG; @@ -650,6 +654,8 @@ function write_deps_pkg_active_image(this_PKG, this_pkg, prefix) { print "$(" this_PKG "_IMAGE): " \ "$(STATEDIR)/" this_pkg ".$(" this_PKG "_CFGHASH).cfghash" > DGEN_DEPS_POST; print "$(" this_PKG "_IMAGE): " "$(" this_PKG "_FILES)" > DGEN_DEPS_POST; + if (GENERATE_REPORTS) + print "$(" this_PKG "_IMAGE): $(STATEDIR)/" this_pkg ".reports" > DGEN_DEPS_POST print "$(STATEDIR)/" this_pkg ".install.post: " "$(" this_PKG "_IMAGE)" > DGEN_DEPS_POST; print "images: " "$(" this_PKG "_IMAGE)" > DGEN_DEPS_POST; # diff --git a/scripts/lib/ptxd_make_world_report.sh b/scripts/lib/ptxd_make_world_report.sh index dbdae5736..6f1f4d9f0 100644 --- a/scripts/lib/ptxd_make_world_report.sh +++ b/scripts/lib/ptxd_make_world_report.sh @@ -108,3 +108,32 @@ ptxd_make_world_fast_report() { ptxd_make_world_report_yaml fast > "${ptx_report_dir}/fast/${pkg_label}.yaml" } export -f ptxd_make_world_fast_report + +ptxd_make_image_reports() { + local generate_report report + local -a verbose + + ptxd_make_image_init || return + + ptxd_in_path PTXDIST_PATH_SCRIPTS generate-report.py && + generate_report="${ptxd_reply}" && + + if [ "${PTXDIST_VERBOSE}" = "1" ]; then + verbose=( --verbose ) + fi + + for report in ${image_reports}; do + ptxd_eval \ + pkg_stamp= \ + PYTHONUNBUFFERED=1 \ + "${generate_report}" \ + "${verbose[@]}" \ + --path "${PTXDIST_PATH//://config/report:}" \ + --template "${report}" \ + --input "${ptx_release_dir}/full-bsp-report.yaml" \ + --output "${ptx_release_dir}/${pkg_pkg}-${report}" \ + --env target="${pkg_pkg}" || return + done + echo +} +export -f ptxd_make_image_reports |