Files

228 lines
9.6 KiB
Makefile

# ABOUTME: Build automation for Sendspin Protocol server and player
# ABOUTME: Provides targets for building, testing, and cleaning binaries
.PHONY: all build player server test test-verbose test-coverage lint clean install \
build-all build-linux build-darwin help conformance \
install-daemon uninstall-daemon \
install-player-daemon uninstall-player-daemon \
install-server-daemon uninstall-server-daemon
# Version from git tag or default
VERSION ?= $(shell git describe --tags --always --dirty 2>/dev/null || echo "dev")
LDFLAGS := -X github.com/Sendspin/sendspin-go/internal/version.Version=$(VERSION)
# Build with -tags=nolibopusfile so gopkg.in/hraban/opus.v2 doesn't link
# libopusfile. Our code never calls the opus.Stream API (the only consumer
# of the opusfile parts), so the linkage was free runtime-dependency weight.
# Override on the command line if you actually need opusfile (e.g. for
# upstream stream_test.go): make BUILDTAGS= test
BUILDTAGS ?= nolibopusfile
export GOFLAGS = -tags=$(BUILDTAGS)
# Default target
all: build
# Build both player and server
build: player server
# Build the player
player:
@echo "Building sendspin-player..."
go build -ldflags "$(LDFLAGS)" -o sendspin-player .
# Build the server
server:
@echo "Building sendspin-server..."
go build -ldflags "$(LDFLAGS)" -o sendspin-server ./cmd/sendspin-server
# Run tests
test:
@echo "Running tests..."
go test ./...
# Run tests with verbose output
test-verbose:
@echo "Running tests (verbose)..."
go test -v ./...
# Run tests with coverage
test-coverage:
@echo "Running tests with coverage..."
go test -v -race -coverprofile=coverage.out -covermode=atomic ./...
go tool cover -html=coverage.out -o coverage.html
@echo "Coverage report: coverage.html"
# Run linter
lint:
@echo "Running golangci-lint..."
@which golangci-lint > /dev/null || (echo "golangci-lint not installed. Install: https://golangci-lint.run/usage/install/" && exit 1)
golangci-lint run --timeout=5m
# Clean built binaries and artifacts
clean:
@echo "Cleaning binaries and artifacts..."
rm -f sendspin-player sendspin-server resonate-player resonate-server
rm -rf bin/
rm -f coverage.out coverage.html
# Install both binaries to GOPATH/bin
install:
@echo "Installing binaries..."
go install -ldflags "$(LDFLAGS)" .
go install -ldflags "$(LDFLAGS)" ./cmd/sendspin-server
# Build all platforms (like CI)
build-all: build-linux build-darwin
# Build Linux binaries
build-linux:
@echo "Building Linux binaries..."
@mkdir -p bin
GOOS=linux GOARCH=amd64 go build -ldflags "$(LDFLAGS)" -o bin/sendspin-player-linux-amd64 .
GOOS=linux GOARCH=arm64 go build -ldflags "$(LDFLAGS)" -o bin/sendspin-player-linux-arm64 .
GOOS=linux GOARCH=amd64 go build -ldflags "$(LDFLAGS)" -o bin/sendspin-server-linux-amd64 ./cmd/sendspin-server
GOOS=linux GOARCH=arm64 go build -ldflags "$(LDFLAGS)" -o bin/sendspin-server-linux-arm64 ./cmd/sendspin-server
# Build macOS binaries
build-darwin:
@echo "Building macOS binaries..."
@mkdir -p bin
GOOS=darwin GOARCH=amd64 go build -ldflags "$(LDFLAGS)" -o bin/sendspin-player-darwin-amd64 .
GOOS=darwin GOARCH=arm64 go build -ldflags "$(LDFLAGS)" -o bin/sendspin-player-darwin-arm64 .
GOOS=darwin GOARCH=amd64 go build -ldflags "$(LDFLAGS)" -o bin/sendspin-server-darwin-amd64 ./cmd/sendspin-server
GOOS=darwin GOARCH=arm64 go build -ldflags "$(LDFLAGS)" -o bin/sendspin-server-darwin-arm64 ./cmd/sendspin-server
# Install sendspin-player as a systemd daemon
install-player-daemon: player
@echo "Installing sendspin-player daemon..."
install -m 755 sendspin-player /usr/local/bin/sendspin-player
install -m 644 dist/systemd/sendspin-player.service /etc/systemd/system/sendspin-player.service
@if [ ! -f /etc/default/sendspin-player ]; then \
install -m 644 dist/systemd/sendspin-player.env /etc/default/sendspin-player; \
echo "Created /etc/default/sendspin-player — edit this file to configure."; \
else \
echo "/etc/default/sendspin-player already exists, not overwriting."; \
fi
@if [ ! -f /etc/sendspin/player.yaml ]; then \
install -d -m 755 /etc/sendspin; \
install -m 644 dist/config/player.example.yaml /etc/sendspin/player.yaml; \
echo "Created /etc/sendspin/player.yaml — edit this file to configure."; \
else \
echo "/etc/sendspin/player.yaml already exists, not overwriting."; \
fi
systemctl daemon-reload
@echo ""
@echo "Installed. To start:"
@echo " sudo systemctl enable --now sendspin-player"
@echo ""
@echo "Configure via /etc/sendspin/player.yaml (preferred) or /etc/default/sendspin-player"
# Install sendspin-server as a systemd daemon
install-server-daemon: server
@echo "Installing sendspin-server daemon..."
install -m 755 sendspin-server /usr/local/bin/sendspin-server
install -m 644 dist/systemd/sendspin-server.service /etc/systemd/system/sendspin-server.service
@if [ ! -f /etc/default/sendspin-server ]; then \
install -m 644 dist/systemd/sendspin-server.env /etc/default/sendspin-server; \
echo "Created /etc/default/sendspin-server — edit this file to configure."; \
else \
echo "/etc/default/sendspin-server already exists, not overwriting."; \
fi
@if [ ! -f /etc/sendspin/server.yaml ]; then \
install -d -m 755 /etc/sendspin; \
install -m 644 dist/config/server.example.yaml /etc/sendspin/server.yaml; \
echo "Created /etc/sendspin/server.yaml — edit this file to configure."; \
else \
echo "/etc/sendspin/server.yaml already exists, not overwriting."; \
fi
systemctl daemon-reload
@echo ""
@echo "Installed. To start:"
@echo " sudo systemctl enable --now sendspin-server"
@echo ""
@echo "Configure via /etc/sendspin/server.yaml (preferred) or /etc/default/sendspin-server"
# Aggregate: install both binaries as systemd daemons
install-daemon: install-player-daemon install-server-daemon
# Uninstall the sendspin-player systemd daemon
uninstall-player-daemon:
@echo "Removing sendspin-player daemon..."
-systemctl stop sendspin-player 2>/dev/null
-systemctl disable sendspin-player 2>/dev/null
rm -f /etc/systemd/system/sendspin-player.service
rm -f /usr/local/bin/sendspin-player
systemctl daemon-reload
@echo "Removed. /etc/default/sendspin-player and /etc/sendspin/player.yaml left in place (manual cleanup if desired)."
# Uninstall the sendspin-server systemd daemon
uninstall-server-daemon:
@echo "Removing sendspin-server daemon..."
-systemctl stop sendspin-server 2>/dev/null
-systemctl disable sendspin-server 2>/dev/null
rm -f /etc/systemd/system/sendspin-server.service
rm -f /usr/local/bin/sendspin-server
systemctl daemon-reload
@echo "Removed. /etc/default/sendspin-server and /etc/sendspin/server.yaml left in place (manual cleanup if desired)."
# Aggregate: uninstall both daemons
uninstall-daemon: uninstall-player-daemon uninstall-server-daemon
# Conformance test suite — runs the Sendspin protocol conformance harness
# against the local sendspin-go checkout. Mirrors what CI does so contributors
# and conformance maintainers can reproduce CI results locally.
#
# Assumes the conformance repo is checked out at ../conformance. Clones it
# (and the aiosendspin reference peer) on first run. The CONFORMANCE_REPO_SENDSPIN_GO
# env var points the harness at this checkout instead of the managed clone.
conformance:
@command -v uv >/dev/null 2>&1 || { echo "uv is required: https://docs.astral.sh/uv/getting-started/installation/"; exit 1; }
@command -v git >/dev/null 2>&1 || { echo "git is required"; exit 1; }
@if [ ! -d ../conformance ]; then \
echo "Cloning Sendspin/conformance into ../conformance..."; \
git clone --depth 1 https://github.com/Sendspin/conformance.git ../conformance; \
fi
@mkdir -p ../conformance/repos
@if [ ! -e ../conformance/repos/aiosendspin ]; then \
echo "Cloning aiosendspin reference peer..."; \
git clone --depth 1 https://github.com/Sendspin/aiosendspin.git ../conformance/repos/aiosendspin; \
fi
@if [ ! -e ../conformance/repos/sendspin-cli ]; then \
echo "Cloning sendspin-cli (supplies the FLAC test fixture)..."; \
git clone --depth 1 https://github.com/Sendspin/sendspin-cli.git ../conformance/repos/sendspin-cli; \
fi
@cd ../conformance && uv sync
@cd ../conformance && CONFORMANCE_REPO_SENDSPIN_GO="$(CURDIR)" uv run python scripts/run_all.py \
--from sendspin-go \
--to aiosendspin,sendspin-go \
--results-dir results/
@echo ""
@echo "Conformance report: $(CURDIR)/../conformance/results/index.html"
@echo "Raw results: $(CURDIR)/../conformance/results/data/"
# Show help
help:
@echo "Sendspin Protocol - Build Targets"
@echo ""
@echo " make - Build player and server"
@echo " make player - Build sendspin-player"
@echo " make server - Build sendspin-server"
@echo " make test - Run tests"
@echo " make test-verbose - Run tests with verbose output"
@echo " make test-coverage- Run tests with coverage report"
@echo " make lint - Run golangci-lint"
@echo " make clean - Remove built binaries"
@echo " make install - Install to GOPATH/bin"
@echo " make build-all - Build all platforms"
@echo " make build-linux - Build Linux binaries"
@echo " make build-darwin - Build macOS binaries"
@echo " make install-daemon - Install both player and server as systemd daemons (Linux, requires root)"
@echo " make install-player-daemon - Install only the player daemon"
@echo " make install-server-daemon - Install only the server daemon"
@echo " make uninstall-daemon - Remove both daemons"
@echo " make uninstall-player-daemon - Remove only the player daemon"
@echo " make uninstall-server-daemon - Remove only the server daemon"
@echo " make conformance - Run protocol conformance suite (clones ../conformance on first run)"
@echo ""
@echo "Version: $(VERSION)"