Show HN: One makefile to rule them all(gist.github.com) |
Show HN: One makefile to rule them all(gist.github.com) |
- $(RM), $(CP), $(MKDIR) and $(ECHO) are unnecessary - these variables are for programs that are not portable. These 4 are some of the few portable ones.
- It only builds and installs a single executable (without extension), no library, no headers
- The install target does not honour DESTDIR, but distributors can get away with prepending it to PREFIX. For programs that use the PREFIX at build time, thats not okay.
Makefile portability is hard. Take this makefile and try to build on FreeBSD or cross-compiling for Windows (where executables have a suffix). Or cross-compiling in general.
.DEFAULT_GOAL = help
.PHONY: help
##@ HELP
help: ## display this help
@awk 'BEGIN {FS = ":.*##"; \
printf "\033[1mUSAGE\n\033[0m make \033[36m<TARGET>\033[0m\n"} \
/^[a-zA-Z_-]+\.*[a-zA-Z]*:.*?##/ {printf " \033[36m%-12s\033[0m %s\n", $$1, $$2} \
/^##@/ {printf "\n\033[1m%s\033[0m\n", substr($$0, 5)} \
/^###/ {printf "\033[0m\t\t %s\033[0m\n", substr($$0, 4)}' $(MAKEFILE_LIST)
.PHONY: foo bar baz
##@ DEMO
foo: bar ## foo target
### additional foo target details
@echo foo
bar: ## bar target
@echo bar
baz: ## baz target
@echo baz https://gist.github.com/prwhite/8168133
My favorite is (since it only depends on a recent bash): SHELL:=/bin/bash
.PHONY: help help_target-funky+names.0k and_with_2_targets_and_spaces_like_bison
help_target-funky+names.0k and_with_2_targets_and_spaces_like_bison: ## Funky ones & bison dual target display ok
echo "bad - why are you not displaying?"
help: ## bash help
help: ## moar bash help
@RE='^[a-zA-Z0-9 ._+-]*:[a-zA-Z0-9 ._+-]*##' ; while read line ; do [[ "$$line" =~ $$RE ]] && echo "$$line" ; done <$(MAKEFILE_LIST) ; RE=''https://git.suckless.org/dmenu/file/Makefile.html
https://git.suckless.org/sprop/file/Makefile.html
with file rule variables (my name for them, `OBJ = ${SRC:.c=.o}`).
include $(shell find $(BUILD_DIR) -type f -name '\*.d')
so that make will check for header file changes. SRC = $(wildcard src/\*.c)
OBJ = $(SRC:.c=.o)
SDEPS = $(SRC:.c=.d)
EXE = myapp
INC = include
CFLAGS ?= -Os -MMD -MP
LDFLAGS ?=
%.o: %.c $(INC) Makefile
$(CC) $(CFLAGS) -c $< -o $@
$(EXE): $(OBJ)
$(LD) $^ $(LDFLAGS) -o $@
# near the bottom of your Makefile
-include $(SDEPS)Some things seem hardcoded and some things are not, e.g. $LANG specifies the file extension (not language) of the input files, but the assumption is that each of these files winds up as a .o, so there's some tweaking required for your projects.
In all seriousness, it would be amazing if make could somehow detect the docker state.