summaryrefslogtreecommitdiff
path: root/Makefile
blob: 62e2b7ecbbf0cb7b15377956539f99446837d9c5 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# SPDX-License-Identifier: GPL-3.0-or-later
# Works with GNU make and BSD make.

DESTDIR ?=
PREFIX  ?= $(HOME)/.local
BINDIR   = $(DESTDIR)$(PREFIX)/bin
SHAREDIR = $(DESTDIR)$(PREFIX)/share
MANDIR   = $(SHAREDIR)/man
DOCDIR   = $(SHAREDIR)/doc/krino
BIN      = krino
VERSION != git describe --tags --always --dirty 2>/dev/null || echo dev
LDFLAGS  = -s -w -X main.version=$(VERSION)
CROSS_PLATFORMS = linux/amd64 linux/arm64 freebsd/amd64 openbsd/amd64

.PHONY: all help build install uninstall test vet fmt lint ci bench cross dist release deps install-hooks clean

all: build

help: ## show this help
	@grep -E '^[a-z-]+:.*## ' Makefile | \
	  awk 'BEGIN {FS = ":.*## "}; {printf "  %-10s %s\n", $$1, $$2}'
	@echo "  version: $(VERSION)   prefix: $(PREFIX)"

build: ## build ./krino; Go fetches module dependencies itself; reports missing optional extractors
	CGO_ENABLED=0 go build -trimpath -ldflags "$(LDFLAGS)" -o $(BIN) ./cmd/krino
	@missing=""; \
	for t in pdftotext antiword catdoc xls2csv catppt; do \
	  command -v "$$t" >/dev/null 2>&1 || missing="$$missing $$t"; \
	done; \
	if [ -n "$$missing" ]; then \
	  echo "optional extractors not found:$$missing (needed for some content rules; run 'make deps' or install by hand)"; \
	else \
	  echo "all optional extractors found: pdftotext antiword catdoc xls2csv catppt"; \
	fi

install: build ## install binary, man pages and examples under $(PREFIX)
	mkdir -p $(BINDIR) $(MANDIR)/man1 $(MANDIR)/man5 $(DOCDIR)/examples
	rm -f $(BINDIR)/$(BIN)
	install -m 755 $(BIN) $(BINDIR)/$(BIN)
	install -m 644 man/krino.1 $(MANDIR)/man1/krino.1
	install -m 644 man/krino.conf.5 $(MANDIR)/man5/krino.conf.5
	install -m 644 examples/*.conf $(DOCDIR)/examples/
	install -m 644 docs/sexp-primer.md $(DOCDIR)/sexp-primer.md

uninstall: ## remove everything install placed, and nothing else
	rm -f $(BINDIR)/$(BIN)
	rm -f $(MANDIR)/man1/krino.1
	rm -f $(MANDIR)/man5/krino.conf.5
	rm -f $(DOCDIR)/sexp-primer.md
	for f in examples/*.conf; do \
	  rm -f $(DOCDIR)/examples/$$(basename "$$f"); \
	done
	-rmdir $(DOCDIR)/examples $(DOCDIR) 2>/dev/null

test: ## run the tests
	go test ./...

vet: ## go vet
	go vet ./...

fmt: ## gofmt the tree
	gofmt -w .

lint: ## lint the man pages
	scripts/man-lint

ci: ## the gate: gofmt, vet, tests, dependencies, no personal data staged, man page lint
	@test -z "$$(gofmt -l .)" || { echo "gofmt needed:"; gofmt -l .; exit 1; }
	go vet ./...
	GOOS=freebsd CGO_ENABLED=0 go vet ./...
	GOOS=openbsd CGO_ENABLED=0 go vet ./...
	go test ./...
	@deps=$$(go list -deps ./... | grep -E '^[a-z0-9-]+\.[a-z]+/' | grep -vE '^golang\.org/x/(term|text|sys)(/|$$)' || true); \
	  test -z "$$deps" || { echo "unexpected dependencies:"; echo "$$deps"; exit 1; }
	@scripts/leak-check
	@scripts/man-lint
	@echo "ci ok"

bench: ## run the Go benchmarks on generated trees
	go test -run '^$$' -bench . -benchmem ./...

cross: ## cross-compile linux/amd64, linux/arm64, freebsd/amd64, openbsd/amd64 into dist/krino-$(VERSION)-<os>-<arch>/
	@case '$(VERSION)' in \
	  ''|*[!A-Za-z0-9._+-]*) \
	    echo "refusing: VERSION must contain only letters, digits, and the characters . - _ +" >&2; \
	    exit 1 ;; \
	esac
	@for t in $(CROSS_PLATFORMS); do \
	  os=$${t%/*}; arch=$${t#*/}; \
	  dir=dist/krino-$(VERSION)-$$os-$$arch; \
	  case "$$dir" in \
	    dist/krino-*) rm -rf "$$dir" ;; \
	    *) echo "refusing to remove unexpected path: $$dir" >&2; exit 1 ;; \
	  esac; \
	  mkdir -p "$$dir"; \
	  echo "cross: $$os/$$arch -> $$dir/$(BIN)"; \
	  CGO_ENABLED=0 GOOS=$$os GOARCH=$$arch go build -trimpath -ldflags "$(LDFLAGS)" -o "$$dir/$(BIN)" ./cmd/krino || exit 1; \
	  for f in README.md LICENSE CHANGELOG.md man/krino.1 man/krino.conf.5 docs/sexp-primer.md; do \
	    test -f "$$f" && cp "$$f" "$$dir/$$(basename "$$f")"; \
	  done; \
	  test -d examples && cp -r examples "$$dir/examples"; \
	done

# dist: cross plus tarballs and SHA256SUMS, no tag. Undocumented plumbing so
# `make release` is verifiable without tagging; deliberately absent from
# `make help` (no `## ` comment).
dist: cross
	@command -v sha256sum >/dev/null 2>&1 && SUM=sha256sum || SUM="sha256 -r"; \
	  tarballs=""; \
	  cd dist && \
	  for t in $(CROSS_PLATFORMS); do \
	    os=$${t%/*}; arch=$${t#*/}; \
	    name=krino-$(VERSION)-$$os-$$arch; \
	    tar czf "$$name.tar.gz" "$$name" || exit 1; \
	    tarballs="$$tarballs $$name.tar.gz"; \
	  done && \
	  $$SUM $$tarballs > SHA256SUMS

release: ## make cross + tarballs + SHA256SUMS in dist/, then tag v$(VERSION) (annotated; never pushes) - usage: make release VERSION=0.0.1
	@case '$(VERSION)' in \
	  ''|*[!A-Za-z0-9._+-]*) \
	    echo "refusing: VERSION must contain only letters, digits, and the characters . - _ +" >&2; \
	    exit 1 ;; \
	esac
	@default_version=$$(git describe --tags --always --dirty 2>/dev/null || echo dev); \
	  test -n "$(VERSION)" && test "$(VERSION)" != "$$default_version" || \
	  { echo "refusing: pass an explicit VERSION, e.g. make release VERSION=0.0.1"; exit 1; }
	@test -z "$$(git status --porcelain)" || \
	  { echo "refusing: working tree is not clean (git status --porcelain)"; exit 1; }
	@git rev-parse -q --verify refs/tags/v$(VERSION) >/dev/null 2>&1 && \
	  { echo "refusing: tag v$(VERSION) already exists"; exit 1; } || true
	@test -f README.md || \
	  { echo "refusing: README.md is missing"; exit 1; }
	$(MAKE) ci
	$(MAKE) dist VERSION=$(VERSION)
	git tag -a "v$(VERSION)" -m "krino v$(VERSION)"
	@echo "release v$(VERSION) built in dist/; tag v$(VERSION) created, not pushed"

deps: ## install the optional content extractors; may ask for privileges
	scripts/deps

install-hooks: ## install the pre-commit hook that runs the leak check
	install -m 755 scripts/hooks/pre-commit "$$(git rev-parse --git-path hooks)/pre-commit"

clean: ## remove build output
	rm -f $(BIN)