Create *.o files in a separate folder - c++

I'm trying to make so that the *.o files are kept in /bin however after running it, the *.o files are not kept.
my file systems is as follows:
> bin
> src
*.cpp
> headers
*.h
makefile
.
CC := g++
CFLAGS := -Isrc/headers
NAME := run
SRC := src/
HSRC := $(SRC)/headers/
OBJ := bin/
SOURCES := $(wildcard $(SRC)*.cpp)
DEPS = $(wildcard $(HSRC)*.h)
OBJECTS := $(patsubst $(SRC)*.cpp,$(OBJ)*.o,$(SOURCES))
$(OBJ)/%.o: %.cpp $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
$(NAME): $(OBJECTS)
$(CC) -o $# $^ $(CFLAGS)
.PHONY: clean
clean:
rm -f $(NAME) $(OBJ)/*.o *~ core $(INCDIR)/*~

Your main, high-level problem is that you are not testing the makefile as you develop it, so the bugs pile up before you know they're there.
The first concrete problem is that your assignment to OBJECTS is incorrect, and doesn't work the way you think it does. The patsubst function uses %, not *, so it ought to be:
OBJECTS := $(patsubst $(SRC)%.cpp,$(OBJ)%.o,$(SOURCES))
The second is that you have not decided whether OBJ should contain a trialing slash. It shouldn't, but that's not the point; the point is that you must be consistent. Look here:
OBJ := bin/
...
$(OBJ)/%.o: %.cpp $(DEPS)
...
See the problem? You have written a rule that will match bin//foo.o but not bin/foo.o, so Make will never invoke it. We must pick one convention or the other; for purposes of this Answer I will pick this one:
OBJ := bin
Third, when you wrote that rule you appear to have overlooked the fact that you put the source files in their own directory, so we must modify it:
$(OBJ)/%.o: $(SRC)%.cpp $(DEPS)
There is still some room for improvement, but this will work.

Related

Many folders project Makefile

I have the following project structure:
common
|-- foo.cpp
|-- foo.h
exercise_1
|-- main.cpp
|-- bar_1.cpp
|-- bar_1.h
exercise_2
|-- main.cpp
|-- bar_2.cpp
|-- bar_2.h
...
How can one organize Makefile to build such project from the main directory e.g.:
make exercise_10
So that this command would build object files in common directory, in exercise_10 folder and link them all to executable in exercise_10. I started with the following:
COMPILER = g++
INCLUDE = -I common/
DEPS = common/*.o
OBJECTS := $(patsubst common/%.cpp, common/%.o, $(wildcard common/*.cpp))
common: $(OBJECTS)
exercise_%:
$(COMPILER) $#/main.cpp $(INCLUDE) -o $#/main $(DEPS)
But it's not working and I don't know what to do next.
Thanks!
If you use GNU make you could define a macro to build any of your exercises. Something like the following:
EXERCISES := $(wildcard exercise_*)
MAINS := $(addsuffix /main,$(EXERCISES))
.PHONY: all
all: $(MAINS)
common-objs := $(patsubst %.cpp,%.o,$(wildcard common/*.cpp))
common-headers := $(wildcard common/*.h)
%.o: %.cpp $(common-headers)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -Icommon -c $< -o $#
# $(1): exercise directory
define BUILD_EXERCISE
.PHONY: $(1)
$(1): $(1)/main
$(1)-objs := $$(patsubst %.cpp,%.o,$$(wildcard $(1)/*.cpp))
OBJS += $$($(1)-objs)
$(1)-headers := $$(wildcard $(1)/*.h)
$$($(1)-objs): $$($(1)-headers)
$(1)/main: $$($(1)-objs) $$(common-objs)
$$(CXX) $$(CXXFLAGS) $$(LDFLAGS) -o $$# $$^ $$(LDLIBS)
endef
$(foreach e,$(EXERCISES),$(eval $(call BUILD_EXERCISE,$(e))))
.PHONY: clean
clean:
rm -f $(MAINS) $(OBJS) $(common-objs)
It looks a bit complicated but it's not. The only trick is the $$ in the BUILD_EXERCISE macro. It is needed because the macro is expanded twice by make. Everything else is straightforward:
CXX, CPPFLAGS, CXXFLAGS, LDFLAGS and LDLIBS are Variables Used by Implicit Rules.
$#, $< and $^ are Automatic Variables.
wildcard, addsuffix, patsubst, foreach, eval and call are make functions.
Phony targets are declared as prerequisites of the .PHONY special target.
The foreach-eval-call construct is a way to programmatically instantiate make statements.
%.o: %.cpp... is a pattern rule.

Save object files in same makefile directory using depend

I have this makefile
appname := fun
srcfiles := $(shell find .. -name "*.cpp")
headerfiles := $(shell find .. -name "*.hpp")
objects := $(patsubst %.cpp, %.o, $(srcfiles))
all: $(srcfiles) $(appname)
$(appname): $(objects)
$(CXX) $(LDFLAGS) -o $(appname) $(objects) $(LDLIBS)
depend: .depend
.depend: $(srcfiles) $(headerfiles)
rm -f ./.depend
$(CXX) $(CXXFLAGS) -MM $^>>./.depend;
clean:
rm -f $(appname) $(objects)
dist-clean: clean
rm -f *~ .depend
include .depend
Where the makefile's parent directory contain all the code (.hpp and .cpp files). Unfortunately, the .o files are saved in the source code, while I want that they're saved in the same directory of the executable (and makefile). This is the same of Default in Eclipse CDT.
How can I modify makefile in order to do that?
PS: I found similar questions, like this one, but none of them used depend for defining the $(objects) task (they're all in `%.o% form).
When you set your objects variable you are simply taking the full pathname to the .cpp file and replacing the suffix with .o. So if you have a file like my/sub/dir/foo.cpp then objects will contain the path my/sub/dir/foo.o. So, of course when you write a rule $(appname): $(objects), make is going to try to build the file my/sub/dir/foo.o. If you want it to build just foo.o instead, then you have to strip off the path as well, not just replace the suffix:
objects := $(patsubst %.cpp,%.o,$(notdir $(srcfiles)))
Now, of course, make will say it doesn't know how to build foo.o, because the default rules only know how to build a .o from a .cpp, not from a .cpp file stashed in my/sub/dir.
To make this work the simplest solution is to use VPATH and you can construct the value for VPATH from the list of directories you got from srcfiles, like so:
VPATH := $(sort $(dir $(srcfiles)))
You might also consider using a better dependency generation solution, for example the one described here.

Out-of-source build doesn't match rule for object files

I'm trying to set up a Makefile for out-of-source builds of a C++ project, based on a template I found on this blog post. However, for some reason, the pattern-matching target $(BUILD_DIR)/$.cpp.o: doesn't seem to be working, because I get errors like "No rule to make target 'build/somefile.cpp.o'."
Here is my Makefile, with some of the unnecessary details removed. Note that the SRCS variable is built up from other variables because eventually I want to support different targets using different sets of source files, but for now SRCS has only one definition and could be defined in one line.
CXX = g++
RM = rm -f
MKDIR_P ?= mkdir -p
SRC_DIR := ./src
BUILD_DIR := ./build
CPPFLAGS := -std=c++14 -g3 -O0 -Wall
LFLAGS := -L"./libraries/mutils"
INCLUDES := -I"$(SRC_DIR)/" -I"./libraries/"
LIBS := -lmutils -lpthread
OBJS = $(SRCS:$(SRC_DIR)/%=$(BUILD_DIR)/%.o)
DEPS = $(OBJS:.o=.d)
COMMON_SRCS := sourcefile1.cpp sourcefile2.cpp sourcefile3.cpp sourcefile4.cpp
COMMON_SRCS := $(addprefix $(SRC_DIR)/,$(COMMON_SRCS))
COMMON_SRCS += $(shell find $(SRC_DIR)/util -name *.cpp)
SIM_SRCS := $(shell find $(SRC_DIR)/simulation -name *.cpp)
SIM_SRCS += $(SRC_DIR)/SimulationMain.cpp
$(BUILD_DIR)/%.cpp.o: %.cpp
$(MKDIR_P) $(dir $#)
$(CXX) $(CPPFLAGS) $(INCLUDES) -c $< -o $#
SRCS = $(COMMON_SRCS) $(SIM_SRCS)
build/simulation: $(OBJS)
$(CXX) $(LFLAGS) $(OBJS) -o $# $(LIBS)
.PHONY: clean
clean:
$(RM) -r $(BUILD_DIR)
-include $(DEPS)
If I try to run this with make build/simulation, I get *** No rule to make target 'build/sourcefile1.cpp.o', needed by 'build/simulation'. Stop. This is the first file in the OBJS list, so it seems like Make expanded all the variables but then couldn't match a single object file to a rule. What could be going wrong here?
My first thought was that the problem is the ./ in BUILD_DIR, and Make can't match build/sourcefile1.cpp.o to the rule ./build/%.cpp.o : %.cpp, but I get the exact same error if I remove the ./ from BUILD_DIR and SRC_DIR.
What's going wrong
The issue is caused by this line:
$(BUILD_DIR)/%.cpp.o: %.cpp
% will be sourcefile1 according to the left-hand side, so expanded line looks like this and the pattern gets ignored:
$(BUILD_DIR)/sourcefile1.cpp.o: sourcefile1.cpp
You need to get src/sourcefile1.cpp on the right to make this rule work.
How to fix it
You can either change the line to:
$(BUILD_DIR)/%.cpp.o: $(SRC_DIR)/%.cpp
Or make paths of object files include src/ (i.e., don't delete $(SRC_DIR) part from their path):
OBJS = $(SRCS:%=$(BUILD_DIR)/%.o)
Both solutions should be equivalent, they just adjust different parts of the rule.

put the object files into a separate folder GNU make

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.

Single top-level makefile with source subdirectories

Firstly, apologies for my ignorance. I'm sure the answer to my question exists in one of the many existing makefile threads here. However, I have been unable to find one that concisely and clearly answers my specific question without obfuscating the answer with details that aren't relevant to my particular situation.
My code directory has a single top-level source file containing main. The rest of the source files are organised in subdirectories according to logical divisions in the system. The code contains no relative paths in the includes. This means that everything works perfectly if all the code is in a single directory using the following, simple makefile:
CC=g++
CFLAGS=-c
LDFLAGS=
SOURCES=Main.cpp Source1.cpp Source2.cpp Source3.cpp Etc.cpp
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=executable
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) -o $#
.cpp.o:
$(CC) $(CFLAGS) $< -o $#
Until now I have been building my code using the NetBeans IDE. This has helped preserve my make ignorance by generating some vast and overly complicated makefiles on my behalf. Now the time has come to distribute my code for public use so I'm looking to produce a makefile will enable me to distribute the code with the directory structure I have.
Can you help?
Regards,
Enthusastic Amateur.
Take a look at this:
# Source directories separated by space
# Example ./ src1/ src2/
SRCDIR = ./ src/
# Directory where object files will be placed
OBJDIR = obj/
# Include directories separated by space
# Example: include1/ include2/
INCDIR = include/
# Directory where binary file will be placed
BINDIR = bin/
# Name of the result file
TARGET = app
# Compiler
CXX = g++
# Retrive list of the source files
SRC = $(wildcard $(addsuffix *.cpp,$(SRCDIR)))
# Generate list of the object files
OBJ = $(addprefix $(OBJDIR), $(patsubst %.cpp, %.o, $(notdir $(SRC))))
VPATH = $(SRCDIR)
# Compilation flags
CXXFLAGS = -std=c++11 -pthread
$(TARGET) : $(OBJ)
#echo Linking...
#mkdir -p $(BINDIR)
#$(CXX) $(CXXFLAGS) -o $(BINDIR)$# $(OBJ)
$(OBJDIR)%.o : %.cpp
#echo Compiling $< in $#...
#mkdir -p $(OBJDIR)
#$(CXX) $(CXXFLAGS) $(addprefix -I,$(INCDIR)) -c -o $# $<
clean :
#$(RM) -r $(OBJDIR)
#$(RM) -r $(BINDIR)
Here you can provide multiple source directories.
And "everything works perfectly" as well if the code is in multiple directories, using the same makefile you already have. No changes needed.