#!/usr/bin/env bash set -euo pipefail usage() { cat <<'EOF' Usage: compare-pack-profile-runs.sh [options] [build-bin-dir] [-- ] Examples: compare-pack-profile-runs.sh \ --left-label pck \ --left-runtime-root /srv/client-runtime-pck \ --right-label m2p \ --right-runtime-root /srv/client-runtime-m2p compare-pack-profile-runs.sh \ --left-label legacy \ --left-runtime-root ../runtime-pck \ --right-label secure \ --right-runtime-root ../runtime-m2p \ ./build-mingw64-lld/bin -- --m2pack-strict-hash 0 Options: --left-runtime-root DIR Runtime root for the first run --right-runtime-root DIR Runtime root for the second run --left-label NAME Label for the first run (default: left) --right-label NAME Label for the second run (default: right) --out-dir DIR Directory for archived reports and compare output --timeout SEC Overrides M2_TIMEOUT for both runs --copy-runtime Materialize runtime instead of symlinking it -h, --help Show this help Behavior: - Runs two captures back-to-back into the same build output - Archives both raw reports and summaries - Writes a combined compare report and prints it to stdout EOF } sanitize_label() { printf '%s' "$1" \ | tr '[:upper:]' '[:lower:]' \ | sed -E 's/[^a-z0-9._-]+/-/g; s/^-+//; s/-+$//; s/-{2,}/-/g' } script_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" repo_root="$(realpath "$script_dir/..")" default_build_bin_dir="$repo_root/build-mingw64-lld/bin" capture_script="${M2_CAPTURE_PACK_PROFILE_SCRIPT:-$script_dir/capture-pack-profile.sh}" parser_script="${M2_PACK_PROFILE_PARSER:-$script_dir/pack-profile-report.py}" left_runtime_root="" right_runtime_root="" left_label="left" right_label="right" out_dir="" timeout_seconds="${M2_TIMEOUT:-20}" copy_runtime=0 while [[ $# -gt 0 ]]; do case "$1" in --left-runtime-root) left_runtime_root="$2" shift 2 ;; --right-runtime-root) right_runtime_root="$2" shift 2 ;; --left-label) left_label="$2" shift 2 ;; --right-label) right_label="$2" shift 2 ;; --out-dir) out_dir="$2" shift 2 ;; --timeout) timeout_seconds="$2" shift 2 ;; --copy-runtime) copy_runtime=1 shift ;; -h|--help) usage exit 0 ;; --) shift break ;; -*) echo "unknown option: $1" >&2 usage >&2 exit 1 ;; *) break ;; esac done if [[ -z "$left_runtime_root" || -z "$right_runtime_root" ]]; then echo "both --left-runtime-root and --right-runtime-root are required" >&2 usage >&2 exit 1 fi build_bin_dir="${1:-$default_build_bin_dir}" if [[ $# -gt 0 ]]; then shift fi build_bin_dir="$(realpath -m "$build_bin_dir")" if [[ -z "$out_dir" ]]; then out_dir="$build_bin_dir/log/pack-profile-runs/$(date +%Y%m%d-%H%M%S)" fi out_dir="$(realpath -m "$out_dir")" mkdir -p "$out_dir" if [[ ! -x "$capture_script" ]]; then echo "capture script not executable: $capture_script" >&2 exit 1 fi if [[ ! -f "$parser_script" ]]; then echo "pack profile parser not found: $parser_script" >&2 exit 1 fi if ! command -v python3 >/dev/null 2>&1; then echo "python3 not found in PATH" >&2 exit 1 fi capture_common_args=( --out-dir "$out_dir" --timeout "$timeout_seconds" ) if [[ "$copy_runtime" -eq 1 ]]; then capture_common_args+=(--copy-runtime) fi "$capture_script" \ "${capture_common_args[@]}" \ --runtime-root "$left_runtime_root" \ --label "$left_label" \ "$build_bin_dir" \ -- "$@" "$capture_script" \ "${capture_common_args[@]}" \ --runtime-root "$right_runtime_root" \ --label "$right_label" \ "$build_bin_dir" \ -- "$@" left_safe_label="$(sanitize_label "$left_label")" right_safe_label="$(sanitize_label "$right_label")" left_report="$out_dir/$left_safe_label.pack_profile.txt" right_report="$out_dir/$right_safe_label.pack_profile.txt" compare_path="$out_dir/compare-$left_safe_label-vs-$right_safe_label.txt" python3 "$parser_script" \ "$left_label=$left_report" \ "$right_label=$right_report" | tee "$compare_path" echo echo "saved compare report: $compare_path"