On 2021-01-25, Zack Weinberg <zackw@xxxxxxxxx> wrote: > I'm not at all familiar with Automake's internals, but the reason I > suggested taking advantage of GNU make extensions was the potential > for _complexity_ reduction of the generated Makefile, not performance. > For instance, this generated rule from one of my other projects [...] To be honest if Automake-generated Makefile.in files only worked for users with, say, sufficiently modern versions of GNU Make, I'm not sure there would be any point in using Automake. GNU make is expressive enough to implement pretty much every useful feature of Automake directly as makefile rules. So for sure, it might be useful to have an includable snippet or something that makes it easier to correctly implement the various targets specified by the GNU Coding Standards, and it might be useful to keep things like the "compile" and "install-sh" scripts presently bundled with Automake, but I think the result would no longer really be Automake. The whole reason I use Automake is because implementing conceptually simple things like per-target CFLAGS is a pain in the butt without make features such as target-specific variables. Automatic dependency generation is a pain without "-include". Maintaining separate lists of object and source files is a pain. Suffix rules are limited in their expressiveness. All of that pain goes away if a package can depend on GNU make. Why would anyone bother with Automake then? In most cases it'd be easier, simpler and more flexible to just write compilation rules by hand, and I think the more involved cases would be better handled by copy+paste boilerplate examples or includable snippets than with a discrete build tool like Automake. When I can assume every user is going to be using GNU make (unreleased stuff mostly), I never bother with Automake. As GNU Emacs was mentioned as a package requiring GNU make, I notice that they do not appear to use Automake either. > Automake _does_ make heavy use of shell constructs embedded inside > frequently-executed rules, for instance > > .c.o: > $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ > $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ > $(am__mv) $$depbase.Tpo $$depbase.Po > > which looks like it could become > > %.o: %.c > $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(@D)/$(DEPDIR)/$(*F).Tpo \ > -c -o $@ $< > $(AM_V_at)$(am__mv) $(@D)/$(DEPDIR)/$(*F).Tpo $(@D)/$(DEPDIR)/$(*F).Po > > and enable Make to bypass the shell altogether. Might be worth > benchmarking on a big program. Has to be an executable, not a > library, though; for libraries, the overhead of the libtool script is > going to dominate. I would like to mention that, if a change like this is a perfomance win, it is almost certainly possible to get the performance benefit without sacrificing correct operation on other makes. In particular, the $(@D), $(@F), and $(*F) variables are specified by POSIX and are widely portable. The only portability problem I am aware of is this one related to the D-suffixed variables, involving a rather obscure make implementation, and is often not a significant problem in practice (for example, writing ./$(@D) instead is typically sufficient to avoid problems due to this issue). % : >baz.c % cat >Makefile <<'EOF' foo.o: foo/bar.c baz.o @echo target=$@ directory=$(@D) file=$(@F) foo/bar.c: @echo target=$@ directory=$(@D) file=$(@F) .c.o: @echo stem=$* directory=$(*D) file=$(*F) EOF % gmake --version GNU Make 4.3 Built for x86_64-pc-linux-gnu Copyright (C) 1988-2020 Free Software Foundation, Inc. [...] % gmake target=foo/bar.c directory=foo file=bar.c stem=baz directory=. file=baz target=foo.o directory=. file=foo.o % dmake -V dmake - Version 4.12 (x86_64-pc-linux-gnu) Copyright (c) 1990,...,1997 by WTI Corp. % dmake target=foo/bar.c directory=foo/ file=bar.c stem=baz directory= file=baz target=foo.o directory= file=foo.o Cheers, Nick