Looks like they're using make as way to much of a programming language instead of the IMO much better declarative approach, way too many loops and function calls rather than dependencies. I'm not sure but it also looks like it's building too many things instead of different build for different configurations.
I dunno, I've never seen a readable Makefile in any system above say 300 files. If you could write readable declarative Makefiles getting the job done, would there be autotools? This is not to say that autotools get the job done beautifully, just that their existence demonstrates how the problem gets us all contort violently to terrible effect like a wounded animal screaming and running into trees.
I admit that I despise make and maybe I don't get the beauty (I get the beauty of the idea but I've never seen it result in actual beautiful Makefiles), and maybe if you linked to what you consider a good open source Makefile, we could discuss this in more concrete terms.
> I dunno, I've never seen a readable Makefile in any system above say 300 files.
The build complexity should be a reflection of the project complexity, not the number of source files. Having to run in multiple environments and separating things into libraries would add complexity for instance, adding a new source file shouldn't. When you start adding calls and loops however, that complexity grows exponentially instead of linearly. This isn't make specific.
> I admit that I despise make and maybe I don't get the beauty (I get the beauty of the idea but I've never seen it result in actual beautiful Makefiles), and maybe if you linked to what you consider a good open source Makefile, we could discuss this in more concrete terms.
Here is one I put together (http://flukus.github.io/2016/11/30/2016_11_30_Rediscovering-...), I tried to make it somewhat real world but there are obviously many caveats, it's dealing with c# (easier to build), dependencies come via nuget, but I think it shows the idea.
The most common anti-pattern I see (again, not just in make) is thinking that there has to be one build that does everything, it will iterate over target OS's and/or environments and produce a build for each one for instance. It's much cleaner to have the OS/environment be one or more parameters and to execute the build script multiple times with the desired parameters.
Developers have a tendency to not realize build scripts are a seperate discipline worth learning.
You use $(shell) and sed in there which I don't think is much different from $(foreach), and perhaps it's gnarlier. Perhaps my counterpoint is "a build system is a program using a library/framework for scheduling work based on dependencies" and make's insistence on builds being about the dependency graph and delegating programming to shell commands and afterthoughts like $foreach, plus its very painful evaluation model with unclear order make for a terrible programming environment.
A big difference is that using sed is producing a single known output that is clearly evident, it's much less clear what all the loops and calls is producing, it may even be an example of premature abstraction.
I don't think relying on shell commands is a bad thing though, it's just part of the unix philosophy, every build tool in existence will call external programs like the compiler itself. I doubt you could find another build tool that can replace values as simply as sed. The shell command would actually be unnecessary on newer versions of make.
Well, I guess I agree with Rob Pike in that the "tools doing one job and doing it well philosophy is dead and the eulogy was delivered by Perl." I think you should write build rules in a programming language and a programming language is something that doesn't make you upgrade to a new version to avoid shelling out to find. Let's agree to disagree :-)
Yes, the Makefiles were an abomination. Nobody could understand them. The reason the makefiles are so heavily macroized like they are is because of cross-compile bootstrapping, where the build rules are the same in many configurations, with slight differences. Effectively, large swaths of the makefiles were parameterized over 4 different values.
Sincere question - why not use autotools? It's a lot easier writing a Makefile.am declaring the parts of the project and having platform specific stuff handled by autoconf.
I find autotools very complex and bloated, but it tends to make builds for different platforms, cross compilation, dependency checking and other tasks easy for me. It's often easier than dealing with (g)make directly IMHO.
The answer here is probably "bootstrapped compilers are hard". Rust compiles itself thrice in a typical compile (most devs do fewer stages when hacking), and the makefile needs to distinguish between these, and it gets more complex while cross compiling where your host/target change halfway through the process. So it's quite possible that it's easier to make work in pure make.