Calling ResumeBackend on a backend that wasn't actually paused (state != StatePaused) would overwrite w.cancel and spawn a fresh probe goroutine without cancelling the old one, leaving two probe loops running for the same backend until process exit. The guard now mirrors EnableBackend's early-return on a non-target state.
278 lines
13 KiB
Makefile
278 lines
13 KiB
Makefile
BINARIES := maglevd maglevc maglevd-frontend maglevt
|
|
MODULE := git.ipng.ch/ipng/vpp-maglev
|
|
PROTO_DIR := proto
|
|
PROTO_FILE := $(PROTO_DIR)/maglev.proto
|
|
GEN_FILES := internal/grpcapi/maglev.pb.go internal/grpcapi/maglev_grpc.pb.go
|
|
|
|
# Web bundle is built by Vite and embedded by the Go binary via //go:embed.
|
|
# Any change under cmd/frontend/web/src/ retriggers an npm build; the
|
|
# generated cmd/frontend/web/dist/index.html is the sentinel.
|
|
FRONTEND_WEB_SRC := $(shell find cmd/frontend/web/src -type f 2>/dev/null) \
|
|
cmd/frontend/web/index.html \
|
|
cmd/frontend/web/package.json \
|
|
cmd/frontend/web/vite.config.ts \
|
|
cmd/frontend/web/tsconfig.json
|
|
FRONTEND_WEB_DIST := cmd/frontend/web/dist/index.html
|
|
|
|
NATIVE_ARCH := $(shell go env GOARCH)
|
|
VERSION := 1.0.2
|
|
COMMIT_HASH := $(shell git rev-parse --short HEAD 2>/dev/null || echo unknown)
|
|
DATE := $(shell date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
LDFLAGS := -X '$(MODULE)/cmd.version=$(VERSION)' \
|
|
-X '$(MODULE)/cmd.commit=$(COMMIT_HASH)' \
|
|
-X '$(MODULE)/cmd.date=$(DATE)'
|
|
|
|
# CGO_ENABLED=0 produces fully static binaries: no libc dependency, so the
|
|
# debian package runs on any Linux-amd64/arm64 host regardless of glibc
|
|
# version (or musl). The only behavioural change is that Go's net package
|
|
# uses the pure-Go resolver instead of libc's getaddrinfo, which skips
|
|
# /etc/nsswitch.conf and NSS modules — fine for DNS-only lookups, which is
|
|
# all maglevd does. govpp has no cgo (its binapi is hand-marshalled Go
|
|
# structs) so this has no effect on multi-VPP-version compatibility.
|
|
export CGO_ENABLED := 0
|
|
|
|
TEST ?= tests/
|
|
|
|
VPP_API_DIR ?= $(HOME)/src/vpp/build-root/install-vpp_debug-native/vpp/share/vpp/api
|
|
|
|
# GO_VERSION is what install-deps-go downloads from go.dev when the
|
|
# system Go is missing or older than this. Debian Trixie only ships
|
|
# golang-go 1.24 (main), and go.mod requires 1.25+, so the `apt install
|
|
# golang-go` path isn't sufficient — we fall back to the upstream
|
|
# tarball in /usr/local/go. Override on the command line to pull a
|
|
# specific patch release: make install-deps GO_VERSION=1.25.5
|
|
GO_VERSION ?= 1.25.0
|
|
|
|
# GOLANGCI_LINT_VERSION is the minimum golangci-lint version that
|
|
# install-deps-go-tools accepts. Raised to 1.64.0 because earlier
|
|
# releases don't understand Go 1.25 syntax (1.64 is the last v1 line
|
|
# and shipped Go 1.25 support; any v2.x release satisfies the floor
|
|
# trivially via version sort). install-deps-go-tools always `go
|
|
# install`s @latest, then asserts the resulting binary reports a
|
|
# version >= this floor as a sanity check. Override on the command
|
|
# line if you want to force a specific minimum, e.g.
|
|
# make install-deps GOLANGCI_LINT_VERSION=2.0.0
|
|
GOLANGCI_LINT_VERSION ?= 1.64.0
|
|
|
|
.PHONY: all build build-amd64 build-arm64 test proto vpp-binapi lint fixstyle fixstyle-web pkg-deb docker docker-push robot-test clean maglevd-frontend-web install-deps install-deps-apt install-deps-go install-deps-go-tools
|
|
|
|
all: build
|
|
|
|
build: $(GEN_FILES) $(FRONTEND_WEB_DIST)
|
|
mkdir -p build/$(NATIVE_ARCH)
|
|
go build -ldflags "$(LDFLAGS)" -o build/$(NATIVE_ARCH)/maglevd ./cmd/server/
|
|
go build -ldflags "$(LDFLAGS)" -o build/$(NATIVE_ARCH)/maglevc ./cmd/client/
|
|
go build -ldflags "$(LDFLAGS)" -o build/$(NATIVE_ARCH)/maglevd-frontend ./cmd/frontend/
|
|
go build -ldflags "$(LDFLAGS)" -o build/$(NATIVE_ARCH)/maglevt ./cmd/tester/
|
|
|
|
build-amd64: $(GEN_FILES) $(FRONTEND_WEB_DIST)
|
|
mkdir -p build/amd64
|
|
GOOS=linux GOARCH=amd64 go build -ldflags "$(LDFLAGS)" -o build/amd64/maglevd ./cmd/server/
|
|
GOOS=linux GOARCH=amd64 go build -ldflags "$(LDFLAGS)" -o build/amd64/maglevc ./cmd/client/
|
|
GOOS=linux GOARCH=amd64 go build -ldflags "$(LDFLAGS)" -o build/amd64/maglevd-frontend ./cmd/frontend/
|
|
GOOS=linux GOARCH=amd64 go build -ldflags "$(LDFLAGS)" -o build/amd64/maglevt ./cmd/tester/
|
|
|
|
build-arm64: $(GEN_FILES) $(FRONTEND_WEB_DIST)
|
|
mkdir -p build/arm64
|
|
GOOS=linux GOARCH=arm64 go build -ldflags "$(LDFLAGS)" -o build/arm64/maglevd ./cmd/server/
|
|
GOOS=linux GOARCH=arm64 go build -ldflags "$(LDFLAGS)" -o build/arm64/maglevc ./cmd/client/
|
|
GOOS=linux GOARCH=arm64 go build -ldflags "$(LDFLAGS)" -o build/arm64/maglevd-frontend ./cmd/frontend/
|
|
GOOS=linux GOARCH=arm64 go build -ldflags "$(LDFLAGS)" -o build/arm64/maglevt ./cmd/tester/
|
|
|
|
# maglevd-frontend-web rebuilds the SolidJS bundle. The Go binary embeds the
|
|
# resulting cmd/frontend/web/dist/ via //go:embed, so a `go build` after
|
|
# this target picks up any asset changes automatically.
|
|
maglevd-frontend-web: $(FRONTEND_WEB_DIST)
|
|
|
|
$(FRONTEND_WEB_DIST): $(FRONTEND_WEB_SRC)
|
|
cd cmd/frontend/web && npm install && npm run build
|
|
|
|
pkg-deb: build-amd64 build-arm64
|
|
debian/build-deb.sh vpp-maglevd amd64 $(VERSION)
|
|
debian/build-deb.sh vpp-maglevd arm64 $(VERSION)
|
|
debian/build-deb.sh vpp-maglev amd64 $(VERSION)
|
|
debian/build-deb.sh vpp-maglev arm64 $(VERSION)
|
|
|
|
# docker — build both container images for the current host arch and
|
|
# load them into the local docker daemon. Uses buildx so the Dockerfile
|
|
# can cross-compile via $TARGETARCH; --load only supports a single
|
|
# platform, so this target is for local smoke tests. Use docker-push
|
|
# for a true multi-arch manifest. Each image is tagged both :v$(VERSION)
|
|
# and :latest in one build, so bumping VERSION is the only change
|
|
# needed to cut a new release — no hand-edited tag lists to forget.
|
|
docker:
|
|
docker buildx build --load --target maglevd -t git.ipng.ch/ipng/vpp-maglevd:v$(VERSION) -t git.ipng.ch/ipng/vpp-maglevd:latest .
|
|
docker buildx build --load --target frontend -t git.ipng.ch/ipng/vpp-maglevd-frontend:v$(VERSION) -t git.ipng.ch/ipng/vpp-maglevd-frontend:latest .
|
|
|
|
# docker-push — build a multi-arch (linux/amd64,linux/arm64) manifest
|
|
# for both images and push it straight to the registry, tagged both
|
|
# :v$(VERSION) and :latest. Buildx won't --load a multi-platform
|
|
# result into the local daemon, so push is the only way to
|
|
# materialise the combined manifest. Assumes the caller is already
|
|
# logged in to git.ipng.ch.
|
|
docker-push:
|
|
docker buildx build --platform linux/amd64,linux/arm64 --push --target maglevd -t git.ipng.ch/ipng/vpp-maglevd:v$(VERSION) -t git.ipng.ch/ipng/vpp-maglevd:latest .
|
|
docker buildx build --platform linux/amd64,linux/arm64 --push --target frontend -t git.ipng.ch/ipng/vpp-maglevd-frontend:v$(VERSION) -t git.ipng.ch/ipng/vpp-maglevd-frontend:latest .
|
|
|
|
test: $(GEN_FILES)
|
|
go test ./...
|
|
|
|
proto: $(GEN_FILES)
|
|
|
|
$(GEN_FILES): $(PROTO_FILE)
|
|
protoc \
|
|
--go_out=. --go_opt=module=$(MODULE) \
|
|
--go-grpc_out=. --go-grpc_opt=module=$(MODULE) \
|
|
$(PROTO_FILE)
|
|
|
|
# vpp-binapi regenerates the Go bindings for VPP API files used by maglevd
|
|
# from a local VPP build. The LB plugin ships with upstream VPP; any newer
|
|
# messages (e.g. lb_conf_get, lb_as_v2_dump) require a VPP build that has
|
|
# them. Override VPP_API_DIR on the command line to point at another tree:
|
|
# make vpp-binapi VPP_API_DIR=/path/to/share/vpp/api
|
|
vpp-binapi:
|
|
@command -v binapi-generator >/dev/null 2>&1 || { \
|
|
echo "installing binapi-generator..."; \
|
|
go install go.fd.io/govpp/cmd/binapi-generator@v0.12.0; \
|
|
}
|
|
rm -rf internal/vpp/binapi
|
|
mkdir -p internal/vpp/binapi
|
|
binapi-generator \
|
|
--input=$(VPP_API_DIR) \
|
|
--output-dir=internal/vpp/binapi \
|
|
--import-prefix=$(MODULE)/internal/vpp/binapi \
|
|
--no-source-path-info \
|
|
--no-version-info \
|
|
lb lb_types
|
|
rm -f internal/vpp/binapi/lb/lb_rpc.ba.go
|
|
|
|
fixstyle: fixstyle-web
|
|
gofmt -w .
|
|
|
|
fixstyle-web:
|
|
cd cmd/frontend/web && npx prettier --write .
|
|
|
|
lint:
|
|
golangci-lint run ./...
|
|
|
|
# install-deps is an opt-in "set up a fresh developer box" target. Tested
|
|
# on Debian Trixie; the apt half should also work on Bookworm and recent
|
|
# Ubuntu LTS. Splits into three sub-targets so they can be run individually:
|
|
#
|
|
# install-deps-apt — Debian-packaged build-time deps (nodejs, npm,
|
|
# protoc, git, make, dpkg-dev, curl).
|
|
# install-deps-go — ensure a Go toolchain >= $(GO_VERSION) is on
|
|
# the system. Downloads the upstream tarball
|
|
# into /usr/local/go when the system Go is
|
|
# missing or older than the go.mod floor.
|
|
# install-deps-go-tools — `go install` the helpers this repo needs
|
|
# (protoc-gen-go, protoc-gen-go-grpc, golangci-
|
|
# lint) and assert golangci-lint is new enough
|
|
# to understand Go 1.25 syntax.
|
|
#
|
|
# Each sub-target is idempotent and safe to re-run.
|
|
install-deps: install-deps-apt install-deps-go install-deps-go-tools
|
|
@echo ""
|
|
@echo "==> All build dependencies installed."
|
|
@echo " Make sure these are on PATH:"
|
|
@echo " /usr/local/go/bin (Go toolchain)"
|
|
@echo " \$$(go env GOPATH)/bin (protoc-gen-go, golangci-lint, ...)"
|
|
|
|
install-deps-apt:
|
|
@set -eu; \
|
|
if [ "$$(id -u)" = 0 ]; then SUDO=""; else SUDO="sudo"; fi; \
|
|
echo "==> Installing apt packages (nodejs, npm, protoc, git, make, dpkg-dev)"; \
|
|
$$SUDO apt-get update; \
|
|
$$SUDO apt-get install -y --no-install-recommends \
|
|
nodejs npm protobuf-compiler git make dpkg-dev \
|
|
ca-certificates curl tar
|
|
|
|
# install-deps-go short-circuits when go env GOVERSION already reports a
|
|
# version >= GO_VERSION. Otherwise it downloads the official upstream
|
|
# tarball (https://go.dev/dl/) and extracts it to /usr/local/go, matching
|
|
# the layout that go.dev recommends and that most Debian setups use for
|
|
# "Go newer than apt provides".
|
|
install-deps-go:
|
|
@set -eu; \
|
|
if [ "$$(id -u)" = 0 ]; then SUDO=""; else SUDO="sudo"; fi; \
|
|
echo "==> Checking Go toolchain (required: $(GO_VERSION)+)"; \
|
|
if command -v go >/dev/null 2>&1; then \
|
|
CURRENT=$$(go env GOVERSION 2>/dev/null | sed 's/^go//'); \
|
|
OLDEST=$$(printf '%s\n%s\n' "$(GO_VERSION)" "$$CURRENT" | sort -V | head -n1); \
|
|
if [ "$$OLDEST" = "$(GO_VERSION)" ] && [ -n "$$CURRENT" ]; then \
|
|
echo " go$$CURRENT already installed (>= $(GO_VERSION)), skipping."; \
|
|
exit 0; \
|
|
fi; \
|
|
echo " go$$CURRENT is older than $(GO_VERSION), upgrading."; \
|
|
else \
|
|
echo " no Go toolchain on PATH, installing."; \
|
|
fi; \
|
|
DEB_ARCH=$$(dpkg --print-architecture); \
|
|
case "$$DEB_ARCH" in \
|
|
amd64) GOARCH=amd64 ;; \
|
|
arm64) GOARCH=arm64 ;; \
|
|
armhf) GOARCH=armv6l ;; \
|
|
*) echo " unsupported architecture: $$DEB_ARCH" >&2; exit 1 ;; \
|
|
esac; \
|
|
TARBALL="go$(GO_VERSION).linux-$$GOARCH.tar.gz"; \
|
|
URL="https://go.dev/dl/$$TARBALL"; \
|
|
echo " downloading $$URL"; \
|
|
curl -fsSL -o "/tmp/$$TARBALL" "$$URL"; \
|
|
echo " installing to /usr/local/go"; \
|
|
$$SUDO rm -rf /usr/local/go; \
|
|
$$SUDO tar -C /usr/local -xzf "/tmp/$$TARBALL"; \
|
|
rm -f "/tmp/$$TARBALL"; \
|
|
echo " installed $$(/usr/local/go/bin/go version)"
|
|
|
|
# install-deps-go-tools installs the three Go binaries this repo calls
|
|
# out to during `make proto` and `make lint`. protoc-gen-go and
|
|
# protoc-gen-go-grpc pin to specific upstream release branches; golangci-
|
|
# lint pulls @latest (the v2 install path) and then we assert the
|
|
# installed version parses as >= GOLANGCI_LINT_VERSION so a stale binary
|
|
# in $GOPATH/bin from a previous dev session doesn't silently get used
|
|
# against Go 1.25 code it can't parse. Run `make install-deps
|
|
# GOLANGCI_LINT_VERSION=2.0.0` if you want to enforce a tighter floor.
|
|
install-deps-go-tools:
|
|
@set -eu; \
|
|
if ! command -v go >/dev/null 2>&1; then \
|
|
export PATH="/usr/local/go/bin:$$PATH"; \
|
|
fi; \
|
|
echo "==> Installing Go tools via 'go install'"; \
|
|
echo " google.golang.org/protobuf/cmd/protoc-gen-go"; \
|
|
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest; \
|
|
echo " google.golang.org/grpc/cmd/protoc-gen-go-grpc"; \
|
|
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest; \
|
|
echo " github.com/golangci/golangci-lint/v2/cmd/golangci-lint"; \
|
|
go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@latest; \
|
|
GOBIN="$$(go env GOBIN)"; \
|
|
if [ -z "$$GOBIN" ]; then GOBIN="$$(go env GOPATH)/bin"; fi; \
|
|
echo "==> Asserting golangci-lint version >= $(GOLANGCI_LINT_VERSION)"; \
|
|
if ! "$$GOBIN/golangci-lint" version >/dev/null 2>&1; then \
|
|
echo " ERROR: $$GOBIN/golangci-lint is not executable" >&2; \
|
|
exit 1; \
|
|
fi; \
|
|
INSTALLED=$$("$$GOBIN/golangci-lint" version 2>&1 | sed -En 's/.*has version v?([0-9][0-9.]*).*/\1/p' | head -n1); \
|
|
if [ -z "$$INSTALLED" ]; then \
|
|
echo " ERROR: could not parse golangci-lint version output" >&2; \
|
|
"$$GOBIN/golangci-lint" version >&2; \
|
|
exit 1; \
|
|
fi; \
|
|
OLDEST=$$(printf '%s\n%s\n' "$(GOLANGCI_LINT_VERSION)" "$$INSTALLED" | sort -V | head -n1); \
|
|
if [ "$$OLDEST" != "$(GOLANGCI_LINT_VERSION)" ]; then \
|
|
echo " ERROR: golangci-lint $$INSTALLED is older than the required $(GOLANGCI_LINT_VERSION)" >&2; \
|
|
echo " The tool understands Go 1.25 syntax only from v1.64.0 / v2.x onward." >&2; \
|
|
exit 1; \
|
|
fi; \
|
|
echo " golangci-lint $$INSTALLED (>= $(GOLANGCI_LINT_VERSION)) OK"
|
|
|
|
tests/.venv: tests/requirements.txt
|
|
python3 -m venv tests/.venv
|
|
tests/.venv/bin/pip install -q -r tests/requirements.txt
|
|
|
|
robot-test: build tests/.venv
|
|
tests/rf-run.sh docker $(TEST)
|
|
|
|
clean:
|
|
rm -rf build/
|
|
rm -f $(GEN_FILES)
|