1
votes

I've got a basic, minimal makefile to compile C++ source; a stripped-down version looks like this:

TARGET = main

OBJ = $(patsubst %.cpp,%.o,$(wildcard *.cpp))
CPPFLAGS = -std=c++11 -Wall

build: $(TARGET)

$(TARGET): $(OBJ)
    @echo "$? --> $@"
    g++ $(CPPFLAGS) -o $@ $?
    @echo

%.o: %.cpp
    @echo "$< --> $@"
    g++ $(CPPFLAGS) -c $<
    @echo

When building from scratch, everything works as expected:

clock.cpp --> clock.o
g++ -std=c++11 -Wall -c clock.cpp

main.cpp --> main.o
g++ -std=c++11 -Wall -c main.cpp

clock.o main.o --> main
g++ -std=c++11 -Wall -o main clock.o main.o

After a change in one of the source files, make rebuilds the corresponding object file, but for some reason skips the existing (unchanged) object file when trying to link (clock.o --> main instead of clock.o main.o --> main):

clock.cpp --> clock.o
g++ -std=c++11 -Wall -c clock.cpp

clock.o --> main
g++ -std=c++11 -Wall -o main clock.o

When running make again, without changing any file, the linking works as expected:

clock.o main.o --> main
g++ -std=c++11 -Wall -o main clock.o main.o

What's the reason for this behavior, and how could it be prevented?

I'm running GNU Make 4.1 on i686 Linux 4.4

1

1 Answers

2
votes

You use wrong automatic variable in g++ $(CPPFLAGS) -o $@ $? recipe. https://www.gnu.org/software/make/manual/html_node/Automatic-Variables.html:

$?

The names of all the prerequisites that are newer than the target, with spaces between them.

So Make does exactly what you ask it to do: link main target from all updated prerequisites and skip untouched prerequisites.

g++ $(CPPFLAGS) -o $@ $^ recipe will fix the problem.