Automating my Makefile - c++

I am learning to create a makefile. My folder structure looks like this..
Project
bin //this is where the executable "e" is kept
e
obj //this is where the obj files generated are kept
Node.o
Node1.o
src //this is where .cpp files resides
Folder
Node.cpp
Folder2
Node1.cpp
include //this is where .hhp files resides
Folder
Node.hpp
Folder2
Node1.hpp
makefile
I am using Ubuntu 12.04 and trying to compile it using g++. The makefile resides in the project folder along with folders: src, include, obj and bin
My makefile looks like this
CC = g++
DEBUG = -g
CFLAGS = -Wall -c $(DEBUG)
LFLAGS = -Wall $(DEBUG)
TARGET = bin/
OBJ = obj/
INCLUDE = include/
SRC = src/
SOURCES=$(wildcard $(SRC)**/*.cpp $(SRC)*.cpp)
HEADERS=$(wildcard include/**/*.hpp include/*.hpp)
OBJECTS=$(patsubst %.cpp,$(OBJ)%.o,$(notdir $(SOURCES)))
All : $(TARGET)e
$(TARGET)e : make_dir $(OBJECTS)
$(CC) $(LFLAGS) $(OBJECTS) -o $#
$(OBJ)Node.o : $(SRC)Folder/Node.cpp $(HEADERS)
$(CC) $(CFLAGS) -I$(INCLUDE) $< -o $#
$(OBJ)Node1.o : $(SRC)Folder2/Node1.cpp $(HEADERS)
$(CC) $(CFLAGS) -I$(INCLUDE) $< -o $#
make_dir:
mkdir -p obj bin
clean :
-rm -rf bin
-rm -rf obj
-rm -f e *.o *~
This piece of code runs just fine but what I would like to do is to replace the below code snippets
$(OBJ)Node.o : $(SRC)Folder/Node.cpp $(HEADERS)
$(CC) $(CFLAGS) -I$(INCLUDE) $< -o $#
$(OBJ)Node1.o : $(SRC)Folder2/Node1.cpp $(HEADERS)
$(CC) $(CFLAGS) -I$(INCLUDE) $< -o $#
with some thing more like
%.o : %.cpp $(HEADERS)
$(CC) $(CFLAGS) -I$(INCLUDE) $< -o $#
Something that generalizes the whole feeding and mapping. In other words, automate the makefile in a way I shouldn't worry or edit until the hierarchy is disturbed.

$(OBJ)/%.o : $(SRC)Folder/%.cpp $(HEADERS)
$(CC) $(CFLAGS) -I$(INCLUDE) $< -o $#

Related

Running Makefile not completely

I am a rookie to MaKefile and I've been learning it recently.
However, I got trouble when I tried to run make command on my terminal.
Here's my Makefile:
CC = g++
CFLAGS = -g -Wall
bin = ./bin/
makedir:
#echo "build ./bin"
mkdir $(bin)
all: algo
OBJS = $(patsubst %.o, $(bin)%.o, BB.o BF.o method.o algo.o)
algo: BB.o BF.o method.o algo.o
$(CC) -o algo $(OBJS)
BB.o: BB.cpp
$(CC) $(CFLAGS) -c $^ -o $(bin)$#
BF.o: BF.cpp
$(CC) $(CFLAGS) -c $^ -o $(bin)$#
method.o: method.cpp
$(CC) $(CFLAGS) -c method.cpp -o $(bin)$#
algo.o: algo.cpp method.hpp
$(CC) $(CFLAGS) -c algo.cpp -o $(bin)$#
clean:
-rm -f $(bin)*
-rmdir $(bin)
-rm -f algo
I tried to put object files in bin directory.
But, the terminal only shows:
build ./bin
mkdir bin
And here's the problem. Only a empty directory named bin being created.
It seems like it didn't do anything after mkdir command.
For more details, it's my directory structure before running make command:
├── algo.cpp
├── BB.cpp
├── BF.cpp
├── Makefile
├── method.cpp
├── method.hpp
I have no idea about it at all, and tried to find any way to solve it but useless.
By the way, I am also a rookie to Stackoverflow.
If I don't ask questions at a good way, let me know and I will get better. Thank you so much!
When you run make without arguments, the recipe for the first target in the Makefile is followed.
Your first target is makedir, whose recipe performs those two commands and nothing else. So, the computer is doing what you asked it to do.
I recommend that you put the all target first, and make makedir a prerequisite of the targets that actually do rely on it:
CC = g++
CFLAGS = -g -Wall
bin = ./bin/
all: algo
OBJS = $(patsubst %.o, $(bin)%.o, BB.o BF.o method.o algo.o)
algo: BB.o BF.o method.o algo.o
$(CC) -o algo $(OBJS)
BB.o: makedir BB.cpp
$(CC) $(CFLAGS) -c $^ -o $(bin)$#
BF.o: makedir BF.cpp
$(CC) $(CFLAGS) -c $^ -o $(bin)$#
method.o: makedir method.cpp
$(CC) $(CFLAGS) -c method.cpp -o $(bin)$#
algo.o: makedir algo.cpp method.hpp
$(CC) $(CFLAGS) -c algo.cpp -o $(bin)$#
makedir:
#echo "build ./bin"
mkdir $(bin)
clean:
-rm -f $(bin)*
-rmdir $(bin)
-rm -f algo
There are better ways to handle build output directory creation, though (example).

Using Makefile compile multiple .cpp in diferent folders to a single build/ directory [duplicate]

GNU Make 3.82
gcc 4.7.2
c89
I have the following make file:
INC_PATH=-I/home/dev_tools/apr/include/apr-1
LIB_PATH=-L/home/dev_tools/apr/lib
LIBS=-lapr-1 -laprutil-1
RUNTIME_PATH=-Wl,-rpath,/home/dev_tools/apr/lib
CC=gcc
CFLAGS=-Wall -Wextra -g -m32 -O2 -D_DEBUG -D_THREAD_SAFE -D_REENTRANT -D_LARGEFILE64_SOURCE $(INC_PATH)
SOURCES=$(wildcard src/*.c)
OBJECTS=$(patsubst %.c, %.o, $(SOURCES))
EXECUTABLE=bin/to
all: build $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(CFLAGS) -o $# $(RUNTIME_PATH) $(OBJECTS) $(LIB_PATH) $(LIBS)
$(OBJECTS): $(SOURCES)
$(CC) $(CFLAGS) -c $(SOURCES) $(LIB_PATH) $(LIBS)
build:
#mkdir -p bin
clean:
rm -rf $(EXECUTABLE) $(OBJECTS) bin
find . -name "*~" -exec rm {} \;
find . -name "*.o" -exec rm {} \;
My directory structure is like this project/src project/bin. My Makefile is in the project (root) folder, and all my *.h and *.c are in the src directory. Currently I have only one source file called timeout.c
I get this error:
gcc: error: src/timeout.o: No such file or directory
I have used this to get all the source files:
SOURCES=$(wildcard src/*.c)
And the object files:
OBJECTS=$(patsubst %.c, %.o, $(SOURCES))
However, the make seems to create the object file in the project root folder where the Makefile is. Should it not put it in the src directory?
You have two problems in this rule (well, three):
$(OBJECTS): $(SOURCES)
$(CC) $(CFLAGS) -c $(SOURCES) $(LIB_PATH) $(LIBS)
You haven't noticed yet, but the rule makes each object dependent on all sources, and tries to build that way. Not a problem as long as you have only one source. Easy to fix with a static pattern rule and an automatic variable:
$(OBJECTS): src/%.o : src/%.c
$(CC) $(CFLAGS) -c $< $(LIB_PATH) $(LIBS)
Also, the command ("$(CC)...") doesn't specify an output file name, so gcc will infer it from the source file name; if you give it src/timeout.c, it will produce timeout.o (in the working directory, project/). So you should specify the desired path to the output file. Easy to do with another automatic variable:
$(OBJECTS): src/%.o : src/%.c
$(CC) $(CFLAGS) -c $< $(LIB_PATH) $(LIBS) -o $#
Use gcc's -o option to write the output file to a particular location. For instance, you could say:
$(CC) $(CFLAGS) -c $(SOURCES) $(LIB_PATH) $(LIBS) -o $(OBJECTS)
Unfortunately, there's a problem with this line: if there is more than one source file in $(SOURCES), it won't work, since $(OBJECTS) will also contain multiple file names, and the -o option only binds to the first argument.
A way to compile each file in a list of source code files is to use implicit rules. In gmake, you would write:
$(EXECUTABLE): $(OBJECTS)
$(CC) $(CFLAGS) -o $# $(RUNTIME_PATH) $(OBJECTS) $(LIB_PATH) $(LIBS)
%.o : %.c
$(CC) $(CFLAGS) -c $< -o $#
where $< is replaced with name of the input file and $# is replaced with the name out the output file.
I solved this request and here is my Makefile and directory tree.
PROJECT := main.exe
DIR_SRC += .
DIR_SRC += ./src
DIR_INC += -lpthread
DIR_INC += -I./inc
DIR_INC += $(addprefix -I, $(DIR_SRC))
SRC_C += $(wildcard $(addsuffix /*.c, $(DIR_SRC)))
#OBJ := $(filter %.o, $(SRC_C:.c=.o))
OBJ := $(patsubst %.c, %.o, $(SRC_C))
EXE := $(PROJECT)
CC_PREFIX :=
CC := $(CC_PREFIX)gcc
CFLAG =
CLIB = -L .
.PHONY:all
all:$(OBJ) $(EXE)
%.o: %.c
$(CC) $(CFLAG) $(DIR_INC) -c $< -o $#
$(EXE): $(OBJ)
$(CC) $(CFLAG) $(CLIB) $(OBJ) -o $#
clean:
rm -r $(EXE) $(OBJ)
See my directory tree:

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/