2

I am talking about this question where the person has updated his final solution with a makefile for the task. I am having a hard time understanding how it's done.

There is a rule:

$(OBJECTS): $(OBJDIR)/%.o : $(SRCDIR)/%.c
    @$(CC) $(CFLAGS) -c $< -o $@

which I am unable to understand, but by intuition I know what it will be doing. Almost everything else is pretty much clear. Thanks!

johan
  • 1,664
  • 2
  • 14
  • 30
Aman Deep Gautam
  • 8,091
  • 21
  • 74
  • 130

2 Answers2

3

This is a static pattern rule. The first field is a list of targets, the second is a target pattern which Make uses to isolate a target's "stem", the third is the prerequisite pattern which Make uses to construct the list of prerequisites.

Suppose you have

SRCDIR = src
OBJDIR = obj
OBJECTS = obj/foo.o obj/bar.o obj/baz.o

$(OBJECTS): $(OBJDIR)/%.o : $(SRCDIR)/%.c
    @$(CC) $(CFLAGS) -c $< -o $@

If you make obj/foo.o, Make first identifies this rule as the one to use (since obj/foo.o is in the target list $(OBJECTS)), matches it against the target pattern obj/%.o and finds that the stem (the part matched by the wildcard %) is foo, then plugs that into the prereq pattern src/%.c and finds that the prerequisite is src/foo.c.

If you've also defined the variables

CC = gcc
CFLAGS = -thisflag -thatflag=something

Then the command in the rule becomes

    @gcc -thisflag -thatflag=something -c src/foo.c -o obj/foo.o

(Note that $< is the first prerequisite and $@ is the target name.)

In answer to your other question: Yes, a makefile can handle a dependency on a header file (x.h) so that if the header has been modified, Make will rebuild the target. No, this makefile doesn't do that. You can modify the makefile by hand, adding rules like

a.o: x.h

assuming you know what the inclusions actually are, or you can have the makefile do it automatically, which is an advanced technique you probably shouldn't attempt yet.

Beta
  • 96,650
  • 16
  • 149
  • 150
1

This line is explaining how to obtain the object files (.o) from the source (.c), it avoids having to repeat the line for each .c file.

The objects will be in OBJDIR and the sources in SRCDIR

$(CC) will contain the compiler, CFLAGS will contain the options for the compiler and -c tells gcc to compile the source into objects.

For example:

  • CC = gcc

  • CFLAGS = -g -Wall

can be converted into gcc -g -Wall -c test.c -o test.o

BlueTrin
  • 9,610
  • 12
  • 49
  • 78
  • Also tell me how does this makefile takes `.h` files which are defined by the user into consideration, if at all it does. I mean including `.h` files in the target list of a rule. – Aman Deep Gautam Jul 26 '12 at 17:02
  • Makefiles don't handle .h files. They simply pass the .c file to the compiler, who is responsible for finding the include required by the file. The most Makefiles do is passing flags to the compiler to add additional include path – Laurent Bourgault-Roy Jul 26 '12 at 17:07
  • @Aman Deep Gautam: Laurent is correct, the Makefile only generates an equivalent series of shell commands. The include folders are passed via -I which is an option of gcc. Most of MakeFiles include a variable to represent the include folders. – BlueTrin Jul 26 '12 at 17:09
  • No. What I am saying is that suppose you have included `x.h` an `a.h` in `a.c` and you changed `x.h` and its corresponding file, wouldn't it be desirable to recompile the `a.c` because `x.h` has changed. – Aman Deep Gautam Jul 26 '12 at 17:13
  • Also one more doubt, why the two colons(:) `$(OBJECTS): $(OBJDIR)/%.o : $(SRCDIR)/%.c` there. what do they do? – Aman Deep Gautam Jul 26 '12 at 17:17
  • This line creates a dependency of the obj to the includes obj: $(SOURCES) $(INCLUDES). I think it is time you spend some time by yourself experimenting with Makefiles and doing some personal research ? – BlueTrin Jul 26 '12 at 17:51