#!/usr/bin/env bash set -euo pipefail usage() { cat <<'EOF' Usage: capture-pack-profile.sh [options] [build-bin-dir] [-- ] Examples: capture-pack-profile.sh --label pck capture-pack-profile.sh --runtime-root ../m2dev-client --label baseline capture-pack-profile.sh ./build-mingw64-lld/bin -- --m2pack-strict-hash 1 Options: --runtime-root DIR Stage runtime content from DIR before launching --label NAME Output label for the captured report --out-dir DIR Directory for archived raw + summary reports --timeout SEC Overrides M2_TIMEOUT for the headless run --copy-runtime Materialize runtime instead of symlinking it -h, --help Show this help Behavior: - Enables M2PACK_PROFILE=1 for the client run - Archives build-bin-dir/log/pack_profile.txt under --out-dir - Writes a parsed summary next to the raw report - Treats timeout exit codes (124/137) as acceptable if the report exists Environment overrides: M2_STAGE_RUNTIME_SCRIPT path to stage-linux-runtime.sh M2_HEADLESS_RUN_SCRIPT path to run-wine-headless.sh M2_PACK_PROFILE_PARSER path to pack-profile-report.py 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" default_runtime_root="$repo_root/../m2dev-client" stage_script="${M2_STAGE_RUNTIME_SCRIPT:-$script_dir/stage-linux-runtime.sh}" run_script="${M2_HEADLESS_RUN_SCRIPT:-$script_dir/run-wine-headless.sh}" parser_script="${M2_PACK_PROFILE_PARSER:-$script_dir/pack-profile-report.py}" runtime_root="" label="" out_dir="" timeout_seconds="${M2_TIMEOUT:-20}" copy_runtime=0 while [[ $# -gt 0 ]]; do case "$1" in --runtime-root) runtime_root="$2" shift 2 ;; --label) 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 build_bin_dir="${1:-$default_build_bin_dir}" if [[ $# -gt 0 ]]; then shift fi build_bin_dir="$(realpath -m "$build_bin_dir")" if [[ -z "$label" ]]; then label="$(date +%Y%m%d-%H%M%S)" fi safe_label="$(sanitize_label "$label")" if [[ -z "$safe_label" ]]; then safe_label="capture" fi if [[ -z "$out_dir" ]]; then out_dir="$build_bin_dir/log/pack-profile-runs" fi out_dir="$(realpath -m "$out_dir")" if [[ -z "$runtime_root" ]]; then if [[ ! -e "$build_bin_dir/config/locale.cfg" || ! -e "$build_bin_dir/pack" ]]; then if [[ -d "$default_runtime_root" ]]; then runtime_root="$default_runtime_root" fi fi fi if [[ -n "$runtime_root" ]]; then runtime_root="$(realpath "$runtime_root")" fi if [[ ! -x "$run_script" ]]; then echo "headless runner not executable: $run_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 mkdir -p "$build_bin_dir/log" "$out_dir" if [[ -n "$runtime_root" ]]; then if [[ ! -x "$stage_script" ]]; then echo "runtime staging script not executable: $stage_script" >&2 exit 1 fi stage_args=() if [[ "$copy_runtime" -eq 1 ]]; then stage_args+=(--copy) fi stage_args+=("$runtime_root" "$build_bin_dir") "$stage_script" "${stage_args[@]}" fi report_path="$build_bin_dir/log/pack_profile.txt" raw_out="$out_dir/$safe_label.pack_profile.txt" summary_out="$out_dir/$safe_label.summary.txt" rm -f "$report_path" set +e M2PACK_PROFILE=1 M2_TIMEOUT="$timeout_seconds" "$run_script" "$build_bin_dir" -- "$@" run_exit=$? set -e if [[ ! -f "$report_path" ]]; then echo "pack profile report was not generated: $report_path" >&2 exit "$run_exit" fi cp "$report_path" "$raw_out" python3 "$parser_script" "$raw_out" > "$summary_out" case "$run_exit" in 0|124|137) ;; *) echo "client run exited with $run_exit; archived report anyway:" >&2 echo " raw: $raw_out" >&2 echo " summary: $summary_out" >&2 exit "$run_exit" ;; esac echo "captured pack profile:" echo " raw: $raw_out" echo " summary: $summary_out"