Reputation: 15847
I'm trying to understand deeply how makefiles work.
For example, I've the following one:
CC = gcc
CFLAGS = -I.
DEPS = int_array.h
OBJS = int_array.o test_int_array.o
%.o: %.c $(DEPS)
$(CC) -c -o $@ $< $(CFLAGS)
test_int_array: $(OBJS)
$(CC) -o $@ $^ $(CFLAGS)
clean:
rm -rf *.o test_int_array *.dSYM
The part that I really don't understand fully is :
...
%.o: %.c $(DEPS)
$(CC) -c -o $@ $< $(CFLAGS)
test_int_array: $(OBJS)
$(CC) -o $@ $^ $(CFLAGS)
...
I know that the option -c
basically indicates just to run the preprocessor, compiling and assembling steps (i.e. without producing executables, I guess).
-o
means to write the output to the specified file. Which file in this case?
I understood that $@
(and $^
for right) is apparently referring to a "left" side, but which one? Is it referring, in the first case, to the left side of :
, that is %.o
?
What does $<
mean?
Could you please explain step by step how the make tool would interpret those two statements?
I think I understood this part more or less:
...
test_int_array: $(OBJS)
$(CC) -o $@ $^ $(CFLAGS)
...
which should mean produce an executable called "test_int_array" (which basically is indicated by these options -o $@
from the $(OBJS)
files on the right (stated using the option $^
).
Is $(CFLAGS)
needed in both cases? Does the order matter?
Upvotes: 3
Views: 110
Reputation: 2221
In a Makefile, each rule follows this format:
resulting_file : source_files
steps to get resulting_file from source_files
What is called respectively lefthand and righthand in a rule is the resulting_file and the source_files.
%.ext : %.ext2
is a pattern rule. It allows your Makefile to automatically create any .ext
file it needs if it can find a file at the same path with .ext2
.
%.c : %.o
is a pattern rule to obtain your .o
files (int_array.o test_int_array.o) from their equivalent .c
files (int_array.c test_int_array.c)
This is invoked when you specify that $(OBJS)
is needed to build the test_int_array
file.
Pattern rules automatically use certain variables, such as $(CFLAGS)
so you do not need to manually add it in that rule. You can find a full list of implicitly used variables in pattern rules here: https://ftp.gnu.org/old-gnu/Manuals/make-3.79.1/html_chapter/make_10.html#SEC96
You can find out about $@
, $<
and $^
and similar here: https://ftp.gnu.org/old-gnu/Manuals/make-3.79.1/html_chapter/make_10.html#SEC101
$@
: the entire lefthand
$<
: the first file in the righthand
$^
: the entire righthand list of files, space separated.
Upvotes: 2
Reputation: 25752
In the example:
test_int_array: $(OBJS)
$(CC) -o $@ $^ $(CFLAGS)
$@
is the filename of the target for this rule: test_int_array
.
$^
is the names of all prerequisites.
This would be whatever is contained in OBJS
, so: int_array.o test_int_array.o
In the example:
%.o: %.c $(DEPS)
$(CC) -c -o $@ $< $(CFLAGS)
$<
is the name of the first prerequisite: %.c
$@
is the filename of the target for this rule: %.o
$(CFLAGS) is not needed for linking, since it only includes the flag -I
. Also the CFLAGS indicates that the flags are used for compiling only, hence C FLAGS.
Upvotes: 3