Running Makefile not completely - c++

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).

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: pattern rules for subdirectory

Here is my project:
project
|--- main.cpp
|--- makefile
|--- test
|--- Test.cpp
|--- Test.h
Here is the makefile:
g++1x:=g++ -std=c++14 -stdlib=libc++ -MMD -MP
cflags:= -Wall -lncurses
PATHS:=./ ./test/
TARGET:=matrix.out
SRC:=$(foreach PATH,$(PATHS),$(wildcard $(PATH)/*.cpp))
OBJDIR:=.obj
OBJ:=$(addprefix $(OBJDIR)/,$(notdir $(SRC:.cpp=.o)))
.PHONY: install
install: $(OBJDIR) $(TARGET)
$(OBJDIR):
mkdir -p $(OBJDIR)
$(TARGET): $(OBJ)
$(g++1x) $(cflags) -o $# $^ -g
$(OBJDIR)/%.o: %.cpp
$(g++1x) -c -o $# $< -g
$(OBJDIR)/%.o: ./test/%.cpp
$(g++1x) -c -o $# $< -g
-include $(addprefix $(OBJDIR)/,$(notdir $(SRC:.cpp=.d)))
.PHONY: clean
clean:
rm -f $(TARGET)
rm -rf $(OBJDIR)
It works well but I have two questions:
1) Is it possible to avoid foreach for PATHS so that I can use the same makefile for all of cpp projects?
2) As you see, to generate main.o and Test.o I write two blocks:
$(OBJDIR)/%.o: ./test/%.cpp and $(OBJDIR)/%.o: %.cpp.
Is it possible to write only once?
I've tried as below but it doesn't work:
$(OBJDIR)/%.o: $(foreach PATH,$(PATHS),$(wildcard $(PATH)/%.cpp))
$(g++1x) -c -o $# $< -g
I've even tried like this but it doesn't work still:
$(OBJDIR)/%.o: %.cpp ./test/%.cpp
$(g++1x) -c -o $# $< -g
You should keep the source tree into your object tree. This way it will be easier to create global rules and keep dependencies.
# Use the shell find command to get the source tree
SOURCES := $(shell find * -type f -name "*.c")
OBJDIR := .objects
# Keep the source tree into the objects tree
OBJECTS := $(addprefix $(OBJDIR)/,$(SOURCES:.c=.o))
all: mytarget
mytarget: $(OBJECTS)
$(CC) $^ -o $#
# As we keep the source tree we have to create the
# needed directories for every object
$(OBJECTS): $(OBJDIR)/%.o: %.c
mkdir -p $(#D)
$(CC) -MMD -MP -c $< -o $#
-include $(OBJECTS:.o=.d)
$ make
mkdir -p .objects
cc -MMD -MP -c main.c -o .objects/main.o
mkdir -p .objects/test
cc -MMD -MP -c test/test.c -o .objects/test/test.o
cc .objects/main.o .objects/test/test.o -o mytarget
$ tree -a
.
├── main.c
├── Makefile
├── mytarget
├── .objects
│   ├── main.d
│   ├── main.o
│   └── test
│   ├── test.d
│   └── test.o
└── test
├── test.c
└── test.h
3 directories, 9 files
EDIT: You can reduce the number of mkdir to the minimum by adding the object directory as an order only prerequisites:
# Do not create the directory
$(OBJECTS): $(OBJDIR)/%.o: %.c
$(CC) -MMD -MP -c $< -o $#
# Every target finishing with "/" is a directory
$(OBJDIR)%/:
mkdir -p $#
# Add the "directory/" as an order only prerequisite
$(foreach OBJECT,$(OBJECTS),$(eval $(OBJECT): | $(dir $(OBJECT))))
Because I can't edit jmlemetayer's answer, here's how to extend the commands for projects with both C and CPP source:
Firstly to generate the object list, just apply the patsubst twice, once for each extension:
SRC_LST := $(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(SOURCES)))
OBJECTS := $(addprefix $(OBJDIR)/,$(SRC_LST))
Then to handle both .cpp and .c files in the implicit rule for compiling:
.SECONDEXPANSION:
$(OBJECTS): $(OBJDIR)/%.o: $$(wildcard %.c*)
mkdir -p $(#D)
ifeq "$(suffix $<)" ".cpp"
$(CPP) -MMD -MP -c $< -o $#
else
$(CC) -MMD -MP -c $< -o $#
endif
If there is a better way I'm happy to update this.

Automating my Makefile

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 $#

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/