Juno
Juno

Reputation: 15

Building nested directories using makefile

I tried to build a nested directories following: Iterating through a list of directories in a Makefile

Here is my script

LAYER1 = a b 
LAYER2 = 1 2 

$(LAYER1)/foo%/run: $(DIR)
       mkdir -p $@

DIR: $(addsuffix /foo$(LAYER2)/run, $(LAYER1))  

The expected output is creating a/foo1/run a/foo2/run b/foo1/run b/foo2/run but the output is only 1 directory named a. How do I create the expected directory structure?

Upvotes: 0

Views: 268

Answers (2)

HardcoreHenry
HardcoreHenry

Reputation: 6387

See MadScientist's answer as to why your answer would not work. As far as something that will work, you likely want code that looks like this:

LAYER1 = a b 
LAYER2 = 1 2

DIRS := $(foreach L1,$(LAYER1),\
           $(foreach L2,$(LAYER2),\
              $(L1)/foo$(L2)/run))

all: | $(DIRS)

$(DIRS):
    mkdir -p $@

Notice the use of order-only dependencies as the prerequisite type for $(DIRS)

Upvotes: 0

MadScientist
MadScientist

Reputation: 101051

What does the rule:

$(LAYER1)/foo%/run: $(DIR)

expand to? It expands to this:

a b/foo%/run: $(DIR)

(I don't know what $(DIR) is supposed to be) which is an explicit rule that tells make how to build two things: a and b/foo%/run (this is not a pattern rule because not all the targets contain %).

Since a here is the first target in the makefile, it's the one that will be run by default when you run make.

What does $(addsuffix /foo$(LAYER2)/run, $(LAYER1)) do? It takes every word in $(LAYER1) and prefixes it by the string /foo$(LAYER2)/run. What is that string? It's /foo1 2/run. So the result of this is:

a/foo1 2/run b/foo1 2/run

which means DIR has the files a/foo1, 2/run, b/foo1, and 2/run as dependencies.

If LAYER1 has multiple words you need to loop through it, not just use it as-is.

Upvotes: 3

Related Questions