ebozkurt
ebozkurt

Reputation: 3

How to append lists in makefile using loops

I am trying to create a list of targets that depend on one file only. The list I want to create is very long and I may have to add even more elements to it, so I would like to use loops to create that target list. The targets differ mainly by their paths.

I think I just need to find out how to append or add to list in makefile, so I can create the target list I want (TARGETS) in a loop.

Here is what I have so far:

.PHONY: all dircreate dircreate_sub

# Create shortcuts to directories ##############################################
DAT4 = data/4-Year/
DAT2 = data/2-Year/
DEPVARS = a b 

# Create directories ###########################################################
dircreate:
    mkdir -p \
    data/ \
    data/4-Year/ \
    data/2-Year/ 

dircreate_sub:
    for d in $(DEPVARS); do \
        mkdir -p data/4-Year/$$d ; \
        mkdir -p data/2-Year/$$d ; \
    done;

TARGETS = \
    for d in $(DEPVARS); do \
        $(DAT4)$$d/train_index.RDS \
        $(DAT2)$$d/train_index.RDS \
        $(DAT4)$$d/test_index.RDS \
        $(DAT2)$$d/test_index.RDS; \
    done;

$(TARGETS): \
    dataprep.R \
    funcs.R \
    ../core/data/analysis.data.RDS
    Rscript $<

all: dircreate dircreate_sub $(TARGETS)

Upvotes: 0

Views: 1053

Answers (2)

MadScientist
MadScientist

Reputation: 100926

Probably you want something like:

TARGETS := $(foreach d,$(DEPVARS),\
    $(DAT4)$d/train_index.RDS \
    $(DAT2)$d/train_index.RDS \
    $(DAT4)$d/test_index.RDS \
    $(DAT2)$d/test_index.RDS)

Note I used := instead of = for efficiency.

Upvotes: 1

HardcoreHenry
HardcoreHenry

Reputation: 6387

You're going to want to use the foreach makefile function:

You could do something like this:

TARGETS := $(foreach depvar,$(DEPVARS),$(DAT4)$$d/train_index.RDS)
TARGETS += $(foreach depvar,$(DEPVARS),$(DAT2)$$d/train_index.RDS)
TARGETS += $(foreach depvar,$(DEPVARS),$(DAT4)$$d/test_index.RDS)
TARGETS += $(foreach depvar,$(DEPVARS),$(DAT2)$$d/test_index.RDS)

or something like this:

TARGETS := $(foreach dat,$(DAT4) $(DAT2),$\
              $(foreach filename,train_index.RDS test_index.RDS,$\
                 $(foreach depvar,$(DEPVARS),$(dat)$(depvar)/$(filename))))

Note: I used the $\ trick to allow going over multiple lines without adding spaces (see here)

if you wanted to do something more complicated, you can always use a shell script to do everything.

TARGETS := $(shell somescript a b c) 

Upvotes: 0

Related Questions