fix(build): silence Windows mkdir "already exists" noise in build logs (#2753)
Co-authored-by: Joao Manso <X363081@bcpcorp.net> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: Carlos Florencio <carlosmflorencio@gmail.com>
This commit is contained in:
+24
-19
@@ -45,10 +45,13 @@ endif
|
||||
ifeq ($(OS)$(MSYSTEM),Windows_NT)
|
||||
RM = cmd /c del /s /q
|
||||
RMDIR = cmd /c rmdir /s /q
|
||||
# cmd's `mkdir` errors when the dir already exists, unlike Unix `mkdir -p`.
|
||||
# Call sites use `-@$(MKDIR) $(BUILD_DIR)` (note the `-` prefix) so the
|
||||
# "already exists" failure is tolerated; on Unix the prefix is a no-op.
|
||||
MKDIR = cmd /c mkdir
|
||||
# cmd's `mkdir` errors and prints "A subdirectory or file <dir> already
|
||||
# exists." when the dir is already there, unlike Unix `mkdir -p`. Check for
|
||||
# the directory first so that expected repeats stay quiet while permission
|
||||
# and invalid-path errors keep their stderr and exit status.
|
||||
define MKDIR
|
||||
cmd /c if not exist "$(subst /,\,$(1))" mkdir "$(subst /,\,$(1))"
|
||||
endef
|
||||
CGO_PREFIX = set CGO_ENABLED=1&
|
||||
DEADCODE_ENV = set GOTOOLCHAIN=$(DEADCODE_GO_TOOLCHAIN)&
|
||||
# Cross-compile prefixes for agentctl helpers bundled with the host build.
|
||||
@@ -78,7 +81,9 @@ ifeq ($(OS)$(MSYSTEM),Windows_NT)
|
||||
else
|
||||
RM = rm -f
|
||||
RMDIR = rm -rf
|
||||
MKDIR = mkdir -p
|
||||
define MKDIR
|
||||
mkdir -p "$(1)"
|
||||
endef
|
||||
CGO_PREFIX = CGO_ENABLED=1
|
||||
DEADCODE_ENV = GOTOOLCHAIN=$(DEADCODE_GO_TOOLCHAIN)
|
||||
GO_LINUX_AMD64 = CGO_ENABLED=0 GOOS=linux GOARCH=amd64
|
||||
@@ -166,13 +171,13 @@ all: build
|
||||
## Build the preview CLI for deploying PR preview environments to Sprites
|
||||
build-preview:
|
||||
@echo "Building preview..."
|
||||
-@$(MKDIR) $(BUILD_DIR)
|
||||
@$(call MKDIR,$(BUILD_DIR))
|
||||
$(GO) build $(GOFLAGS) -ldflags "$(LDFLAGS)" -o $(BUILD_DIR)/preview$(EXE) ./cmd/preview
|
||||
|
||||
## Build the mock-agent binary for testing
|
||||
build-mock-agent:
|
||||
@echo "Building mock-agent..."
|
||||
-@$(MKDIR) $(BUILD_DIR)
|
||||
@$(call MKDIR,$(BUILD_DIR))
|
||||
$(GO) build $(GOFLAGS) -ldflags "$(LDFLAGS)" -o $(BUILD_DIR)/mock-agent$(EXE) ./cmd/mock-agent
|
||||
|
||||
## Build the winjob helper — wraps a subprocess in a Windows Job Object so
|
||||
@@ -183,7 +188,7 @@ build-mock-agent:
|
||||
## helper stays for any other consumer.
|
||||
build-winjob:
|
||||
@echo "Building winjob..."
|
||||
-@$(MKDIR) $(BUILD_DIR)
|
||||
@$(call MKDIR,$(BUILD_DIR))
|
||||
$(GO) build $(GOFLAGS) -ldflags "$(LDFLAGS)" -o $(BUILD_DIR)/winjob$(EXE) ./cmd/winjob
|
||||
|
||||
## Build and run acpdbg — usage: make acpdbg ARGS="probe auggie"
|
||||
@@ -193,7 +198,7 @@ acpdbg: build-acpdbg
|
||||
## Build the acpdbg binary — raw ACP JSON-RPC debugger (see .agents/skills/acp-debug)
|
||||
build-acpdbg:
|
||||
@echo "Building acpdbg..."
|
||||
-@$(MKDIR) $(BUILD_DIR)
|
||||
@$(call MKDIR,$(BUILD_DIR))
|
||||
$(GO) build $(GOFLAGS) -ldflags "$(LDFLAGS)" -o $(BUILD_DIR)/acpdbg$(EXE) ./cmd/acpdbg
|
||||
|
||||
## Build the complete development binary set.
|
||||
@@ -214,7 +219,7 @@ build-runtime: build-agentctl build-agentctl-remote build-kandev
|
||||
## launcher prebuild does not pull in agentctl helpers it does not use yet.
|
||||
build-kandev:
|
||||
@echo "Building $(BINARY_NAME)..."
|
||||
-@$(MKDIR) $(BUILD_DIR)
|
||||
@$(call MKDIR,$(BUILD_DIR))
|
||||
$(CGO_PREFIX) $(GO) build $(GOFLAGS) -tags fts5 -ldflags "$(LDFLAGS)" -o $(BUILD_DIR)/$(BINARY_NAME)$(EXE) ./cmd/kandev
|
||||
|
||||
## Build all binaries (unified + individual services + agentctl)
|
||||
@@ -225,7 +230,7 @@ build-all: build build-agentctl
|
||||
## Build the agentctl sidecar binary (includes embedded MCP server)
|
||||
build-agentctl:
|
||||
@echo "Building agentctl..."
|
||||
-@$(MKDIR) $(BUILD_DIR)
|
||||
@$(call MKDIR,$(BUILD_DIR))
|
||||
$(GO) build $(GOFLAGS) -ldflags "$(LDFLAGS)" -o $(BUILD_DIR)/agentctl$(EXE) ./cmd/agentctl
|
||||
|
||||
## Build only the agentctl helpers needed by the development profile.
|
||||
@@ -237,33 +242,33 @@ build-agentctl-remote: build-agentctl-linux build-agentctl-linux-arm64 build-age
|
||||
## Build agentctl for linux/amd64 (used by Docker/Sprites and Linux SSH hosts)
|
||||
build-agentctl-linux:
|
||||
@echo "Building agentctl for linux/amd64..."
|
||||
-@$(MKDIR) $(BUILD_DIR)
|
||||
@$(call MKDIR,$(BUILD_DIR))
|
||||
$(GO_LINUX_AMD64) $(GO) build $(GOFLAGS) -ldflags "$(LDFLAGS)" -o $(BUILD_DIR)/agentctl-linux-amd64 ./cmd/agentctl
|
||||
|
||||
## Build agentctl for linux/arm64 (used by ARM Linux SSH hosts, e.g. Graviton)
|
||||
build-agentctl-linux-arm64:
|
||||
@echo "Building agentctl for linux/arm64..."
|
||||
-@$(MKDIR) $(BUILD_DIR)
|
||||
@$(call MKDIR,$(BUILD_DIR))
|
||||
$(GO_LINUX_ARM64) $(GO) build $(GOFLAGS) -ldflags "$(LDFLAGS)" -o $(BUILD_DIR)/agentctl-linux-arm64 ./cmd/agentctl
|
||||
|
||||
## Build agentctl for darwin/arm64 (used by Apple Silicon SSH hosts)
|
||||
build-agentctl-darwin-arm64:
|
||||
@echo "Building agentctl for darwin/arm64..."
|
||||
-@$(MKDIR) $(BUILD_DIR)
|
||||
@$(call MKDIR,$(BUILD_DIR))
|
||||
$(GO_DARWIN_ARM64) $(GO) build $(GOFLAGS) -ldflags "$(LDFLAGS)" -o $(BUILD_DIR)/agentctl-darwin-arm64 ./cmd/agentctl
|
||||
$(call adhoc_sign_darwin,$(BUILD_DIR)/agentctl-darwin-arm64)
|
||||
|
||||
## Build agentctl for darwin/amd64 (used by Intel Mac SSH hosts)
|
||||
build-agentctl-darwin-amd64:
|
||||
@echo "Building agentctl for darwin/amd64..."
|
||||
-@$(MKDIR) $(BUILD_DIR)
|
||||
@$(call MKDIR,$(BUILD_DIR))
|
||||
$(GO_DARWIN_AMD64) $(GO) build $(GOFLAGS) -ldflags "$(LDFLAGS)" -o $(BUILD_DIR)/agentctl-darwin-amd64 ./cmd/agentctl
|
||||
$(call adhoc_sign_darwin,$(BUILD_DIR)/agentctl-darwin-amd64)
|
||||
|
||||
## Build mock-agent for linux/amd64 (used by Docker E2E tests)
|
||||
build-mock-agent-linux:
|
||||
@echo "Building mock-agent for linux/amd64..."
|
||||
@$(MKDIR) $(BUILD_DIR)
|
||||
@$(call MKDIR,$(BUILD_DIR))
|
||||
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 $(GO) build $(GOFLAGS) -ldflags "$(LDFLAGS)" -o $(BUILD_DIR)/mock-agent-linux-amd64 ./cmd/mock-agent
|
||||
|
||||
|
||||
@@ -284,7 +289,7 @@ HOST_GOARCH := $(shell $(GO) env GOARCH)
|
||||
e2e-plugin-package:
|
||||
@echo "Packaging plugin-fixture for e2e ($(HOST_GOOS)-$(HOST_GOARCH))..."
|
||||
@$(RMDIR) $(FIXTURE_STAGE_DIR)
|
||||
@$(MKDIR) $(FIXTURE_STAGE_DIR)/server
|
||||
@$(call MKDIR,$(FIXTURE_STAGE_DIR)/server)
|
||||
cp $(FIXTURE_PACKAGE_DIR)/manifest.yaml $(FIXTURE_STAGE_DIR)/manifest.yaml
|
||||
cp -r $(FIXTURE_PACKAGE_DIR)/ui $(FIXTURE_STAGE_DIR)/ui
|
||||
$(GO) build $(GOFLAGS) -o $(FIXTURE_STAGE_DIR)/server/plugin-$(HOST_GOOS)-$(HOST_GOARCH)$(EXE) ./cmd/plugin-fixture
|
||||
@@ -385,7 +390,7 @@ PROTOC_GEN_GO_GRPC_VERSION := v1.5.1
|
||||
.PHONY: proto
|
||||
proto:
|
||||
@echo "Generating proto stubs..."
|
||||
@$(MKDIR) $(PROTO_TOOLS_BIN)
|
||||
@$(call MKDIR,$(PROTO_TOOLS_BIN))
|
||||
GOBIN=$(PROTO_TOOLS_BIN) $(GO) install google.golang.org/protobuf/cmd/protoc-gen-go@$(PROTOC_GEN_GO_VERSION)
|
||||
GOBIN=$(PROTO_TOOLS_BIN) $(GO) install google.golang.org/grpc/cmd/protoc-gen-go-grpc@$(PROTOC_GEN_GO_GRPC_VERSION)
|
||||
cd proto && PATH="$(PROTO_TOOLS_BIN):$$PATH" $(GO) run github.com/bufbuild/buf/cmd/buf@$(BUF_VERSION) generate
|
||||
@@ -426,7 +431,7 @@ deps:
|
||||
## Build for multiple platforms
|
||||
build-cross:
|
||||
@echo "Building for multiple platforms..."
|
||||
-@$(MKDIR) $(BUILD_DIR)
|
||||
@$(call MKDIR,$(BUILD_DIR))
|
||||
CGO_ENABLED=1 GOOS=linux GOARCH=amd64 $(GO) build -tags fts5 -ldflags "$(LDFLAGS)" -o $(BUILD_DIR)/$(BINARY_NAME)-linux-amd64 ./cmd/kandev
|
||||
CGO_ENABLED=1 GOOS=darwin GOARCH=amd64 $(GO) build -tags fts5 -ldflags "$(LDFLAGS)" -o $(BUILD_DIR)/$(BINARY_NAME)-darwin-amd64 ./cmd/kandev
|
||||
CGO_ENABLED=1 GOOS=darwin GOARCH=arm64 $(GO) build -tags fts5 -ldflags "$(LDFLAGS)" -o $(BUILD_DIR)/$(BINARY_NAME)-darwin-arm64 ./cmd/kandev
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
# check-make-shells — assert that apps/backend/Makefile's run/dev/start-debug
|
||||
# and deadcode targets expand to the correct per-shell command line, without
|
||||
# running them.
|
||||
# building them.
|
||||
#
|
||||
# The Makefile dispatches on two independent axes:
|
||||
# * EXE suffix — keyed on $(OS): any Windows build (native cmd/PowerShell
|
||||
@@ -19,13 +19,15 @@
|
||||
# without having to run on each. The harness itself is bash (grep, sed), so it
|
||||
# needs a POSIX shell — it runs in the Linux CI job and under Git Bash/WSL
|
||||
# locally, not from native cmd.exe/PowerShell. Covers the Make-target dispatch
|
||||
# that the backend Go CI jobs don't exercise.
|
||||
# that the backend Go CI jobs don't exercise. When cmd.exe is available, the
|
||||
# script also runs an isolated mkdir probe without building any binaries.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
backend_dir="$(cd "$(dirname "$0")/../apps/backend" && pwd)"
|
||||
|
||||
status=0
|
||||
windows_mkdir_recipe=
|
||||
|
||||
# expect <label> <OS> <MSYSTEM> <target> <expected recipe tail>
|
||||
expect() {
|
||||
@@ -51,6 +53,9 @@ expect() {
|
||||
fi
|
||||
if [ "$got" = "$want" ]; then
|
||||
printf 'ok %-16s %-12s %s\n' "$label" "$target" "$got"
|
||||
if [ "$label" = windows-native ] && [ "$target" = build-kandev ]; then
|
||||
windows_mkdir_recipe="$got"
|
||||
fi
|
||||
else
|
||||
printf 'FAIL %-16s %-12s\n want: %s\n got: %s\n' \
|
||||
"$label" "$target" "$want" "$got"
|
||||
@@ -91,6 +96,56 @@ expect git-bash Windows_NT MINGW64 deadcode \
|
||||
'GOTOOLCHAIN=go1.26.0 go run golang.org/x/tools/cmd/deadcode@v0.48.0 -tags fts5 ./...' \
|
||||
'golang.org/x/tools/cmd/deadcode'
|
||||
|
||||
# mkdir — the Windows branch must check for the directory before calling cmd's
|
||||
# mkdir, so rebuilding over an existing bin/ stays quiet while other errors stay
|
||||
# visible. Unix and Git Bash use idempotent `mkdir -p`, which is silent by design.
|
||||
expect unix '' '' build-kandev 'mkdir -p "bin"' mkdir
|
||||
expect windows-native Windows_NT '' build-kandev 'cmd /c if not exist "bin" mkdir "bin"' mkdir
|
||||
expect git-bash Windows_NT MINGW64 build-kandev 'mkdir -p "bin"' mkdir
|
||||
|
||||
# When cmd.exe is available, execute the captured native-Windows recipe against
|
||||
# a temporary directory. This checks that an existing directory stays quiet.
|
||||
check_native_mkdir_behavior() {
|
||||
local recipe=$1 cmd_bin inner probe_name probe_dir stderr_file first_status
|
||||
if ! cmd_bin=$(command -v cmd.exe 2>/dev/null); then
|
||||
printf 'skip %-16s cmd.exe is not available\n' "native-mkdir"
|
||||
return
|
||||
fi
|
||||
|
||||
probe_name=".make-shell-check-$$"
|
||||
probe_dir="$backend_dir/$probe_name"
|
||||
stderr_file=$(mktemp)
|
||||
inner=${recipe#cmd /c }
|
||||
inner=${inner//bin/$probe_name}
|
||||
|
||||
rm -rf "$probe_dir"
|
||||
first_status=0
|
||||
(cd "$backend_dir" && "$cmd_bin" /c "$inner") 2>"$stderr_file" || first_status=$?
|
||||
if [ "$first_status" -ne 0 ] || [ ! -d "$probe_dir" ] || [ -s "$stderr_file" ]; then
|
||||
printf 'FAIL %-16s first mkdir did not create a quiet directory\n' "native-mkdir"
|
||||
status=1
|
||||
rm -rf "$probe_dir"
|
||||
rm -f "$stderr_file"
|
||||
return
|
||||
fi
|
||||
|
||||
: >"$stderr_file"
|
||||
(cd "$backend_dir" && "$cmd_bin" /c "$inner") 2>"$stderr_file" || true
|
||||
if [ -s "$stderr_file" ]; then
|
||||
printf 'FAIL %-16s existing directory wrote to stderr\n' "native-mkdir"
|
||||
status=1
|
||||
else
|
||||
printf 'ok %-16s existing directory stayed quiet\n' "native-mkdir"
|
||||
fi
|
||||
|
||||
rm -rf "$probe_dir"
|
||||
rm -f "$stderr_file"
|
||||
}
|
||||
|
||||
if [ -n "$windows_mkdir_recipe" ]; then
|
||||
check_native_mkdir_behavior "$windows_mkdir_recipe"
|
||||
fi
|
||||
|
||||
# Static guard: no literal /dev/null inside $(shell ...).
|
||||
#
|
||||
# Unlike a recipe, which only ever runs on a platform its target supports,
|
||||
@@ -122,6 +177,6 @@ else
|
||||
fi
|
||||
|
||||
if [ "$status" -eq 0 ]; then
|
||||
echo "All Makefile shell-dispatch checks passed (3 shells x 4 targets, plus static guard)."
|
||||
echo "All Makefile shell-dispatch checks passed (run/dev/start-debug/deadcode/build-kandev across 3 shells, plus static guard)."
|
||||
fi
|
||||
exit "$status"
|
||||
|
||||
Reference in New Issue
Block a user