how to include and compile a library in a makefile - c++

I'm trying to build this hello world project that includes a library with both .h and .cpp files (and hence the library needs to be compiled too). The directory structure is
helloworld/lib/StanfordCPPLib/console.h
/src/hello.h
/src/hello.cpp
You can see the project code here
When I run make with the following makefile, i get an error that console.h (which is included by hello.cpp) cannot be found
CC=gcc
CFLAGS=-I.
DEPS = hello.h
OBJ = hello.o
#console.h is in lib/StanfordCPPLib and it is included by hello.cpp
INC=-I../lib/StanfordCPPLib
%.o: %.c $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
hellomake: $(OBJ)
g++ -o $# $^ $(CFLAGS) $(INC)
How to include the StanfordLibrary in this makefile so that it is both included and compiled.
(note, I'm aware the original sourcecode contains a QT creator file, however, I'm trying to build it using make)

The main problem is that your rule for building objs:
%.o: %.c $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
doesn't use your include path in $(INC)
Another problem is that you are matching on the wrong file extension. e.g. %.c should be %.cpp.
You also have some extra redundant junk in there, so I suggest you update your makefile like this to get the idea:
CC=gcc
DEPS = hello.h
OBJ = hello.o
INC=-I. -I../lib/StanfordCPPLib
%.o: %.cpp $(DEPS)
$(CC) $(INC) -c $<
hellomake: $(OBJ)
g++ -o $# $^
This builds fine in my little mock setup.
Remember that it is actually necessary for you to use g++ under hellomake: for everything to link properly.

Related

SFML library doesn't link with makefile compilation

I have been trying to link the SFML dlls to my windows C++ project, but I can't get it to work. I always end up with:
fatal error: SFML/System.hpp: No such file or directory
I've tried a bunch of things but nothing changes the issue.
Here is my makefile:
PROGRAM = zero_flip
OBJS = src/main.o src/Math.o src/card.o src/game_board.o src/indicator.o src/ui.o
CXX = g++
CXX_FLAGS = -O0 -g -Wall -Wextra -Wno-unused-parameter -Wno-unused-variable
LIB_DIRS = -L./Resources/libs/
LIBS = -lsfml-system -lsfml-graphics -lsfml-window -lsfml-audio
LNK_FLAGS = $(LIB_DIRS) $(LIBS)
DEPS=$(OBJS:.o=.d)
.PHONY: all clean
all: $(PROGRAM)
-include $(DEPS)
%.o: %.cpp
$(CXX) $(CXX_FLAGS) $(LNK_FLAGS) $< -o $#
$(PROGRAM): $(OBJS)
$(CXX) $(CXX_FLAGS) $(LNK_FLAGS) $^ -o $#
clean:
rm -f $(OBJS) $(DEPS) $(PROGRAM) && clear
The "./Resources/libs/" directory contains:
openal32.dll
sfml-audio-2.dll
sfml-audio-d-2.dll
sfml-graphics-2.dll
sfml-graphics-d-2.dll
sfml-system-2.dll
sfml-system-d-2.dll
sfml-window-2.dll
sfml-window-d-2.dll
Can anyone get me unstuck please this is driving me mad.
This is wrong:
%.o: %.cpp
$(CXX) $(CXX_FLAGS) $(LNK_FLAGS) $< -o $#
This rule says it will compile a source file into an object file, but the recipe actually builds a complete executable: it will compile the source file like xxx.cpp then link it into a program named xxx.o. You need to invoke just the compiler here, not the linker, so you should not have $(LNK_FLAGS) and you need to add the -c option to tell the compiler to stop after compiling and not link.
Then you need to add an -I option to the compile line telling the compiler where to find the header files needed during compilation... in this case SFML/System.hpp.

Need help understanding makefile pattern rule % : %.o

I want to change this makefile into something simpler using pattern rules I read about in a book:
VPATH = src
CPPFLAGS = -I include
main.o: main.cpp
g++ $(CPPFLAGS) $<
TwoDimensionalShape.o: TwoDimensionalShape.cpp
g++ -c $(CPPFLAGS) $<
Square.o: Square.cpp Square.h
g++ -c $(CPPFLAGS) $<
Circle.o: Circle.cpp Circle.h
g++ -c $(CPPFLAGS) $<
Rectangle.o: Rectangle.cpp Rectangle.h
g++ -c $(CPPFLAGS) $<
Triangle.o: Triangle.cpp Triangle.h
g++ -c $(CPPFLAGS) $<
ShapeStack.o: ShapeStack.cpp ShapeStack.h
g++ -c $(CPPFLAGS) $<
ScreenManager.o: ScreenManager.cpp ScreenManager.h
g++ -c $(CPPFLAGS) $<
ScreenState.o: ScreenState.cpp ScreenState.h
g++ -c $(CPPFLAGS) $<
SquareState.o: SquareState.cpp SquareState.h
g++ -c $(CPPFLAGS) $<
CircleState.o: CircleState.cpp CircleState.h
g++ -c $(CPPFLAGS) $<
After reading the book I can write the above using pattern rules like this. But I don't understand how it is working:
#source files are in "src" folder.
VPATH = src
#header files are in "include" folder.
CPPFLAGS = -I include -Wall
all: main.o TwoDimensionalShape.o Square.o Circle.o Rectangle.o Triangle.o ShapeStack.o ScreenManager.o ScreenState.o SquareState.o CircleState.o
g++ $(CPPFLAGS) $^
%.o: %.cpp
g++ -c $(CPPFLAGS) $<
%: %.o
g++ $<
This makefile is correct however I don't understand how it is working.
If I change for example 2 source files, how does this makefile understand to only compile the changed two source files and not all of source files?
In the book I read, example was about C not C++ and last line was %: %.c. Then why is my line which is %: %.o working? Shouldn't it be %: %.cpp?
This makefile is correct however I don't understand how it is working.
If your new Makefile is a replacement for the old one, it is definitely NOT working.
In the "old" one you have e.g.
ShapeStack.o: ShapeStack.cpp ShapeStack.h
which tells that ShapeStack.o depends on the .cpp and header file. Your new Makefile did not have any dependencies to other files which will result in a lot of trouble. Simply touch one of your headers and type make. Nothing will happen!
So at minimum you have to introduce your source file dependecies, maybe manual as in your old makefile or with some more automatism which uses the dependency check from the compiler, using gcc it is with "gcc -MM".
For getting automated prerequisites see https://www.gnu.org/software/make/manual/html_node/Automatic-Prerequisites.html
And using vpath can result in a lot of trouble. There are some articels, e.g.:
http://make.mad-scientist.net/papers/how-not-to-use-vpath/
Some example Makefiles can be found already here:
minimum c++ make file for linux

How to write specific rule for a target in makefile?

I know the title is quite ambiguous but I just don't know how to describe my problem concisely. Please edit that if you want.
Currently my makefile is like the following:
CC = g++
CFLAGS = -Wall -g
TARGET = foobar
SRC_FILES = foo.cpp bar.cpp main.cpp
OBJ_FILES := $(SRC_FILES:.cpp=.o)
$(TARGET): $(OBJ_FILES)
$(CC) $(CFLAGS) $^ -o $#
%.o: %.cpp %.h
$(CC) $(CFLAGS) -c $<
clean:
rm -rf *.o $(TARGET)
The problem is that this structure requires main.cpp to have a main.h header file, which I don't really have. How can I handle this nicely?
GCC (and probably Clang) can build a list of dependencies for you; This way, you can simply make your object files from their source (cpp) file:
depend: .depend
.depend: $(SRC_FILES)
rm -f ./.depend
$(CC) $(CFLAGS) -MM $^ -MF ./.depend;
include .depend
%.o: %.cpp
$(CC) $(CFLAGS) -c $<
You might also find interest in the makedepend tool.

How to specify the dependency of each source file on its corresponding header file by using wild cards?

Should be a simple makefile question, but didn't find a solution after some quick surfing.
Basically I have a bunch of "cpp" codes, each of which has a corresponding header file with the same stem name. I want to specify the dependency of each source file on its corresponding header file by using wild cards. The last commented-out line is what I want to add, and apparently its not working as intended.
SOURCES=a.cpp b.cpp c.cpp
HEADERS=$(SOURCES:.cpp=.h)
OBJECTS=$(SOURCES:.cpp=.o)
$(OBJECTS): %.o: %.cpp
$(CC) -fPIC -c $< -o $#
#$(OBJECTS): $(HEADERS)
You can add this:
$(OBJECTS): %.o: %.h
or modify your rule:
$(OBJECTS): %.o: %.cpp %.h
$(CC) -fPIC -c $< -o $#

What's wrong with this makefile

I am new to makefiles. I have a makefile, I want it generated a shared library from more than one .cpp files. But the following makefile only generated different .so based on the same .cpp file. Can anyone help?
SRC_DIR = $(PROJECT_BASE_DIR)/src
SRCFILES = $(wildcard $(SRC_DIR)/*.cpp)
OBJFILES = $(patsubst $(SRC_DIR)/%.cpp,$(BUILD_TARGET_DIR)/%.$(OBJ_EXTENSION),$(SRCFILES))
...
ifeq ($(OS),$(OS_LINUX))
$(CLIENTLIB): $(OBJFILES)
gcc $(CXXFLAGS) -o $# $< $(LINKER_FLAGS)
$(OBJFILES): $(SRCFILES) ==> I believe this is the line with problem.
gcc $(CXXFLAGS) -c -o $# $<
Currently you're trying to convert all .cpp files to all .o files in one compilation step.
Change:
$(OBJFILES): $(SRCFILES) ==> I believe this is the line with problem.
gcc $(CXXFLAGS) -c -o $# $<
to:
%.$(OBJ_EXTENSION): %.cpp
gcc $(CXXFLAGS) -c -o $# $<
These are the rules I use in my makefile and they work, hope it can help you
CFILES = $(wildcard *.c)
OBJS = $(CFILES:%.c=%.o)
%.o: %.c
$(CC) $(CFLAGS) -I$(INCLUDE) $< -o $#