GNU make does not build headers correctly if changed - c++

I have this makefile:
CC=g++
CFLAGS=-c -Wall
all: hello
hello: main.o client.o
$(CC) main.o client.o -o hello
client.o: client.cpp client.h
$(CC) $(CFLAGS) client.cpp -o client.o
main.o: main.cpp
$(CC) $(CFLAGS) main.cpp -o main.o
clean:
rm -rf *o hello
Whenever I make changes in hello.h, client.o is rebuilt when I execute make. But when I try the resulting executable ./hello the change does not seem to happen.
The change is only reflected on ./hello if I add client.h to the main.o: rule like that
main.o: main.cpp client.h
$(CC) $(CFLAGS) main.cpp -o main.o
This will make things very difficult to maintain my code, any idea how to solve this problem?
Edit:
tried this change:
main.o: main.cpp
$(CC) $(CFLAGS) -MD main.cpp -o main.o
but did not help.
UPDATE (final version):
TARGET = hello
CC = g++
CPPFLAGS = -Wall -MP -MD
LINKER = g++ -o
LFLAGS = -Wall
SRCDIR = src
OBJDIR = obj
BINDIR = bin
SOURCES := $(wildcard $(SRCDIR)/*.cpp)
INCLUDES := $(wildcard $(SRCDIR)/*.h)
OBJECTS := $(SOURCES:$(SRCDIR)/%.cpp=$(OBJDIR)/%.o)
DEPS := $(SOURCES:$(SRCDIR)/%.cpp=$(OBJDIR)/%.d)
RM = rm -rf
DIR_GUARD = mkdir -p $(#D)
$(BINDIR)/$(TARGET): $(OBJECTS)
#$(DIR_GUARD)
#$(LINKER) $# $(LFLAGS) $(OBJECTS)
#echo "Linking complete!"
$(OBJECTS): $(OBJDIR)/%.o: $(SRCDIR)/%.cpp
#$(DIR_GUARD)
#$(CC) $(CPPFLAGS) -c $< -o $#
#echo "Compiled "$<" successfully!"
-include $(DEPS)
.PHONEY: clean
clean:
#$(RM) $(OBJDIR)/* $(BINDIR)/*
#echo "Cleanup complete!"
Thanks guys for all the help, you are truly amazing.

The problem is that the dependency of main.o on client.h is not specified in your Makefile. Use:
main.o: main.cpp client.h
$(CC) $(CFLAGS) main.cpp -o main.o

Related

Im working on a makefile which should build a library and then also include that library when building the entire program

INC_DIR = ./include
SRC_DIR = ./src
OBJ_DIR = ./obj
SRC_FILES = $(wildcard $(SRC_DIR)/*.cpp))
H_FILES = $(wildcard $(INC_DIR)/*.cpp)
OBJ_FILES=$(patsubst $(SRC_DIR)/%.cc,$(OBJ_DIR)/%.o,$(SRC_FILES)
TARGET = PT3
CC = g++
CFLAGS = - fPIC -c -Wall -Werror -pedantic -std=c++11 -Wno-c++11-extensions
CPPFLAGS = $(addprefix -I, $(INC_DIR))
clean:
rm -f $(OBJECTS) $(TARGET)
all: $(TARGET)
$(TARGET): $(OBJECTS)
$(CC) $(CFLAGS) $(CPPFLAGS) -o $# $^
%.o: %.cc
$(CC) $(CFLAGS) $(CPPFLAGS) -o $# -c $<
g++ -shared -fPIC -o libtest.so $(OBJECTS)
main.o: main.cc
$(CC) $(CFLAGS) $(CPPFLAGS) -L/pt3/lib -o maintest main.cc -libtest
this is currently what I have and i know its not syntactically right or remotely working but Im getting stuck on creating the shared library so I dont even know what else wouldnt compile.**
INC_DIR = ./include
SRC_DIR = ./src
SRC_FILES = $(sort $(shell find $(SRC_DIR) -name '*.cc'))
OBJ_FILES = $(SRC_FILES:.cc=.o)
TARGET = PT3
CC = g++
CFLAGS = -fPIC -Wall -Werror -pedantic -std=c++11 -Wno-c++11-extensions
CPPFLAGS = $(addprefix -I, $(INC_DIR))
#clean:
# rm -f $(OBJECTS) $(TARGET)
all: $(TARGET)
$(TARGET): $(OBJ_FILES)
$(CC) $(CFLAGS) $(CPPFLAGS) -o $# $^
%.o: %.cc
$(CC) $(CFLAGS) $(CPPFLAGS) -o $# -c $<
libtest.so: $(OBJ_FILES)
$(CC) -shared -fPIC -o $# $^
maintest: main.o libtest.so
$(CC) $(CFLAGS) $(CPPFLAGS) -L. -o maintest main.o -libtest
this is what i rewrote the code to however Im getting a no input files error, but Im not sure if thats coming from a wrong read / failure to get into the required folders, or due to possibly missing a -o or -c?
Ive worked on the code some more following the suggestions and have come to this:
CXX = g++
CXXFLAGS := -Wall -Werror -pedantic -std=c++11 -Wno-c++11-extensions
SRC_FILES = $(wildcard $(SRC_DIR)/*.cpp)
OBJECTS=$(patsubst $(SRC_DIR)/%.cpp,$(OBJ_DIR)/%.o,$(SRC_FILES))
INC_DIR = include
SRC_DIR = src
OBJ_DIR = obj
TEST_DIR = tests
LIB_DIR = lib
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
$(CXX) $(CXXFLAGS) -fPIC -Iinclude -o $# -c $<
clean:
rm -f $(OBJECTS) $(TEST_DIR)/main.o
$(LIB_DIR)/libtest.so: $(OBJECTS)
#echo frank
$(CXX) -shared -fPIC -o $# $^
$(TEST_DIR)/main.o: $(TEST_DIR)/main.cc
$(CXX) $(CXXFLAGS) -Iinclude -o $# -c $<
maintest: $(TEST_DIR)/main.o $(LIB_DIR)/libtest.so
$(CXX) $(CXXFLAGS) -Llib -Iinclude -o $# $< -ltest
everything seems to compile fine however when running the maintest program it returns an error saying: error while loading shared libraries: libtest.so: cannot open shared object file: No such file or directory
thanks for the suggestions so far I feel like Im on the verge of actually getting the makefile working as intended
You've already written the recipe for the library (which builds it in the working directory -- we can change that later if you want):
g++ -shared -fPIC -o libtest.so $(OBJECTS)
The next step is to put it into a rule:
libtest.so: $(OBJECTS)
g++ -shared -fPIC -o libtest.so $(OBJECTS)
Then clean it up:
libtest.so: $(OBJECTS)
g++ -shared -fPIC -o $# $^
It looks as if you want the executable to be maintest, so let's write a rule for that:
maintest: main.o libtest.so
$(CC) $(CFLAGS) $(CPPFLAGS) -L. -o maintest main.o -ltest
Give that a try. We can make further adjustments once that much works.
EDIT: I see that there are a few other problems in your makefile. Your variables won't work as written. Do you name your source files "foo.cc" or "foo.cpp"?
EDIT: I can see that we'll have to do this in stages.
Step 1. Try this:
CXX = g++
CXXFLAGS := -Wall -Werror -pedantic -std=c++11 -Wno-c++11-extensions
INC_DIR = include
SRC_DIR = src
OBJ_DIR = obj
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
$(CXX) $(CXXFLAGS) -Iinclude -o $# -c $<
Try to build one or two object files with this, as in make obj/foo.o.
Step 2. Add a rule for main.o, and test it:
$(OBJ_DIR)/main.o: main.cc
$(CXX) $(CXXFLAGS) -Iinclude -o $# -c $<
Step 3. Add a "do nothing" rule for the library, and verify that it builds all of the objects:
SRC_FILES = $(wildcard $(SRC_DIR)/*.cpp)
OBJECTS=$(patsubst $(SRC_DIR)/%.cpp,$(OBJ_DIR)/%.o,$(SRC_FILES))
libtest.so: $(OBJECTS)
#echo doing nothing
Step 4. Change the library rule to actually build the library:
libtest.so: $(OBJECTS)
$(CXX) -shared -fPIC -o $# $^
Step 5. Add a rule to build the test:
maintest: main.o libtest.so
$(CXX) $(CXXFLAGS) -L. -o $# $< -ltest

C++, Pass a command line argument to makefile

I need to pass a command line argument which is a file name as a string to the program(main.cpp) in the makefile. I have seen most of the other post but don't understand how to implement them into my file. How should I proceed to do that? Thank you!
main.cpp
Program structure
makefile
OBJS = main.o HashTable.o Book.o
SOURCE = main.cpp HashTable.cpp Book.cpp
HEADER = HashTable.h Book.h
OUT = book
CC = g++
FLAGS = -g -c -Wall -Wextra -std=c++1z
all: $(OBJS)
$(CC) -g $(OBJS) -o $(OUT) $(LFLAGS)
main.o: main.cpp
$(CC) $(FLAGS) main.cpp
HashTable.o: HashTable.cpp
$(CC) $(FLAGS) HashTable.cpp
Book.o: Book.cpp
$(CC) $(FLAGS) Book.cpp
clean:
rm -f $(OBJS) $(OUT)

GCC linking a static library

I have seen questions like these on SO but everyone has different answers and directory structures that aren't working for me.
My makefile:
CC = g++
DEBUG = -g -std=c++11
TARGET = main
OBJECT_FILES = BingResultSet.o main.o
INC_PATH = -I HTTPClientLib/include
LIB_PATH = -L HTTPClientLib/lib/
start: clean BingResultSet.o main.o
$(CC) $(DEBUG) $(INC_PATH) $(LIB_PATH) $(OBJECT_FILES) -o $(TARGET)
rm -f *.o
BingResultSet.o: BingResultSet.cpp BingResultSet.h
$(CC) $(DEBUG) $(INC_PATH) $(LIB_PATH) -c BingResultSet.cpp
main.o: main.cpp
$(CC) $(DEBUG) $(INC_PATH) $(LIB_PATH) -c main.cpp
clean:
rm -f $(OBJECT_FILES) $(TARGET)
My file structure:
/Desktop/DataMiner/.cpp, .h, and makefile
/Desktop/DataMiner/HTTPClientLib/include/HTTPClient.h
/Desktop/DataMiner/HTTPClientLib/lib/HTTPClient.a
What's the correct way to link my static lib in my makefile?
Here's my $0.02:
there was no static library involved. Assuming you meant the .o files
you mix dependencies and build rules, instead, avoid repeating build rules:
$(TARGET): $(OBJECT_FILES)
$(CXX) $(DEBUG) $(INC_PATH) $^ -o $# $(LIB_PATH)
%.o: %.cpp
$(CXX) $(DEBUG) $(INC_PATH) -c $< -o $#
You used CC for a C++ compiler. That's strange. Use CXX
You used LDFLAGS when you were just compiling
You hardcoded the source and destination paths. Instead use the automatic variables ($^, $< for source; $# for destination)
You tried to hardcode header dependencies. That's error-prone and messes up source specification (you don't want $^ to list .h files in your command line...). Instead, use gcc -MM¹ to generate the dependencies for you!
Next, do a conditional include of those dependencies:
.depends:
$(CXX) -MM $(CXXFLAGS) -c *.cpp > $#
-include .depends
It's usually handy to keep the .o files so you can speed up builds. Of course, this was not a good plan until you generated the header dependencies automatically. If you insist, you can comment the .PRECIOUS target. Intermediate targets are automatically deleted by GNU Make
Here's the integrated offering I ended up with:
CXX = g++
TARGET = main
OBJECT_FILES = BingResultSet.o main.o
INC_PATH = -I HTTPClientLib/include
LIB_PATH = -L HTTPClientLib/lib/
CPPFLAGS = -g -std=c++11
CPPFLAGS+= $(INC_PATH)
# standard derived flags:
CXXFLAGS+=$(CPPFLAGS)
LDFLAGS+=$(LIB_PATH)
start: .depends $(TARGET)
$(TARGET): $(OBJECT_FILES)
$(CXX) $(CXXFLAGS) $^ -o $# $(LDFLAGS)
%.o: %.cpp
$(CXX) $(CXXFLAGS) -c $< -o $#
clean:
rm -f .depends $(OBJECT_FILES) $(TARGET)
# to keep the .o files:
.PRECIOUS: $(OBJECT_FILES)
.depends:
$(CXX) -MM $(CXXFLAGS) -c *.cpp > $#
-include .depends
On a very simple sample set of files you get:
$ make clean
rm -f .depends BingResultSet.o main.o main
$ make
g++ -MM -g -std=c++11 -I HTTPClientLib/include -c *.cpp > .depends
g++ -I HTTPClientLib/include -c BingResultSet.cpp -o BingResultSet.o
g++ -I HTTPClientLib/include -c main.cpp -o main.o
g++ -I HTTPClientLib/include BingResultSet.o main.o -o main -L HTTPClientLib/lib/
$ cat .depends
BingResultSet.o: BingResultSet.cpp BingResultSet.h
main.o: main.cpp BingResultSet.h
test.o: test.cpp
¹ (or similar, see man-page)

Linker input file unused c++ g++ make file

I am unable to figure out what is causing this error that I keep getting upon making my project:
i686-apple-darwin11-llvm-g++-4.2: -lncurses: linker input file unused because linking not done
And my make file looks like this:
CC = g++
LIB_FLAGS = -l ncurses
FLAGS = $(LIB_FLAGS)
DEPENDENCIES = window.o element.o
# FINAL OUTPUTS
main: main.cpp $(DEPENDENCIES)
$(CC) $(FLAGS) -o main.out main.cpp $(DEPENDENCIES)
# MODULES
window.o: main.h classes/window.cpp
$(CC) $(FLAGS) -c classes/window.cpp
element.o: main.h classes/element.cpp
$(CC) $(FLAGS) -c classes/element.cpp
# CLEAN
clean:
rm -rf *.o
rm main.out
Everything compiles okay, but I'm just curious what is causing this error message and what it means..
You are passing linker options to a compiler invocation together with -c, which means that linking is not performed and thereby -l options are unused. In your case, your LIB_FLAGS should not be in FLAGS, but instead specified in the the main: ... rule:
main: main.cpp
$(CC) $(FLAGS) $(LIB_FLAGS) ...
Do not give link flags when you compile (-c flag) your source files. Take a look for this example makefile (very similar as in makefile docs)
CPP = g++
CPPFLAGS =-Wall -g
OBJECTS = main.o net.o
PREFIX = /usr/local
.SUFFIXES: .cpp .o
.cpp.o:
$(CPP) $(CPPFLAGS) -c $<
.o:
$(CPP) $(CPPFLAGS) $^ -o $#
main: $(OBJECTS)
main.o: main.cpp
net.o: net.cpp net.h
.PHONY:
install: main
mkdir -p $(PREFIX)/bin
rm -f $(PREFIX)/bin/main
cp main $(PREFIX)/bin/main
clean:
rm -f *.o main
As has been mentioned already you're passing linker-related flags at the compile stage. Usually you want different flags for compiling and linking, e.g.
CC = g++
CPPFLAGS = -Wall -g -c -o $#
LDFLAGS = -l ncurses -o $#
DEPENDENCIES = main.o window.o element.o
# FINAL OUTPUTS
main: $(DEPENDENCIES)
$(CC) $(LDFLAGS) $(DEPENDENCIES)
# MODULES
main.o: main.h main.cpp
$(CC) $(CPPFLAGS) main.cpp
window.o: main.h classes/window.cpp
$(CC) $(CPPFLAGS) classes/window.cpp
element.o: main.h classes/element.cpp
$(CC) $(CPPFLAGS) classes/element.cpp
# CLEAN
clean:
-rm main $(DEPENDENCIES)

How to get the line numbers for GDB?

Is there a specific way to do this? I'm speaking in general purposes. When I try to launch my program in GDB for example, I get this notification:
Reading symbols from /home/amsterdam/Code/c++/opengl_03/bin/opengl_03...(no debugging symbols found)...done.
It makes me wonder if I have to find a specific file for this?
Update
Note: I have already tried the following command:
nm --debug-sym <your_executable> | grep debug
with no success; it refuses to display anything.
Here is my Makefile:
BIN = bin/
OBJ = obj/
TARGET = opengl_03
DEPS = main.o displayinit.o initializer.o algorithms.o matrix3f.o window.o vertex3.o
CC = g++
CFLAGS = -g -ggdb
LIBS = -lglut -lGLEW -lGL
INCLUDEPATH = -L/usr/include/ -L/usr/lib/ -L/usr/lib/x86_64-linux-gnu/
$(TARGET) : $(DEPS)
$(CC) $(CFLAGS) -o $(BIN)$(TARGET) $(DEPS) $(LIBS) $(INCLUDEPATH)
displayinit.o : displayinit.cpp displayinit.h
$(CC) $(CFLAGS) -c displayinit.cpp $(LIBS) $(INCLUDEPATH) #&& mv displayinit.o $(OBJ)displayinit.o
initializer.o : initializer.cpp initializer.h
$(CC) $(CFLAGS) -c initializer.cpp $(OBJ) $(LIBS) $(INCLUDEPATH)
algorithms.o : algorithms.cpp algorithms.h
$(CC) $(CFLAGS) -c algorithms.cpp $(OBJ) $(LIBS) $(INCLUDEPATH)
matrix3f.o : matrix3f.cpp matrix3f.h
$(CC) $(CFLAGS) -c matrix3f.cpp $(OBJ) $(LIBS) $(INCLUDEPATH)
vertex3.o : vertex3.cpp vertex3.h
$(CC) $(CFLAGS) -c vertex3.cpp $(OBJ) $(LIBS) $(INCLUDEPATH)
window.o : window.cpp window.h
$(CC) $(CFLAGS) $(LIBS) $(INCLUDEPATH) -c window.cpp $(OBJ)
main.o : main.cpp
$(CC) $(CFLAGS) $(LIBS) $(INCLUDEPATH) -c main.cpp $(OBJ)
You need to include debugging symbols when you compile. For example if you are using gcc add the flag -ggdb.
You need to compile with debug symbols included gcc -g option and make sure you don't strip your executable. More details in this link.
-------------------------------------------------Edit-------------------------------------------
Your Makefile does not look good, why don't you use
boilerplate Makefiles. You can find it here, works well for me.