vanilla
vanilla

Reputation: 13

Why doesn't my make file leave behind object files?

I am new to make files and I put this together with a bit of trial & error. This code is used to compile my c++ program.

My main.cpp file in the same folder as the makefile. I have a lib/ folder that contains the headers main depends on.

The following makefile results in a correct and complete compilation of my code. But I was expecting that I would find *.o objects left behind. (Note that I've tried to make both with and without the "clean" rule, and I get the same results both times.)

#
# Makefile
#

CXX = g++
CCFLAGS = -O3 -I/sw/include -L/sw/lib
      ## /sw/include and /sw/lib contain dependencies for files in my lib/
LDFLAGS = -lpng
OPTS = $(CCFLAGS) $(LDFLAGS)

SOURCES = $(wildcard lib/*.cpp) main.cpp
OBJECTS = $(SOURCES: .cpp = .o)
TARGET = spirals

$(TARGET): $(OBJECTS)
    $(CXX) $(OPTS) $^ -o $@

.PHONY: depend
depend:
    g++ -MM $(SOURCES) > depend
      ## generate dependencies list
include depend

.PHONY: clean
clean:
    rm -f *.o lib/*.o $(TARGET)

Also, in case it matters, I'm on MacOSX and my program is designed in xcode. (I know that xcode has its own build flow, but I'm designing a command-line program for a linux system and I'd like to test compilation & linking in a bash environment instead of only going through xcode.)

Questions:

  1. Am I correct to expect makefiles to produce *.o files that stick around once the main target has been created?

  2. If so, why doesn't my makefile do this?

Upvotes: 1

Views: 733

Answers (1)

John Marshall
John Marshall

Reputation: 7005

If you observe what command your $(TARGET) rule causes to be run:

g++ -O3 -I/sw/include -L/sw/lib -lpng lib/bar.cpp lib/foo.cpp main.cpp -o spirals

you'll see that $(OBJECTS) in fact contains *.cpp files, and there are no *.o files sticking around because you haven't asked for any.

The problem is here:

OBJECTS = $(SOURCES:.cpp=.o)

In your GNU makefile as written, this substitution reference is written with excess spaces, so never matches anything and $(OBJECTS) ends up the same as $(SOURCES). Rewrite it as above and it'll do what you expect.

(Other notes: -lpng needs to go at the end of the link command to work in general, so you should introduce another make variable (traditionally called $(LDLIBS)) so as to arrange that. Especially as someone new to makefiles, you would do better to spell out your dependencies explicitly rather than playing games with $(wildcard) and a computed $(OBJECTS). -I options are needed during compilation while -L options are used during linking, so it would be good to arrange separate $(CXXFLAGS)/$(LDFLAGS) variables used in separate rules so they are only added when required.)

Upvotes: 4

Related Questions