mirror of
https://github.com/multica-ai/multica.git
synced 2026-09-28 13:23:48 +08:00
#7271 derives the Windows `.exe` suffix from a parse-time `go env GOOS`, which cannot see GOOS passed as a Make variable: `make build GOOS=windows` still emits PE binaries named `bin/server`, `bin/multica`, `bin/migrate` — the exact artifacts #7255 reported as unable to re-exec themselves. The top-level `export` puts the Make variable in the recipe's environment, so `go build` targets Windows while the name says otherwise. Reading `$(GOOS)` first covers both invocation forms, and making the assignment target-specific keeps the toolchain probe on `build` alone: a global assignment is expanded on every make invocation — `export` expands even a recursive one — so `make help` / `make clean` printed `go: Command not found` on checkouts without Go. Adds scripts/makefile-build.test.sh to pin both invocation forms, the non-Windows names, and the no-Go case, wired into the backend CI job that already runs the other Makefile-adjacent shell tests. Co-authored-by: Bohan-J <bohan@devv.ai> Co-authored-by: multica-agent <github@multica.ai>
86 lines
3.2 KiB
Bash
Executable File
86 lines
3.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
# `make build` has to name its outputs the way the *target* platform expects.
|
|
# Windows refuses to execute an extensionless file, so a Windows source build
|
|
# whose artifacts are named `multica` produces a CLI that cannot re-exec itself
|
|
# as a daemon (#7255) — the build succeeds and the failure surfaces later as a
|
|
# misleading "not found" at startup.
|
|
#
|
|
# The suffix is derived from GOOS, which reaches a build two ways: as an
|
|
# environment variable and as a Make variable on the command line. `go build`
|
|
# honors both, so a suffix that honors only one silently rebuilds the original
|
|
# bug. Nothing else covers this: the Go test suite never runs the Makefile, and
|
|
# CI's own build steps call `go build` directly.
|
|
|
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
cd "$ROOT_DIR"
|
|
|
|
fail() {
|
|
echo "$1" >&2
|
|
exit 1
|
|
}
|
|
|
|
# The recipe reads `-o bin/server$(EXE) ./cmd/server`, so the trailing space is
|
|
# what keeps an expected `bin/server` from matching an emitted `bin/server.exe`.
|
|
require_outputs() {
|
|
local label=$1 suffix=$2 output=$3 binary
|
|
|
|
for binary in server multica migrate; do
|
|
grep -Fq -- "-o bin/${binary}${suffix} " <<<"$output" ||
|
|
fail "$label: expected 'go build ... -o bin/${binary}${suffix}', got:
|
|
$output"
|
|
done
|
|
}
|
|
|
|
# A `go` shim that records every invocation, so the assertions below can tell
|
|
# "the Makefile probed the toolchain" from "the Makefile did not" without
|
|
# depending on how the host PATH is laid out.
|
|
probe_dir="$(mktemp -d)"
|
|
trap 'rm -rf "$probe_dir"' EXIT
|
|
real_go="$(command -v go || true)"
|
|
cat >"$probe_dir/go" <<EOF
|
|
#!/usr/bin/env bash
|
|
echo "\$@" >>"$probe_dir/invocations"
|
|
[ -n "$real_go" ] || exit 1
|
|
exec "$real_go" "\$@"
|
|
EOF
|
|
chmod +x "$probe_dir/go"
|
|
|
|
probe_count() {
|
|
[ -f "$probe_dir/invocations" ] || { echo 0; return; }
|
|
wc -l <"$probe_dir/invocations" | tr -d ' '
|
|
}
|
|
|
|
require_outputs "GOOS=windows in the environment" .exe \
|
|
"$(GOOS=windows make -n build)"
|
|
require_outputs "GOOS=windows as a Make variable" .exe \
|
|
"$(make -n build GOOS=windows)"
|
|
require_outputs "GOOS=linux in the environment" "" \
|
|
"$(GOOS=linux make -n build)"
|
|
require_outputs "GOOS=darwin as a Make variable" "" \
|
|
"$(make -n build GOOS=darwin)"
|
|
|
|
# Non-build targets must not reach for a Go toolchain: `make help` and
|
|
# `make clean` are the first thing a frontend-only contributor runs, and a
|
|
# global suffix assignment makes every one of them print `go: Command not
|
|
# found` on a checkout with no Go installed.
|
|
PATH="$probe_dir:$PATH" make -n clean >/dev/null
|
|
PATH="$probe_dir:$PATH" make help >/dev/null
|
|
[ "$(probe_count)" = 0 ] ||
|
|
fail "non-build targets invoked go $(probe_count) time(s): $(cat "$probe_dir/invocations")"
|
|
|
|
# With no GOOS given, the suffix has to follow the toolchain's own default.
|
|
if [ -n "$real_go" ]; then
|
|
host_suffix=""
|
|
[ "$("$real_go" env GOOS)" = windows ] && host_suffix=.exe
|
|
require_outputs "no GOOS set" "$host_suffix" \
|
|
"$(PATH="$probe_dir:$PATH" make -n build)"
|
|
[ "$(probe_count)" != 0 ] ||
|
|
fail "no GOOS set: expected the build target to resolve GOOS via go env"
|
|
else
|
|
echo "skipping the host-default case: no go toolchain on PATH"
|
|
fi
|
|
|
|
echo "✓ make build names its outputs for the target platform"
|