How can I store my .o files in a sepparate folder? - makefile

INCDIR=include
SRCDIR=src
SRC = $(wildcard $(SRCDIR)/*.cpp)
DEPS = $(wildcard $(INCDIR)/*.h)
OBJ = $(SRC:.cpp=.o)
CFLAGS = -I$(INCDIR) -Wall -Weffc++ -Wextra -Wsign-conversion
CC=g++
preprocessor: $(OBJ)
$(CC) $(OBJ) -o $# $(CFLAGS)
$(SRCDIR)/%.o: $(SRCDIR)/%.cpp
$(CC) -c $(CFLAGS) $^ -o $#
clean:
rm $(SRCDIR)/*.o preprocessor
This is my current makefile, if I wanted to store my .o files in a sepparate directory, src/obj for example, how would I have to modify it?

Many ways to do it, but according to your own code, you could do:
INCDIR=include
SRCDIR=src
OBJDIR=obj
SRC= $(wildcard $(SRCDIR)/*.cpp)
DEPS= $(wildcard $(INCDIR)/*.h)
OBJ=$(patsubst %.cpp, $(OBJDIR)/%.o, $(notdir $(SRC)))
CFLAGS= -I$(INCDIR) -Wall -Weffc++ -Wextra -Wsign-conversion
CC=g++
$(OBJDIR):
#if ! [ -d $(#) ]; then\
echo "==> creating dir: $(#)";\
mkdir $(#);\
fi
preprocessor: $(OBJDIR) $(OBJ)
$(CC) $(OBJ) -o $# $(CFLAGS)
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp
$(CC) -c $(CFLAGS) $^ -o $#
clean:
rm $(OBJDIR)/*.o preprocessor
printobj: $(OBJDIR)
#echo "$(OBJ)"
will output:
$ gmake preprocessor
g++ -c -Iinclude -Wall -Weffc++ -Wextra -Wsign-conversion src/a.cpp -o obj/a.o
g++ -c -Iinclude -Wall -Weffc++ -Wextra -Wsign-conversion src/b.cpp -o obj/b.o
g++ obj/a.o obj/b.o -o preprocessor -Iinclude -Wall -Weffc++ -Wextra -Wsign-conversion
NOTE: the target printobj is just here to output what you could expect, the target $(OBJDIR) ensure your directory exist before creating object files.

The are just a few things to change:
INCDIR := include
SRCDIR := src
OBJDIR := $(SRCDIR)/obj
SRC := $(wildcard $(SRCDIR)/*.cpp)
DEPS := $(wildcard $(INCDIR)/*.h)
OBJ := $(patsubst $(SRCDIR)/%.cpp,$(OBJDIR)/%.o,$(SRC))
CFLAGS := -I$(INCDIR) -Wall -Weffc++ -Wextra -Wsign-conversion
CC := g++
preprocessor: $(OBJ)
$(CC) $^ -o $# $(CFLAGS)
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp | $(OBJDIR)
$(CC) -c $(CFLAGS) $< -o $#
$(OBJDIR):
mkdir -p "$#"
clean:
rm -f $(OBJ) preprocessor
Note some other minor modifications:
the | $(OBJDIR) order-only prerequisite and the $(OBJDIR): rule to ensure the objects directory exists before compiling,
:= instead of = for all make variable assignments because you don't need recursively expanded variables here,
$^ instead of $(OBJ) in the link recipe because using automatic variables in recipes makes them more generic,
$< instead of $^ in the compile recipe because you compile only the first prerequisite, not all of them,
rm -f $(OBJ) preprocessor instead of rm $(SRCDIR)/*.o preprocessor to remove only the object files of the project and avoid errors if none exists.

Related

Why does my Makefile with pattern rules not create debugging symbols for main?

I am using this auto-generated Makefile with pattern rules, that I oviously do not understand yet. I want to create debuggins symbols and then debug main, but it doesn't work. There is a -g flag. Adding $(LDFLAGS) statement above after $(ODIR) does not print one as expcted.
IDIR =./include
CC=g++
CFLAGS = -I$(IDIR)
LDFLAGS = -g
ODIR=./
LIBS=
_OBJ = main.o
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
$(ODIR)/%.o: %.c
$(CC) -c -o $# $< $(CFLAGS)
main: $(OBJ)
$(CC) $(LDFLAGS) -o $# $^ $(CFLAGS) $(LIBS)
.PHONY: clean
clean:
rm -f $(ODIR)/*.o
This is the terminal output
g++ -c -o Source.o Source.cpp
g++ -g -o Source Source.o -I./include
Your sources are C++ (.cpp) but your Makefile contains explicit instructions for building C files. Make is therefore falling back to its built in implicit rules.
Also note that by convention those rules use $(CXX) to refer to the C++ compiler, with $(CXXFLAGS) replacing $(CFLAGS), and the -I flag belongs in $(CPPFLAGS):
IDIR =./include
CPPFLAGS = -I$(IDIR)
CXXFLAGS = -g
ODIR=.
LIBS=
_OBJ = main.o
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
$(ODIR)/%.o: %.cpp
$(CXX) -c -o $# $(CPPFLAGS) $(CXXFLAGS) $<
main: $(OBJ)
$(CXX) $(CXXFLAGS) $(LDFLAGS) -o $# $^ $(LIBS)
.PHONY: clean
clean:
rm -f $(OBJ)
If you were to do away with the ODIR handling and use the conventional variable names you could do without the explicit .o: .cpp rule altogether.

How to compile source objects into another directory and then build an executable?

Good day. I am in a directory, where is Makefile and folders src and bin. How can I compile object files into bin folder and then build an executable file?
I read some instructions and added $(BIN) before %.o, but it didn't helped, object files appear in folder with makefile. Where is the problem?
CC = arm-linux-gnueabihf-gcc
CXX = arm-linux-gnueabihf-g++
CPPFLAGS = -I .
CFLAGS =-g -std=gnu99 -O1 -Wall
CXXFLAGS = -g -std=gnu++11 -O1 -Wall
LDFLAGS = -lrt -lpthread
SRCDIR = src
BIN = bin
SOURCES = $(wildcard $(SRCDIR)/*.cpp) $(wildcard $(SRCDIR)/*.c)*
...
OBJECTS += $(filter %.o,$(SOURCES:%.c=%.o))
OBJECTS += $(filter %.o,$(SOURCES:%.cpp=%.o))
#$(warning OBJECTS=$(OBJECTS))
ifeq ($(filter %.cpp,$(SOURCES)),)
LINKER = $(CC)
LDFLAGS += $(CFLAGS) $(CPPFLAGS)
else
LINKER = $(CXX)
LDFLAGS += $(CXXFLAGS) $(CPPFLAGS)
endif
$(BIN)/%.o:%.c
$(CC) $(CFLAGS) -c $<
$(BIN)/%.o:%.cpp
$(CXX) $(CXXFLAGS) -c $<
all: $(TARGET_EXE)
$(TARGET_EXE): $(OBJECTS)
$(LINKER) $(LDFLAGS) -L. $^ -o $#
.PHONY : dep all run copy-executable debug
dep: depend
depend: $(SOURCES) *.h
echo '# autogenerat`enter code here`ed dependencies' > depend
ifneq ($(filter %.c,$(SOURCES)),)
$(CC) $(CFLAGS) $(CPPFLAGS) -w -E -M $(filter %.c,$(SOURCES)) \
>> depend
endif
ifneq ($(filter %.cpp,$(SOURCES)),)
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -w -E -M $(filter %.cpp,$(SOURCES)) \
>> depend
endif
clean:
rm -f *.o *.a $(OBJECTS) $(TARGET_EXE) connect.gdb depend
...
It's not clear to me how this makefile can works as well as it does, given that you haven't told it where to find the source files (unless you do so in one of the elided sections).
In these rules:
$(BIN)/%.o:%.c
$(CC) $(CFLAGS) -c $<
$(BIN)/%.o:%.cpp
$(CXX) $(CXXFLAGS) -c $<
you tell the compiler to build object files, but you don't specify where to build them, and the default is to build them in the working directory. You can override that with the -o option:
$(BIN)/%.o:%.c
$(CC) $(CFLAGS) -c $< -o $#
$(BIN)/%.o:%.cpp
$(CXX) $(CXXFLAGS) -c $< -o $#
Once you have the object files where you want them (bin/), you must ensure that the linking rule:
$(TARGET_EXE):$(OBJECTS)
$(LINKER) $(LDFLAGS) -L. $^ -o $#
can find them. The best way to do that is to ensure that OBJECTS contains the correct paths to the object files. I'm not sure how to advise you to do that, since from the look of your makefile that variable might not contain what you think it does.
EDIT:
Let's take this in stages.
Suppose we have on source file, src/foo.c. What we want is:
src/foo.c -> bin/foo.o
bin/foo.o -> foo
This requires two rules, which we can write like this:
$(BIN)/%.o: src/%.c
$(CC) $(CFLAGS) -c $< -o $#
$(TARGET_EXE): bin/foo.o
$(LINKER) $(LDFLAGS) -L. $^ -o $#
We actually have many source files, some of which are C++ files. So we must have a rule for them:
$(BIN)/%.o: src/%.cpp
$(CXX) $(CXXFLAGS) -c $< -o $#
and construct a longer list of objects:
OBJECTS := bin/foo.o bin/bar.o bin/baz.o bin/quartz.o...
$(TARGET_EXE): $(OBJECTS)
$(LINKER) $(LDFLAGS) -L. $^ -o $#
(Mixing C and C++ seems unhealthy to me, but never mind.)
And how do we construct that list of objects? We must start with the list of sources which wildcard can produce:
SRC := src
C_SOURCES := $(wildcard $(SRC/*.c)
# this is src/foo.c src/bar.c
SRC := src
CPP_SOURCES := $(wildcard $(SRC/*.cpp)
# this is src/baz.cpp src/quartz.cpp
and then convert them to the object file names we actually want:
BIN := bin
OBJECTS := $(patsubst $(SRC)/%.cpp,$(BIN)/%.o, $(CPP_SOURCES))
OBJECTS += $(patsubst $(SRC)/%.c,$(BIN)/%.o, $(C_SOURCES))
# this is bin/foo.o bin/bar.o bin/baz.o bin/quartz.o
That should give you the effect you want, and if you understand it you will understan why your old makefile did not.

makefile error: opening dependency file .d/file_name.Td: No such file or directory

I am trying to adapt a makefile (that I found here) that automatically generates dependencies. However, when I run make I get the following error message:
t#t-XPS-13-9365:~/pf/test$ make
g++ -MT .o/test_resamplers.o -MD -MP -MF .d/test_resamplers.Td -std=c++11 -g -Wall -Wextra -pedantic -I/usr/local/include/UnitTest++ -I/usr/include/eigen3 -I../include -c -o .o/test_resamplers.o test_resamplers.cpp
test_resamplers.cpp:155:1: fatal error: opening dependency file .d/test_resamplers.Td: No such file or directory
}
^
compilation terminated.
Makefile:66: recipe for target '.o/test_resamplers.o' failed
make: *** [.o/test_resamplers.o] Error 1
Perhaps I am using the wrong DEPFLAGS variable in my makefile. I did switch the compiler from clang++ in the example to g++. Here's my makefile:
# output binary
BIN := run_tests
# source files
SRCS := \
main.cpp test_cf_filters.cpp test_resamplers.cpp test_rv_eval.cpp \
test_rv_samp.cpp test_utils.cpp
# intermediate directory for generated object files
OBJDIR := .o
# intermediate directory for generated dependency files
DEPDIR := .d
# object files, auto generated from source files
OBJS := $(patsubst %,$(OBJDIR)/%.o,$(basename $(SRCS)))
# compilers (at least gcc and clang) don't create the subdirectories automatically
$(shell mkdir -p $(dir $(OBJS)) >/dev/null)
# C++ compiler
CXX := g++
# linker
LD := g++
# C++ flags
CXXFLAGS := -std=c++11
# C/C++ flags
CPPFLAGS := -g -Wall -Wextra -pedantic -I/usr/local/include/UnitTest++ -I/usr/include/eigen3 -I../include
# linker flags
LDFLAGS := "-L../bin" "-L/usr/local/lib"
# flags required for dependency generation; passed to compilers
DEPFLAGS = -MT $# -MD -MP -MF $(DEPDIR)/$*.Td
# libraries
LDLIBS := -lpf -lUnitTest++
# compile C++ source files
COMPILE.cc = $(CXX) $(DEPFLAGS) $(CXXFLAGS) $(CPPFLAGS) -c -o $#
# link object files to binary
LINK.o = $(LD) $(LDFLAGS) $(LDLIBS) -o $#
# precompile step
PRECOMPILE =
# postcompile step
POSTCOMPILE = mv -f $(DEPDIR)/$*.Td $(DEPDIR)/$*.d
all: $(BIN)
.PHONY: clean
clean:
$(RM) -r $(OBJDIR) $(DEPDIR)
.PHONY: help
help:
#echo available targets: all dist clean distclean install uninstall check
$(BIN): $(OBJS)
$(LINK.o) $^
$(OBJDIR)/%.o: %.c
$(OBJDIR)/%.o: %.c $(DEPDIR)/%.d
$(PRECOMPILE)
$(COMPILE.c) $<
$(POSTCOMPILE)
$(OBJDIR)/%.o: %.cpp
$(OBJDIR)/%.o: %.cpp $(DEPDIR)/%.d
$(PRECOMPILE)
$(COMPILE.cc) $<
$(POSTCOMPILE)
$(OBJDIR)/%.o: %.cc
$(OBJDIR)/%.o: %.cc $(DEPDIR)/%.d
$(PRECOMPILE)
$(COMPILE.cc) $<
$(POSTCOMPILE)
$(OBJDIR)/%.o: %.cxx
$(OBJDIR)/%.o: %.cxx $(DEPDIR)/%.d
$(PRECOMPILE)
$(COMPILE.cc) $<
$(POSTCOMPILE)
.PRECIOUS = $(DEPDIR)/%.d
$(DEPDIR)/%.d: ;
-include $(DEPS)
You create the object directory with this line:
$(shell mkdir -p $(dir $(OBJS)) >/dev/null)
but you don't create the DEPDIR anywhere, so when the compiler tries to create a file there it fails.
You could add this line to make the dependency directory:
$(shell mkdir -p $(DEPDIR))
Or, add it into the previous shell function.

CPPUTestMakeFile Help linking

I am trying to make a makefile, which can make an exe for CppUTest. It can not find the headers, what have I done wrong? First time making a makefile, not 100% sure what I'm doing.
#The compiler to use
CC = g++
LINK = -g -pedantic -Wall -lstdc++ -lpthread -ldl -lm -Wl,-rpath,.
COMPILE = -g -O3 -D_THREAD_SAFE -pedantic -Wall -c -Wno-deprecated
#Name of the EXE file to create.
EXE = ./Tests
SRCS = $(shell ls *.cpp)
OBJS = $(subst .cpp,.o,$(SRCS))
#Extra flags to give to the C compiler.
CFLAGS =
#Libraries to include
LIBS= -lCppUTestExt -lCppUTest -lm
#Extra flags to give to the C++ compiler.
CXXFLAGS = -I/home/mg/DS-5-Workspace/Tests/include
#Extra flags to give to compilers when they are supposed to invoke the linker, ‘ld’,
#such as -L. Libraries (-lfoo) should be added to the LDLIBS variable
#instead.
LDFLAGS = -L/home/mg/DS-5-Workspace/Tests/cpputest/lib
#Extra flags to give to the C preprocessor and programs that use it (the C and
#Fortran compilers).
CPPFLAGS =
.SUFFIXES: .o .cpp
.cpp.o:
$(CC) $(CFLAGS) $(CXXFLAGS) $(LDFLAGS) $(COMPILE) $(LIBS) $<
all: $(OBJS)
$(CC) $(CFLAGS) $(CXXFLAGS) $(LDFLAGS) $(LIBS) $(OBJS) -o $(EXE) $(LINK)
-include depend.mak
depend:
g++ -MM $(SRCS) > depend.mak
#static:
#ar -crvs $(a) $(OBJS)
#shared: $(OBJS)
#$(CC) -shared -Wl,-soname -lc -o $(so) $(OBJS)
clean:
rm -rf $(OBJS) depend.mak $(EXE) $(so) $(a)
I have the following error:
error: CppUTest/CommandLineTestRunner.h: No such file or directory
Well, you're mixing up a lot of things.
Let's clean this up and keep only what is needed :
EXE := Tests
SRC_DIR := .
OBJ_DIR := obj
SRC := $(wildcard $(SRC_DIR)/*.cpp)
OBJ := $(SRC:$(SRC_DIR)/%.cpp=$(OBJ_DIR)/%.o)
CPPFLAGS := -I/home/mg/DS-5-Workspace/Tests/include
CPPFLAGS += -MMD -MP -D_THREAD_SAFE
CXXFLAGS := -W -Wall -Wno-deprecated -pedantic -O3 -g
LDFLAGS := -L/home/mg/DS-5-Workspace/Tests/cpputest/lib
LDFLAGS += -Wl,-rpath,.
LDLIBS := -lCppUTestExt -lCppUTest -lm -lstdc++ -lpthread -ldl
.PHONY: all clean fclean re
all: $(EXE)
clean:
$(RM) -f -r $(OBJ_DIR)
fclean: clean
$(RM) -f $(EXE)
re: fclean all
$(EXE): $(OBJ)
$(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $#
# %.a: $(OBJ)
# $(AR) crvs $# $^
# ranlib $#
# %.so: CXXFLAGS += -fPIC
# %.so: $(OBJ)
# $(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $#
$(OBJ_DIR):
#mkdir -p $#
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp | $(OBJ_DIR)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $# -c $<
-include $(OBJ:.o=.d)
Some explanations :
Avoid the $(shell ...) function, because it'll be executed each time the variable is called if assigned with the = operator instead of := operator.
$(CC) is a built-in variable containing cc or gcc (should be equivalent). Use the built-in $(CXX) to use g++.
-g, -pedantic, -O3, -Wno-deprecated and -Wall are compiler flags, they should be in the CFLAGS (for C) or CXXFLAGS (for C++) built-in variables.
-I <path> and -D_THREAD_SAFE are preprocessor flag, thus should be in the CPPFLAGS built-in variable.
-MMD -MP will auto-generate dependency files (.d extension) for each .o file. You can read more here.
.cpp.o: is a suffix rule, and suffix rules are the old-fashioned way of defining implicit rules for make. You should just rely upon these implicit rules make already know about or make your own the modern way.
You don't need to define .SUFFIXES: by yourself for such widely used targets. The variable SUFFIXES is defined to the default list of suffixes before make reads any makefiles. Make 3.82 defines these suffixes by default :
.SUFFIXES: .out .a .ln .o .c .cc .C .cpp .p .f .F .m .r .y .l .ym .yl .s .S .mod .sym .def .h .info .dvi .tex .texinfo .texi .txinfo .w .ch .web .sh .elc .el
If you have any questions, go on.

How to make specific binary from specific object file?

Here is my makefile, i have object files in obj/ directory, and i need to compile them into binaries in bin/ folder, but somehow it doesn't work as i wanted it to work, any ideas?
SOURCES= $(wildcard *.c)
OBJECTS:= $(patsubst %.c, %.o, $(SOURCES))
OBJECTS:= $(addprefix obj/,$(OBJECTS))
NAMES:= $(patsubst %.c, %, $(SOURCES))
NAMES:= $(addprefix bin/,$(NAMES))
CC=gcc
CFLAGS= -Wall -c -o
DIRS = bin obj
all: $(DIRS) $(NAMES)
$(NAMES): $(OBJECTS)
$(CC) -o $# $<
obj/%.o: %.c
$(CC) $(CFLAGS) $# $<
$(DIRS):
mkdir -p $#
clean:
rm -rf $(DIRS)
Actual output:
mkdir -p bin
mkdir -p obj
gcc -Wall -c -o obj/task1.o task1.c
gcc -Wall -c -o obj/task2.o task2.c
gcc -Wall -c -o obj/task3.o task3.c
gcc -o bin/task1 obj/task1.o
gcc -o bin/task2 obj/task1.o
gcc -o bin/task3 obj/task1.o
Expected output:
mkdir -p bin
mkdir -p obj
gcc -Wall -c -o obj/task1.o task1.c
gcc -Wall -c -o obj/task2.o task2.c
gcc -Wall -c -o obj/task3.o task3.c
gcc -o bin/task1 obj/task1.o
gcc -o bin/task2 obj/task2.o
gcc -o bin/task3 obj/task3.o
In this rule:
$(NAMES): $(OBJECTS)
$(CC) -o $# $<
each executable depends on all objects. And since $< grabs only the first prerequisite, all you see is obj/task1.o.
Do it this way:
bin/%: obj/%.o
$(CC) -o $# $<
or this way:
$(NAMES): bin/% : obj/%.o
$(CC) -o $# $<

Resources