diff options
author | Robin Jarry <robin@jarry.cc> | 2023-08-02 21:37:25 +0200 |
---|---|---|
committer | Robin Jarry <robin@jarry.cc> | 2023-08-11 21:13:39 +0200 |
commit | d725defa07b544eef09fe17e24b6fb52255846a4 (patch) | |
tree | 98bb5e4affd86b75cc31941643fee5335153eaf3 /GNUmakefile | |
parent | 2788078187c21e1713cbb86368ea4d91b2823bae (diff) | |
download | aerc-d725defa07b544eef09fe17e24b6fb52255846a4.tar.gz |
mk: deprecate BSD make in favor of GNU make
Being portable between BSD and GNU make is a nightmare. It restricts
features to a very minimal surface and in turn requires a lot of code
duplication and manual updating of file lists.
Worse, aerc's makefile relies on the shell assignment operator (!=)
which has been supported by BSD make 2.2 since 1997 but GNU make 4.0
since 2013. Unfortunately, MacOS runs GNU make 3.8 which does not have
that feature. Reducing the feature set even more.
Stop that nonsense and remove BSD make compatibility. The majority of
aerc's users either run a GNU Linux distribution or MacOS. For those who
run any *BSD variant, it is easy for them to install GNU make (gmake) if
they don't have it installed already.
Use GNU make constructs to generate build and install rules dynamically
based on source files discovery.
GNU make will use "GNUmakefile" in priority over "Makefile" if possible.
Leverage this to display an explicit message when other flavours of make
are used. Leave a "Makefile" with a .DEFAULT: target and rename the
actual file to "GNUmakefile".
Signed-off-by: Robin Jarry <robin@jarry.cc>
Acked-by: Moritz Poldrack <moritz@poldrack.dev>
Diffstat (limited to 'GNUmakefile')
-rw-r--r-- | GNUmakefile | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/GNUmakefile b/GNUmakefile new file mode 100644 index 00000000..819ad239 --- /dev/null +++ b/GNUmakefile @@ -0,0 +1,199 @@ +# variables that can be changed by users +# +VERSION ?= `git describe --long --abbrev=12 --tags --dirty 2>/dev/null || echo 0.15.2` +PREFIX ?= /usr/local +BINDIR ?= $(PREFIX)/bin +SHAREDIR ?= $(PREFIX)/share/aerc +LIBEXECDIR ?= $(PREFIX)/libexec/aerc +MANDIR ?= $(PREFIX)/share/man +GO ?= go +GOFLAGS ?= `contrib/goflags.sh` +BUILD_OPTS ?= -trimpath +GO_LDFLAGS := +GO_LDFLAGS += -X main.Version=$(VERSION) +GO_LDFLAGS += -X main.Flags=$$(echo -- $(GOFLAGS) | base64 | tr -d '\r\n') +GO_LDFLAGS += -X git.sr.ht/~rjarry/aerc/config.shareDir=$(SHAREDIR) +GO_LDFLAGS += -X git.sr.ht/~rjarry/aerc/config.libexecDir=$(LIBEXECDIR) +GO_LDFLAGS += $(GO_EXTRA_LDFLAGS) +CC ?= cc +CFLAGS ?= -O2 -g + +# internal variables used for automatic rules generation with macros +gosrc = $(shell find * -type f -name '*.go') go.mod go.sum +man1 = $(subst .scd,,$(notdir $(wildcard doc/*.1.scd))) +man5 = $(subst .scd,,$(notdir $(wildcard doc/*.5.scd))) +man7 = $(subst .scd,,$(notdir $(wildcard doc/*.7.scd))) +docs = $(man1) $(man5) $(man7) +cfilters = $(subst .c,,$(notdir $(wildcard filters/*.c))) +filters = $(filter-out filters/vectors filters/test.sh filters/%.c,$(wildcard filters/*)) +gofumpt_tag = v0.5.0 + +# Dependencies are added dynamically to the "all" rule with macros +.PHONY: all +all: aerc + @: + +aerc: $(gosrc) + $(GO) build $(BUILD_OPTS) $(GOFLAGS) -ldflags "$(GO_LDFLAGS)" -o aerc + +.PHONY: dev +dev: + $(RM) aerc + $(MAKE) --no-print-directory aerc BUILD_OPTS="-trimpath -race" + GORACE="log_path=race.log strip_path_prefix=git.sr.ht/~rjarry/aerc/" ./aerc + +.PHONY: fmt +fmt: + $(GO) run mvdan.cc/gofumpt@$(gofumpt_tag) -w . + +linters.so: contrib/linters.go + $(GO) build -buildmode=plugin -o linters.so contrib/linters.go + +.PHONY: lint +lint: linters.so + @contrib/check-whitespace `git ls-files ':!:filters/vectors'` && \ + echo white space ok. + @$(GO) run mvdan.cc/gofumpt@$(gofumpt_tag) -d . | grep ^ \ + && echo The above files need to be formatted, please run make fmt && exit 1 \ + || echo all files formatted. + $(GO) run github.com/golangci/golangci-lint/cmd/golangci-lint@v1.51.2 run \ + $$(echo $(GOFLAGS) | sed s/-tags=/--build-tags=/) + +.PHONY: vulncheck +vulncheck: + $(GO) run golang.org/x/vuln/cmd/govulncheck@latest ./... + +.PHONY: tests +tests: $(cfilters) + $(GO) test $(GOFLAGS) ./... + filters/test.sh + +.PHONY: debug +debug: aerc.debug + @echo 'Run `./aerc.debug` and use this command in another terminal to attach a debugger:' + @echo ' dlv attach $$(pidof aerc.debug)' + +aerc.debug: $(gosrc) + $(GO) build $(GOFLAGS) -gcflags=*=-N -gcflags=*=-l -ldflags="$(GO_LDFLAGS)" -o aerc.debug + +.PHONY: doc +doc: $(docs) + @: + +.PHONY: clean +clean: + $(RM) $(docs) aerc $(cfilters) + +# Dependencies are added dynamically to the "install" rule with macros +.PHONY: install +install: + @: + +.PHONY: checkinstall +checkinstall: + $(DESTDIR)$(BINDIR)/aerc -v + for m in $(man1); do test -e $(DESTDIR)$(MANDIR)/man1/$$m || exit; done + for m in $(man5); do test -e $(DESTDIR)$(MANDIR)/man5/$$m || exit; done + for m in $(man7); do test -e $(DESTDIR)$(MANDIR)/man7/$$m || exit; done + +.PHONY: uninstall +uninstall: + @echo $(installed) | tr ' ' '\n' | sort -ru | while read -r f; do \ + echo rm -f $$f && rm -f $$f || exit; \ + done + @echo $(dirs) | tr ' ' '\n' | sort -ru | while read -r d; do \ + if [ -d $$d ] && ! ls -Aq1 $$d | grep -q .; then \ + echo rm $$d && rmdir $$d || exit; \ + fi; \ + done + +.PHONY: gitconfig +gitconfig: + git config format.subjectPrefix "PATCH aerc" + git config sendemail.to "~rjarry/aerc-devel@lists.sr.ht" + @mkdir -p .git/hooks + @rm -f .git/hooks/sendemail-validate* + @if grep -q GIT_SENDEMAIL_FILE_COUNTER `git --exec-path`/git-send-email 2>/dev/null; then \ + ln -svf ../../contrib/sendemail-validate .git/hooks/sendemail-validate && \ + git config sendemail.validate true; \ + fi + +.PHONY: check-patches +check-patches: + @contrib/check-patches origin/master.. + +# Generate build and install rules for one man page +# +# $1: man page name (e.g: aerc.1) +# +define install_man +$1: doc/$1.scd + scdoc < $$< > $$@ + +$1_section = $$(subst .,,$$(suffix $1)) +$1_install_dir = $$(DESTDIR)$$(MANDIR)/man$$($1_section) +dirs += $$($1_install_dir) +installed += $$($1_install_dir)/$1 + +$$($1_install_dir)/$1: $1 | $$($1_install_dir) + install -m644 $$< $$@ + +all: $1 +install: $$($1_install_dir)/$1 +endef + +# Generate build and install rules for one filter +# +# $1: filter source path or name +# +define install_filter +ifneq ($(wildcard filters/$1.c),) +$1: filters/$1.c + $$(CC) $$(CFLAGS) $$(LDFLAGS) -o $$@ $$< + +all: $1 +endif + +$1_install_dir = $$(DESTDIR)$$(LIBEXECDIR)/filters +dirs += $$($1_install_dir) +installed += $$($1_install_dir)/$$(notdir $1) + +$$($1_install_dir)/$$(notdir $1): $1 | $$($1_install_dir) + install -m755 $$< $$@ + +install: $$($1_install_dir)/$$(notdir $1) +endef + +# Generate install rules for any file +# +# $1: source file +# $2: mode +# $3: target dir +# +define install_file +dirs += $3 +installed += $3/$$(notdir $1) + +$3/$$(notdir $1): $1 | $3 + install -m$2 $$< $$@ + +install: $3/$$(notdir $1) +endef + +# Call macros to generate build and install rules +$(foreach m,$(docs),\ + $(eval $(call install_man,$m))) +$(foreach f,$(filters) $(cfilters),\ + $(eval $(call install_filter,$f))) +$(foreach f,$(wildcard config/*.conf),\ + $(eval $(call install_file,$f,644,$(DESTDIR)$(SHAREDIR)))) +$(foreach s,$(wildcard stylesets/*),\ + $(eval $(call install_file,$s,644,$(DESTDIR)$(SHAREDIR)/stylesets))) +$(foreach t,$(wildcard templates/*),\ + $(eval $(call install_file,$t,644,$(DESTDIR)$(SHAREDIR)/templates))) +$(eval $(call install_file,contrib/aerc.desktop,644,$(DESTDIR)$(PREFIX)/share/applications)) +$(eval $(call install_file,aerc,755,$(DESTDIR)$(BINDIR))) +$(eval $(call install_file,contrib/carddav-query,755,$(DESTDIR)$(BINDIR))) + +$(sort $(dirs)): + mkdir -p $@ |