ghurpost ghurpost - 22 days ago 7
C++ Question

-I flag in the makefile does not result in a header file being found (gtest/gtest.h)

Previously I was struggling with creating a makefile in root directory that would deal with source files being in

src
folder and headers in
include
folder. Following this I wanted to add another folder
tests
where I would keep .cpp files with tests. Unfortunately I have problems with this.

The folder structure is:

.
|__makefile
|
|__/src
| |
| |__[regular .cpp files]
|
|__/include
| |
| |__[.h files]
| |
| |__/gtest
| |
| |__gtest.h
|
|__/tests
|
|__test_factorial.cpp


./tests/test_factorial.cpp:

#include "gtest/gtest.h"
#include "factorial.h"

// some tests


makefile:

CC = g++

CFLAGS = -Wall

INCLUDES = -I./include

LIBS = -lgtest -lpthread

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

.PHONY: clean depend

SRCS := $(filter-out ./tests/main_tests.cpp, $(SRCS))
OBJS = $(SRCS:.cpp=.o)
OBJS := $(OBJS:./src%=.%)

release: $(OBJS)
$(CC) $(CFLAGS) -o app $(OBJS) $(LIBS)

VPATH = ./src:./tests

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

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

depend: .depend

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

include .depend


When I execute
make
from the root directory all the files from /src compile fine (I end up having object files in the root directory for them) but I get an error for .cpp file from /tests directory:

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


What might be important, the .depend file seems to have it all right:

test_factorial.o: tests/test_factorial.cpp include/gtest/gtest.h \
include/factorial.h


What is wrong with the makefile?

EDIT

I believe this fragment of the error:

<builtin>: recipe for target 'tests/test_factorial.o' failed


suggests that something is wrong in this part of the makefile:

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

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


Why it's trying to do
./tests/test_factorial.o
rather than
./test_factorial.o
? Let me underline again that object files for ./src/*.cpp files end up in root directory, i.e.
./*.o
, not
./src/*.o
.

Answer

Your makefile is building

tests/test_factorial.o

from

tests/test_factorial.cpp

and that doesn't match the rule

%.o: ./tests/%.cpp

So it is instead using a builtin rule. (As an aside, the convention is to build c++ files using $(CXX) and $(CXXFLAGS) not $(CC)).

Try a rule pattern of

./tests/%.o: ./tests/%.cpp

The reason that your Makefile uses the name tests/test_factorial.o is because

OBJS = $(SRCS:.cpp=.o)

which (it should be obvious) makes the path to the .o file the same as the path to the .cpp.

You have a subsequent rule stripping the path src/

OBJS := $(OBJS:./src%=.%)

and no similar rule for tests/