put the object files into a separate folder GNU make - c++

I am trying to generate the object files (.o files) into a separate folder. It worked well. The problem is the object files generated were not put into the folder I wanted them to be. The following is my makefile:
OBJDIR :=objdir
SOURCES=$(wildcard ./src/*.c)
OBJS=$(patsubst %.c, %.o, $(SOURCES))
vpath %.h ./src
vpath %.c ./src
optest : $(OBJS)
cc -o optest $(OBJS)
$(OBJDIR)/main.o : add.h mul.h did.h
$(OBJDIR)/add.o : add.h
$(OBJDIR)/mul.o : mul.h
$(OBJDIR)/did.o : did.h
$(OBJS): | $(OBJDIR)
$(OBJDIR):
mkdir $(OBJDIR)
clean :
rm -rf $(OBJDIR)
rm -f optest
My .h and .c files are put in the ./src folder. The result of above makefile is that all the object files are also put in ./src folder rather than the objdir folder. Can anyone give any suggestion?

Two issues: you haven't substituted your source files correctly, and the implicit rule for compiling will only work for objects and sources with matching paths.
objdir := objdir
sources := $(wildcard src/*.c)
objs := $(sources:src/%.c=$(objdir)/%.o)
deps := $(objs:.o=.d)
CPPFLAGS := -MMD -MP
.PHONY: clean
optest: $(objs)
$(LINK.o) $^ $(LDLIBS) -o $#
$(objs): $(objdir)/%.o: src/%.c | $(objdir)
$(COMPILE.c) $(OUPUT_OPTION) $<
$(objdir): ; mkdir $#
clean: ; $(RM) $(objs) $(deps) optest
-include $(deps)
Other stuff:
Recycle the builtin recipes instead of rolling your own
Use dependency generation instead of specifying each dependency manually
Don't delete entire directories, even if you created them, stick to the files the makefile is responsible for
Rules that don't actually make a file should be .PHONY.

Related

Makefile target with wildcard is not working

I have a simple project, whose folder structure is something like:
ls -R
.:
build include makefile src
./build:
./include:
myfunc.h
./src:
main.cpp myfunc.cpp
I want to compile the .cpp sources into .o object files, which should end into ./build folder. Using the GNUmake documentation and other sources (e.g. Proper method for wildcard targets in GNU Make), I wrote this makefile:
CXX := g++
CXXFLAGS += -I./include
CXXFLAGS += -Wall
OBJDIR := ./build
SRCDIR := ./src
PROGRAM = release
DEPS = myfunc.h
SRC = $(wildcard $(SRCDIR)/*.cpp)
OBJ = $(patsubst $(SRCDIR)/%.cpp, $(OBJDIR)/%.o, $(SRC))
all: $(PROGRAM)
$(PROGRAM): $(OBJ)
$(CXX) $(CXXFLAGS) -o $(PROGRAM) $(OBJ)
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp $(DEPS)
$(CXX) $(CXXFLAGS) -c $< -o $#
.PHONY: clean
clean:
rm $(PROGRAM) $(OBJ)
But I get the error message: make: *** No rule to make target 'build/main.o', needed by 'release'. Stop.. I tried a lot of different ways but I cannot manage to have my .o files end up in the ./build directory. Instead, everything works if I put them in the root directory of the project. I can also make it work by specifying a rule for each object file, but I'd like to avoid that. What am I missing?
(I am using GNUmake version 4.3)
The problem is here:
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp $(DEPS)
$(CXX) $(CXXFLAGS) -c $< -o $#
See the $(DEPS)? That expands to myfunc.h. The compiler knows where to find that file (or would if this recipe were executed), because you've given it -I./include, but Make doesn't know where to find it (so it passes over this rule).
Add this line:
vpath %.h include
P.S. If you want to be really clean, you can add a variable:
INCDIR := ./include
CXXFLAGS += -I$(INCDIR)
vpath %.h $(INCDIR)

Adding INCLUDE, LIB and LD_LIBRARY_PATH in Makefile

I am writing a new Makefile and would like to copy my object files in obj/ folder. I tried to add OBJ directory folder but it is not picking up. I am sure I am missing something. For now I moved .o files from src/ folder to obj/ folder after compilation.
Could you please let me know how to add INCLUDES and LIB_INCLUDES in this makefile. As include path is not there in Makefile it is expecting me to specify complete (relative) path in source code while including header file.
Also, I would like to include some external libraries (LD_LIBRARY_PATH) statically in my executable, so how can I specify those in Makefile:
APPNAME := MyApp.x
SOURCE_DIR := ./src
INCLUDE_DIR := ./include
OBJECT_DIR := ./obj
BIN_DIR := ./bin
CC := g++
CCFLAGS := -g -Wall
SRCFILES := $(wildcard $(SOURCE_DIR)/*.cpp)
INCLUDES := $(INCLUDE_DIR)
LIB_INCLUDES := $(INCLUDE_DIR)
OBJECTS := $(patsubst %.cpp, %.o, $(SRCFILES))
all: $(APPNAME)
$(APPNAME): $(OBJECTS)
$(CC) $(CCFLAGS) $(LDFLAGS) -o $(BIN_DIR)/$(APPNAME) $(OBJECTS) $(LDLIBS)
\mv -f $(SOURCE_DIR)/*.o obj
depend: .depend
.depend: $(SRCFILES)
rm -f ./.depend
$(CC) -I$(INCLUDES) $(CCFLAGS) $^>>./.depend;
clean:
rm -f $(OBJECTS)
dist-clean: clean
rm -f *~ .depend
include .depend
Created separate thread for this request - lubgr.
Try this (for the sake of brevity, I stripped off the .depend part and both clean targets):
APPNAME := MyApp.x
SOURCE_DIR := src
INCLUDE_DIR := include
OBJECT_DIR := obj
BIN_DIR := bin
CC := g++
CCFLAGS := -g -Wall
SRCFILES := $(wildcard $(SOURCE_DIR)/*.cpp)
INCLUDES := $(INCLUDE_DIR)
OBJECTS := $(SRCFILES:$(SOURCE_DIR)/%.cpp=$(OBJECT_DIR)/%.o)
all: $(BIN_DIR)/$(APPNAME)
$(BIN_DIR)/$(APPNAME): $(OBJECTS)
$(CC) $(CCFLAGS) -o $# $(OBJECTS)
$(OBJECT_DIR)/%.o: $(SOURCE_DIR)/%.cpp
$(CC) $(CCFLAGS) -I$(INCLUDES) -o $# -c $<
For further static libraries, you pass them to the linker just like object files, e.g.
STATIC_LIBS = lib/libfirst.a lib/libsecond.a
$(BIN_DIR)/$(APPNAME): $(OBJECTS)
$(CC) $(CCFLAGS) -o $# $(OBJECTS) $(STATIC_LIBS)
This differs when it comes to linking against shared libraries, but as you said your libs are all compiled into static ones, this should work.

Build (make) lib every time, recompile project only if lib is newer

I have the following project structure:
lib/
Makefile
src/...
inc/...
build/
inc/...
lib/libmylib.a
subproj1/
src/main.cpp
Makefile
The Makefile in the lib folder is designed to create the file libmylib.a and copy the relevant header files to the build/inc folder.
I want the Makefile in subproj1 to always call make -C ../lib, but only re-compile file if headers have changed, and re-link only if necessary (one object file or libmylib.a is newer).
I have the following (non-defined variables such as CC are defined in another file):
LIBDIR = ../lib
SRCDIR = src
OBJDIR = obj
SRCS = $(SRCDIR)/main.cpp
MAIN=myexe
OBJS = $(SRCS:$(SRCDIR)/%.cpp=$(OBJDIR)/%.o)
DEPS = $(OBJS:.o=.d)
all: $(MAIN)
debug: CFLAGS += -g -DDEBUG
debug: LFLAGS += -g
debug: $(MAIN)
$(MAIN): $(OBJS) $(LIBDIR)/build/lib/libmylib.a
$(CC) $^ -o $# $(LIBS) $(LFLAGS)
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp $(LIBDIR)/build/lib/libmylib.a
mkdir -p $(OBJDIR)
$(CC) -c -o $# $(CFLAGS) $(INCS) -MD -MF $(patsubst %.o, %.d, $#) $<
$(LIBDIR)/build/lib/libmylib.a:
make -C $(LIBDIR)
-include $(DEPS)
.PHONY: clean $(LIBDIR)/build/lib/libmylib.a
clean:
$(RM) obj/* $(MAIN)
The above will re-compile main.cpp even if nothing has changed in the lib folder. If I remove $(LIBDIR)/build/lib/libmylib.a from the $(OBJDIR)/%.o rule, the .cpp file will not be re-compiled if a header changed (I would need to run make twice).
Is there a way to have the .cpp files in subproj1 being compiled only if the header files in lib have changed (or if the .cpp files themselves have changed), and to get myexe built only if one of the .cpp has been re-compiled (newer .o) or if libmylib.a is newer?
With recursive makefiles you need to execute the sub-project makefiles in correct order because the dependency tree is incomplete (e.g. this makefile does not know that updating $(LIBDIR)/build/lib/libmylib.a also updates those headers). It is easy to do that with a shell script or a top-level makefile.
Alternatively, your makefile must execute the sub-makefiles unconditionally in correct order, which can be done with shell function, e.g.:
LIBDIR := ../lib
pid := $(shell ps -o ppid= $$$$)
$(shell ${MAKE} -C ${LIBDIR} >/proc/$(pid)/fd/1 2>/proc/$(pid)/fd/2)
That $(LIBDIR)/build/lib/libmylib.a rule should be removed, the object files should not depend on the .a and it should not be marked as .PHONY.
This makes sure that building in ${LIBDIR} happens before this makefile analyzes file timestamps in ${LIBDIR}.
Now your auto-generated header dependencies should just work.
This might be a bit cleaner.
LIBDIR = ../lib
SRCDIR = src
OBJDIR = obj
SRCS = $(SRCDIR)/main.cpp
MAIN=myexe
OBJS = $(SRCS:$(SRCDIR)/%.cpp=$(OBJDIR)/%.o)
DEPS = $(OBJS:.o=.d)
all: makelib
$(MAKE) $(MAIN)
debug: CFLAGS += -g -DDEBUG
debug: LFLAGS += -g
debug: $(MAIN)
$(MAIN): $(OBJS)
$(CC) $^ -o $# $(LIBS) $(LFLAGS)
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp
mkdir -p $(OBJDIR)
$(CC) -c -o $# $(CFLAGS) $(INCS) -MD -MF $(patsubst %.o, %.d, $#) $<
makelib:
make -C $(LIBDIR)
-include $(DEPS)
.PHONY: clean makelib
clean:
$(RM) obj/* $(MAIN)
The main target all requires makelib to be built, and then it recursively calls itself for the target $(MAIN) (so all of $(MAIN)'s dependencies will be recalculated after makelib has finished building).

Set Makefile to build in another directory

Lets say my Makefile is located in the same directory as the sources and I want to store object files in obj/ subdirectory and the target executable in bin/ subdirectory.
src/
main.cpp
test.cpp
test.h
/many other *.cpp files and headers/
Makefile
obj/
bin/
The problem with my Makefile is that I cannot get the OBJECTS variable to
contain a list of *.o files with the samy names as *.cpp files, but in OBJDIR subdirectory.
Currently it only works if I name all object files one by one.
CXX=g++
CXXFLAGS=-c -Wall
LDFLAGS=
SOURCES=$(wildcard *.cpp) # very convenient wildcard
BINDIR=bin
OBJDIR=obj
OBJECTS=$(OBJDIR)/main.o $(OBJDIR)/test.o # how do I make a wildcard here?
TARGET=$(BINDIR)/my_executable
all: $(SOURCES) $(TARGET)
$(TARGET): $(OBJECTS)
$(CXX) $(LDFLAGS) $(OBJECTS) -o $#
$(OBJECTS): $(OBJDIR)/%.o: %.cpp
$(CXX) $(CXXFLAGS) -c $< -o $#
clean:
rm -rf $(OBJDIR)/$(OBJECTS) $(BINDIR)/$(TARGET)
Please help
Thank you!
Similar question to yours already exists on this site here:
Can I compile all .cpp files in src/ to .o's in obj/, then link to binary in ./?
either way something like this should solve your problem:
OBJ_FILES := $(addprefix obj/,$(notdir $(CPP_FILES:.cpp=.o)))

How to write a Makefile with separate source and header directories?

Following this tutorial...
I have 2 source files and 1 header file. I want to have them in separate directories like in the tutorial.
So I set this project up:
.
├── include
│   └── hellomake.h
├── Makefile
└── src
├── hellofunc.c
└── hellomake.c
Makefile:
IDIR =../include
CC=gcc
CFLAGS=-I$(IDIR)
ODIR=obj
LDIR =../lib
_DEPS = hellomake.h
DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS))
_OBJ = hellomake.o hellofunc.o
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
$(ODIR)/%.o: %.c $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
hellomake: $(OBJ)
gcc -o $# $^ $(CFLAGS)
.PHONY: clean
clean:
rm -f $(ODIR)/*.o *~ core $(INCDIR)/*~
The error I generate says:
gcc -o hellomake -I../include
gcc: fatal error: no input files
compilation terminated.
make: *** [hellomake] Error 4
What's happening?
Your tutorial promotes old and bad practices, you should avoid it IMHO.
In your rule here:
$(ODIR)/%.o: %.c $(DEPS)
You're telling make to look for sources in the current directory while they actually reside in the src directory, thus this pattern is never used and you have no suitable one.
Make sure you organize your project directory like this :
root
├── include/
│ └── all .h files here
├── lib/
│ └── all third-party library files (.a/.so files) here
├── src/
│ └── all .c files here
└── Makefile
Then let's take the process step by step, using good practices.
Firstly, don't define anything if you don't need to. Make has a lot of predefined variables and functions that you should use before trying to do it manually. In fact, he has so many that you can compile a simple file without even having a Makefile in the directory at all!
List your source and build output directories:
SRC_DIR := src
OBJ_DIR := obj
BIN_DIR := bin # or . if you want it in the current directory
Name your final target, that is, your executable:
EXE := $(BIN_DIR)/hellomake
List your source files:
SRC := $(wildcard $(SRC_DIR)/*.c)
From the source files, list the object files:
OBJ := $(SRC:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o)
# You can also do it like that
OBJ := $(patsubst $(SRC_DIR)/%.c, $(OBJ_DIR)/%.o, $(SRC))
Now let's handle the flags
CPPFLAGS := -Iinclude -MMD -MP # -I is a preprocessor flag, not a compiler flag
CFLAGS := -Wall # some warnings about bad code
LDFLAGS := -Llib # -L is a linker flag
LDLIBS := -lm # Left empty if no libs are needed
(CPP stands for C PreProcessor here, not CPlusPlus! Use CXXFLAGS for C++ flags and CXX for C++ compiler.)
The -MMD -MP flags are used to generate the header dependencies automatically. We will use this later on to trigger a compilation when only a header changes.
Ok, time to roll some recipes now that our variables are correctly filled.
It is widely spread that the default target should be called all and that it should be the first target in your Makefile. Its prerequisites shall be the target you want to build when writing only make on the command line:
all: $(EXE)
One problem though is Make will think we want to actually create a file or folder named all, so let's tell him this is not a real target:
.PHONY: all
Now list the prerequisites for building your executable, and fill its recipe to tell make what to do with these:
$(EXE): $(OBJ)
$(CC) $(LDFLAGS) $^ $(LDLIBS) -o $#
(CC stands for C Compiler.)
Note that your $(BIN_DIR) might not exist yet so the call to the compiler might fail. Let's tell make that you want it to check for that first:
$(EXE): $(OBJ) | $(BIN_DIR)
$(CC) $(LDFLAGS) $^ $(LDLIBS) -o $#
$(BIN_DIR):
mkdir -p $#
Some quick additional notes:
$(CC) is a built-in variable already containing what you need when compiling and linking in C
To avoid linker errors, it is strongly recommended to put $(LDFLAGS) before your object files and $(LDLIBS) after
$(CPPFLAGS) and $(CFLAGS) are useless here, the compilation phase is already over, it is the linking phase here
Next step, since your source and object files don't share the same prefix, you need to tell make exactly what to do since its built-in rules don't cover your specific case:
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $#
Same problem as before, your $(OBJ_DIR) might not exist yet so the call to the compiler might fail. Let's update the rules:
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c | $(OBJ_DIR)
$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $#
$(BIN_DIR) $(OBJ_DIR):
mkdir -p $#
Ok, now the executable should build nicely. We want a simple rule to clean the build artifacts though:
clean:
#$(RM) -rv $(BIN_DIR) $(OBJ_DIR) # The # disables the echoing of the command
(Again, clean is not a target that needs to be created, so add it to the .PHONY special target!)
Last thing. Remember about the automatic dependency generation? GCC and Clang will create .d files corresponding to your .o files, which contains Makefile rules for us to use, so let's include that in here:
-include $(OBJ:.o=.d) # The dash silences errors when files don't exist (yet)
Final result:
SRC_DIR := src
OBJ_DIR := obj
BIN_DIR := bin
EXE := $(BIN_DIR)/hellomake
SRC := $(wildcard $(SRC_DIR)/*.c)
OBJ := $(SRC:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o)
CPPFLAGS := -Iinclude -MMD -MP
CFLAGS := -Wall
LDFLAGS := -Llib
LDLIBS := -lm
.PHONY: all clean
all: $(EXE)
$(EXE): $(OBJ) | $(BIN_DIR)
$(CC) $(LDFLAGS) $^ $(LDLIBS) -o $#
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c | $(OBJ_DIR)
$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $#
$(BIN_DIR) $(OBJ_DIR):
mkdir -p $#
clean:
#$(RM) -rv $(BIN_DIR) $(OBJ_DIR)
-include $(OBJ:.o=.d)
the make utility, with no specific 'target' will make the first target in the file.
The first target is usually named 'all'
For the posted file, will make the object files and will not continue to make the executable when the target is not given in the command line
Suggest the following:
SHELL := /bin/sh
# following so could define executable name on command line
# using the '-D' parameter
#ifndef $(NAME)
NAME := hellomake
#endif
# use ':=' so macros only evaluated once
MAKE := /usr/bin/make
CC := /usr/bin/gcc
CFLAGS := -g -Wall -Wextra -pedantic
LFLAGS :=
ODIR := obj
IDIR := ../include
LIBS :=
LIBPATH := ../lib
DEPS := $(wildcard $(IDIR)/*.h)
SRCS := $(wildcard *.c)
OBJS := $(SRCS:.c=.o)
.PHONY: all
all: $(NAME) $(OBJS)
$(ODIR)/%.o: %.c $(DEPS)
$(CC) $(CFLAGS) -c -o $# $< -I$(DEPS)
$(NAME): $(OBJS)
$(CC) $(LFLAGS) -o $# $^ -L$(LIBPATH) -l$(LIBS)
.PHONY: clean
clean:
rm -f $(ODIR)/*.o
rm -f $(NAME)
however, in your proposed project,
not every source file needs every header file
so should use either gcc or sed to generate the dependency files
then use makefile rules similar to the following,
which may need a little 'tweaking' for your project
because the include files are not in the same directory
as the source files:
DEP := $(SRCS:.c=.d)
#
#create dependency files
#
%.d: %.c
#
# ========= START $< TO $# =========
$(CC) -M $(CPPFLAGS) $< > $#.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $# : ,g' < $#.$$$$ > $#; \
rm -f $#.$$$$
# ========= END $< TO $# =========
#
# compile the .c files into .o files using the compiler flags
#
%.o: %.c %.d
#
# ========= START $< TO $# =========
$(CC) $(CCFLAGS) -c $< -o $# -I$(IDIR)
# ========= END $< TO $# =========
#
# include the contents of all the .d files
# note: the .d files contain:
# <filename>.o:<filename>.c plus all the dependencies for that .c file
# I.E. the #include'd header files
# wrap with ifneg... so will not rebuild *.d files when goal is 'clean'
#
ifneq "$(MAKECMDGOALS)" "clean"
-include $(DEP)
endif
The simple Makefile definitions seem OK to me as they appear in your question. Try specifying the compiler options before the file names:
$(ODIR)/%.o: %.c $(DEPS)
$(CC) $(CFLAGS) -c -o $# $<
hellomake: $(OBJ)
gcc $(CFLAGS) -o $# $^
You need to run make from the source directory.
When you got this error"
*gcc: fatal error: no input files
compilation terminated.*
", that means you do not have object files,
just check out that line "${OBJS} := " in Makefile.
Hi, bro!
If your project "helloFunc" 's architecture are just liking this:
helloFunc
|
|__Makefile
|__build
|__include
| |__hellomake.h
|__src
|__hellofunc.cpp
|__hellomake.cpp
your Makefile should be just like this:
# This is a Makefile for separated multiple sources to build with VSCode on mac
# Thanks, Job Vranish.
# (https://spin.atomicobject.com/2016/08/26/makefile-c-projects/)
# Reference: Makefile Tutorial
# (https://makefiletutorial.com/)
# Reference: #yagiyuki from Qiita
# (https://qiita.com/yagiyuki/items/ff343d381d9477e89f3b)
# Reference: simonsso from Github
# (https://github.com/simonsso/empty-cpp-project/blob/master/Makefile)
# Reference: Chinese Website blogger CDNS
# (https://blog.csdn.net/qq_22073849/article/details/88893201)
# (1)Compiler
# clang++
CXX = clang++
# (2)Compile options
# -Wall -Wextra -std=c++11 -g
CXX_FLAGS = -Wall -Wextra -std=c++11 -g
# (3)Build task directory path
# I do care about out-of-source builds
# ./build
BUILD_DIR ?= ./build
# (4)Source files directory path
# ./src
SRC_DIRS ?= ./src
# (5)Library files directory path
LIBDIR :=
# (6)Add library files
LIBS :=
# (7)Target file, excutable file.
# main
TARGET ?= main
# (8)Source files(code), to be compiled
# Find source files we want to compile
# *expression must around by single quotos
# ./src/bank.cpp ./src/main.cpp
SRCS := $(shell find $(SRC_DIRS) -name '*.cpp' -or -name '*.c' -or -name '*.s')
# (9)Object files
# String substituion for every C/C++ file
# e.g: ./src/bank.cpp turns into ./build/bank.cpp.o
# ./build/bank.cpp.o ./build/main.cpp.o
OBJS := $(patsubst %.cpp, ${BUILD_DIR}/%.cpp.o, $(notdir $(SRCS)))
# (10)Dependency files
# which will generate a .d file next to the .o file. Then to use the .d files,
# you just need to find them all:
#
DEPS := $(OBJS:.o=.d)
# (11)Include files directory path
# Every folder in ./src find include files to be passed via clang
# ./include
INC_DIRS := ./include
# (12)Include files add together a prefix, clang make sense that -I flag
INC_FLAGS := $(addprefix -I,$(INC_DIRS))
# (13)Make Makefiles output Dependency files
# That -MMD and -MP flags together to generate Makefiles
# That generated Makefiles will take .o as .d to the output
# That "-MMD" and "-MP" To generate the dependency files, all you have to do is
# add some flags to the compile command (supported by both Clang and GCC):
CPP_FLAGS ?= $(INC_FLAGS) -MMD -MP
# (14)Link: Generate executable file from object file
# make your target depend on the objects files:
${BUILD_DIR}/${TARGET} : $(OBJS)
$(CXX) $(OBJS) -o $#
# (15)Compile: Generate object files from source files
# $# := {TARGET}
# $< := THE first file
# $^ all the dependency
# C++ Sources
$(BUILD_DIR)/%.cpp.o: $(SRC_DIRS)/%.cpp
$(MKDIR_P) $(dir $#)
$(CXX) $(CPP_FLAGS) $(CXX_FLAGS) -c $< -o $#
#(16)Delete dependence files, object files, and the target file
.PHONY: all clean
all: ${BUILD_DIR}/${TARGET}
clean:
$(RM) $(DEPS) $(OBJS) ${BUILD_DIR}/${TARGET}
-include $(DEPS)
MKDIR_P ?= mkdir -p
Changing that Makefile to your needed Linux version:
# (1)Compiler
# g++
CXX = g++
# (2)Compile options
# -Wall -Wextra -std=c++11 -g
CXX_FLAGS = -Wall -Wextra -std=c++11 -g
# (3)Build task directory path
# I do care about out-of-source builds
# ./build
BUILD_DIR ?= ./build
# (4)Source files directory path
# ./src
SRC_DIRS ?= ./src
# (5)Library files directory path
LIBDIR :=
# (6)Add library files
LIBS :=
# (7)Target file, excutable file.
# main
TARGET ?= main
# (8)Source files(code), to be compiled
# Find source files we want to compile
# *expression must around by single quotos
# ./src/bank.cpp ./src/main.cpp
SRCS := $(shell find $(SRC_DIRS) -name '*.cpp' -or -name '*.c' -or -name '*.s')
# (9)Object files
# String substituion for every C/C++ file
# e.g: ./src/bank.cpp turns into ./build/bank.cpp.o
# ./build/bank.cpp.o ./build/main.cpp.o
OBJS := $(patsubst %.cpp, ${BUILD_DIR}/%.cpp.o, $(notdir $(SRCS)))
# (10)Dependency files
# which will generate a .d file next to the .o file. Then to use the .d files,
# you just need to find them all:
#
DEPS := $(OBJS:.o=.d)
# (11)Include files directory path
# Every folder in ./src find include files to be passed via clang
# ./include
INC_DIRS := ./include
# (12)Include files add together a prefix, gcc make sense that -I flag
INC_FLAGS := $(addprefix -I,$(INC_DIRS))
# (13)Make Makefiles output Dependency files
# That -MMD and -MP flags together to generate Makefiles
# That generated Makefiles will take .o as .d to the output
# That "-MMD" and "-MP" To generate the dependency files, all you have to do is
# add some flags to the compile command (supported by both Clang and GCC):
CPP_FLAGS ?= $(INC_FLAGS) -MMD -MP
# (14)Link: Generate executable file from object file
# make your target depend on the objects files:
${BUILD_DIR}/${TARGET} : $(OBJS)
$(CXX) $(OBJS) -o $#
# (15)Compile: Generate object files from source files
# $# := {TARGET}
# $< := THE first file
# $^ all the dependency
# C++ Sources
$(BUILD_DIR)/%.cpp.o: $(SRC_DIRS)/%.cpp
$(MKDIR_P) $(dir $#)
$(CXX) $(CPP_FLAGS) $(CXX_FLAGS) -c $< -o $#
#(16)Delete dependency files, object files and the target file
.PHONY: all clean
all: ${BUILD_DIR}/${TARGET}
clean:
$(RM) $(DEPS) $(OBJS) ${BUILD_DIR}/${TARGET}
-include $(DEPS)
MKDIR_P ?= mkdir -p
What you need to notice is that your "Makefile" file is the same directory of the include files and sources files,
so you need to change your "IDIR:=../include" to "IDIR:=./include" in your "Makefile".
END!
Here's what i'm using in my windows setup:
CC = g++
CFLAGS = -Wall -std=c++20
SRCDIR = src
HEADDIR = include
OBJDIR = build
BINDIR = bin
# where the executable will be stored
EXECUTABLE := $(BINDIR)/main
# list of all source files
SOURCES := $(wildcard $(SRCDIR)/*.cpp)
# list of all header files
INCLUDES := $(wildcard $(HEADDIR)/*.h)
# from the list of all source files, create a list of all object files
OBJECTS := $(SOURCES:$(SRCDIR)/%.cpp=$(OBJDIR)/%.o)
# all: clean $(EXECUTABLE)
all: $(EXECUTABLE)
# Link: Generate executable file from object file
$(EXECUTABLE): $(OBJECTS)
#echo LINKING..... $(CC) -o $# $(OBJECTS)
#$(CC) -o $# $(OBJECTS)
#echo RUNNING: $(EXECUTABLE)
#$(EXECUTABLE)
# Compile: Generate object files from source files
# $# := {EXECUTABLE}
# $< := THE first file
# $^ all the dependency
# C++ Sources
$(OBJDIR)/%.o : $(SRCDIR)/%.cpp | makedirs
#echo COMPILING... $(CC) $(CFLAGS) -c "$<" -o "$#"
#$(CC) $(CFLAGS) -c $< -o $#
# `|` is order-only-prerequisites
# https://www.gnu.org/software/make/manual/html_node/Prerequisite-Types.html
makedirs:
# check if the file exists; if not, create it
# mkdir -p $(OBJDIR) in linux
#if not exist "$(OBJDIR)" mkdir $(OBJDIR)
#if not exist "$(BINDIR)" mkdir $(BINDIR)
#Delete dependence files, object files, and the EXECUTABLE file
clean:
#echo CLEANING UP
# check if the directories exist; if so, delete them
#if exist "$(OBJDIR)" rmdir /s /q $(OBJDIR)
#if exist "$(BINDIR)" rmdir /s /q $(BINDIR)