Subject: Re: [PATCH] Makefile: dedup git-ls-files output to prevent duplicate targets

From: Junio C Hamano <[email-masked]>
Date: Wed, 25 May 2022 21:02:57 -0700

Jiang Xin <[email-masked]> writes:

> From: Jiang Xin <[email-masked]>
>
> If there are unresolved conflicts left in the working tree, "make" may
> report warnings as follows:
>
>     Makefile:xxxx: target '.build/pot/po/FOO.c.po' given more than once
>                    in the same rule
>
> The duplicate targets are introduced by the following pattern rule we
> added in the preceding commit for incremental build of "po/git.pot",
>
>     $(LOCALIZED_C_GEN_PO): .build/pot/po/%.po: %
>
> and the duplicate entries in $(LOCALIZED_C_GEN_PO) come from the
> "git ls-files" command in SOURCES_CMD.
>
> We can pass the option "--deduplicate" to git-ls-files to suppress
> duplicate entries for unresolved conflicts.

Thanks for a quick response.

We certainly can say "your SOURCES_CMD MUST NOT produce duplicates"
and passing the --deduplicate option is one valid way to fix this
specific case.

But I wonder if a more future-proof solution is to dedup the output
of the SOURCES_CMD ourselves on the Makefile side.  That way, even
if we update SOURCES_CMD in a way that could contain duplicates, we
won't have to worry about duplicates.

---

It feels way overkill to "sort" the list just to dedup its elements,
but that is what GNU Make documentation info page recommends us to
do, and we already do use it for deduplication in our Makefile
twice.

'$(sort LIST)'
     Sorts the words of LIST in lexical order, removing duplicate words.
     The output is a list of words separated by single spaces.  Thus,

          $(sort foo bar lose)

     returns the value 'bar foo lose'.

     Incidentally, since 'sort' removes duplicate words, you can use it
     for this purpose even if you don't care about the sort order.

diff --git i/Makefile w/Makefile
index 2b61f66259..1d3d3deba1 100644
--- i/Makefile
+++ w/Makefile
@@ -860,7 +860,7 @@ SOURCES_CMD = ( \
 		-o \( -name '*.sh' -type f -print \) \
 		| sed -e 's|^\./||' \
 	)
-FOUND_SOURCE_FILES := $(shell $(SOURCES_CMD))
+FOUND_SOURCE_FILES := $(sort $(shell $(SOURCES_CMD)))
 
 FOUND_C_SOURCES = $(filter %.c,$(FOUND_SOURCE_FILES))
 FOUND_H_SOURCES = $(filter %.h,$(FOUND_SOURCE_FILES))