This is my first Makefile, and I can't figure out some of the syntax used. The questions are marked below:
C := gcc
CFLAGS := -Wall -Werror -std=
PROG := program_1\
program_2\
program_3
SRCS := program_1.c \
program_2.c \
program_3.c
OBJS := ${SRCS:.c=.o}
all: ${OBJS}
${CC} ${OBJS} -o ${PROG}
clean:
rm -f ${PROG} ${OBJS}
.c.o:
${CC} ${CFLAGS} -c $<
What does .c=.o
mean? in
OBJS := ${SRCS:.c=.o}
Not sure what $<
means here, and .c.o
?
.c.o: ${CC} ${CFLAGS} -c $<
The simple answer is that %.o is a target that matches any file ending in .o. "%.o: %. c" means that any file ending in .o depends on the same filename ending in . c to be present.
Here's a quick and dirty intro : Files. All you need is a file called "makefile" or "Makefile". Comments Pound signs ("#") are comments to end of line. Variables CC = gcc. means that the variable CC contains "gcc".
Double dollar sign If you want a string to have a dollar sign, you can use $$ . This is how to use a shell variable in bash or sh . Note the differences between Makefile variables and Shell variables in this next example.
The order of rules is not significant, except for determining the default goal: the target for make to consider, if you do not otherwise specify one. The default goal is the target of the first rule in the first makefile. If the first rule has multiple targets, only the first target is taken as the default.
First of all, your Makefile
has a bug, it does not make the intended targets. Did you try it?
Second, it is not well written; not following best current practices.
So I will first show you the better version of your Makefile, both correct, as well as written with the best practices:
CFLAGS := -Wall -Werror -std=
SRCS := program_1.c \
program_2.c \
program_3.c
OBJS := ${SRCS:c=o}
PROGS := ${SRCS:.c=}
.PHONY: all
all: ${PROGS}
${PROGS} : % : %.o Makefile
${CC} $< -o $@
clean:
rm -f ${PROGS} ${OBJS}
%.o: %.c Makefile
${CC} ${CFLAGS} -c $<
Now, the answers to your questions are:
${SRCS:.c=.o}
means, take the variable value ${SRCS}
, which is a string composed of words separated by spaces, and for each word, replace the suffix .c
with .o
. I dropped .
in my code because it is not needed and it is common to replace only suffixes after the dot.
This syntax is similar to bash string suffix replacement (for one word) if you are familiar with that.
$<
when used in the "recipe", means "the first prerequisite" - the first thing after the :
in the line above.
and the last question is no longer relevant: .o.c
syntax is obsolete and not recommended currently.
Please take a look at my "10 Commandments" - my answer at this post:
makefile enforce library dependency ordering
, they will give you an idea about the best practices. Then you can also read up in the GNU Make manual, about the terms above in quotes, that I did not explain here.
You didn't specify exactly which variant of make
you're using -- there are many. I'm going to assume you are using GNU make, the most widely used variant.
In GNU make, $(SRCS:.c=.o)
is a substitution reference, and it means "the value of the SRCS
variable, where .c
is replaced by .o
when it appears at the end of a word." In your example, SRCS
has the value program_1.c program_2.c program_3.c
, so $(SRCS:.c=.o)
means program_1.o program_2.o program_3.o
.
The .c.o
is an example of what's known an old-fashioned suffix rule. It tells GNU make "here's how to build a .o file from a .c file with the same name." The modern equivalent is a pattern rule which would look the same except to use %.o: %.c
in place of .c.o
.
Finally, $<
is an automatic variable which means "the name of the first prerequisite".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With