Subject: Re: [PATCH v2 4/8] Makefile: move ".SUFFIXES" rule to shared.mak

From: Ævar Arnfjörð Bjarmason <[email-masked]>
Date: Tue, 22 Feb 2022 12:14:57 +0100

On Mon, Feb 21 2022, Taylor Blau wrote:

> On Fri, Dec 24, 2021 at 06:37:43PM +0100, Ævar Arnfjörð Bjarmason wrote:
>>     $ git -c hyperfine.hook.setup= hyperfine -L rev HEAD~1,HEAD~0 -s 'make -C Documentation man' 'make -C Documentation -j1 man'
>>     Benchmark 1: make -C Documentation -j1 man' in 'HEAD~1
>>       Time (mean ± σ):     121.7 ms ±   8.8 ms    [User: 105.8 ms, System: 18.6 ms]
>>       Range (min … max):   112.8 ms … 148.4 ms    26 runs
>>
>>     Benchmark 2: make -C Documentation -j1 man' in 'HEAD~0
>>       Time (mean ± σ):      97.5 ms ±   8.0 ms    [User: 80.1 ms, System: 20.1 ms]
>>       Range (min … max):    89.8 ms … 111.8 ms    32 runs
>>
>>     Summary
>>       'make -C Documentation -j1 man' in 'HEAD~0' ran
>>         1.25 ± 0.14 times faster than 'make -C Documentation -j1 man' in 'HEAD~1'
>
> Nice speed-up. Though I am not sure I totally understand where it comes
> from ;). Reading 30248886ce8 and the documentation on .SUFFIXES from
> [1], I am still unclear. I guess removing the obsolete built-in suffix
> rules gives make less work to do in general?

I'll update the commit message, but basically the same applies as for
2/8 here (<[email-masked]>),
or if you run "make" with "--debug=a". I.e. if before/after this change you do:

    git clean -dxf; make -C Documentation/ --debug=a git-status.1 >/tmp/b 2>&1
    git clean -dxf; make -C Documentation/ --debug=a git-status.1 >/tmp/a 2>&1

You'll get:
    
    $ wc -l /tmp/[ba]
       6515 /tmp/a
     144051 /tmp/b
     150566 total

Which e.g. for "git-status.txt" starts with (I cut a lot out, there's
way more than this just for that file):
    
          Considering target file 'git-status.txt'.
           Looking for an implicit rule for 'git-status.txt'.
    -      Trying pattern rule with stem 'git-status.txt'.
    -      Trying implicit prerequisite 'git-status.txt.o'.
    -      Trying pattern rule with stem 'git-status.txt'.
    -      Trying implicit prerequisite 'git-status.txt.c'.
    -      Trying pattern rule with stem 'git-status.txt'.
    -      Trying implicit prerequisite 'git-status.txt.cc'.
    -      Trying pattern rule with stem 'git-status.txt'.
    -      Trying implicit prerequisite 'git-status.txt.C'.
    -      Trying pattern rule with stem 'git-status.txt'.
    -      Trying implicit prerequisite 'git-status.txt.cpp'.
    -      Trying pattern rule with stem 'git-status.txt'.
    -      Trying implicit prerequisite 'git-status.txt.p'.
    -      Trying pattern rule with stem 'git-status.txt'.
    -      Trying implicit prerequisite 'git-status.txt.f'.
    -      Trying pattern rule with stem 'git-status.txt'.
    -      Trying implicit prerequisite 'git-status.txt.F'.
    -      Trying pattern rule with stem 'git-status.txt'.
    -      Trying implicit prerequisite 'git-status.txt.m'.
    -      Trying pattern rule with stem 'git-status.txt'.
    -      Trying implicit prerequisite 'git-status.txt.r'.
    -      Trying pattern rule with stem 'git-status.txt'.
    -      Trying implicit prerequisite 'git-status.txt.s'.
    -      Trying pattern rule with stem 'git-status.txt'.
    -      Trying implicit prerequisite 'git-status.txt.S'.
    -      Trying pattern rule with stem 'git-status.txt'.
    -      Trying implicit prerequisite 'git-status.txt.mod'.
    -      Trying pattern rule with stem 'git-status.txt'.
    -      Trying implicit prerequisite 'git-status.txt.sh'.
    -      Trying pattern rule with stem 'git-status.txt'.
    -      Trying implicit prerequisite 'git-status.txt.o'.
    [...]

I.e. given a foo.txt "make" by default will exhaustively consider foo
foo.txt.c, foo.txt.cpp etc. etc.

This is all ultimately a part of make's implicit rule
mechanism. I.e. even if you have no Makefile at all you can run "make
main" if you have a main.c in your directory, and it'll discover it and
compile it with implicit rules, unless you explicitl disable them,
e.g. with "-r":
    
    $ rm Makefile hello; make hello
    rm: cannot remove 'Makefile': No such file or directory
    rm: cannot remove 'hello': No such file or directory
    cc   hello.o   -o hello
    $ rm Makefile hello; make -r hello
    rm: cannot remove 'Makefile': No such file or directory
    make: *** No rule to make target 'hello'.  Stop.

> So long as we're not depending on any of these, this seems like a nice
> little boost to me.

Yes, definitely!

>> diff --git a/shared.mak b/shared.mak
>> index 29f0e69ecb9..155ac84f867 100644
>> --- a/shared.mak
>> +++ b/shared.mak
>> @@ -9,6 +9,11 @@
>>  %:: s.%
>>  %:: SCCS/s.%
>>
>> +## Likewise delete default $(SUFFIXES). See:
>> +##
>> +##     info make --index-search=.DELETE_ON_ERROR
>> +.SUFFIXES:
>
> Hmm. s/DELETE_ON_ERROR/SUFFIXES? Or perhaps I'm holding this whole thing
> incorrectly:
>
>     ~/s/git [nand] (ab/make-noop) $ info make --index-search=.DELETE_ON_ERROR
>     no index entries found for '.DELETE_ON_ERROR'
>     ~/s/git [nand] (ab/make-noop) $ info make --index-search=.SUFFIXES
>     no index entries found for '.SUFFIXES'

Yes that's a copy/paste error, it should be .SUFFIXES.

But both commands should work, or emit an error like:

    $ info doesnotexist --index-search=.DELETE_ON_ERROR
    info: No menu item 'doesnotexist' in node '(dir)Top'

A broken OS package? Self-built "make"?

In any case I could also link to
https://www.gnu.org/software/make/manual/html_node/Suffix-Rules.html;
which is the same information online (but may not match your local
"make" version)>