|
| 1 | +############################################################################## |
| 2 | +# Project configuration |
| 3 | + |
| 4 | +PACKAGE := queue-sheet |
| 5 | +BINARY := $(PACKAGE) |
| 6 | +CABAL_FILE := $(PACKAGE).cabal |
| 7 | +PROJECT := $(PACKAGE)-haskell |
| 8 | + |
| 9 | +############################################################################## |
| 10 | +# Make configuration |
| 11 | + |
| 12 | +ifeq ($(origin .RECIPEPREFIX), undefined) |
| 13 | + $(error GNU Make 4.0 or later required) |
| 14 | +endif |
| 15 | +.RECIPEPREFIX := > |
| 16 | + |
| 17 | +SHELL := bash |
| 18 | +.SHELLFLAGS := -o nounset -o errexit -o pipefail -c |
| 19 | + |
| 20 | +MAKEFLAGS += --no-builtin-rules |
| 21 | +MAKEFLAGS += --warn-undefined-variables |
| 22 | + |
| 23 | +RESOLVER_ARGS := |
| 24 | +ifneq ($(origin RESOLVER), undefined) |
| 25 | + RESOLVER_ARGS := "--resolver" "$(RESOLVER)" |
| 26 | +endif |
| 27 | + |
| 28 | +STACK_YAML_ARGS := |
| 29 | +ifneq ($(origin CONFIG), undefined) |
| 30 | + STACK_YAML_ARGS := "--stack-yaml" "$(CONFIG)" |
| 31 | +endif |
| 32 | + |
| 33 | +############################################################################## |
| 34 | +# Functions |
| 35 | + |
| 36 | +define all_files |
| 37 | + find . -not -path '*/\.*' -type f |
| 38 | +endef |
| 39 | + |
| 40 | +define die |
| 41 | + (echo "error: $(1)" ; false) |
| 42 | +endef |
| 43 | + |
| 44 | +define hs_files |
| 45 | + find . -not -path '*/\.*' -type f -name '*.hs' |
| 46 | +endef |
| 47 | + |
| 48 | +############################################################################## |
| 49 | +# Rules |
| 50 | + |
| 51 | +_default: build |
| 52 | +.PHONY: _default |
| 53 | + |
| 54 | +build: |
| 55 | +> @command -v hr >/dev/null 2>&1 && hr -t || true |
| 56 | +> @stack build $(RESOLVER_ARGS) $(STACK_YAML_ARGS) |
| 57 | +.PHONY: build |
| 58 | + |
| 59 | +clean: |
| 60 | +> @stack clean |
| 61 | +.PHONY: clean |
| 62 | + |
| 63 | +clean-all: clean |
| 64 | +> @rm -rf .stack-work |
| 65 | +> @rm -rf build |
| 66 | +> @rm -f *.yaml.lock |
| 67 | +.PHONY: clean-all |
| 68 | + |
| 69 | +grep: |
| 70 | +> $(eval E:= "") |
| 71 | +> @test -n "$(E)" || $(call die,"usage: make grep E=expression") |
| 72 | +> @$(call all_files) | xargs grep -Hn '$(E)' || true |
| 73 | +.PHONY: grep |
| 74 | + |
| 75 | +help: |
| 76 | +> @echo "make build build package (default) *" |
| 77 | +> @echo "make clean clean package" |
| 78 | +> @echo "make clean-all clean package and remove artifacts" |
| 79 | +> @echo "make grep grep all non-hidden files for expression E" |
| 80 | +> @echo "make help show this help" |
| 81 | +> @echo "make hlint run hlint on all Haskell source" |
| 82 | +> @echo "make hsgrep grep all Haskell source for expression E" |
| 83 | +> @echo "make hsrecent show N most recently modified Haskell files" |
| 84 | +> @echo "make hssloc count lines of Haskell source" |
| 85 | +> @echo "make man build man page" |
| 86 | +> @echo "make recent show N most recently modified files" |
| 87 | +> @echo "make repl enter a REPL *" |
| 88 | +> @echo "make source-git create source tarball of git TREE" |
| 89 | +> @echo "make source-tar create source tarball using tar" |
| 90 | +> @echo "make test run tests, optionally for pattern P *" |
| 91 | +> @echo "make todo search for TODO items" |
| 92 | +> @echo "make version show current version" |
| 93 | +> @echo |
| 94 | +> @echo "* Use RESOLVER to specify a resolver." |
| 95 | +> @echo "* Use CONFIG to specify a Stack configuration file." |
| 96 | +.PHONY: help |
| 97 | + |
| 98 | +hlint: |
| 99 | +> @$(call hs_files) | xargs hlint |
| 100 | +.PHONY: hlint |
| 101 | + |
| 102 | +hsgrep: |
| 103 | +> $(eval E := "") |
| 104 | +> @test -n "$(E)" || $(call die,"usage: make hsgrep E=expression") |
| 105 | +> @$(call hs_files) | xargs grep -Hn '$(E)' || true |
| 106 | +.PHONY: hsgrep |
| 107 | + |
| 108 | +hsrecent: |
| 109 | +> $(eval N := "10") |
| 110 | +> @find . -not -path '*/\.*' -type f -name '*.hs' -printf '%T+ %p\n' \ |
| 111 | +> | sort --reverse \ |
| 112 | +> | head -n $(N) |
| 113 | +.PHONY: hsrecent |
| 114 | + |
| 115 | +hssloc: |
| 116 | +> @$(call hs_files) | xargs wc -l | tail -n 1 | sed 's/^ *\([0-9]*\).*$$/\1/' |
| 117 | +.PHONY: hssloc |
| 118 | + |
| 119 | +man: |
| 120 | +> $(eval VERSION := $(shell \ |
| 121 | + grep '^version:' $(CABAL_FILE) | sed 's/^version: *//')) |
| 122 | +> $(eval DATE := $(shell date --rfc-3339=date)) |
| 123 | +> @mkdir -p build |
| 124 | +> @pandoc -s -t man -o build/$(BINARY).1 \ |
| 125 | +> --variable header="$(BINARY) Manual" \ |
| 126 | +> --variable footer="$(PROJECT) $(VERSION) ($(DATE))" \ |
| 127 | +> doc/$(BINARY).1.md |
| 128 | +.PHONY: man |
| 129 | + |
| 130 | +recent: |
| 131 | +> $(eval N := "10") |
| 132 | +> @find . -not -path '*/\.*' -type f -printf '%T+ %p\n' \ |
| 133 | +> | sort --reverse \ |
| 134 | +> | head -n $(N) |
| 135 | +.PHONY: recent |
| 136 | + |
| 137 | +repl: |
| 138 | +> @stack exec ghci $(RESOLVER_ARGS) $(STACK_YAML_ARGS) |
| 139 | +.PHONY: repl |
| 140 | + |
| 141 | +source-git: |
| 142 | +> $(eval TREE := "HEAD") |
| 143 | +> $(eval BRANCH := $(shell git rev-parse --abbrev-ref $(TREE))) |
| 144 | +> @test "${BRANCH}" = "master" || echo "WARNING: Not in master branch!" >&2 |
| 145 | +> $(eval VERSION := $(shell \ |
| 146 | + grep '^version:' $(CABAL_FILE) | sed 's/^version: *//')) |
| 147 | +> @mkdir -p build |
| 148 | +> @git archive --format=tar --prefix=$(PROJECT)-$(VERSION)/ $(TREE) \ |
| 149 | +> | xz \ |
| 150 | +> > build/$(PROJECT)-$(VERSION).tar.xz |
| 151 | +.PHONY: source-git |
| 152 | + |
| 153 | +source-tar: |
| 154 | +> $(eval VERSION := $(shell \ |
| 155 | + grep '^version:' $(CABAL_FILE) | sed 's/^version: *//')) |
| 156 | +> @mkdir -p build |
| 157 | +> @sed -e 's,^/,./,' -e 's,/$$,,' .gitignore > build/.gitignore |
| 158 | +> @tar \ |
| 159 | +> --exclude-vcs \ |
| 160 | +> --exclude-ignore-recursive=build/.gitignore \ |
| 161 | +> --transform "s,^\.,$(PROJECT)-$(VERSION)," \ |
| 162 | +> -Jcf build/$(PROJECT)-$(VERSION).tar.xz \ |
| 163 | +> . |
| 164 | +> @rm -f build/.gitignore |
| 165 | +.PHONY: source-tar |
| 166 | + |
| 167 | +test: |
| 168 | +> $(eval P := "") |
| 169 | +> @command -v hr >/dev/null 2>&1 && hr -t || true |
| 170 | +> @test -z "$(P)" \ |
| 171 | +> && stack test $(RESOLVER_ARGS) $(STACK_YAML_ARGS) \ |
| 172 | +> || stack test $(RESOLVER_ARGS) $(STACK_YAML_ARGS) \ |
| 173 | +> --test-arguments '--pattern $(P)' |
| 174 | +.PHONY: test |
| 175 | + |
| 176 | +todo: |
| 177 | +> @find . -type f \ |
| 178 | +> -not -path '*/\.*' \ |
| 179 | +> -not -path './build/*' \ |
| 180 | +> -not -path './project/*' \ |
| 181 | +> -not -path ./Makefile \ |
| 182 | +> | xargs grep -Hn TODO || true |
| 183 | +.PHONY: todo |
| 184 | + |
| 185 | +version: |
| 186 | +> @grep '^version:' $(CABAL_FILE) | sed 's/^version: */$(PROJECT) /' |
| 187 | +.PHONY: version |
0 commit comments