diff --git a/.github/workflows/build-main.yml b/.github/workflows/build-main.yml new file mode 100644 index 00000000..d3428eaf --- /dev/null +++ b/.github/workflows/build-main.yml @@ -0,0 +1,15 @@ +name: PMIx Standard + +on: push + +jobs: + build: + runs-on: ubuntu-latest + steps: + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - name: Check out the code + uses: actions/checkout@v1 + # Run the container tester + - name: Build and Test + run: docker run --rm -v ${GITHUB_WORKSPACE}:/home/pmixer/pmix-standard jjhursey/pmix-standard /bin/bash -c "cp -R /home/pmixer/pmix-standard pmix-build && cd pmix-build && make" + shell: bash diff --git a/.gitignore b/.gitignore index ff1ce006..6500d8a3 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,4 @@ figs/~$drawings.pptx *.soc _minted* sources/_autogen_/ +debug-files diff --git a/Makefile b/Makefile index 3b6cc43f..f3be2837 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,8 @@ version=4.0 OPENPMIX_BRANCH ?= "v4.0" -default: pmix-standard.pdf + +all: pmix-standard.pdf check CHAPTERS= \ TitlePage.tex \ @@ -47,12 +48,13 @@ INTERMEDIATE_FILES=pmix-standard.pdf \ pmix-standard.blg \ pmix-standard.synctex.gz \ pmix-standard.xwm \ - *.idx *.ilg *.ind + *.idx *.ilg *.ind \ + debug-files all: pmix-standard.pdf pmix-standard.pdf: $(CHAPTERS) $(SOURCES) pmix.sty pmix-standard.tex figs/pmix-logo.png - rm -f $(INTERMEDIATE_FILES) + rm -rf $(INTERMEDIATE_FILES) @echo "-------------------------------------------------------------" @echo "If error occurs check pmix-standard.log and pmix-standard.ind" @echo "-------------------------------------------------------------" @@ -68,34 +70,36 @@ pmix-standard.pdf: $(CHAPTERS) $(SOURCES) pmix.sty pmix-standard.tex figs/pmix-l pdflatex -interaction=batchmode -file-line-error pmix-standard.tex || \ pdflatex -interaction=errorstopmode -file-line-error pmix-standard.tex < /dev/null pdflatex -interaction=batchmode -file-line-error pmix-standard.tex - @./bin/check-doc.sh - @echo "====> Success" @cp pmix-standard.pdf pmix-standard-${version}.pdf -FORCECHECK: - -check: check-doc check-openpmix +check: check-doc display-stats # Includes # - make check-decl # - make check-attr-ref -check-doc: pmix-standard.pdf FORCECHECK +check-doc: pmix-standard.pdf @./bin/check-doc.sh + @echo "========> Success <========" -check-attr-ref: pmix-standard.pdf FORCECHECK +check-attr-ref: pmix-standard.pdf @echo "====> Checking for Attributes Declared, but not referenced" @./bin/check-attr-refs.py -check-decl: pmix-standard.pdf FORCECHECK +check-decl: pmix-standard.pdf @echo "====> Checking for Multi-declared items" @./bin/check-multi-declare.py # The default is defined near the top of the Makefile # To change the default at runtime you can manually set the envar: # OPENPMIX_BRANCH=master make check-openpmix -check-openpmix: pmix-standard.pdf FORCECHECK +check-openpmix: pmix-standard.pdf @echo "====> Checking cross-reference with OpenPMIx" @./bin/check-openpmix.py -b ${OPENPMIX_BRANCH} +display-stats: pmix-standard.pdf + @echo "====> Display Stats" + @mkdir -p debug-files + @./bin/display-stats.py -f debug-files/std + clean: rm -f $(INTERMEDIATE_FILES) pmix-standard-*.pdf diff --git a/README.md b/README.md index f0deaa1d..02368e9b 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![Build Status](https://travis-ci.org/pmix/pmix-standard.svg?branch=master)](https://travis-ci.org/pmix/pmix-standard) +[![Build Status](https://github.com/pmix/pmix-standard/actions/workflows/build-main.yml/badge.svg)](https://github.com/pmix/pmix-standard/actions/workflows/build-main.yml) # PMIx Standard diff --git a/bin/check-attr-refs.py b/bin/check-attr-refs.py index 44085479..d04a9a4e 100755 --- a/bin/check-attr-refs.py +++ b/bin/check-attr-refs.py @@ -1,4 +1,4 @@ -#!/usr/bin/python -u +#!/usr/bin/env -S python3 -u import sys import os diff --git a/bin/check-multi-declare.py b/bin/check-multi-declare.py index 584a3f97..a9b779ab 100755 --- a/bin/check-multi-declare.py +++ b/bin/check-multi-declare.py @@ -1,4 +1,4 @@ -#!/usr/bin/python -u +#!/usr/bin/env -S python3 -u import sys import os diff --git a/bin/check-openpmix.py b/bin/check-openpmix.py index dd61a2a3..759e14a4 100755 --- a/bin/check-openpmix.py +++ b/bin/check-openpmix.py @@ -1,4 +1,4 @@ -#!/usr/bin/python -u +#!/usr/bin/env -S python3 -u import sys import os diff --git a/bin/display-stats.py b/bin/display-stats.py new file mode 100755 index 00000000..d545aea5 --- /dev/null +++ b/bin/display-stats.py @@ -0,0 +1,144 @@ +#!/usr/bin/env -S python3 -u + +import sys +import os +import re +import argparse +import subprocess +import shutil + +class Reference: + def __init__(self, name): + self.name = name + self.is_dep = False + self.is_rm = False + + def __str__(self): + if self.is_dep: + return self.name + " (Deprecated)" + elif self.is_rm: + return self.name + " (Removed)" + else: + return self.name + + def __cmp__(self, other): + return (self.name < other.name) + +def display_header(): + print("Valid | Deprecated | Removed | Description") + display_footer() + +def display_footer(): + print("------+------------+---------+--------------") + +def display_counts(refs, desc, filename = None): + num_total = len(refs) + num_dep = sum(x.is_dep for x in refs) + num_rm = sum(x.is_rm for x in refs) + num_active = num_total - num_dep - num_rm + + print("%5d | %10d | %7d | %s" % (num_active, num_dep, num_rm, desc)) + + if filename is not None: + output = filename + "-" + desc + "-Deprecated.txt"; + with open(output, "w") as f: + for x in sorted(refs, key=lambda x: x.name): + if x.is_dep is True: + f.write(x.name + "\n") + output = filename + "-" + desc + "-Removed.txt"; + with open(output, "w") as f: + for x in sorted(refs, key=lambda x: x.name): + if x.is_rm is True: + f.write(x.name + "\n") + output = filename + "-" + desc + ".txt"; + with open(output, "w") as f: + for x in sorted(refs, key=lambda x: x.name): + if x.is_dep is False and x.is_rm is False: + f.write(x.name + "\n") + +if __name__ == "__main__": + std_all = [] + std_attributes = [] + std_macros = [] + std_consts = [] + std_structs = [] + std_apis = [] + + # + # Command line parsing + # + parser = argparse.ArgumentParser(description="PMIx Standard Display Interface Stats") + parser.add_argument("-v", "--verbose", help="Verbose output", action="store_true") + parser.add_argument("-d", "--debug", help="Debugging output", action="store_true") + parser.add_argument("-f", "--filename", help="File prefix to write values") + + parser.parse_args() + args = parser.parse_args() + + if os.path.exists("pmix-standard.aux") is False: + print("Error: Cannot find the .aux files necessary for processing in the current directory.") + print(" Please run this script from the base PMIx Standard build directory, and with a recent build.") + sys.exit(1) + + # + # Extract all declarations + # + all_ref_strs = ["attr", "const", "struct", "macro", "apifn"] + for ref_str in all_ref_strs: + if args.verbose is True: + print("-"*50) + print("Extracting Standard: \""+ref_str+"\"") + print("-"*50) + + # subsection.A is Appendix A: Python Bindings + p = subprocess.Popen("grep \"newlabel{"+ref_str+"\" pmix-standard.aux | grep -v \"subsection.A\"", + stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True, close_fds=True) + sout = p.communicate()[0].decode("utf-8").splitlines() + if p.returncode != 0: + print("Error: Failed to extract declared \""+ref_str+"\". grep error code "+str(p.returncode)+")"); + sys.exit(2) + + for line in sout: + line = line.rstrip() + m = re.match(r"\s*\\newlabel{"+ re.escape(ref_str) + r":(\w+)", line) + if m is None: + print("Error: Failed to extract an \""+ref_str+"\" on the following line") + print(" line: "+line) + sys.exit(1) + + ref = Reference(m.group(1)) + ref.is_dep = re.search(r"Deprecated", line) is not None + ref.is_rm = re.search(r"Removed", line) is not None + std_all.append(ref) + + if args.debug is True: + print("DEBUG: Classify: %s" % ref) + + if ref_str == "attr": + std_attributes.append(ref) + elif ref_str == "const": + std_consts.append(ref) + elif ref_str == "struct": + std_structs.append(ref) + elif ref_str == "macro": + std_macros.append(ref) + elif ref_str == "apifn": + std_apis.append(ref) + else: + print("Error: Failed to classify: %s" % ref) + sys.exit(1) + p.wait() + + # + # Display summary + # + display_header() + display_counts(std_apis, "APIs", args.filename) + display_counts(std_attributes, "Attributes", args.filename) + display_counts(std_consts, "Constants", args.filename) + display_counts(std_macros, "Macros", args.filename) + display_counts(std_structs, "Structs", args.filename) + display_footer() + display_counts(std_all, "Totals") + + sys.exit(0)