Repository navigation
Expand file tree
/
Copy pathMakefile
More file actions
213 lines (176 loc) · 8.1 KB
/
Copy pathMakefile
File metadata and controls
213 lines (176 loc) · 8.1 KB
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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
#
# Makefile for crossrefapi, a Go package and command line tool.
#
# Everyday targets: build, test, test-live, install, uninstall, clean
# Release targets: generate, release, dist (see "Releasing" below)
#
# A plain `make`, `make build`, `make test` and `make install` need only git,
# make, go and pandoc. `cmt` is run only by `make generate` and by
# `make release`, never by the everyday targets, so a fresh clone builds with
# the committed version.go, CITATION.cff and installers.
#
PROJECT = crossrefapi
GIT_GROUP = caltechlibrary
PROGRAMS = $(shell ls -1 cmd)
# version.go is left out: it has a rule (cmt, under generate), and listing it
# here would make every build run cmt through that rule.
PACKAGE = $(shell ls -1 *.go | grep -v 'version.go')
MAN_PAGES = $(shell ls -1 docs/*.1.md 2>/dev/null | sed -E 's|^docs/||; s/\.1.md/.1/g')
VERSION = $(shell grep '"version":' codemeta.json | cut -d\" -f 4)
RELEASE_HASH = $(shell git log --pretty=format:'%h' -n 1)
BRANCH = $(shell git branch | grep '* ' | cut -d\ -f 2)
OS = $(shell uname)
PREFIX = $(HOME)
ifneq ($(prefix),)
PREFIX = $(prefix)
endif
EXT =
ifeq ($(OS), Windows)
EXT = .exe
endif
# One entry per release platform: name:GOOS:GOARCH
PLATFORMS = Linux-x86_64:linux:amd64 Linux-aarch64:linux:arm64 \
macOS-x86_64:darwin:amd64 macOS-arm64:darwin:arm64 \
Windows-x86_64:windows:amd64 Windows-arm64:windows:arm64
build: $(PROGRAMS) man
# Building a program also writes its manual page (the program's own -help
# output) into docs/, which is where the documentation site is built from.
$(PROGRAMS): $(PACKAGE)
@mkdir -p bin
go build -o "bin/$@$(EXT)" ./cmd/$@
@mkdir -p docs
@./bin/$@$(EXT) -help >docs/$@.1.md
# man renders each docs/NAME.1.md into man/man1/NAME.1.
man: $(MAN_PAGES)
$(MAN_PAGES): .FORCE
@mkdir -p man/man1
pandoc docs/$@.md --from markdown --to man -s >man/man1/$@
# test runs offline: vet, the Go tests (the two that call the live CrossRef API
# skip themselves unless -mailto is given) and the release script's tests.
test: .FORCE
go vet ./...
go test ./...
./release_test.bash
# test-live also calls the live CrossRef API, which asks callers to identify
# themselves. Run: make test-live MAILTO=you@example.edu
test-live: .FORCE
@if [ -z "$(MAILTO)" ]; then echo 'usage: make test-live MAILTO=you@example.edu' >&2; exit 2; fi
go test . -mailto "$(MAILTO)"
# check vets the code and lists, without changing them, files gofmt would
# reformat. Existing files are not reformatted as a side effect of other work.
check: .FORCE
go vet ./...
@UNFORMATTED="$$(gofmt -l . )"; if [ -n "$$UNFORMATTED" ]; then echo "not gofmt-formatted (left as is):"; echo "$$UNFORMATTED"; fi
# NOTE: on macOS you must use "mv" instead of "cp" to avoid problems
install: build .FORCE
@if [ ! -d $(PREFIX)/bin ]; then mkdir -p $(PREFIX)/bin; fi
@echo "Installing programs in $(PREFIX)/bin"
@for FNAME in $(PROGRAMS); do if [ -f ./bin/$$FNAME ]; then mv -v ./bin/$$FNAME $(PREFIX)/bin/$$FNAME; fi; done
@echo ""
@echo "Make sure $(PREFIX)/bin is in your PATH"
@echo ""
@if [ ! -d $(PREFIX)/man/man1 ]; then mkdir -p $(PREFIX)/man/man1; fi
@for MAN_PAGE in $(MAN_PAGES); do cp -v man/man1/$$MAN_PAGE $(PREFIX)/man/man1/;done
@echo ""
@echo "Make sure $(PREFIX)/man is in your MANPATH"
@echo ""
uninstall: .FORCE
@echo "Removing programs in $(PREFIX)/bin"
-for FNAME in $(PROGRAMS); do if [ -f $(PREFIX)/bin/$$FNAME ]; then rm -v $(PREFIX)/bin/$$FNAME; fi; done
-for MAN_PAGE in $(MAN_PAGES); do if [ -f "$(PREFIX)/man/man1/$$MAN_PAGE" ]; then rm "$(PREFIX)/man/man1/$$MAN_PAGE"; fi; done
hash: .FORCE
@git log --pretty=format:'%h' -n 1
clean: .FORCE
-if [ -d bin ]; then rm -fR bin; fi
-if [ -d dist ]; then rm -fR dist; fi
-if [ -d man ]; then rm -fR man; fi
-if [ -d testout ]; then rm -fR testout; fi
status:
git status
save:
@git commit -am "$${msg:-Quick Save}"
git push origin $(BRANCH)
refresh:
git fetch origin
git pull origin $(BRANCH)
#
# Releasing
#
# 1. Edit codemeta.json by hand: version, dateModified, releaseNotes.
# 2. make release regenerates version.go, CITATION.cff and both installers
# from codemeta.json with cmt (the only place cmt runs
# besides an explicit `make generate`), rebuilds the
# program and its manual page from that version.go, runs
# the tests, builds one zip per platform in dist/ and
# runs release-check, which stops here if anything does
# not carry the version and the hash of the commit.
# 3. ./release.bash refuses if anything beyond those files is uncommitted,
# asks for confirmation, commits and pushes the regenerated
# files ("prep for vX.Y.Z"), and creates the DRAFT GitHub
# release from dist/*.zip. Publish the draft from the
# repository's releases page (or with gh release edit).
#
# generate runs cmt over codemeta.json. Run it when the version or the
# metadata change; a plain `make` leaves the committed copies alone.
generate: version.go CITATION.cff installer.sh installer.ps1
version.go: .FORCE
cmt codemeta.json version.go
CITATION.cff: .FORCE
cmt codemeta.json CITATION.cff
installer.sh: .FORCE
cmt codemeta.json installer.sh
installer.ps1: .FORCE
cmt codemeta.json installer.ps1
# dist builds one zip per platform in PLATFORMS, starting from an empty dist/.
dist: build .FORCE
@rm -fR dist
@mkdir -p dist
@for ENTRY in $(PLATFORMS); do \
NAME=$$(echo $$ENTRY | cut -d: -f1); GOOS=$$(echo $$ENTRY | cut -d: -f2); GOARCH=$$(echo $$ENTRY | cut -d: -f3); \
SUFFIX=""; if [ "$$GOOS" = "windows" ]; then SUFFIX=".exe"; fi; \
rm -fR dist/stage; mkdir -p dist/stage/bin; \
for FNAME in $(PROGRAMS); do \
env GOOS=$$GOOS GOARCH=$$GOARCH go build -o "dist/stage/bin/$${FNAME}$$SUFFIX" ./cmd/$$FNAME || exit 1; \
done; \
cp LICENSE codemeta.json CITATION.cff README.md INSTALL.md dist/stage/; \
cp -R docs man dist/stage/; \
(cd dist/stage && zip -qr ../$(PROJECT)-v$(VERSION)-$$NAME.zip .) || exit 1; \
echo "dist/$(PROJECT)-v$(VERSION)-$$NAME.zip"; \
done
@rm -fR dist/stage
release-version: .FORCE
@$(MAKE) -B generate
# release-check stops the release unless version.go, the installers,
# CITATION.cff, the manual pages in docs/ and the zip files all carry the
# version in codemeta.json and the hash of the commit being released.
release-check: .FORCE
@HASH=$$(git log --pretty=format:%h -n 1); \
if ! grep -q 'Version = "$(VERSION)"' version.go; then \
echo "error: version.go does not carry version $(VERSION)" >&2; exit 1; fi; \
if ! grep -q "ReleaseHash = \"$$HASH\"" version.go; then \
echo "error: version.go does not carry hash $$HASH" >&2; exit 1; fi; \
if ! grep -q '^version: $(VERSION)' CITATION.cff; then \
echo "error: CITATION.cff does not carry version $(VERSION)" >&2; exit 1; fi; \
for FNAME in installer.sh installer.ps1; do \
if ! grep -q 'VERSION.*"$(VERSION)"' $$FNAME; then \
echo "error: $$FNAME does not carry version $(VERSION)" >&2; exit 1; fi; \
done; \
for FNAME in docs/*.?.md; do \
if ! head -4 $$FNAME | grep -q "version $(VERSION) $$HASH"; then \
echo "error: $$FNAME does not carry version $(VERSION) $$HASH" >&2; exit 1; fi; \
done; \
COUNT=0; \
for ENTRY in $(PLATFORMS); do \
NAME=$$(echo $$ENTRY | cut -d: -f1); ZIP=dist/$(PROJECT)-v$(VERSION)-$$NAME.zip; \
if [ ! -f $$ZIP ]; then echo "error: missing $$ZIP" >&2; exit 1; fi; \
for PAGE in $$(unzip -Z1 $$ZIP 'docs/*.?.md'); do \
if ! unzip -p $$ZIP $$PAGE | head -4 | grep -q "version $(VERSION) $$HASH"; then \
echo "error: $$ZIP $$PAGE does not carry version $(VERSION) $$HASH" >&2; exit 1; fi; \
done; \
COUNT=$$((COUNT + 1)); \
done; \
echo "release-check: version.go, CITATION.cff, installers, docs/ and $$COUNT zip files carry $(VERSION) $$HASH"
# release: see "Releasing" above. It commits nothing; release.bash does that.
release: clean release-version test dist release-check
@printf "\nrelease-check passed. Now run: ./release.bash (or ./release.bash --dry-run first)\n\n"
.FORCE: