# KeepOrg: build and publish entrypoint. # # Every target is a real file where it can be, so make rebuilds only what # changed. Run `make help` for the list. include versions.mk GO := go BUILD := build DIST := dist GOFLAGS := -trimpath HOSTOS := $(shell $(GO) env GOOS) HOSTARCH := $(shell $(GO) env GOARCH) GO_SRC := $(shell find . -name '*.go' -not -path './$(DIST)/*' -not -path './$(BUILD)/*') go.mod # The version stamped into a binary depends on the platform it is built for. version_for = $(strip \ $(if $(filter linux,$(1)),$(VERSION_LINUX),\ $(if $(filter darwin,$(1)),$(VERSION_MACOS),\ $(if $(filter windows,$(1)),$(VERSION_WINDOWS),\ $(if $(filter freebsd openbsd netbsd,$(1)),$(VERSION_BSD),0.0.0))))) os_of = $(word 1,$(subst -, ,$(1))) arch_of = $(word 2,$(subst -, ,$(1))) HOST_CLIENT := $(BUILD)/$(HOSTOS)-$(HOSTARCH)/keeporg HOST_SERVER := $(BUILD)/$(HOSTOS)-$(HOSTARCH)/keeporgd .DEFAULT_GOAL := help # ---------------------------------------------------------------- developing help: ## show this help @printf 'KeepOrg %s\n\n' "$(VERSION_LINUX)" @grep -hE '^[a-zA-Z0-9_%/.-]+:.*?## ' $(MAKEFILE_LIST) \ | sort | awk 'BEGIN{FS=":.*?## "}{printf " \033[1m%-22s\033[0m %s\n", $$1, $$2}' @printf '\nVersions: server %s linux %s macos %s windows %s bsd %s android %s (code %s)\n' \ "$(VERSION_SERVER)" "$(VERSION_LINUX)" "$(VERSION_MACOS)" "$(VERSION_WINDOWS)" \ "$(VERSION_BSD)" "$(VERSION_ANDROID)" "$(ANDROID_VERSION_CODE)" fmt: ## format the Go sources gofmt -w $(filter %.go,$(GO_SRC)) vet: ## run go vet $(GO) vet ./... test: ## run the whole test suite $(GO) test ./... test-race: ## run the test suite under the race detector $(GO) test -race ./... check: fmt vet test ## format, vet and test clean: ## remove build and dist output rm -rf $(BUILD) $(DIST) # ------------------------------------------------------------------ building .PHONY: all server client all: server client ## build the server and client for this host server: $(HOST_SERVER) ## build the server for this host client: $(HOST_CLIENT) ## build the desktop client for this host $(BUILD)/%/keeporg: $(GO_SRC) @mkdir -p $(dir $@) GOOS=$(call os_of,$*) GOARCH=$(call arch_of,$*) CGO_ENABLED=0 \ $(GO) build $(GOFLAGS) \ -ldflags "-s -w -X main.Version=$(call version_for,$(call os_of,$*))" \ -o $@ ./cmd/keeporg $(BUILD)/%/keeporgd: $(GO_SRC) @mkdir -p $(dir $@) GOOS=$(call os_of,$*) GOARCH=$(call arch_of,$*) CGO_ENABLED=0 \ $(GO) build $(GOFLAGS) \ -ldflags "-s -w -X main.Version=$(VERSION_SERVER)" \ -o $@ ./cmd/keeporgd $(BUILD)/windows-%/keeporg.exe: $(GO_SRC) @mkdir -p $(dir $@) GOOS=windows GOARCH=$* CGO_ENABLED=0 \ $(GO) build $(GOFLAGS) -ldflags "-s -w -X main.Version=$(VERSION_WINDOWS)" \ -o $@ ./cmd/keeporg .PHONY: cross cross: ## build every desktop and server binary cross: $(BUILD)/linux-amd64/keeporg $(BUILD)/linux-arm64/keeporg \ $(BUILD)/linux-amd64/keeporgd $(BUILD)/linux-arm64/keeporgd \ $(BUILD)/darwin-amd64/keeporg $(BUILD)/darwin-arm64/keeporg \ $(BUILD)/freebsd-amd64/keeporg $(BUILD)/freebsd-arm64/keeporg \ $(BUILD)/windows-amd64/keeporg.exe # ------------------------------------------------------------------ packaging DEB_ARCH ?= $(HOSTARCH) DEB_CLIENT := $(DIST)/keeporg_$(VERSION_LINUX)_$(DEB_ARCH).deb DEB_SERVER := $(DIST)/keeporgd_$(VERSION_SERVER)_$(DEB_ARCH).deb .PHONY: deb deb-client deb-server deb: deb-client deb-server ## build both Debian packages deb-client: $(DEB_CLIENT) ## build the client .deb deb-server: $(DEB_SERVER) ## build the server .deb $(DEB_CLIENT): $(BUILD)/linux-$(DEB_ARCH)/keeporg packaging/deb/client/control.in \ packaging/deb/client/changelog packaging/systemd/keeporg.service scripts/build-deb.sh client $(VERSION_LINUX) $(DEB_ARCH) $@ $(DEB_SERVER): $(BUILD)/linux-$(DEB_ARCH)/keeporgd packaging/deb/server/control.in \ packaging/deb/server/changelog packaging/systemd/keeporgd.service scripts/build-deb.sh server $(VERSION_SERVER) $(DEB_ARCH) $@ DMG_ARCH ?= $(HOSTARCH) DMG := $(DIST)/KeepOrg-$(VERSION_MACOS)-$(DMG_ARCH).dmg .PHONY: dmg dmg: $(DMG) ## build the macOS DMG with an /Applications symlink (macOS only) $(DMG): $(BUILD)/darwin-$(DMG_ARCH)/keeporg packaging/macos/Info.plist.in \ packaging/macos/launcher.sh packaging/macos/launch-agent.plist.in scripts/build-dmg.sh $(VERSION_MACOS) $(DMG_ARCH) $(APPID_MACOS) $@ ZIP := $(DIST)/keeporg-$(VERSION_WINDOWS)-windows-amd64.zip .PHONY: windows windows: $(ZIP) ## build the Windows zip $(ZIP): $(BUILD)/windows-amd64/keeporg.exe packaging/windows/README.txt @mkdir -p $(DIST) rm -rf $(BUILD)/windows-stage && mkdir -p $(BUILD)/windows-stage cp $(BUILD)/windows-amd64/keeporg.exe $(BUILD)/windows-stage/ cp packaging/windows/README.txt $(BUILD)/windows-stage/ cp packaging/windows/keeporg-task.xml $(BUILD)/windows-stage/ cd $(BUILD)/windows-stage && zip -q -r ../../$@ . # -------------------------------------------------------------------- android GRADLE ?= $(shell test -x android/gradlew && echo ./gradlew || echo gradle) # Gradle 8.9+ and JDK 17+ are required by the Android Gradle plugin. ANDROID_HOME ?= $(HOME)/android-sdk APK_BUILT := android/app/build/outputs/apk/release/app-release-unsigned.apk APK := $(DIST)/$(APPID_ANDROID)_$(ANDROID_VERSION_CODE).apk .PHONY: android android: $(APK) ## build the unsigned release APK under its publishing name .PHONY: android-lint android-lint: ## run Android lint; any finding fails the build cd android && ANDROID_HOME="$(ANDROID_HOME)" $(GRADLE) --no-daemon :app:lintRelease @cat android/app/build/reports/lint-results.txt $(APK): $(shell find android/app/src -type f 2>/dev/null) android/app/build.gradle.kts @test -d "$(ANDROID_HOME)/platforms" || { \ printf 'no Android SDK at %s\nset ANDROID_HOME, or see android/README.md\n' "$(ANDROID_HOME)" >&2; \ exit 1; } cd android && ANDROID_HOME="$(ANDROID_HOME)" $(GRADLE) --no-daemon assembleRelease \ -PversionName=$(VERSION_ANDROID) -PversionCode=$(ANDROID_VERSION_CODE) @mkdir -p $(DIST) cp $(APK_BUILT) $@ @printf 'built %s\n' "$@" # ------------------------------------------------------------------- container # Either engine will do; podman needs no daemon and no root. CONTAINER ?= $(shell command -v podman 2>/dev/null || command -v docker 2>/dev/null || echo docker) IMAGE ?= keeporgd IMAGE_TAG ?= $(VERSION_SERVER) # podman defaults to the OCI image format, which has no HEALTHCHECK field. IMAGE_FORMAT := $(if $(findstring podman,$(CONTAINER)),--format docker,) IMAGE_TAR := $(DIST)/keeporgd-$(VERSION_SERVER)-oci.tar .PHONY: docker docker: ## build the server container image $(CONTAINER) build $(IMAGE_FORMAT) --build-arg VERSION=$(VERSION_SERVER) \ -t $(IMAGE):$(IMAGE_TAG) -t $(IMAGE):latest . @printf 'built %s:%s\n' "$(IMAGE)" "$(IMAGE_TAG)" .PHONY: docker-run docker-run: docker ## run the image on 127.0.0.1:8765 with throwaway state $(CONTAINER) run --rm -it \ -p 127.0.0.1:8765:8765 \ -e KEEPORG_MASTER_KEY="$$(head -c 32 /dev/urandom | base64)" \ -e KEEPORG_ADMIN_PASSWORD="$${KEEPORG_ADMIN_PASSWORD:-dev-password-1}" \ $(IMAGE):$(IMAGE_TAG) -addr :8765 -data /var/lib/keeporg -url http://127.0.0.1:8765 .PHONY: docker-save docker-save: $(IMAGE_TAR) ## save the image as a tarball under dist/ $(IMAGE_TAR): docker @mkdir -p $(DIST) $(CONTAINER) save --format oci-archive -o $@ $(IMAGE):$(IMAGE_TAG) 2>/dev/null || \ $(CONTAINER) save -o $@ $(IMAGE):$(IMAGE_TAG) @printf 'saved %s\n' "$@" # --------------------------------------------------------------------- publish FDROID_HOST ?= rcmd@garage.rcmd.space FDROID_UNSIGNED ?= /var/lib/fdroid/unsigned FDROID_METADATA ?= /var/lib/fdroid/metadata .PHONY: android-publish android-publish: $(APK) ## upload the APK and metadata to the private F-Droid repo (manual) @printf 'publishing %s to %s:%s\n' "$(notdir $(APK))" "$(FDROID_HOST)" "$(FDROID_UNSIGNED)" scp $(APK) $(FDROID_HOST):$(FDROID_UNSIGNED)/ scp android/metadata/$(APPID_ANDROID).yml $(FDROID_HOST):$(FDROID_METADATA)/ @printf 'uploaded. Sign and publish on the repo host with `fdroid publish && fdroid update`.\n' .PHONY: dist dist: deb windows ## build every artifact this host can build @printf '\nartifacts in %s:\n' "$(DIST)" @ls -1 $(DIST) # -------------------------------------------------------------------- versions .PHONY: bump bump: ## bump a version: make bump PLATFORM=android PART=minor scripts/bump.sh "$(PLATFORM)" "$(PART)" .PHONY: changelog changelog: ## add a changelog entry: make changelog PKG=server MSG="what changed" scripts/changelog.sh "$(PKG)" \ "$(if $(filter server,$(PKG)),$(VERSION_SERVER),$(VERSION_LINUX))" "$(MSG)" # ------------------------------------------------------------------ local runs .PHONY: run-server run-server: $(HOST_SERVER) ## run a server on 127.0.0.1:8765 with data in ./.devdata KEEPORG_ADMIN_PASSWORD=$${KEEPORG_ADMIN_PASSWORD:-dev-password-1} \ $(HOST_SERVER) -addr 127.0.0.1:8765 -data .devdata -url http://127.0.0.1:8765 .PHONY: run-client run-client: $(HOST_CLIENT) ## run the sync agent with the local configuration $(HOST_CLIENT) run