Question Details

No question body available.

Tags

arrays bash makefile

Answers (2)

May 29, 2025 Score: 2 Rep: 30,828 Quality: Medium Completeness: 60%

Make expands the recipes once, just before passing the result to the shell. So, the recipe of your first attempt:

run:
    for m in 1 2 3 ; do \
        echo Info : MONTH = ${MONTH[$${m}]}; \
        echo Info : DATE  = ${DATE[$${m}]}; \
    done

Expands as:

for m in 1 2 3 ; do echo Info : MONTH = ; echo Info : DATE  = ; done

because there are no make variables named MONTH[${m}] or DATE[${m}]. The recipe of your second attempt:

run:
    for m in 1 2 3 ; do \
        echo Info : MONTH = $(word $$m, ${MONTH}); \
        echo Info : DATE  = $(word $$m, ${DATE}); \
    done

fails with error Makefile:5: invalid first argument to 'word' function: '$m'. Stop. when expanded by make because $m is not a valid value for the first parameter of make function word.

You could create a list of MONTH.DATE words using make functions join and addsuffix. This would simplify a bit your problem:

MONTH := jan feb mar
DATE := 01 03 05
MONTH.DATE := $(join $(addsuffix .,$(MONTH)),$(DATE))

Then, your recipe can loop over this list and use shell parameter substitutions to compute the month and the date from the loop variable:

MONTH := jan feb mar
DATE := 01 03 05
MONTH.DATE := $(join $(addsuffix .,$(MONTH)),$(DATE))

.PHONY: run

run: @for md in $(MONTH.DATE); do \ m=$${md%.}; d=$${md#.}; \ echo Info : MONTH = $$m; \ echo Info : DATE = $$d; \ done

But if your echo commands are a replacement for a more complex processing and if your for loops could (should?) be unrolled you could create a multi-targets rule for all MONTH.DATE words and compute the month and the date from the target name:

MONTH := jan feb mar
DATE := 01 03 05
MONTH.DATE := $(join $(addsuffix .,$(MONTH)),$(DATE))

.PHONY: run $(MONTH.DATE)

run: $(MONTH.DATE)

$(MONTH.DATE): @md=$@; m=$${md%.}; d=$${md#*.}; \ echo Info : MONTH = $$m; \ echo Info : DATE = $$d

A side benefit is that make can process all jobs in parallel (try make -j3). If the jobs are computation intensive and your computer is multi-core the benefit can be significant.

May 29, 2025 Score: 1 Rep: 51,930 Quality: Low Completeness: 40%

You can try turning MONTH and DATE into bash arrays first:

MONTH := jan feb mar
DATE := 01 03 05

run: SHELL := /bin/bash run: m=($(MONTH)) d=($(DATE)); \ for i in {0..2}; do \ echo Info : MONTH = $${m[i]}; \ echo Info : DATE = $${d[i]}; \ done