开发者

Makefile compiling multiple times the same sources

** Question edited **

Here's a typical Makefile template :

TARGET   = my_prog               # project name

CC       = gcc -o
CFLAGS   = -Wall
SOURCES  := $(wildcard *.c)
INCLUDES := $(wildcard *.h)
OBJECTS  := $(SOURCES:.c=*.o)
rm       = rm -f

$(TARGET): $(OBJECTS)
    @$(CC) $(TARGET) $(CFLAGS) $(SOURCES)
    @echo "Compilation complete!"

clean:
    @$(rm) $(TARGET) $(OBJECTS)
    @echo "Cleanup complete!"

Question : why is the line 11 (@S(CC) $(TARGET) ...) still echoing when calling make ?

Answer : Because the problem is in the default rule and line 11 is fine.

** UPDATE **

I now have this Makefile

# project name
TARGET   = my_prog

CC       = gcc -c
CFLAGS   = -Wall -I.
LINKER   = gcc -o
LFLAGS   = -Wall
SOURCES  := $(wildcard *.c)
INCLUDES := $(wildcard *.h)
OBJECTS  := $(SOURCES:.c=*.o)
rm       = rm -f

$(TARGET): $(OBJECTS)
    $(LINKER) $(TARGET) $(LFLAGS) $(OBJECTS)

$(OBJECTS): $(SOURCES开发者_运维技巧) $(INCLUDES)
    $(CC) $(CFLAGS) $(SOURCES)

clean:
    $(rm) $(TARGET) $(OBJECTS)

Question : Why is $(CC) $(CFLAGS) $(SOURCES) being executed n times, where n is the number of source files ?

** UPDATE 2 **

Would this be a good way to solve this (seems to work...) ?

$(TARGET): obj
    $(LINKER) $(TARGET) $(LFLAGS) $(OBJECTS)

obj: $(SOURCES) $(INCLUDES)
    $(CC) $(CFLAGS) $(SOURCES)


The command $(CC) $(CFLAGS) $(SOURCES) is executed n times, because the rule is executed n times, because there are n objects to be built, because the $(TARGET) rule has that many objects as prerequisites. If you want the command to be run only once, replace all those prerequisites with a single PHONY prerequisite, whose rule executes the command.

But there's no reason to do it that way. You can just make the command more selective, so that it builds only the one object that was the actual target. That way Make doesn't waste time rebuilding the same objects over and over, and if one or two source files have been changed, Make will rebuild only the relevant objects, not all of them:

$(OBJECTS): %.o : %.c $(INCLUDES)
  $(CC) $(CFLAGS) $<

This rule is conservative-- it assumes that every object depends on every header, so it will sometimes rebuild things unnecessarily. You can make it better, either by hand if you know the real dependencies or automatically with a more advanced technique.

EDIT:

Your "update 2" is a decent solution, but I would suggest you add the line

.PHONY: obj

to tell Make that there will be no file called "obj". Otherwise Make will run the obj rule every time, trying to build that file.

This still has the problem that if you change one source file, e.g. foo.c, Make will rebuild all the objects.

The $< I used above is an automatic variable. It means "the first prerequisite". So when Make tries to build foo.o, it will evaluate to foo.c.

EDIT:

Jack Kelly (curse him!) has pointed out that I am wrong about how PHONY targets work: the obj rule will always run, and so will the TARGET rule, whether any source files have changed or not. So the "update 2" method is effective, but crude.


I think the output is coming from generating the .o files, not geverating my_prog

Looks like you don't have a rule for creating the .o files, so make is using the default one.

Try putting this:

@echo "starting compilation"

on the line before your line 11 build command

And you can see that "starting compilation" is output after the gcc line.

Perhaps line 10 should read:

$(TARGET): $(SOURCES)

?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜