Makefile compiling even though header files doesn't change - c++

I have a makefile which compiles a program with many dependencies like this:
CXX=g++
IDIR=lib
CFLAGS=-Wall -O2 -std=c++11 -I$(IDIR)
UDIR=utils
CFILES=Utils.cpp Structs.cpp Registry.cpp Dealer.cpp
CFILES:=$(patsubst %.cpp,$(UDIR)/%.cpp,$(CFILES))
DEPS=$(wildcard $(IDIR)/*.hh)
ODIR=obj
OBJ:=$(patsubst $(UDIR)/%.cpp,$(ODIR)/%.o,$(CFILES))
CDIR=strategies
EXTRA_CFILES=$(wildcard $(CDIR)/Strategy*.cpp)
CFILES += $(EXTRA_CFILES)
EXTRA_OBJ:=$(patsubst $(CDIR)/%.cpp,$(ODIR)/%.o,$(EXTRA_CFILES))
OBJ += $(EXTRA_OBJ)
all: create_header environment.exe
create_header:
chmod +x create_headers.sh
bash create_headers.sh
$(ODIR)/%.o: $(UDIR)/%.cpp $(DEPS)
$(CXX) -c -o $# $< $(CFLAGS)
$(ODIR)/%.o: $(CDIR)/%.cpp $(DEPS)
$(CXX) -c -o $# $< $(CFLAGS)
environment.o: environment.cpp $(OBJ)
$(CXX) -c -o $# $< $(CFLAGS)
environment.exe: environment.o $(OBJ)
$(CXX) $(CFLAGS) $^ -o $#
m='Auto'
git_upload:
git add -A
git commit -m "$(m)"
git push
.PHONY: clean
clean:
rm -rf $(ODIR)/*.o *.exe
However, when I type make, it is always compiling everything. I only want it to compile the dependencies when a change has been made, either to header or implementation files. The problem is, it is always compiling everything even though I haven't changed anything.

Related

Makefile : Compiling a library in a subdirectory

I want a makefile to compile a library (DRNG) with another makefile located in a subdirectory.
Here is what I have done :
.PHONY: out.exe clean drng
DRNG_DIR=./libdrng-1.0/
clean:
make clean -C $(DRNG_DIR)
#rm -f out.exe *.o
drng:
cd $(DRNG_DIR) && ./configure
make -C $(DRNG_DIR)
CC=g++
CFLAGS=-Wall -Werror -std=c++11
LDFLAGS=-L$(DRNG_DIR) -ldrng
objects=...
%.o: %.cpp
$(CC) -c $(CFLAGS) $*.cpp -o $*.o
out.exe: drng main.o $(objects)
$(CC) $(CFLAGS) $^ -o $# $(LDFLAGS)
I get an error : g++: drng: no such file or directory
Make is trying to compile 'drng'. I thought putting it in PHONY was supposed to prevent that.

Make recompiles non modified files

I have a makefile for my program but I got everything recompiled every time I run it, even if I modify nothing.
Every time I run make it recompiles simHwIntf.cpp showHelp.cpp and sendFromFile.cpp
This is my make file:
IDIR = inc
LDIR = -L/usr/lib/x86_64-linux-gnu/
SDIR = src
ODIR = obj
BINDIR = bin
LDLIBS = -luhd
OBJ = $(patsubst %,$(ODIR)/%,$(O_FILES))
CC = g++
CFLAGS = -Wall -std=c++11 -I $(IDIR) #-Werror
BINARIES= main
C_FILES = simHwIntf.cpp showHelp.cpp sendFromFile.cpp
H_FILES = simHwIntf.h
O_FILES = $(C_FILES:.cpp=.o)
all: $(BINARIES)
#echo "Make file executed"
$(BINARIES): $(O_FILES)
$(CC) $(CFLAGS) -o $(BINDIR)/$# $(OBJ) $(LDIR) $(LDLIBS)
fileCreator: fileCreator.o
$(CC) $(CFLAGS) -o $(BINDIR)/$# $(ODIR)/fileCreator.o
fileHandler: fileHandler.o
$(CC) $(CFLAGS) -o $(BINDIR)/$# $(ODIR)/fileHandler.o
backYard: backYard.o
$(CC) $(CFLAGS) -o $(BINDIR)/$# $(ODIR)/backYard.o
%.o: $(SDIR)/%.cpp $(IDIR)/$(H_FILES)
$(CC) $(CFLAGS) -c -o $(ODIR)/$# $<
clean:
-rm -rf $(ODIR)/*.o *~
distclean: clean
-rm -rf $(BINDIR)/*
Each time the output in the shell is:
g++ -Wall -std=c++11 -I inc -c -o obj/simHwIntf.o src/simHwIntf.cpp
g++ -Wall -std=c++11 -I inc -c -o obj/showHelp.o src/showHelp.cpp
g++ -Wall -std=c++11 -I inc -c -o obj/sendFromFile.o src/sendFromFile.cpp
g++ -Wall -std=c++11 -I inc -o bin/main obj/simHwIntf.o obj/showHelp.o obj/sendFromFile.o -L/usr/lib/x86_64-linux-gnu/ -luhd
Make file executed
I've already search and read this: (How do I make Makefile to recompile only changed files?) but didn't help much.
Anybody that could give me a hand with this ?
I have a doubt with the directories, maybe one or several directories are re-created each time I run make and this causes everything inside to look like new to the compiler.
Thanks
You can see what triggered the build by echoing the dependencies that changed. Add this to your %.o target :
#echo [triggered by changes in $?]
You should also use the VPATH special variable instead of specifying the sources path in your %.o target. See GNU make VPATH documentation
Please try replacing
%.o: $(SDIR)/%.cpp $(IDIR)/$(H_FILES)
$(CC) $(CFLAGS) -c -o $(ODIR)/$# $<
with
$(ODIR)/%.o: $(SDIR)/%.cpp $(IDIR)/$(H_FILES)
$(CC) $(CFLAGS) -c -o $(ODIR)/$# $<
Directories matter when you define targets.
If a define a rule
myexec: objdir/myexec.o
$(CC) $(CFLAGS) -o bindir/myexec objdir/myexec.o $(LDFLAGS)
Make believes that that this would create the file myexec in the working directory. When you rerun make the target myexec wasn't found, so it will be created again. Add the paths in the targets and it should work.
Try replacing
BINARIES= main
with
BINARIES= $(BINDIR)/main
and the rule
$(CC) $(CFLAGS) -o $(BINDIR)/$# $(OBJ) $(LDIR) $(LDLIBS)
with
$(CC) $(CFLAGS) -o $# $^ $(LDIR) $(LDLIBS)
And change the other rules similarly.
Note, in general it is a bad idea to use $# in combination with a path when creating the target in some rule (as in $(BINDIR)/$#), because this will never create the actual target file. A bare $# should be sufficient.

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 change my makefile to build into a separate folder

I have the following makefile:
CC=g++
CCOPTS=-Wall -Wextra -g
OBJS = manager.o tcpcon.o
TARGETS = manager
.PHONY: all clean
$(TARGETS) : $(OBJS)
$(CC) -o $# $^ $(CFLAGS) $(LIBS)
all: $(TARGETS) $(OBJS)
clean:
rm -f $(TARGETS) $(OBJS)
%: %.cpp
$(CC) $(CCOPTS) -o $# $<
Is there a way I can make my .o and bin files be built into a directory called build? I tried going through some tutorials, but I guess I just don't fully understand makefiles..
Don't feel too bad; I'm not sure anyone fully understands makefiles.
BUILD_DIR = build
OBJS = $(BUILD_DIR)/manager.o $(BUILD_DIR)/tcpcon.o
TARGETS = $(BUILD_DIR)/manager
...
$(BUILD_DIR)/%.o: %.cpp
$(CC) -c $(CCOPTS) -o $# $<

Using make to move .o files to a separate directory

I've tried numerous attempts to move my .o files to my obj folder, but no matter what I do, it simply just doesn't work.
Judging from the makefile provided, what is the best method to move .o files to a specified folder?
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
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) $(LIBS) $(INCLUDEPATH) -c displayinit.cpp && mv displayinit.o $(OBJ)displayinit.o
initializer.o : initializer.cpp initializer.h
$(CC) $(LIBS) $(INCLUDEPATH) -c initializer.cpp $(OBJ)
algorithms.o : algorithms.cpp algorithms.h
$(CC) -c algorithms.cpp $(OBJ)
matrix3f.o : matrix3f.cpp matrix3f.h
$(CC) $(LIBS) $(INCLUDEPATH) -c matrix3f.cpp $(OBJ)
vertex3.o : vertex3.cpp vertex3.h
$(CC) $(LIBS) $(INCLUDEPATH) -c vertex3.cpp $(OBJ)
window.o : window.cpp window.h
$(CC) $(LIBS) $(INCLUDEPATH) -c window.cpp $(OBJ)
main.o : main.cpp
$(CC) $(LIBS) $(INCLUDEPATH) -c main.cpp $(OBJ)
To specify where the object is created use -o
window.o : window.cpp window.h
$(CC) $(LIBS) $(INCLUDEPATH) -c window.cpp -o $(OBJ)/$#
Here is what you could do:
specify the directory where you want the object files to go
OBJDIR = objdir
Create a list of object files that need to be compiled, from the list of all .cpp files by replacing .cpp with .o and add the prefix $(OBJDIR)/ to it:
OBJ = $(addprefix $(OBJDIR)/, $(patsubst %.cpp, %.o, $(wildcard *.cpp)))
So your $(OBJ) will look like: objdir/window.o objdir/main.o and so on
Add a target to create the directory if it does not exist:
$(OBJDIR):
mkdir $(OBJDIR)
Make the directory target before you make your main target:
all: $(OBJDIR) myapp
Rule to compile all the .o object files in $(OBJDIR) from .cpp files in the current directory:
$(OBJDIR)/%.o: %.cpp
$(GCC) $(CPPFLAGS) -c $< -o $#
This will result in something like:
g++ -c main.cpp -o objdir/main.o
Your main target is unchanged:
$(TARGET): $(OBJ)
$(GCC) $(LDFLAGS) -o $# $^
This will look like:
g++ -o myapp objdir/window.o objdir/main.o
For completeness add clean target to cleanup objects:
clean:
#rm -f $(TARGET) $(wildcard *.o)
#rm -rf $(OBJDIR)
And define .PHONY targets, e.g. these will be made even if directories or files with the same name exist:
.PHONY: all clean
So it should look like:
OBJDIR = objdir
OBJ = $(addprefix $(OBJDIR)/, $(patsubst %.cpp, %.o, $(wildcard *.cpp)))
TARGET = my app
.PHONY: all clean
all: $(OBJDIR) $(TARGET)
$(OBJDIR):
mkdir $(OBJDIR)
$(OBJDIR)/%.o: %.cpp
$(GCC) $(CPPFLAGS) -c $< -o $#
$(TARGET): $(OBJ)
$(GCC) $(LDFLAGS) -o $# $^
clean:
#rm -f $(TARGET) $(wildcard *.o)
#rm -rf $(OBJDIR)
And if you have files such as main.cpp and a.cpp this is what make would do:
> ls
Makefile a.cpp main.cpp
> make
mkdir objdir
g++ -I. -c a.cpp -o objdir/a.o
g++ -I. -c main.cpp -o objdir/main.o
g++ -o myapp objdir/a.o objdir/main.o
> ls
Makefile a.cpp main.cpp objdir myapp
> make clean
> ls
Makefile a.cpp main.cpp
And if you want to read more details about any of the above have a look at GNU make doc page
In response to the comment, some more tips:
1) Remove some redundancy
This part is very repetitive:
displayinit.o : displayinit.cpp displayinit.h
$(CC) $(LIBS) $(INCLUDEPATH) -c displayinit.cpp && mv displayinit.o $(OBJ)displayinit.o
initializer.o : initializer.cpp initializer.h
$(CC) $(LIBS) $(INCLUDEPATH) -c initializer.cpp $(OBJ)
algorithms.o : algorithms.cpp algorithms.h
$(CC) -c algorithms.cpp $(OBJ)
# ...
You can replace it by two parts:
1) a more general rule, something like:
%.o: %.cpp
$(CC) -c $(LIBS) $(INCLUDEPATH) $< -o $#
$< and $# are automatic variables, $# expands to the name of currently built target and $< is the first dependency ($^ would be "all the dependencies", there are more such vars - see the Make manual).
2) any additional deps (i.e. headers):
displayinit.o: displayinit.h
matrix3f.o: matrix3f.h
main.o: main.h window.h displayinit.h
#etc
Note: For each .o file, its dependencies should contain:
the .cpp from which it is built (the dependency is from the general rule),
all .h files which are included from that .cpp files (which you need to add later).
Note that you omitted the latter part in your original makefile. This would cause you some problems one day.
2) Generate the deps automatically
Basically every time you add an #include in any of your files, you'd need to modify your makefile to reflect the new dependency between .cpp/.o and .h files. This is very troublesome, but fortunately there are automated solutions for that. There are two approaches for C/C++ here:
Use your compiler to generate the dependencies for you (gcc/g++ -MM for instance).
Use an additional tool such as makedepend.
Either way, you need to include that set of dependencies dynamically in the makefile. This needs some trickery, but once you have it, you never have to worry about dependencies. Have a google for "C++ makefile dependencies", there should be plenty of resources.
Here's a to-the-point doc about Make.
Following worked for me :
g++ test.cpp -c -o obj/test.o
So in your case, for example, you would make the following modification :
displayinit.o : displayinit.cpp displayinit.h
$(CC) $(LIBS) $(INCLUDEPATH) -c displayinit.cpp -o displayinit.o $(OBJ)displayinit.o
Also, for the final compilation, you need to pick up the .o files from the obj folder, so modify DEPS to have bin/<xyz>.o. Alternatively, you could cd obj before the final build :
$(TARGET) : $(DEPS)
cd $(OBJ)
$(CC) $(CFLAGS) -o ../$(BIN)$(TARGET) $(DEPS) $(LIBS) $(INCLUDEPATH)
In the first target, add the command to move the files to the desired dir.
$(TARGET) : $(DEPS)
$(CC) $(CFLAGS) -o $(BIN)$(TARGET) $(DEPS) $(LIBS) $(INCLUDEPATH)
mv *.o obj/