makefile: remove duplicate words without sorting

Boring $eval based method:

define uniq =
  $(eval seen :=)
  $(foreach _,$1,$(if $(filter $_,${seen}),,$(eval seen += $_)))
  ${seen}
endef

w := z z x x y c x

$(info $(sort $w))
$(info $(call uniq,$w))

Extremely fiendish make standard library recursive call (recursive make considered extremely fiendish?):

uniq = $(if $1,$(firstword $1) $(call uniq,$(filter-out $(firstword $1),$1)))

It's worth noting that no variables are damaged in this second formulation (see seen in the first). It is preferable just for that (given the lack of locals in make)!

EDIT

My obscure comment about recursive make above seems to have muddied the waters somewhat. "Recursive" in the context of this post means recursive function. It really has nothing to do with the execrable recursive make.

The latter (recursive) definition of uniq is extremely nice, performant, small, and is definitely the one to use.


You could echo the words through awk:

echo foo bar foo baz bar | tr ' ' '\n' | awk '!a[$0]++'

Deduping one-liner taken from catonmat.

(Don't forget to double the $ to $$ in a Makefile.)


Depends on where you need it and whether you use GNU make. If you just want to uniq the list of target prerequisites, it's as easy as (http://www.gnu.org/software/make/manual/make.html#Quick-Reference) :

The value of $^ omits duplicate prerequisites, while $+ retains them and preserves their order.

So, a rule like

exe: $(OBJS)
        $(LD) -o $@ $^

will filter duplicates from $(OBJS) automagically, while still leaving order of other items the same.

Tags:

Makefile