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.
Related
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!
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I know there a lot of questions about mixing .cpp and .c files into one makefile, but I haven't seen the issue of mixed substitution reference addressed. I am having issues with it.
My makefile is structure is based on this answer:
LIB=mylib.so
CPPSRCS += hello.cpp
CSRCS += goodbye.c
OBJS = $(CSRCS:.c=.o) $(CPPSRCS:.cpp=.o)
# Separate rules for .cpp and .c files, link together to form library.
# All pretty standard stuff and I am sure it will work if we goodbye.o and
# hello.o are present.
This doesn't work, and I get the old no rule to make target error. What am I doing wrong? How can I do substitution reference on two types of files into one variable?
In order to have a makefile work for both C and C++, you need separate rules for each language - although some rules are the same.
Another issue would be the linker. A C only project will use one linker and not the other.
I'm dumping my makefile here (it's from this project).
As you can see from this example, there are two different build rules, one for objects created with C file and another for objects created with C++. When the first one fails, the second one is attempted, so sharing a list of objects is made possible.
Also, you might notice that the C++ rule has this line $(eval CCL = $(CPP)) which sets the linker variable (CCL) to the C++ linker in projects where C++ is used. This way, when the build rule is called, it uses the correct linker.
Another thing to look at is the way this code deals with lists and extension substitution. Notice the use of the foreach, addsuffix and basename functions... this is distinctly more complex then the $(CSRCS:.c=.o) you suggested.
I would recommend you add a rule that displays the make variables, so you can debug any that have gone astray (see the demo), it a great way to learn as well as resolve issues.
A few words of warning about the makefile I'm pasting here...
It works for both C and C++ (mixed) projects and it's almost "plug and play", but you must to change the folder names and target files to fit your folder structure.
Also, notice that it will delete the whole of your project if you define the temporary folder as the project folder (it's defined as tmp for a reason, as it makes cleanup real easy).
In the future I might update it so any src subfolders are automatically added, but at the moment I need that extra control to exclude some folders.
This makefile is mostly a work of laziness... I hate updating makefiles all the time, so I have a low-cost makefile that mostly calculates everything on it's own... unless I change the project's folder structure or need different libraries.
NAME=demo
OUT_ROOT=./tmp
TMP_ROOT=./tmp
SRC_ROOT=.
SRC_EXTRA_FOLDERS=src src/http
LIBS=-pthread -lssl -lcrypto
INCLUDE=/usr/local/include
CC=#gcc
CPP=#g++
DB=#lldb
OPTIMIZATION=O3
#auto computed values
BIN = $(OUT_ROOT)/$(NAME)
SRCDIR = $(SRC_ROOT) $(foreach dir, $(SRC_EXTRA_FOLDERS), $(addsuffix /,$(basename $(SRC_ROOT)))$(dir))
SRC = $(foreach dir, $(SRCDIR), $(wildcard $(addsuffix /, $(basename $(dir)))*.c*))
BUILDTREE =$(foreach dir, $(SRCDIR), $(addsuffix /, $(basename $(TMP_ROOT)))$(basename $(dir)))
OBJS = $(foreach source, $(SRC), $(addprefix $(TMP_ROOT)/, $(addsuffix .o, $(basename $(source)))))
CCL = $(CC)
# the C flags
CFLAGS=-Wall -g -$(OPTIMIZATION) -std=c11 $(foreach dir,$(INCLUDE),$(addprefix -I, $(dir))) $(foreach dir,$(SRCDIR),$(addprefix -I, $(dir)))
CPPFLAGS= -Wall -$(OPTIMIZATION) -std=c++11 $(foreach dir,$(INCLUDE),$(addprefix -I, $(dir))) $(foreach dir,$(SRCDIR),$(addprefix -I, $(dir)))
$(NAME): build
build: $(OBJS)
$(CCL) -o $(BIN) $^ -$(OPTIMIZATION) $(LIBS)
$(TMP_ROOT)/%.o: %.c
$(CC) -o $# -c $^ $(CFLAGS)
$(TMP_ROOT)/%.o: %.cpp
$(CPP) -o $# -c $^ $(CPPFLAGS)
$(eval CCL = $(CPP))
clean:
-#rm $(BIN)
-#rm -R $(TMP_ROOT)
-#mkdir -p $(BUILDTREE)
execute:
#$(BIN)
run: | clean build execute
db: | clean build
$(DB) $(BIN)
vars:
#echo "BIN: $(BIN)"
#echo ""
#echo "SRCDIR: $(SRCDIR)"
#echo ""
#echo "SRC: $(SRC)"
#echo ""
#echo "BUILDTREE: $(BUILDTREE)"
#echo ""
#echo "OBJS: $(OBJS)"
#echo ""
#echo "CFLAGS: $(CFLAGS)"
#echo ""
#echo "CPPFLAGS: $(CPPFLAGS)"
As par Toby Speight's suggestion, I added the pipe sign (|) to mark the prerequisites as ordered, for all the concurrency people out there.
Abstract:
I have a .c file and a .cpp file with the same name in the same parent folder. I no longer wish to compile the .c file but doesn't want to remove it from the folder too.
Even though I explicitly specify to compile the .cpp file, the makefile was making use of the .c file. How can I fix this issue?
On renaming file3.c to another name, file3.cpp gets compiled.
Details:
The files present in 'src' folder are:
file1.c
file2.c
file3.c
file3.cpp
file4.cpp
Important extracts from the makefile:
SOURCE_FILES := ./src/file1.c \
./src/file2.c \
./src/file3.cpp \
./src/file4.cpp
OBJS = $(patsubst %.cpp,%.o,$(filter %.cpp, $(SOURCE_FILES))) \
$(patsubst %.c,%.o,$(filter %.c, $(SOURCE_FILES)))
all : $(OBJS)
$(CXX) $(CFLAGS) $(INCLUDES) -o $(PROJECT).bin $(OBJS) $(LDFLAGS) $(LIBRARIES)
.cpp.o:
$(CXX) $(CFLAGS) $(INCLUDES) -c $< -o $#
#echo 'CPP FILE : ' $<
.c.o:
$(CXX) $(CFLAGS) $(INCLUDES) -c $< -o $#
#echo 'C FILE : ' $<
On doing 'make', the log of the echo command gives:
C FILE : ./src/file1.c
C FILE : ./src/file2.c
C FILE : ./src/file3.c
CPP FILE : ./src/file4.cpp
Questions:
How can the above issue be solved?
Is there an easier way to fetch values for my OBJS variable?
The method make uses to pick which of two possible matching rules gets used depends on which version of make you are using. (It changed between 3.81 and 3.82 and I believe got tweaked slightly for 4.0+ but am not certain about that.)
I believe make 3.81 used the last matching rule and make 3.82+ uses the matching rule with the shortest stem (the bit that matches the %) and then the first matching rule between rules that have similar stem lengths.
So it would seem like you are using make 3.81 currently.
In that case it should be possible to simply swap the order of your two rules to get the behavior you want (assuming you always want .cpp files to "win").
Alternatively you could try giving make an explicit prerequisite for the file3.o target instead of letting it guess. (i.e. file3.o: file3.cpp)
That said neither of your explicit suffix rules is necessary as make already contains default rules to build .o files from both .c and .cpp files. (I don't know the relative ordering between them so you likely will need the explicit prerequisite, assuming that works, for the built-in rules to work correctly.)
Also you might want to look at using Pattern Rules instead of Old-Fashioned Suffix Rules just as a point of current practice.
The only improvement to your populating the OBJS variable that I can see, offhand, is to filter on the results and so just filter once.
OBJS = $(filter %.o,$(patsubst %.cpp,%.o,$(SOURCE_FILES)) \
$(patsubst %.c,%.o,$(SOURCE_FILES)))
That said you could also use Substitution References instead of explicit calls to $(patsubst) to shorten that a bit.
OBJS = $(filter %.o,$(SOURCE_FILES:.cpp=.o) $(SOURCE_FILES:.c=.o))
You have rules for both .c ==> .o and .cpp ==> .o.
In your case the rule for file3.c is run first since the newly created file3.o file now exists. Since the target file3.o file exists, there is no reason to compile file3.cpp.
Looking at the make manual, if there are 2 rules for the same target, the last rule is used.
I'm learning about makefiles. What I tried is writing my own one after a little reading. The problem is, I always get errors connected with c++11 standard, even though I put the compiler flag needed into makefile. Here is the error:
/usr/include/c++/4.6/bits/c++0x_warning.h:32:2: error:
#error This file requires compiler and library support for the upcoming
ISO C++ standard, C++0x. This support is currently experimental, and
must be enabled with the -std=c++0x or -std=gnu++0x compiler options.
And here is the makefile:
CC = g++
LD = g++
NAME = app
OBJ_DIR = obj
SRC_DIR = src
CXX_FLAGS = -std=c++0x
SRC = $(shell find $(SRC_DIR) -type f -regex ".*\.cpp")
OBJ = $(subst $(SRC_DIR), $(OBJ_DIR), $(addsuffix .o, $(basename $(SRC))))
all: $(NAME)
$(NAME): $(OBJ)
$(LD) $< -o $# $(CXX_FLAGS)
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
$(CC) $< -o $# $(CXX_FLAGS)
clean:
rm $(NAME) $(OBJ_DIR) -rf
Notice that I've put CXX_FLAGS after checking out other questions on stack overflow, but to no avail. I still get the same error. It's like make is ignoring my flag. Is there a solution to this?
And yes, I can compile with -std=c++0x flag without make, so my compiler is not a problem obviously.
Does the directory obj exist?
A better way to write this would be:
OBJ = $(patsubst $(SRC_DIR)/%.cpp,$(OBJ_DIR)/%.o,$(SRC))
You can add $(info OBJ = $(OBJ)) etc. after these lines to print them out. Basically the results of these operations don't match your pattern rules, so make is using the default pattern rules.
I strongly discourage this kind of thing (using find) though. I always, always type out the source files I want to compile. It doesn't take more than a few seconds to add a new file, and it ensures you don't start throwing random junk into your program when you least expect it.
Your compile command is also wrong: you've forgotten the -c flag which is important. I recommend people just use the same command as the default rules (run make -p -f/dev/null to see the default rules).:
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
$(COMPILE.cc) $(OUTPUT_OPTION) $<
This does require you to use the standard flags variables (i.e., CXX not CC and CXXFLAGS not CXX_FLAGS) but that's a good idea anyway.
Its not actually using your rule for building the object file. Comment it out and you'll see that it still invokes "g++ -c".
Part of the problem is that the command subst you are using to define OBJ interprets its arguments as literals. Rewrite it as
OBJ = $(subst src, obj, $(addsuffix .o, $(basename $(SRC))))
and you'll at least get the desired OBJ.
You have spaces at the ends of the lines that define SRC_DIR and OBJ_DIR. This means that subst won't do anything, since it's looking for "src " rather than "src".
In turn, this means that it will try to build src/whatever.o rather than obj/whatever.o and, since there is no rule for that, it will fall back to the default rule rather than yours.
Once you've fixed that, you'll need to add -c to the compile command, to produce an object file rather than an executable.
To generate dependency files I can use something like this to generate dependency files:
-include $(patsubst %.cpp,build/%.d,$(SRC))
build/%.o: %.cpp
$(CC) $(CXXFLAGS) -c -o $# $<
$(CC) $(CXXFLAGS) -MM -MT $# -MF $(patsubst %.o,%.d,%#) $<
This generates everything and puts both the object and dependency files into the build dir where I want them. But this makes two dependency lines for the <file>.o targets, one from the -include rule and with all the header dependencies, and one which is from the pattern rule. Will this get interpreted correctly, i.e. when a header is modified, the object will be recompiled via the command specified for the pattern rule?
Edit: So this approach does in fact work quite well. I guess I'd like somebody to provide an answer which gives me some insight into what it is exactly that make does in these situations. For instance, what if a different command was given for both rules for the same target? My guess would be that it gives an error since it wouldn't be obvious which command to execute.
You should add one more pattern rule to express the dependency between the .cpp and .d files and use that rule to create the .d files (second line in the pattern rule of your question) instead of creating the .d files unconditionally. It might make sense to introduce another dependency between all .h and .cpp files and all .d files to force re-creating the .d files if a header or source file changes.
Here's the separate rule for .d files (hope I got it right):
-include $(patsubst %.cpp,build/%.d,$(SRC))
build/%.o: %.cpp
$(CC) $(CXXFLAGS) -c -o $# $<
build/%.d: %.cpp
$(CC) $(CXXFLAGS) -MM -MT $# -MF $<
Edit: So this approach does in fact
work quite well. I guess I'd like
somebody to provide an answer which
gives me some insight into what it is
exactly that make does in these
situations.
I'm afraid currently it would only work by chance (or you have not given all relevant pieces from the make file). See, you have not expressed any dependency between .d files and .cpp files. This, however, is needed so that your .d files get updated before inclusion as make file fragment.
For instance, what if a
different command was given for both
rules for the same target? My guess
would be that it gives an error since
it wouldn't be obvious which command
to execute.
With that syntax it wouldn't make a difference. But there are some special cases where splitting the rules into two (though otherwise identical rules) has merit. I strongly recommend you get the book "Managing Projects with GNU Make" to get a grip on the various ways of working with GNU Make. The only other recommendation in connection with GNU Make is to read to read the paper here.
Yes, you can specify several rules for one file, and they get merged into one.
See the GNU Make documentation.
[...] There can only be one recipe to be executed for a file. [...]
An extra rule with just prerequisites can be used to give a few extra prerequisites to many files at once.
And I second that there should be separate rule for .d files. It's names in many projects are deps or depend.
POSIX 7 also says that multiple lines for a given target work http://pubs.opengroup.org/onlinepubs/9699919799/
A target that has prerequisites, but does not have any commands, can be used to add to the prerequisite list for that target. Only one target rule for any given target can contain commands.
so long as only one has the commands.