Files
m2dev-client-src/scripts/capture-pack-profile.sh
server 2d9beb4793
Some checks failed
build / Windows Build (push) Has been cancelled
Add pack profile capture workflow
2026-04-15 16:39:16 +02:00

194 lines
4.5 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
usage() {
cat <<'EOF'
Usage:
capture-pack-profile.sh [options] [build-bin-dir] [-- <client args...>]
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"