Using make to move .o files to a separate directory - c++

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/

Related

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 create makefile specifying ifferent directories for object and executable files

--folder
----book.h
----book.cpp
----library.h
----library.cpp
----main.cpp
this is the directory structure and I have created this make file which generate object files and executable files in the same directory.
main : main.o book.o library.o
g++ main.o book.o library.o -o main
main.o : main.cpp book.h library.h
g++ -c main.cpp
library.o : library.cpp library.h book.h
g++ -c library.cpp
book.o : book.cpp book.h
g++ -c book.cpp
clean:
rm -f *.o main
But i want to create folders obj and bin respectively for object files and executable files in the folder. How can I do it?
Maybe something like this
TARGET = bin/main
SOURCES = main.cpp book.cpp library.cpp
OBJ_DIR = obj
OBJECTS = $(SOURCES:%.cpp=$(OBJ_DIR)/*.o)
$(TARGET): $(OBJECTS)
$(LD) $(LDFLAGS) $^ -o $# $(LIBS)
$(OBJ_DIR)/%.o: %.cpp
$(CXX) $(CXXFLAGS) $< -c -o $#
This requires that the bin and obj directories exist first.
Read the GNU Make manual for more information.
I had some time over so I wrote up a complete and automated Makefile for you. This will create the directories if they do not exist.
BINDIR = bin/
OBJDIR = obj/
TARGET = $(BINDIR)target
SOURCES = main.cpp book.cpp library.cpp
LD = g++
OBJECTS = $(SOURCES:%.cpp=$(OBJDIR)%.o)
.PHONY: all
all: target
.PHONY: target
target: before_target actual_target after_target
.PHONY: before_target
before_target: $(OBJDIR) $(BINDIR)
.PHONY: actual_target
actual_target: $(TARGET)
.PHONY: after_target
after_target:
$(TARGET): $(OBJECTS)
$(LD) $(LDFLAGS) $^ -o $# $(LIBS)
$(OBJDIR)%.o: %.cpp
$(CXX) $(CXXFLAGS) $^ -c -o $#
$(OBJDIR) $(BINDIR):
mkdir $#
.PHONY: clean
clean:
-rm -rf $(BINDIR)
-rm -rf $(OBJDIR)
Use VPATH! Here is an article that does an excellent (and detailed) job of showing you how: Multi-Architecture Builds.
And here is the basic theory:
First, there will be a single level of recursion. This will be to handle automatically cding into the object directory, not for any directory-hierarchy reason.
Second, you will use VPATH to specify the location of the source code relative to the object directory: VPATH=../src
Third ... um ... profit!
Here's a simplified example (not tested). You can expand this, or follow along with the article to get a "richer" version:
ifneq (obj,$(notdir $(CURDIR)))
# Not in object directory, so we must be in root (src) directory!
.SUFFIXES:
OBJDIR := obj
MAKETARGET = $(MAKE) --no-print-directory -C $# -f $(CURDIR)/Makefile \
SRCDIR=$(CURDIR) $(MAKECMDGOALS)
.PHONY: $(OBJDIR)
$(OBJDIR):
;+#[ -d $# ] || mkdir -p $#
+#$(MAKETARGET)
Makefile : ;
%.mk :: ;
% :: $(OBJDIR) ; :
.PHONY: clean
clean:
rm -rf $(OBJDIR)
else
VPATH=../src
CXX := g++ # The default, just so you know it's here
# CXXFLAGS = ...
# LDFLAGS = ...
# LDLIBS = ...
main : main.o book.o library.o
main.o : main.cpp book.h library.h
library.o : library.cpp library.h book.h
book.o : book.cpp book.h
endif
You can just prefix your objects with obj/ and your executable with bin/ and add a command to make the directories mkdir -p bin etc..
# make your subfolders targets
all: bin obj bin/main
bin/main : obj/main.o obj/book.o obj/library.o
g++ -o bin/main obj/main.o obj/book.o obj/library.o
obj/main.o : main.cpp book.h library.h
g++ -c -o obj/main.o main.cpp
obj/library.o : library.cpp library.h book.h
g++ -c -o obj/library.o library.cpp
obj/book.o : book.cpp book.h
g++ -c -o obj/book.o book.cpp
# create subfolders if not present
bin obj:
mkdir -p bin
mkdir -p obj
clean:
rm -f bin/* obj/*
Then just type make (makes targer all).

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

a couple of Makefile issues

I've got this Makefile:
CFLAGS = -c -Wall
CC = g++
EXEC = main
SOURCES = main.cpp listpath.cpp Parser.cpp
OBJECTS = $(SOURCES: .cpp=.o)
EXECUTABLE = tp
DIR_SRC = /src/
DIR_OBJ = /obj/
all: $(SOURCES) $(OBJECTS)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(CFLAGS) $(OBJECTS) -o $#
.cpp.o:
$(CC) $(CFLAGS) $< -o $#
clean:
rm $(OBJECTS) $(EXECUTABLE)
Note this:
I'm in the directory "." which contains the makefile
The folder "./src" EXISTS, and has all the .h and .cpp files
The folder "./obj" doesn't exist, I want makefile to create it and put all the .o there
The error I get is:
No rules to build "main.cpp", necessary for "all". Stopping.
Help!
All right, from the top:
CFLAGS = -c -Wall
CC = g++
# EXEC = main never used, not needed
SOURCES = main.cpp listpath.cpp Parser.cpp
So far, so good. Note that this SOURCES doesn't mention DIR_SRC, so we'll have to make that connection later (and $(DIR_SRC)$(SOURCES) won't work, because the path must be appended to each member of the list). But OBJECTS really needs paths (e.g. /obj/main.o):
OBJECTS = $(patsubst %.cpp, $(DIR_OBJ)%.o, $(SOURCES))
EXECUTABLE = tp
DIR_SRC = /src/
DIR_OBJ = /obj/
(Personally I don't like putting the trailing slash in the variable, but it's a matter of taste.) The first target is the default target, so it should build what you actually want built:
all: $(EXECUTABLE)
Don't worry about listing the sources as prerequisites; they will sort themselves out later.
$(EXECUTABLE): $(OBJECTS)
$(CC) $(CFLAGS) $^ -o $# # <-- note the automatic variable $^
The .cpp.o convention doesn't really work here; we'll have to spell it out. And we must tell Make to search $(DIR_SRC) for .cpp files:
$(OBJECTS): $(DIR_OBJ)%.o: %.cpp $(DIR_OBJ)
$(CC) $(CFLAGS) $< -o $#
$(DIR_OBJ):
mkdir $#
vpath %.cpp $(DIR_SRC)
And tell Make that clean is not a real target, just to be safe:
.PHONY: clean
clean:
rm $(OBJECTS) $(EXECUTABLE)
EDIT:
I shouldn't have attempted so much in one step. Let's try something simpler:
$(DIR_OBJ)%.o: $(DIR_SRC)%.cpp $(DIR_OBJ)
$(CC) $(CFLAGS) $< -o $#
Edit the SOURCES to include the source directory (e.g. src/main.cpp etc.).
For the object files, consider something like this:
OBJECTS = $(subst src/,obj/,$(SOURCES:%.cpp=%.o))
# ...
all: $(SOURCES) build
.PHONY: build
build: pre_build $(EXECUTABLE)
.PHONY: pre_build
pre_build: obj
obj:
-mkdir obj
$(EXECUTABLE): $(OBJECTS)
$(CC) $(CFLAGS) $^ -o $#