3 ms·
If you're going to use Makefiles as a top-level build wrapper you might be interested in self-documenting targets. https://marmelab.com/blog/2016/02/29/auto-do
by sam_bristow 2y ago
If you're going to use Makefiles as a top-level build wrapper you might be interested in self-documenting targets.
https://marmelab.com/blog/2016/02/29/auto-documented-makefile.html https://marmelab.com/blog/2016/02/29/auto-documented-makefil...
- Groxx 2y agoI've been using this for a while now - it's fantastic, highly recommended for non-core-Unix-build-stuff. Just make `help` your default recipe and voila, a massive drop in people asking "how do I run tests in make" -> they probably tried to `make` already and it told them how.
- ___timor___ 2y agoGreat idea, added to my todo :)
- _benj 2y agoGreat tip! Thanks for sharing :-)
- JonChesterfield 2y agoThe punchline here is a help target that digs through your makefiles looking for comments: help: @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' I stumbled over .*? since ? usually means optional, but turns out it means lazy in this context. The $$ would be makefile escaping. Dropping the grep and changing the regex slightly, I just appended this to an overengineered makefile: # Help idea derived from https://marmelab.com/blog/2016/02/29/auto-documented-makefile.html # Prints the help-text from `target: ## help-text`, slightly reformatted and sorted .PHONY: help help: ## Write this help awk 'BEGIN {FS = ":.*#+"}; /^[a-zA-Z_*.-]+:.*## .*$$/ {printf "%-30s %s\n", $$1, $$2}' $(MAKEFILE_LIST) | sort Very nice idea, thanks for sharing it!
- konfekt 2y agoWhich make version does the latter command use? For GNU make 4.2.1 on Linux, I hade more luck with something along the lines of @awk '/^[a-zA-Z_-]+:[^#]*## .*$$/ {match($$0, /## (.*)$$/, arr); printf "\033[36m%-30s\033[0m %s\n", $$1, substr($$0, RSTART+3)}' $(MAKEFILE_LIST)
- JonChesterfield 2y agoLooks like 4.3 but I don't think it matters - awk vs gawk/nawk might be significant though, gawk 5.2 on the machine I ran this on. The match with substr is interesting. It's more complicated than setting the field separator to something like :|#+ but should mean : in the help text works. For something one only writes and debugs once, probably better to do the complicated thing that always works. gawk will write the groups to an array, that's possibly more legible (and slower? should be slower than the leading non-capture //) @gawk 'match($$0, /^([a-zA-Z_*.-]+):.*## (.*)$$/, arr) {printf " %-30s %s\n", arr[1], arr[2]}' $(MAKEFILE_LIST) | sort
- ceving 2y agoIf you can give up regexp greediness sed+column can do it: sed -rn 's/^([^:]+):.*[ ]##[ ](.+)/\1:\2/p' $(MAKEFILE_LIST) | column -ts: -l2 | sort
- JonChesterfield 2y agoSed confuses me more than awk but you're right. That would also remove the only use of awk in my makefile (sed is there already for hacking around spaces in filenames). Whitespace padding output in sed is probably horrible, column looks simpler than printf via bash or trying to use make's $info.
- defrost 2y agoWhilst acknowledging that "Confused by SED" has overlap with "have used SED for 40 years and have three books purely on SED" I can recommend https://www.grymoire.com/Unix/Sed.html https://www.grymoire.com/Unix/Sed.html as a reference some might occasionally swear by. Anyhow, sed is a marvelous utility. Unfortunately, most people never learn its real power. The language is very simple, but the documentation is terrible. The Solaris on-line manual pages for sed are five pages long, and two of those pages describe the 34 different errors you can get. A program that spends as much space documenting the errors as it does documenting the language has a serious learning curve.