I'm really new to makefile and I'm struggling to make it compile all the .cpp files inside the src folder.
right now the makefile looks like this:
SRC_DIR = src
OBJ_DIR = build/obj
INCLUDE_DIR = $(SRC_DIR)/inc
SRC_DIRS = $(wildcard $(SRC_DIR) $(SRC_DIR)/* $(INCLUDE_DIR)/*)
C_FILES = $(filter %.cpp, $(wildcard $(SRC_DIRS)/*.cpp))
OBJ_FILES = $(addprefix $(OBJ_DIR)/, $(notdir $(C_FILES:.cpp=.o)))
INCLUDE_PATH = -I$(INCLUDE_DIR)
CXXFLAGS = $(INCLUDE_PATH)
CXX = g++
CFLAGS = -Wall -g
CC = gcc
$(OBJ_DIR)/%.o: $(SRC_DIRS)/%.cpp
pile: $(OBJ_FILES)
test:
#echo $(C_FILES)
#echo $(OBJ_FILES)
and what I want to achieve with each rule is:
pile: when calling make pile it should check for all the .o files inside build/obj.
$(OBJ_DIR)/%.cpp: find the equivalent .cpp file inside the source folder and compile it.
I suppose that there's something wrong with my second rule, but I can't really tell why cause the test rule is printing all the files.. :/
thank you in advance for any help.
Looks like SRC_DIRS could be an array which will not be happy with that matcher function.
Try changing:
$(OBJ_DIR)/%.o: $(SRC_DIRS)/%.cpp
to
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
There are many problems here but the most fundamental is that you are not actually defining a rule when you write this line:
$(OBJ_DIR)/%.o: $(SRC_DIRS)/%.cpp
A rule consists of targets, prerequisites and a recipe. Here you have not provided a recipe, so you haven't told make how to actually build anything.
The other issue is as mentioned by #Ryan-Miller; you can't use multiple directories in a single rule like this. But you can just avoid the complexity anyway if all your source files are in a single directory.
If that's not what you want please make your question clear as to ALL the different things you need. You wrote "$(OBJ_DIR)/%.cpp: find the equivalente .cpp file inside the source folder and compiles it". How exactly are you defining "the equivalent .cpp file"? Computer programming is all about the details!
Related
I am trying to have my cpp source files and my object files in separate directories, so I'm trying to use Make's patsubst to replace the paths. After nothing was compiling, I made a phony target to simply print out the relevant variables and I discovered that patsubst was returning nothing. This doesn't make a lot of sense to me, as from what I can tell, targets that don't match the pattern should pass through unchanged, so even if my patterns are malformed I should still be seeing something get returned.
My variables are declared like this:
SRC_DIR := source/
SRC := $(wildcard $(SRC_DIR)*.cpp)
OBJ_DIR := obj/
OBJ := $(PATSUBST $(SRC_DIR)%.cpp, $(OBJ_DIR)%.o, $(SRC))
My phony target that just prints out the above variables looks like this:
.PHONY: print
print:
#echo $(SRC_DIR)
#echo $(SRC)
#echo $(OBJ_DIR)
#echo $(OBJ)
and the result of running make print is this:
user#athena:~/proj$ make print
source/
source/main.cpp source/util.cpp
obj/
user#athena:~/proj$
Other things I've tried
I've tried SRC_DIR and OBJ_DIR having trailing slashes and not having them, I've tried $(SRC:$(SRC_DIR)%.cpp=$(OBJ_DIR)%.o) which did work, and $(OBJ) would have both main.o and util.o, but then my static rule ($(OBJ): $(OBJ_DIR)%.o : $(SRC_DIR)%.cpp) would only trigger for main.cpp, and wouldn't try to compile util.cpp, which I'm considering a completely separate issue?
I hope I'm just doing something dumb and there's a simple fix, but I've been racking my brain and I can't see what would be causing patsubst to just be blank. Any help would be greatly appreciated.
Like (virtually) all programming languages, makefiles are case-sensitive. $(FOO) is not the same as $(foo), and $(PATSUBST ...) is not the same as $(patsubst ...).
In fact, $(PATSUBST ...) is nothing and expands to the empty string.
Im currently trying to get my makefile independend from my folder structure. So far i worked with a single specific folder containing all my .cpp files. My .o files are all placed in a seperate OBJ/ folder. However i now want my makefile to automatically grab all .cpp files from all subdirectories (any depth if possible) but still place all .o files the one same OBJ folder. This is how my makefile looks at the moment:
CC = g++ -g
SRC = Src/
OBJ = Obj/
BIN = Bin/
INC = -I Lib/GLFW/include/\
-I Lib/GLAD/include/\
-I Lib/STB/\
-I Lib/GLM/\
-I Src/Header/
LIB = -L Lib/GLFW/lib-mingw-w64 -lglfw3 -lopengl32 -lglu32 -lgdi32
EXE = $(BIN)Test.exe
SOURCEFILES = $(wildcard $(SRC)**/*.cpp)
OBJECTFILES = $(patsubst $(SRC)%.cpp,$(OBJ)%.o,$(SOURCEFILES))
all: $(SOURCEFILES) $(EXE)
$(EXE) : $(OBJECTFILES)
$(CC) -o $# $^ $(LIB)
$(OBJ)%.o: $(SRC)%.cpp
$(CC) -c $< $(INC) -o $#
It somewhat does what i want, but for some reason it currently is required to have the same folder structure of my SRC/ directory in OBJ/ aswell: If my .cpp file is SRC/foldername/name.cpp my makefile wants to create the .o as OBJ/foldername/name.o. I want it to be OBJ/name.o for all files regardless of the structure of SRC/ . What do i need to change to achieve that?
My second question is about the include path. As it can be seen in the makefile, all my header files are in a single directory Src/Header/. Is it possible to somehow also automatically get and link the right .h files from Src/ and it's subdirectories?
If you want to flatten paths, you can use notdir.
Unfortunately, because %.o is "magic", you can't just wrap it in a $(notdir).
By the way, as a matter of style, I'd leave the trailing slash out of those variables and use it in the expressions instead; it'll be much easier to read, and more flexible too.
This works for me:
SRC=srcPath
OBJ=objPath
SOURCEFILES = $(wildcard $(SRC)/**/*.cpp)
OBJECTFILES = $(addprefix $(OBJ)/, $(notdir $(patsubst $(SRC)/%.cpp, %.o, $(SOURCEFILES))))
all:
echo $(OBJECTFILES)
More pleasing alternatives surely exist, but the point is that you can use notdir to build your solution.
Flattening your object files in one single directory is not necessarily a very good idea. Your Makefile is getting more complex (see below) and there is a name collision possibility if, by accident, you have two source files with the same base name.
Anyway, it is what you want, and here is a possible solution:
SRC = Src
OBJ = Obj
SOURCEFILES = $(wildcard $(SRC)/**/*.cpp)
# $(1): full path to source file
define CompileRule
$$(OBJ)/$$(patsubst %.cpp,%.o,$$(notdir $(1))): $(1)
$$(CC) -c $$< $$(INC) -o $$#
endef
$(foreach f,$(SOURCEFILES),$(eval $(call CompileRule,$(f))))
It iteratively instantiates custom compilation rules for each of your source files. See the GNU make manual for a complete explanation.
I am not sure I fully understand your second question but if you want to find all header files in Src and build the list of -I<dir> compile options, you can probably try something like:
HEADERFILES := $(wildcard $(SRC)/**/*.h)
HEADERDIRS := $(sort $(dir $(HEADERFILES)))
INCLUDES := $(patsubst %,-I%,$(HEADERDIRS))
But it is very sub-optimal because every directory containing header files will be involved as -I<dir> in the compilation of every source file.
Last but not least, your next step could be "how do I automatically get the list of all header files a source file depends on?". If it is, you should probably have a look at this post about Auto-Dependency Generation.
I'm trying to clean up my project a little and I want to put object files and include files in a separate folder and be able to compile another makefile in my a different testing subdirectory. I would like to do this so that the make file in the testing directory doesn't have to know about the objects in the the above directory: I have been struggling all day trying to figure out make and compilation.
Not sure what I'm doing wrong but in addition to this question I would be appreciative of any information to straighten out my thinking about make and g++ so in the future I know where to look.
Anyways I have 2 Questions both with regards to my project layout:
Project
inc/
-- header files
-obj/
--object files
-source
-make file for project that compiles objects in obj directory (makefile0)
-testing/
--test1/
---test.cc
---makefile1
Question 1
So I want to include the header files in the inc directory in test.cc and then just focus on compiling test.cc like I would if I included a standard library header file. Right now I need to make reference to the object in ../../obj/ in makefile1 and would like to ignore that. and just do something simple like
g++ -I ../../inc/ -c test.cc
How is it possible to do this?
Question 2
In makefile0, for each source file I have to append a $(OBJ) or $(INC) to the front of any file I have in those folders and wondering if there is anyway to clean up my make file an do something like
Spinless2DFieldIndex.o: Spinless2DFieldIndex.cc Utils.o Dispersion.h
instead of
$(ODIR)/Spinless2DFieldIndex.o: Spinless2DFieldIndex.cc $(ODIR)/Utils.o $(INC)/Dispersion.h
The following should work:
Project/Makefile
objdir := obj/
vpath %.cc source
vpath %.o $(objdir)
CPPFLAGS := -Iinc -MMD -MP
.PHONY: all
all: testing/test1/test
include source/Makefile
include testing/test1/Makefile
Project/source/Makefile
override objects := $(objdir)obj.o
$(objects): $(objdir)%.o: %.cc
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(OUTPUT_OPTION) $<
clean:: ; $(RM) $(objects) $(objects:.o=.d)
-include $(objects:.o=.d)
Project/testing/test1/Makefile
override dir := $(dir $(lastword $(MAKEFILE_LIST)))
$(dir)test: obj.o
clean:: ; $(RM) $(dir)test $(dir)test.d
-include $(dir)test.d
This should allow for a certain amount of modularity, although the asymmetry in the makefiles betrays the fact that your idea of having a separate obj directory while at the same time wanting to have the test executables in their own directory is perhaps not the best way to organize things. Personally I use a more configure style of makefile that recreates the project tree in the current working directory which helps separate the source from the build.
I am going over this tutorial and it has something like this
# File names
EXEC = run
SOURCES = $(wildcard *.cpp)
OBJECTS = $(SOURCES:.cpp=.o)
.....
%.o: $(SRCPATH)/%.cpp $(INC)
$(CC) $(CXXFLAGS) $(INCLUDES) -c $< -o $#
I am not sure if I understand the document and would appreciate it if someone could explain the last two statements. Here are my three questions regarding Makefile
Question 1 :
Whats the difference between
SOURCES = $(wildcard *.cpp)
and
SOURCES = $(*.cpp)
It says that the second case only works if .cpp files exist since they do not therefore it wont work. My question is why does the first one work ?
Question 2:
What does the 'wildcard *' mean ?
what does the last statement OBJECTS = $(SOURCES:.cpp=.o) mean ?
Question 3:
What does %.o mean when it is placed as a target ? Whats the difference between
*.o , %.o and wildcard *.cpp
SOURCES = $(*.cpp)
SOURCES = *.cpp
SOURCES = $(wildcard *.cpp)
The first one is an error, the second expands too late (not on definition), the third searches for all files with suffix .cpp in the source directories.
The builtin-function wildcard is used to force wildcard-expansion where it does not naturally occur.
OBJECTS = $(SOURCES:.cpp=.o)
That means OBJECTS is assigned the value of SOURCES, after substituting every .cpp at the end of an item with .o.
And %.o as a target means you are defining a rule for creating .os from something else.
References: GNU make manual
See here for a good basic makefile: https://stackoverflow.com/a/26579143
All of your questions are answerable via a reading of the GNU Make Manual.
The section on wildcards in the GNU Make Manual is worth reading for what I believe the author of that page was trying to explain about not using *.cpp as it may not do what you want. (The authors point about make ignoring modification times because of the bare glob is, however, entirely incorrect.)
That section continues into the section on the wildcard function. Which is just a make-expanded globbing function to control time of expansion (variable definition time instead of variable use time).
$(SOURCES:.cpp=.o) is a Substitution Reference.
%.o as a target is a Pattern Rule.
*.o is a glob.
$(wildcard *.cpp) (not wildcard *.cpp) was covered earlier.
I'm playing around some tutorial code from this OpenCV 2 Cookbook. The code doesn't come with any Makefiles, and I'd like to create a Makefile that can Make all of the files in the codebase. My plan is to compile all the files with profiling, and then make a script that runs all the executables and collects the gprof results. Then, I can get some intuition for the computation time of various OpenCV functions.
The codebase is arranged like this: tutorial_code/Chapter[1-10]/*.cpp
Each .cpp file is self-sufficient and can be compiled without linking against other modules in this codebase. (There are a few small header-only libraries, though.)
Here are a couple things that I'm stuck up on:
Typically, the $(EXEC) in a Makefile represents a file that is the culmination of much of the building effort. However, in my case, I want to create a separate $(EXEC) for each .cpp file. I think I'm close to getting this right, but so far my Makefile just generates *.o but not *.out
I understand that SOURCES = $(wildcard *.cpp) is a way to "collect" the set of cpp files in the current directory. It would make sense that SOURCES = $(wildcard */*.cpp) would drill down and grab all .cpp files in the subdirectories. It doesn't seem to work, though.
Starting from this tutorial, I set up a Makefile that implements the proposed functionality. It doesn't quite work... $(wildcard */*.cpp) doesn't seem to drill down into directories, and I'm not sure how to do something like $< and $# to refer to basefilename.o and to create basefilename.out.
CC = g++
CC_FLAGS = -w `pkg-config opencv --cflags`
LINK = g++
LINKOPTS = -pg `pkg-config opencv --libs`
SOURCES = $(wildcard */*.cpp)
OBJECTS = $(SOURCES:.cpp=.o)
EXEC = $(SOURCES:.cpp=.out)
%.out: %.o
$(LINK) $< $(LINKOPTS) -o $#
%.o: %.cpp
$(CC) -c $(CC_FLAGS) $< -o $#
clean:
rm -f $(EXEC) $(OBJECTS)
I'm fairly familiar with Makefiles and OpenCV, and I haven't had a problem compiling my own projects by hand-coding the lists of dependencies, objects, etc in Makefiles. However, for the matter at hand, it'd be fantastic to just automatically make everything without much user intervention.
Feel free to comment, email, or message me for a copy of the codebase that I'm trying to compile.
I've also thought of making a script that iterates through the tutorial_code/Chapter[1-10] directories and creates one Makefile for each directory. Then, I'd make an other function in the script to call Make once in each directory. The idea of doing one grand Makefile sounds like more fun, though.
EDIT: This does work if I use SOURCES = $(wildcard *.cpp) and place the Makefile in the same directory where cpp files are located. However, I'm still trying to figure out how to have $(wildcard */*.cpp) drill down into subdirectories.
EDIT 2: The Makefile shown above now works properly. To see the earlier version, feel free to scroll through the edit history.
You can write a version of wildcard that works recursively to any depth using only make functions:
find-recursive = \
$(wildcard $1/$2) \
$(foreach f,$(wildcard $1/*/.),\
$(call find-recursive,$(patsubst %/.,%,$f),$2))
SOURCES = $(call find-recursive,.,*.cpp)