ghurpost ghurpost - 18 days ago 6
C++ Question

-I flag in the makefile does not result in a header file being found

I have a file ./src/test.cpp:

#include "test.h"

void Hi() {

std::cout << "Hi, indeed..." << std::endl;
}


test.h is located in ./include folder.

This is my makefile:

CC = g++

CFLAGS = -Wall

INCLUDES = -I./include

SRCS = $(shell find ./src/ -name '*.cpp')

.PHONY: clean depend

OBJS = $(SRCS:.cpp=.o)
OBJS := $(OBJS:./src%=.%)

release: $(OBJS)
$(CC) $(CFLAGS) -o app_name $(OBJS)

VPATH = ./src

../%.o: %.cpp
$(CC) $(CFLAGS) $(INCLUDES) -c $*.cpp

depend: .depend

.depend: $(SRCS)
rm -f ./.depend
$(CC) $(CFLAGS) -MM $^ > ./.depend;

include .depend


As a result I get an error:

g++ -c -o test.o ./src/test.cpp
./src/test.cpp:1:18: fatal error: test.h: No such file or directory
compilation terminated.
<builtin>: recipe for target 'test.o' failed
make: *** [test.o] Error 1


Also the file
.depend
is completely empty.

How to resolve the issue? The makefile is in root directory:

./
makefile
./src/
test.cpp
main.cpp
./include/
test.h

Answer

What G.M. is trying to say is that you have defined a pattern rule that knows how to build a target matching a pattern ../%.o. But, when you ask make to build objects, they are of the form ./xxx.o; e.g., after:

SRCS = $(shell find ./src/ -name '*.cpp')

suppose SRCS contains ./src/foo.cpp. Now after this:

OBJS = $(SRCS:.cpp=.o)
OBJS := $(OBJS:./src%=.%)

OBJS will contain the value ./foo.o (by the way, a simpler way to get this behavior is to use the patsubst function: $(patsubst ./src/%.cpp,./%.o,$(SRCS))).

So, make will try to build the file ./foo.o. Since there's no explicit rule for this it will look for an implicit rule.

It sees your pattern rule, but that says how to build ../%.o which does not match the object file make wants to build ./foo.o, so your rule is ignored.

Then make will go look for some other implicit rules and it will find the built-in rule that knows how to build a .o file from a .cpp file, and it will use that. That rule doesn't use your variable $(INCLUDES), so your compile fails.

You need to either fix your OBJS settings to create filenames like ../foo.o instead of ./foo.o, if you really want your object files to appear in the parent directory, or else change your pattern rule to build %.o not ../%.o.

Comments