bugmake - Bugs: bug #64339, $(filter) and $(filter-out)...


bug #64339: $(filter) and $(filter-out) interpret "match" in surprising ways

Submitter:  Eli Zaretskii <eliz>
Submitted:  Thu 22 Jun 2023 07:07:13 PM UTC
Severity:  3 - Normal Item Group:  Documentation
Status:  Fixed Privacy:  Public
Assigned to:  psmith Open/Closed:  Closed
Component Version:  SCM Operating System:  Any
Fixed Release:  SCM Triage Status:  Small Effort
* Mandatory Fields

Add a New Comment Rich Markup

Sun 07 Jan 2024 03:25:10 PM UTC, comment #2: 

I updated the documentation, thanks Eli.

Paul D. Smith <psmith>
Group administrator
Thu 22 Jun 2023 07:15:54 PM UTC, comment #1: 

I believe that the use of PATTERN here is intended to make you understand that it's the same matching rules as with pattern rules or other uses of patterns, such as the patsubst function; patterns that don't contain a "%" always require the entire word to match identically, everywhere in GNU Make.

However it's not an excuse: definitely the docs could be more clear here.

Paul D. Smith <psmith>
Group administrator
Thu 22 Jun 2023 07:07:13 PM UTC, original submission:  

The GNU Make Manual says:

'$(filter-out PATTERN...,TEXT)'
     Returns all whitespace-separated words in TEXT that do not match
     any of the PATTERN words, removing the words that do match one or
     more.  This is the exact opposite of the 'filter' function.

     For example, given:

          objects=main1.o foo.o main2.o bar.o
          mains=main1.o main2.o

     the following generates a list which contains all the object files
     not in 'mains':

          $(filter-out $(mains),$(objects))

Note that the text doesn't really say what it means to "match" in this context, nor what exactly is PATTERN. The example might make you believe the "match" means "substring". That is A "matches" B if A is some substring of B. But this is not the case. Observe:

$ make -f-
ORIG=foo123 bar-xyz baz-yes
EXCLUDE=bar foo
        @echo "$(filter-out $(EXCLUDE),$(ORIG))"
=> foo123 bar-xyz baz-yes

That is, "foo123" does NOT match "foo", and "bar-xyz" does NOT match "bar". The following does work, though:

$ make -f-
ORIG=./foo ./bar ./baz
EXCLUDE=%bar %foo
        @echo "$(filter-out $(EXCLUDE),$(ORIG))"
=> ./baz

So now we perhaps understand that PATTERN is something that includes the % wildcard somewhere. This should be explained in the manual, and the manual should also somehow justify the special case of exact string equality, in which case the % wildcard is not required.

IOW, having the exact string equality as the only example in this case is misleading and confusing. I learned this the hard way, having just spent an hour debugging my Makefile where $(filter-out) didn't do its job, because I thought "./foo" should match "foo", based on what the manual says.

Eli Zaretskii <eliz>
Group Member


(Note: upload size limit is set to 16384 kB, after insertion of the required escape characters.)

Attach Files:

No files currently attached


Depends on the following items: None found

Items that depend on this one: None found


Carbon-Copy List
  • -email is unavailable- added by psmith (Posted a comment)
  • -email is unavailable- added by eliz (Submitted the item)

    There are 0 votes so far. Votes easily highlight which items people would like to see resolved in priority, independently of the priority of the item set by tracker managers.

    Only logged-in users can vote.


    Follow 6 latest changes.

    Date Changed by Updated Field Previous Value => Replaced by
    2024-01-07 psmith StatusNone Fixed
        Assigned toNone psmith
        Open/ClosedOpen Closed
        Fixed ReleaseNone SCM
        Triage StatusNone Small Effort
    2024-01-07 psmith Item GroupNone Documentation

    Back to the top

    Powered by Savane 3.12.
    Corresponding source code