Julian Jocque
Julian Jocque

Reputation: 964

Confused how my Makefile is remaking object files

My make file is failing to find my include directory when it tries to remake object files. For example, when I call make tests I get the output:

g++    -c -o sdl_class.o sdl_class.cpp
sdl_class.cpp:9:23: fatal error: sdl_class.h: No such file or directory
#include <sdl_class.h>
                   ^
compilation terminated.
make: *** [sdl_class.o] Error 1

My Makefile is this:

#Originally from: http://www.cs.colby.edu/maxwell/courses/tutorials/maketutor/
#But will be heavily modified
IDIR =../include
CC=g++
CFLAGS=-w -I$(IDIR)

#ODIR=obj
LDIR =../lib

LIBS=-lSDL2

_DEPS = sdl_class.h SDL_image.h 
DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS))

OBJ = sdl_class.o tests.o 
#OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))


%.o: %.cpp $(DEPS)
    $(CC) -c -o $@ $< $(CFLAGS) $(LIBS)

tests: sdl_class.o tests.o
    $(CC) -o $@ $^ $(CFLAGS) $(LIBS)

all: $(OBJ)
    $(CC) -o $@ $^ $(CFLAGS) $(LIBS)

.PHONY: clean

clean:
    rm -f *.o *~ core $(IDIR)/*~ 

My understanding is that when I call make tests, that it should attempt to remake the sdl_class.o file. This should then call the %.o rule, which should try to make the object file by calling something like:

g++ -c -o sdl_class.o sdl_class.cpp -w -I../include -lSDL2

However, this is not the case as it looks like it is calling $(CC) -c -o $@ $< $(CFLAGS) $(LIBS), as you can see from above.

Do I have a fundamental misunderstanding about how make builds its rules? Seems likely, this is my first Makefile. Perhaps I am confused on how compilation works in general, as I'm somewhat new to that as well.

Upvotes: 0

Views: 331

Answers (2)

MadScientist
MadScientist

Reputation: 100856

I would say that the problem is that one or more of the files ../include/sdl_class.h or ../include/SDL_image.h does not exist. Because of that, make is deciding that your pattern rule does not match (because not all the prerequisites can be found or made) and it defaults to the built-in rule to create object files from .cpp files.

The built-in rules use the make variables CXX for the C++ compiler and CXXFLAGS for the C++ flags: the CC and CFLAGS variables are used for the C compiler. That's why your settings for CFLAGS are being ignored.

If you run make -d sdl_class.o you'll see which file make is looking for and why it decides to not use your pattern rule.

If you rewrite your rules like this it will work better:

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

sdl_class.o tests.o: $(DEPS)

because make will now complain that the relevant files can't be found or created.

There are other issues, of course. You shouldn't be passing $(LIBS) to your compile command; that belongs only in your link line. And, you should probably stick to the standard variables CXX for the C++ compiler, CPPFLAGS for preprocessor flags like -I and -D, and CXXFLAGS for C++ compiler flags. Also, linker library flags like -L../lib go in LDFLAGS and linker libraries like -lSDL2 go in LDLIBS.

Upvotes: 1

Michel Billaud
Michel Billaud

Reputation: 1826

CC/CCFLAGS are for C compilation. You should use CXX and CXXFLAGS for C++. They are used in built-in rules and in the LINK.cc macro, making the Makefile much simpler, and thus less error prone.

CXXFLAGS = -Wall ...
prog :  foo.o bar.o
      $(LINK.cc) -o $@ $^

see Default linker setting in Makefile for linking C++ object files

Upvotes: 0

Related Questions