gnu make. recompile unchanged files only - c++

Help me with makefile, please. I want `make' to recompile only files that have been changed. Here is my makefile:
ROOT_DIR= ..
BUILD_TYPE= Release
BUILD_DIR= $(ROOT_DIR)/$(BUILD_TYPE)
O_DIR= $(BUILD_DIR)/obj
TARGETS= ftp_auto_backup sftp_auto_backup
CXX= g++
CXXFLAGS= -DBOOST_THREAD_USE_LIB -O3 -Wall -fmessage-length=0
FTP_LDFLAGS= -static-libstdc++ -static-libgcc -s -L $(ROOT_DIR)/lib/Release -l:libboost_thread-mgw46-mt-1_49.a -l:libcommon.a \
-l:libfile.a -l:libfilesearcher.a -l:libftpclient.a -l:libftplib.a -l:libdbclient.a -l:libsqlite3.a -l:libscheduler.a -l:libws2_32.a
SFTP_LDFLAGS= -static-libstdc++ -static-libgcc -s -L $(ROOT_DIR)/lib/Release -l:libboost_thread-mgw46-mt-1_49.a -l:libcommon.a \
-l:libfile.a -l:libfilesearcher.a -l:libdbclient.a -l:libsqlite3.a -l:libscheduler.a -l:libsftpclient.a -l:libws2_32.a -l:libssh.dll
OBJECTS= appconfig.o backuplauncher.o clientbackup.o main.o
LD_OBJECTS= $(addprefix $(O_DIR)/,$(OBJECTS))
all: init $(TARGETS)
debug: CXXFLAGS= -O0 -g3 -Wall -fmessage-length=0
debug: BUILD_TYPE= Debug
debug: all
init:
#mkdir -p $(BUILD_DIR)
#mkdir -p $(O_DIR)
ftp_auto_backup: set_type_ftp $(OBJECTS)
$(CXX) -o $(BUILD_DIR)/$#.exe $(LD_OBJECTS) $(FTP_LDFLAGS)
sftp_auto_backup: set_type_sftp $(OBJECTS)
$(CXX) -o $(BUILD_DIR)/$#.exe $(LD_OBJECTS) $(SFTP_LDFLAGS)
set_type_ftp:
$(eval CXXFLAGS+=-DPROJECT_TYPE=FTP)
set_type_sftp:
$(eval CXXFLAGS+=-DPROJECT_TYPE=SFTP)
%.o: %.cpp
$(CXX) -c $(CXXFLAGS) $< -o $(O_DIR)/$#
clean:
rm -rf $(addprefix $(ROOT_DIR)/Release/obj/,$(OBJECTS)) $(addprefix $(ROOT_DIR)/Debug/obj/,$(OBJECTS))
rm -rf $(addprefix $(ROOT_DIR)/Release/,$(addsuffix .exe,$(TARGETS))) $(addprefix $(ROOT_DIR)/Debug/,$(addsuffix .exe,$(TARGETS)))
Yes, I know about Generating Prerequisites Automatically, but should I really use it?
Thanks in advance!

Your targets depend on objects in the current directory, not in obj/. Change to this:
ftp_auto_backup: set_type_ftp $(LD_OBJECTS)
$(CXX) -o $(BUILD_DIR)/$#.exe $(LD_OBJECTS) $(FTP_LDFLAGS)
sftp_auto_backup: set_type_sftp $(LD_OBJECTS)
$(CXX) -o $(BUILD_DIR)/$#.exe $(LD_OBJECTS) $(SFTP_LDFLAGS)
# (...)
$(O_DIR)/%.o: %.cpp
$(CXX) -c $(CXXFLAGS) $< -o $#
And yes, if you want your object files to recompile not only when you change the .cpp file, but also when you change the header (.h) files, you need to generate those prerequisites...

I suppose that %.o : %.cpp is not enough, you should use VPATH to let know make where the sources are:
vpath %.cpp src

Related

How do I create object files into a different directory than Makefile's one?

I'm new on using Makefiles because I've been programming with VS2019 on Windows, solving all my compilation and linking problems.
This is the result:
BUILD_DIR:= ./build
SRC_DIRS := ./src
INCL_DIR := ./includes
CC := /usr/bin/g++ #Compiler used
LVERSION := -std=c++17 #Language Version
CXXFLAGS := -g #Cpp flags
CFLAGS := -Wall #Compiler Flags
LFLAGS := -lstdc++fs #Linker Flags
SRCS := Audio.cpp Song.cpp Visual.cpp VisualSong.cpp
LIBS :=
INCLUDES := $(SRCS:%.cpp=$(INCL_DIR)/%.h)
OBJS := $(SRCS:%.cpp=$(BUILD_DIR)/%.o)
PROG := progName.exe
progName: $(OBJS)
$(CC) $(CFLAGS) $(CXXFLAGS) -o $(INCLUDES) $(PROG) $(OBJS)
$(BUILD_DIR)/%.o: $(INCL_DIR)/%.h $(SRC_DIRS)/%.cpp
$(CC) ${CFLAGS} $(CXXFLAGS) $(LVERSION) ${LFLAGS} -c $^
.PHONY: progName
clean:
/bin/rm -rf build/*.o $(PROG) includes/*.gch
This makefile works until is trying to look on objects file, supposedly created on build directory but, in the end, they're created in Makefile's directory, which is an inconvenient since all what i want is to have separated files for organization purposes.
I know that somehow using implicit rules that are using the dst's directory should do the trick, but i think that I'm missing something on the way...
I'm on a Windows 10 machine with WSL for Ubuntu, but this shouldn't be a problem at all for this problem.
Could anyone explain to me what am I missing?
Look at this rule:
$(BUILD_DIR)/%.o: $(INCL_DIR)/%.h $(SRC_DIRS)/%.cpp
$(CC) ${CFLAGS} $(CXXFLAGS) $(LVERSION) ${LFLAGS} -c $^
Ostensibly it is the rule to build build/foo.o, but the recipe ($(CC)...) actually builds foo.o. There is an easy fix:
$(BUILD_DIR)/%.o: $(INCL_DIR)/%.h $(SRC_DIRS)/%.cpp
$(CC) ${CFLAGS} $(CXXFLAGS) $(LVERSION) ${LFLAGS} -c $^ -o $#
Once that works I suggest you make one further change:
$(BUILD_DIR)/%.o: $(SRC_DIRS)/%.cpp $(INCL_DIR)/%.h
$(CC) ${CFLAGS} $(CXXFLAGS) $(LVERSION) ${LFLAGS} -c $< -o $#

Makefile compiling the good files without the dependencies

I have a problem with the dependencies in my Makefile.
There is no problem with the compilation, it compiles perfectly the good *.cc and *.hh but unfortunately, it does not re-compile the dependencies, thus there is no update in the executable.
Here is my makefile:
EXEC ?= program
SRCS = $(shell find -name *.cc)
DEP = $(SRCS:.cc=.d)
OBJDIR = objs
OBJS = $(SRCS:./%.cc=$(OBJDIR)/%.o)
CXX = g++
CFLAGS = -std=c++14 $(addprefix "-I", $(shell find -type d))
## Clean rule
.PHONY: clean
clean:
rm -rf $(OBJDIR)
rm -f $(EXEC)
$(EXEC) : $(OBJS)
#echo "Linking: $#"
$(CXX) $(OBJS) -o $#
-include $(DEP)
$(OBJDIR)/%.o : ./%.cc ./%.hh
#mkdir -p $(#D)
#echo "Compiling: $<"
#$(CXX) -c $(CFLAGS) -MT $# -MMD -MP -o $# $<
It is probably something related to the flag used by g++ but I do not manage to find the solution;
Thanks in advance for the help that you can provide on this issue,
If you do not specify the filename for the generated dependency files, it is going to be ${#:%.o=%.d} (compiler logic). I.e. your dependency files are in $(OBJDIR) and not in ./ where your makefile expects them to be.
Two alternative solutions:
DEP := $(OBJS:%.o=%.d).
#$(CXX) -c $(CFLAGS) -MT $# -MMD -MP -MF $(<:%.cc=%.d) -o $# $<

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.

C++ Makefile. .o in different subdirectories

I have some problems trying to put .o files into a separate directory (/build).
Actually, my sources (in /src) contain some subdirectories, and my Makefile only create the .o of the .cpp contained at the first "level". The other .o are just ignored, so, the target cannot be created.
In my /src directory, I have "three levels" (src/first/second/).
Here's the code of the Makefile :
CC=g++
CFLAGS=-W -Wall -ansi -pedantic -s -O3 -Os -std=c++11 -fpermissive
LDFLAGS= -lboost_system -lboost_regex
SRCDIR=src
HEADDIR=include
LIBDIR=build
BINDIR=bin
BIN=LTN
SRC = $(wildcard src/*.cpp src/*/*.cpp src/*/*/*.cpp)
OBJ = $(patsubst %.cpp,$(LIBDIR)/%.o,$(SRC))
all: $(BIN)
LTN: $(OBJ)
$(CC) -o $(BINDIR)/$# $^ $(LDFLAGS)
$(LIBDIR)/$(SRCDIR)/%.o: $(SRCDIR)/%.cpp $(HEADDIR)/%.h
$(CC) -o $# -c $< $(CFLAGS)
.PHONY = clean
You can try this:
CC=g++
CFLAGS=-W -Wall -ansi -pedantic -s -O3 -Os -std=c++11 -fpermissive
LDFLAGS= -lboost_system -lboost_regex
SRCDIR=src
HEADDIR=include
LIBDIR=build
BINDIR=bin
BIN=LTN
SRC=$(shell find . -name '*.cpp')
TMP=$(subst $(SRCDIR),$(LIBDIR), $(SRC))
OBJ=$(patsubst %.cpp,%.o,$(TMP))
all: $(BIN)
LTN: $(OBJ)
#[ ! -d $(BINDIR) ] & mkdir -p $(BINDIR)
$(CC) -o $(BINDIR)/$# $^ $(LDFLAGS)
$(LIBDIR)/%.o: $(SRCDIR)/%.cpp
#[ ! -d $(dir $#) ] & mkdir -p $(dir $#)
$(CC) -o $# -c $< $(CFLAGS)
.PHONY = clean

c++ makefile with multiple program, autodetection of source files

I recently lost 5 hours to figure out how I could write the makefile I need. I'm not an informaticien or programmer so I'd like some comments on what I managed to do. I already looked a lot on different sites but still...
I need a makefile that creates different executables: prog1, prog2...
To create the .o files, as I have many files with many dependencies, I don't want to specify them all. So I want/need to use automatic variables with a pattern rule. To speed up the compilation I also take care to only recompile the modified files. I achieved this by using the -MD flag that creates a .d file saved in the $(BUILD) directory.
What I still can't do is to detect automatically which .o files prog1 needs. So for now I have to specify them automatically... If you know how to do that automatically...
I also would like to save the .o files in the $(BUILD) directory, but I can't make it work.
Any advice are welcome !
Thx
CXX = g++
ERRORS = -Wall -Wextra -pedantic
LAPACK = -llapack -lblas
OPTION = -O3 -fopenmp
CXXFLAGS = $(LAPACK) $(ERRORS) $(OPTION)
LDFLAGS = $(LAPACK) $(ERRORS) $(OPTION)
BUILD=build
SRCS=(wildcard *.cpp)
all:prog1 prog2 ...
prog1:prog1.o dep_only_for_prog_1.o dep_for_all_progs.o dep_for_some_progs.o
$(CXX) -o $# $^ $(LDFLAGS) $(NOASSERT)
prog2:prog2.o dep_only_for_prog_2.o dep_for_all_progs.o dep_for_some_progs.o
$(CXX) -o $# $^ $(LDFLAGS) $(NOASSERT)
...
%.o:%.cpp
$(CXX) -MD -c $(CXXFLAGS) $(NOASSERT) $< -o $#
mv $(<:.cpp=.d) $(BUILD)
-include $(addprefix $(BUILD)/$(SRCS:.cpp=.d))
clean:
rm -f *.o $(BUILD)/*
You just can't get make to infer somehow which files belong to which programs, but you CAN make your makefile simpler to read and update. Also you have a few bad things here, such as adding $(LAPACK) (which contains linker flags) to $(CXXFLAGS) (which are passed to the compiler).
Try:
PROGRAMS = prog1 prog2
prog1_SOURCES = prog1.cpp dep_only_for_prog_1.cpp \
dep_for_all_progs.cpp dep_for_some_progs.cpp
prog2_SOURCES = prog2.cpp dep_only_for_prog_2.cpp \
dep_for_all_progs.cpp dep_for_some_progs.cpp
#----- Don't need to change below here
CXX = g++
ERRORS = -Wall -Wextra -pedantic
LAPACK = -llapack -lblas
OPTION = -O3 -fopenmp
CXXFLAGS = $(ERRORS) $(OPTION)
LDFLAGS = $(LAPACK) $(ERRORS) $(OPTION)
BUILD=build
SRCS := $(wildcard *.cpp)
all: $(PROGRAMS)
.SECONDEXPANSION:
$(PROGRAMS): $$($$#_SOURCES:%.cpp=%.o)
$(CXX) -o $# $^ $(LDFLAGS) $(NOASSERT)
%.o : %.cpp
$(CXX) -MD -c $(CXXFLAGS) $(NOASSERT) $< -o $#
mv $(<:.cpp=.d) $(BUILD)
-include $(addprefix $(BUILD)/$(SRCS:.cpp=.d))
clean:
rm -f *.o $(BUILD)/*
Or you can use eval if you want.