Spn
Spn

Reputation: 450

Use of %.o : %.c in makefile

I have this makefile :

CC = gcc
CFLAGS = -std=c99 -W -Wall
CFLAGSS = -std=c99 -W
LIBS = -lm

prog : main.o double.o coord2D.o coord3D.o
    $(CC) $^ $(LIBS) -o $@

%.o : %.c
    $(CC) $(CFLAGS) $< -c

coord2D.o: coord2D.c coord2D.h double.h
coord3D.o: coord3D.c coord3D.h double.h
double.o: double.c double.h
main.o: main.c double.h coord2D.h coord3D.h

My question :
What does the line "%.o : %.c" do ?

Where I am :
I've done a lot of researches but I still don't know exactly how it works.
From what I've learned, when we type "make":
- we go to the first rule "prog" which contains the dependency "main.o"
- because of that, we go to the rule "main.o" which is recognized by "%.o : %.c" because it contains the pattern "main.o : main.c" and compiled.
- we then go back to "prog", which contains "double.o" and we repeat the steps

Is this how it works ? If so, I have a second question : what if we write "%.o : %.c coord2D.h double.h" ? Will it only take the rule "main.o" in consideration because it's the only one which contains a file ".c" and the two ".h" files ?

Upvotes: 8

Views: 28878

Answers (3)

Dave Neary
Dave Neary

Reputation: 337

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.

The following line, starting with a tab, is the rule to use whenever you are generating a file of the form %.o. So, for example:

The executable "prog" requires "main.o" to be built (line 6). make looks for a rule to build main.o - it finds two:

  1. The more specific rule (specifying the filename by name):
    main.o: main.c double.h coord2D.h coord3D.h

This rule specifies all of the dependencies for main.o. One consequence of this is that main.o will be recompiled if any of these files is newer than main.o (i.e. has been changed in the meantime)

  1. The general rule:
    %.o: %.c
             $(CC) $(CFLAGS) $< -c

This will run the command "gcc -std=c99 -W -Wall main.c -c "$<" is another wild card, it means "include the first prerequisite filename from the target line here" - in this case, main.c

The other wild cards in other lines here are "$@" (include the target here) and $^ (include the full list of prerequisites here). The command for prog will expand to:

gcc main.o double.o coord2D.o coord3D.o -lm -o prog

Wild card rules like this allow you to build complex projects with very few rules.

Upvotes: 11

battlmonstr
battlmonstr

Reputation: 6290

Your question is mostly answered here - Multiple Rules for One Target.

Please read it, it is short and has examples, but the gist of it is:

One file can be the target of several rules. All the prerequisites mentioned in all the rules are merged into one list of prerequisites for the target.

So if you have a particular target like "coord2D.o", it takes all the rules where the left side matches, and combines all the right sides.

Note that in such case only one rule can have a recipe (like $(CC) command in your case), all the others are empty, and are used to just split the dependencies declaration across several lines.

In your case you could avoid mentioning coord2D.c and other C files in additional rules, because it is already covered by %.c. Also you could move double.h common dependency to the common %.o rule to avoid repetition.

There's also a facility to generate the header file dependency rules described here, although it is advanced and a bit complicated.

Upvotes: 0

imsky
imsky

Reputation: 3279

Yes, that is how pattern-specific variables work. As for your second question, no - both rules will apply (however without the static pattern rules and no .h files, Make would use an implicit rule).

Upvotes: 0

Related Questions