Live data from Hacker News

How I stopped worrying and loved Makefiles

gagor.pro

61–70 of 144 posts

Re: How I stopped worrying and loved Makefiles

#62
post #21

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-makefil...

I'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.

Great idea, added to my todo :)

Re: How I stopped worrying and loved Makefiles

#63

I'd love some minor tweak of Make to compare/cache with hashes instead of mtime. A worse-is-better Bazel if you will.

This might be worth building into the makefile interpreter. Doing it in the makefiles themselves is quite difficult to get right and very messy.

Re: How I stopped worrying and loved Makefiles

#64

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-makefil...

The 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…

Which 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)

Re: How I stopped worrying and loved Makefiles

#65
post #52

Earlier quoted context omitted.

Thats only really a problem for C/C++, which I have had the misfortune to make build systems for. The solution is not to ship complicated and bug infested build systems, it is to fix the dependency problem in the same way any other language has done so far and until we do this, ship the dependencies with the program. And if you aren't making a GUI and don't need to target Windows, just wrap it in Docker, which enforc…

> Thats only really a problem for C/C++ Even if that would be true, still every language that isn't C (or JS in the browser) needs to link or build against some C (or Fortran), which results in more or less working solutions on how to integrate with or build C sources. Of course you may not see that (as long as it works), because somebody else has wrapped that up in a package (or whatever) for your language of choice…

>But any other language than C or C++ (sadly, _way_ less than "any other") solves that by using a complicated and bug infested build system(s) and package manager(s) or a combination of both.

Which would go away if C++ had a working package manager, that worked in the same way every other language did, was written once only and about as bug free as the compiler. This would also allow you to ship the source code for the library with a simple file that list the dependencies you need.

I guess my final issue boils down to this: CMake does too much and too little. It is too hard to get it reliably pull down the libraries I want to use and it can do too much as part of the build to the point that it becomes too complicated.

Do one thing, and do it well.

Re: How I stopped worrying and loved Makefiles

#66
post #65

Earlier quoted context omitted.

> Thats only really a problem for C/C++ Even if that would be true, still every language that isn't C (or JS in the browser) needs to link or build against some C (or Fortran), which results in more or less working solutions on how to integrate with or build C sources. Of course you may not see that (as long as it works), because somebody else has wrapped that up in a package (or whatever) for your language of choice…

>But any other language than C or C++ (sadly, _way_ less than "any other") solves that by using a complicated and bug infested build system(s) and package manager(s) or a combination of both. Which would go away if C++ had a working package manager, that worked in the same way every other language did, was written once only and about as bug free as the compiler. This would also allow you to ship the source code for t…

Oh, please don't get me wrong, I hate CMake and Autotools (I'm not sure which is worse). And both Vcpkg and Conan have their own problems.

Re: How I stopped worrying and loved Makefiles

#67

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-makefil...

The 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…

If you can give up regexp greediness sed+column can do it:

    sed -rn 's/^([^:]+):.*[ ]##[ ](.+)/\1:\2/p' $(MAKEFILE_LIST) | column -ts: -l2 | sort

Re: How I stopped worrying and loved Makefiles

#68
post #64

Earlier quoted context omitted.

The 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…

Which 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)

Looks 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

Re: How I stopped worrying and loved Makefiles

#69
post #67

Earlier quoted context omitted.

The 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…

If you can give up regexp greediness sed+column can do it: sed -rn 's/^([^:]+):.*[ ]##[ ](.+)/\1:\2/p' $(MAKEFILE_LIST) | column -ts: -l2 | sort

Sed 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.

Re: How I stopped worrying and loved Makefiles

#70
post #67

Earlier quoted context omitted.

If you can give up regexp greediness sed+column can do it: sed -rn 's/^([^:]+):.*[ ]##[ ](.+)/\1:\2/p' $(MAKEFILE_LIST) | column -ts: -l2 | sort

Sed 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.

Whilst 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

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.
Post reply on HN