I have two makefiles
The first :
dir = ../dir1
dis = ../dir2
test:
$(MAKE) -C $(dir)
The second one :
DIRS = dir1 dir2 dir3
test:
for dir in $(DIRS); do \
if $(MAKE) -C $$dir ; then \
true; \
else \
exit 1; \
fi; \
done
Why in the for loop I need $$dir when in a simple recipe I have to write $(dir)
Another question: I have this other makefile, in which I have this other for loop:
all clean dep depend print:
for dir in $(DIRS); do \
if $(MAKE) $(MAKE_FLAGS) -C $$dir $@; then \
true; \
else \
exit 1; \
fi; \
done
What is the meaning of $@ in the line
if $(MAKE) $(MAKE_FLAGS) -C $$dir $@; then \
I know this is an Automatic Variable that matches the file name of the target of the rule. Here the target appears to be a command like cancel:
cancell:
rm -rf *.o
One is a makefile variable the other is a shell variable. $(directoryName)
will be resolved by make, as it's reading. For $$directoryName
, make converts the $$
to $
, and passes that to the shell (so $$directoryName
becomes$directoryName
). The shell expands it to whatever it has in its environment.
A bit more detail:
If, in make, you define (outside of any recipe)
var := 1
then var
is a make variable. If you then call
all:
echo $(var)
Then make expands the recipe to echo ../dir1
before passing the command to the shell. If, on the other hand, you do:
all:
var=1; echo $$var
Then make passes var=1; echo $var
to the shell. The shell sets var
to 1
, and then prints it. Notice if you tried:
all:
var=1;
echo $$var
Then the recipe will not print anything -- that's because the first line is run in a shell, which sets var
to 1
, but then exits. The next line runs, which passes echo $var
in a new shell, but this shell doesn't know what var
was set to in the previous shell.
In addition, if you run var=1;make
, then make will set a makefile variable var
to be 1
when it starts. Thus a $(info $(var))
will show 1, in this case.
For syntax, in make you can do var := 1
(with spaces). In bash you cannot add spaces. In bash, $var
refers to the variable var. In make $var
refers to $v
followed by the literal ar
. (In make you have to use either {}
or ()
to refer to multicharacter variables). In bash, you can either use {}
, or no braces ($(var)
has a different meaning in bash).
make also has two flavors of variables, one defined with :=
and one with =
.