From a20ccb37e1db629a23df0135457b9a02b2ec458a Mon Sep 17 00:00:00 2001 From: Tyler Wilding Date: Fri, 2 Aug 2024 23:26:50 -0400 Subject: [PATCH] ci: add a workflow to compare compilation output with master --- .github/workflows/compiler-output-check.yaml | 95 ++++++++++++++++++++ scripts/gsrc/compare-compilation-outputs.py | 59 ++++++++++-- scripts/gsrc/jak1-sprite-adjustments.py | 1 - 3 files changed, 149 insertions(+), 6 deletions(-) create mode 100644 .github/workflows/compiler-output-check.yaml diff --git a/.github/workflows/compiler-output-check.yaml b/.github/workflows/compiler-output-check.yaml new file mode 100644 index 0000000000..57fb1465be --- /dev/null +++ b/.github/workflows/compiler-output-check.yaml @@ -0,0 +1,95 @@ +name: Compiler Output Check + +on: + workflow_call: + inputs: + cmakePreset: + required: true + type: string + cachePrefix: + required: true + type: string + +jobs: + build: + name: Clang + runs-on: ubuntu-20.04 + timeout-minutes: 60 + + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + + - name: Install Package Dependencies + run: | + sudo apt update + sudo apt install build-essential cmake \ + clang gcc g++ lcov make nasm libxrandr-dev \ + libxinerama-dev libxcursor-dev libpulse-dev \ + libxi-dev zip ninja-build libgl1-mesa-dev libssl-dev + + - name: Setup sccache + uses: hendrikmuhs/ccache-action@v1.2.13 + with: + variant: sccache + key: linux-ubuntu-20.04-${{ inputs.cachePrefix }}-${{ inputs.cmakePreset }}-${{ github.sha }} + restore-keys: linux-ubuntu-20.04-${{ inputs.cachePrefix }}-${{ inputs.cmakePreset }} + max-size: 1000M + + - name: CMake Generation (PR) + env: + CC: clang + CXX: clang++ + run: | + cmake -B build --preset=${{ inputs.cmakePreset }} \ + -DCMAKE_C_COMPILER_LAUNCHER=sccache \ + -DCMAKE_CXX_COMPILER_LAUNCHER=sccache + + - name: Build goalc (PR) + run: cmake --build build --parallel $((`nproc`)) --target goalc + + - name: Compile and preserve (PR) + run: | + ./build/goalc/goalc --game jak1 --cmd "(make-group \"all-code\")" + ./build/goalc/goalc --game jak2 --cmd "(make-group \"all-code\")" + ./build/goalc/goalc --game jak3 --cmd "(make-group \"all-code\")" + mv ./out/jak1/obj ./out/jak1/obj.pr + mv ./out/jak2/obj ./out/jak2/obj.pr + mv ./out/jak3/obj ./out/jak3/obj.pr + + - name: Checkout Master + uses: actions/checkout@v4 + with: + ref: master + + - name: CMake Generation (master) + env: + CC: clang + CXX: clang++ + run: | + cmake -B build --preset=${{ inputs.cmakePreset }} \ + -DCMAKE_C_COMPILER_LAUNCHER=sccache \ + -DCMAKE_CXX_COMPILER_LAUNCHER=sccache + + - name: Build goalc (master) + run: cmake --build build --parallel $((`nproc`)) --target goalc + + - name: Compile and preserve (master) + run: | + ./build/goalc/goalc --game jak1 --cmd "(make-group \"all-code\")" + ./build/goalc/goalc --game jak2 --cmd "(make-group \"all-code\")" + ./build/goalc/goalc --game jak3 --cmd "(make-group \"all-code\")" + mv ./out/jak1/obj ./out/jak1/obj.master + mv ./out/jak2/obj ./out/jak2/obj.master + mv ./out/jak3/obj ./out/jak3/obj.master + + - name: Compare Results and Produce Report + run: | + python ./scripts/gsrc/compare-compilation-outputs.py --base "./out/jak1/obj.master,./out/jak2/obj.master,./out/jak3/obj.master" --compare "./out/jak1/obj.pr,./out/jak2/obj.pr,./out/jak3/obj.pr" --markdown + SCRIPT_EXIT_CODE=$? + cat ./comp-diff-report.md >> $GITHUB_STEP_SUMMARY + if [ "$SCRIPT_EXIT_CODE" -ne 0 ]; then + exit 1 + fi + + diff --git a/scripts/gsrc/compare-compilation-outputs.py b/scripts/gsrc/compare-compilation-outputs.py index 714a0507f4..213874b7c3 100644 --- a/scripts/gsrc/compare-compilation-outputs.py +++ b/scripts/gsrc/compare-compilation-outputs.py @@ -4,6 +4,23 @@ import os import hashlib +import argparse + +parser = argparse.ArgumentParser("compare-compilation-outputs") +parser.add_argument("--base", help="The base branch directories", type=str) +parser.add_argument("--compare", help="The potentially modified directories to compare", type=str) +parser.add_argument("--markdown", help="The format to output results as a markdown file './comp-diff-report.md'", action="store_true") +args = parser.parse_args() + +to_markdown_file = False +if args.markdown: + to_markdown_file = True + +# Usage example +base_directory = args.base +compare_directory = args.compare + +markdown_lines = [] def hash_file(filepath): """Returns the MD5 hash of the file.""" @@ -19,8 +36,13 @@ def compare_directories(base_dir, compare_dir): missing_files = [] # Iterate through files in the base directory + total_files = 0 for root, _, files in os.walk(base_dir): for file in files: + if file is ".gitignore": + continue + total_files = total_files + 1 + base_file_path = os.path.join(root, file) relative_path = os.path.relpath(base_file_path, base_dir) compare_file_path = os.path.join(compare_dir, relative_path) @@ -34,20 +56,47 @@ def compare_directories(base_dir, compare_dir): missing_files.append(relative_path) # Report results + print(f'Comparing {base_directory} with {compare_directory}') + markdown_lines.append(f'### Comparing `{base_directory}` with `{compare_directory}`') if not mismatched_files and not missing_files: print("All files matched successfully.") + markdown_lines.append(f'All `{total_files}` files matched successfully ✅') + return 0 else: + markdown_lines.append(f'### Comparing `{base_directory}` with `{compare_directory}`') + markdown_lines.append(f'Found potential problems ❌') + markdown_lines.append(f'- {len(mismatched_files)} different files:') + markdown_lines.append(f'- {len(missing_files)} missing files:') + markdown_lines.append("| file | result |") + markdown_lines.append("|------|--------|") if mismatched_files: print("Mismatched files:") + markdown_printed_already = 0 for file in mismatched_files: print(f" - {file}") + if markdown_printed_already < 25: + markdown_lines.append(f"| {file} | different |") + markdown_printed_already = markdown_printed_already + 1 + if len(mismatched_files) > 25: + markdown_lines.append(f"| ...and {len(mismatched_files) - 25} other files | different |") if missing_files: print("Missing files:") + markdown_printed_already = 0 for file in missing_files: print(f" - {file}") + if markdown_printed_already < 25: + markdown_lines.append(f"| {file} | missing |") + markdown_printed_already = markdown_printed_already + 1 + if len(missing_files) > 25: + markdown_lines.append(f"| ...and {len(missing_files) - 25} other files | missing |") + return 1 -# Usage example -base_directory = './out/jak1/obj' -compare_directory = './out/jak1/obj_master' -print(f'Comparing {base_directory} with {compare_directory}') -compare_directories(base_directory, compare_directory) + +result = compare_directories(base_directory, compare_directory) + +if to_markdown_file: + with open('./comp-diff-report.md', 'w') as md_file: + md_file.writelines(markdown_lines) + print("Wrote results to ./comp-diff-report.md") + +exit(result) \ No newline at end of file diff --git a/scripts/gsrc/jak1-sprite-adjustments.py b/scripts/gsrc/jak1-sprite-adjustments.py index 45f8b49d25..231f822ecd 100644 --- a/scripts/gsrc/jak1-sprite-adjustments.py +++ b/scripts/gsrc/jak1-sprite-adjustments.py @@ -276,4 +276,3 @@ for adjust in adjustments: function_string += f" ((fequal-epsilon? aspect-ratio {aspect_ratio} 0.01) {value:.1f})\n" function_string += f" (else\n (+ {coefficients[0]}\n (* {coefficients[1]} aspect-ratio)\n (* {coefficients[2]} aspect-ratio aspect-ratio)\n (* {coefficients[3]} aspect-ratio aspect-ratio aspect-ratio)))))\n" print(function_string) - \ No newline at end of file