How can you find the index of a word in a list in GNU make?

1

I want to be able to have multiple lists in make, all the same size, one of which contains filenames and the others containing info related to those files, in the same respective order. I want to be able to pass specific info for a file to a program that builds that file. For example, if X is a list of filenames (say matching % in the rule below) and Y and Z are info about those files, I'd like to be able to have a rule like this:

%.a: %.b:
    myprogram $(Y[$(*)]) $(Z[$(*)]) $< $@

where $(*) is the make variable equal to the part of the filename matched by %. Of course, variables in make can't be indexed with [].

tedtoal

Posted 2016-03-14T19:47:57.330

Reputation: 111

Answers

0

I did find this solution. The only shortcoming really is that it requires selection of a special character not present in the lists in question.

EMPTY :=
SPACE := $(EMPTY) $(EMPTY)

# Pick a non-space character that NEVER appears in any word in $S.  Here we use a comma.
XX := ,

S := This is very funny world and YOU is the funniest of all!
FIND := YOU
$(info Find $(FIND) in $(S))

S := $(XX)$(subst $(SPACE),$(XX),$(S))$(XX)
$(info S is $(S))
S := $(subst $(XX)$(FIND)$(XX),$(XX)$(FIND)$(SPACE),$(S))
$(info S is $(S))
S := $(firstword $(S))
$(info S is $(S))
S := $(subst $(XX),$(SPACE),$(S))
$(info S is $(S))
IDX = $(words $(S))
$(info IDX of $(FIND) is $(IDX))

# Combine into a giant function that can be called.
IDX = $(words $(subst $(XX),$(SPACE),$(firstword $(subst $(XX)$(2)$(XX),$(XX)$(2)$(SPACE),$(XX)$(subst $(SPACE),$(XX),$(1))$(XX)))))
$(info Index of $(FIND) is $(call IDX,$(S),$(FIND)))

# Define a function that returns the list element of the first argument that
# is at the same position as the second argument is in the third argument.
ATIDX = $(word $(call IDX,$3,$2),$1)

So the rule would look like:

%.a: %.b
    myprogram $(call, ATIDX,$(Y),$(*),$(X)) $(call ATIDX,$(Z),$(*),$(X)) $< $@ 

tedtoal

Posted 2016-03-14T19:47:57.330

Reputation: 111

Thanks for sharing. However, it does not work 100% correct. $(warning test $(call IDX,aaa bbb ccc ddd,eee)) and $(warning test $(call IDX,aaa bbb ccc ddd,ddd)) both return 4. I can provide a slightly better version that returns 5 (out of index) when the word is not fond: IDX = $(words $(subst $(XX),$(SPACE),$(firstword $(subst $(XX)$(2)$(XX),$(SPACE)$(2)$(SPACE),$(XX)IDX***DUMMY$(XX)$(subst $(SPACE),$(XX),$(1))$(XX))))) – kuga – 2018-08-22T16:04:44.910