Makefile target errors - c++

I have been reading a book on SFML game development and they use unique_ptr's. And to use them I know that I must use the -std=c++11 flag when compiling, however I have been having issues doing this with a Makefile. Below is a copy of my Makefile:
flags = -lsfml-graphics -lsfml-window -lsfml-system
main: main.cpp texture_holder.o
g++ main.cpp texture_holder.o -o Run $(flags) -std=c++11
texture_holder: texture_holder.cpp texture_holder.h
g++ texture_holder.cpp -c -std=c++11
.PHONY: clean
clean:
rm *.o Run
When just typing make I get errors about unique_ptr not being a member of std. But what I can't figure out, is that when I type make texture_holder texture_holder.cpp does compile just fine then running make builds the application. Do I have something ordered wrong or am I missing anything? If it helps, I can attach the code that I am using, but like I said, it builds just fine when I build the texture_holder target first.

You have wrong rule for texture_holder.o, it should be this:
texture_holder.o: texture_holder.cpp texture_holder.h
g++ texture_holder.cpp -c -std=c++11
Ie. including the .o extension.
What happens with your question's version is, when you do make texture_holder, you execute that particular rule, which does not actually create corresponding file texture_holder, it creates texture_holder.o, because well, that's what the commend produces. The texture_holder rule is effectively a phony rule, similar to main and clean (and btw, you should add main to .PHONY too).
If you make main, then to create texture_holder.o, make uses implicit rule (because there is no explicit one), which uses different compile command.

You have a rule for making texture_holder, not texture_holder.o. The rule for main will attempt to make texture_holder.o using the default compilation rule, not your special one. The default rule won't specify -std=c++11, hence the error.

Related

Makefile with multiple targets and creates a directory with executable

I don't often use makefiles therefore I only how to make basic ones. I've tried reading on how to solve my issue but I am lost. What I need is a makefile that has two targets all and test. Both of these targets need to compile the program with g++ -std=c+11 -Wall -Werror -ansi -pedantic and the only file that needs to be compiled is main.cpp when the executable is built by the compiler it needs to put the executable in a new directory called bin. And I'm assuming that if I were to use the makefile again it would need to check if bin was already created.
I know how to create a simple makefile such as
all:
g++ -std=c++11 -Wall -Werror -ansi -pedantic main.cpp
That creates an executable named a.out in the current directory, but that's about as far as my knowledge of makefileS go
All that a Makefile does is specify the build dependencies, and the commands to execute to build those dependencies.
Things like creating the output directories, et. al. is not make's job per se, but rather something that's up to the commands that makes executes to do. Neither does the Makefile specify where the output of the build commands go. That, of course, is specified by the actual commands that get executed. With gcc, for example, the -o option specifies where the compilation output goes. So:
all: bin/main
test: bin/main
bin/main: main.cpp
mkdir -p bin
g++ -std=c++11 -Wall -Werror -ansi -pedantic -o bin/main main.cpp
It's very convenient to use mkdir -p in these situations. If the given directory does not exist, it gets created. If it already exists, mkdir just quietly terminates without an error.

Understanding the Dependencies of a Makefile (C++)

While working on a C++ project, I noticed that I was making changes to one of the header files linked in my main code, but the make utility was not registering it. I had to force it to compile differently given the changes using "make - B".
I want to know why this is the case; is it because of how my makefile is written, how my files depend on each other, both, or neither?
Here is my makefile:
CXXFLAGS = -Wall -Werror -std=c++11 -pedantic -Wvla -g
//CXXFLAGS = -std=c++11
all: main.o game.o zombie.o
g++ $(FLAGS) game.o main.o zombie.o -o main $(CXXFLAGS)
game: game.cpp
g++ $(FLAGS) -c game.cpp $(CXXFLAGS)
zombie: zombie.cpp
g++ $(FLAGS) -c zombie.cpp $(CXXFLAGS)
main: main.cpp
g++ $(FLAGS) -c main.cpp pairing_heap.h $(CXXFLAGS)
I made a change to pairing_heap.h which is #included in my main file.
Why did make not notice that it should compile again? Because I feel like this is a conceptual misunderstanding, I felt that it was not necessary to include the changes I made or the output difference when I did "make - B". They were simple things like cout's and cerr's included in the new pairing_heap.h that were not being picked up until forced.
Let me know if I need to provide any more information.
Thank you.
You are listing pairing_heap.h in the recipe for main, which does not make it a dependency of main (besides, you should never pass headers to the compiler like this), for that you need to write the rule as follows:
main: main.cpp pairing_heap.h
g++ $(FLAGS) -c main.cpp $(CXXFLAGS)
There are a number of other things that are incorrect in your file, such as the fact that your targets are not actual files (main: should be main.o: etc.), and you aren't making use of automatic variables or pattern rules, but it's probably easier to just replace everything with the following
CPPFLAGS := -MMD -MP
CXXFLAGS := -Wall -Werror -std=c++11 -pedantic -Wvla -g
SOURCES := $(wildcard *.cpp)
main: $(SOURCES:.cpp=.o)
-include $(SOURCES:.cpp=.d)
which leverages make's implicit rules and gcc's/clang's auto dependency generation to make an executable called main.
Make doesn't really know anything about any particular programming language or tool, so it doesn't understand that C/C++ files depend on headers as well as source files. It just has rules of the form
target: dependencies
actions
All it knows from this is that the file target depends on the files listed in dependencies, and if any of those files are newer, the commands in actions should be run to update target. That's really it -- everything that make does comes from this simple idea of target files, dependencies, and actions.
Now there is more to it -- make has a bunch of built-in rules for common things you often want to do, as well as ways to specify 'pattern' rules -- rules where the target contains a wildcard, so can be used for many different targets that depend on other files with related names.
Now in your case, you have the rule:
all: main.o game.o zombie.o
g++ $(FLAGS) game.o main.o zombie.o -o main $(CXXFLAGS)
which says to remake the file all, if its older than the files main.o, game.o or zombie.o it should run the command. That's the first rule in the file, so it is what gets built by default when you type make.
Now, you probably don't have a file called all (if you did make probably wouldn't do anything), but that's generally fine, as if it doesn't exist, its obviously not up to date, so the command needs to run.
When a command needs to run, it also checks any of the dependencies to see if they in turn have dependencies that are older (so need to be rebuilt). Since these files all end in .o, they match a built-in rule that knows how to build them from a file with the same name, except ending with .cpp, so its runs those actions if (and only if) the .cpp file is newer.
Now, you say, "what about my other rules -- what do they do?" Well it turns out they don't do anything. They are rules to build files named game, zombie, and main, and since you never ask to build those files and nothing else depends on them, they do nothing. You might as well delete them.
You also ask "How do I make it rebuild if the header file changes?" Well, if you add a rule with no actions (just target and dependencies) it will just add those dependencies to another rule (built-in in this case) that does have an action. So if you add a line like:
main.o: pairing_heap.h
(with no action), make will add this dependency to the built-in rule that know how to build main.o from main.cpp and will run that rule (recompiling main.cpp) if either main.cpp or pairing_hep.h is newer than main.o -- which is exactly what you want.

Makefile using c++ instead of g++ - Why?

I seem to be having an issue getting my makefile to build my C++ file correctly. My makefile code is below; the file I am trying to compile is named "avl.cc" (which is working and compiles properly).
CC=g++
CFLAGS=-g -O2
PROGS=avl
all: $(PROGS)
$#:
$(CC) $(CFLAGS) $# $#.cc
.PHONY: clean
clean:
rm $(PROGS)
However, when I enter the command make or make all, I get
c++ avl.cc -o avl
And the debugging symbols I want from the -g flag don't come up. A similar makefile (only changing the PROGS variable) worked for a similar project, so I am not sure what I'm doing wrong. Does anyone have any tips? Thanks!
From Makefile documentation about automatic variables:
It’s very important that you recognize the limited scope in which
automatic variable values are available: they only have values within
the recipe. In particular, you cannot use them anywhere within the
target list of a rule; they have no value there and will expand to the
empty string.
This means you cannot use $# as a rule, which means the default c++ compilation rule of Makefile is used, and since you did not use the correct variable names for c++ compilation, they are also ignored.
You can replace CC by CXX and CFLAGS by CXXFLAGS to work with c++.
You don't have a target for 'avl', so make uses a default rule.
Try changing the makefile to this:
CC=g++
CFLAGS=-g -O2
PROGS=avl
all: $(PROGS)
$(PROGS):
$(CC) $(CFLAGS) -o $# $#.cc
.PHONY: clean
clean:
rm $(PROGS)
I had the exact same question but a much different source of the problem. There were typos or misnamed files in my makefile. Make found no rules for such files but tried to compile targets with the c++ compiler. This made the process seem like it was ignoring my rules and imposing its own, switching compilers since I needed g++. Finally I tried using the -r option, and then the resulting different error messages allowed me to figure out what was really wrong. Below is the entry from the make man page for option -r.
-r, --no-builtin-rules
Eliminate use of the built-in implicit rules. Also clear out the default
list of suffixes for suffix rules.

Writing a makefile to build dynamic libraries

I have a makefile in my src directory.
The makefile should build the data structures, which are in DataStructures/, and then iterate over all cpp files in calculations/ and create a corresponding .so file in ../bin/calculations
I tried the following syntax:
DAST = DataStructures/
COMPS = computations/
BIN = ../bin/
OBJECTS = ${DAST}Atom.o ${DAST}Molecule.o
COMPILE = g++ -Wall -g -c -std=c++0x -I/usr/local/include/openbabel-2.0 LINK = g++ -Wall -g -std=c++0x ${OBJECTS} -lopenbabel -I/usr/local/include/openbabel-2.0
all: ${BIN}main ${DAST}Molecule.o ${DAST}Atom.o ${BIN}${COMPS}%.so
${BIN}main: ${OBJECTS} main.cpp
${LINK} main.cpp -o ${BIN}main
${DAST}Molecule.o: ${DAST}Molecule.h ${DAST}Molecule.cpp
${COMPILE} ${DAST}Molecule.cpp -o ${DAST}Molecule.o
${DAST}Atom.o: ${DAST}Atom.h ${DAST}Atom.cpp
${COMPILE} ${DAST}Atom.cpp -o ${DAST}Atom.o
${BIN}${COMPS}%.o: ${COMPS}%.cpp
gcc -Wall -fPIC -c -lopenbabel $< -I/usr/local/include/openbabel-2.0 -std=c++0x
${BIN}${COMPS}%.so: ${COMPS}%.o
gcc -shared -Wl,-soname,libcsmtest.so.1 -o libcsmtest.so $#
clean:
rm -rf ${OBJECTS}
.PHONY: all clean
But it obviously doesn't work, as I get the following output:
shai#ubuntu:~/csm/csm2/src$ make all
make: *** No rule to make target `../bin/computations/%.so', needed by 'all'. Stop.
thanks
You need to specify in the all: target, the prerequisites explicitly.
In Makefile parlance, % is a wildcard that can be used in automatic rules. However, the all: target is a simple target with no such wildcard, thus ${BIN}${COMPS}%.so is wrong in that context.
Please note that when I say 'wildcard' in this context, this wildcard matches the target against the prerequisites, not against the filesystem like * do in glob expressions.
Also, while your hart is in the right place, as a matter of style, your Makefile can be better:
Intermediary objects, should not be prerequisites of the all target, but only the final targets you wish to ship.
There is a mix of automatic and simple rules to specify the creation of objects.
Typically one doesn't write an automatic rule for %.so, because a library is often constructed from more than one object.
The dependencies between an object and header files is a complex issue. In short you need to specify that the resulting object depends on the *.cpp (or .c) as well as all the headers included (directly and indirectly) by the *.cpp file.
By convention, that is well supported by GNU make, instead of using ${COMPILE} as you do, one should use $(CXX) for your C++ compiler, and $(CXXFLAGS) for the standard flags you wish to pass to that compiler.
You need something like
SOBJECTS = ...
all: ${BIN}main ${SOBJECTS}
...
You need a way to gather all the *.so names in the variable SOBJECTS. You can do this manually, or use some of make's internal functions to scan the source directory.
Also notice that I removed the two *.o files as dependencies from the all target. They are not final goals of the build (I assume), so you don't need to mention them there.
Besides this there are other stylistic points which I would do differently, but at the moment they are not causing immediate problems, so I won't digress, but I advise you to have a look at some tutorials to see how things are done generally.
For starters, look at Paul's Rules of Makefiles, and How Not to Use VPATH.

Am I using a Makefile for C++ correctly?

Makefile
default:
(!) g++ -Werror -Wunused-variable -Wunused-value -Wunused-function -Wfloat-equal -Wall -ansi -o main -pedantic-errors main.cpp
'/home/HomeName/Desktop/main'
I have been using this code to compile a C++ file. Is this a good way of using this code in the makefile? Moreover, I wonder if the line marked with (!) has the compiler options in the correct order.
So, your makefile itself does not contain the '(!)' marking, I believe.
What you have 'works'. It compiles the program with a stringent set of options and then runs it by absolute pathname.
However, it is not very flexible:
it will only build main if you run make
it will always build main even if you built it a moment ago
if you run make main, it will use a different set of commands to build the program, and it won't run the program.
It would be better - it would allow you to move the code more easily - if the line to run the program used the current directory.
And it would be better if you used some of the built-in features of make.
The C++ and C compilers are very tolerant of various orders for their options; what you have is OK.
Inside make, the C++ compiler is known by the macro CXX; it takes a set of flags defined by CXXFLAGS. You could, therefore, use:
CXX = g++
CXXFLAGS_W = -Werror -Wunused-variable -Wunused-value -Wunused-function \
-Wfloat-equal -Wall
CXXFLAGS_M = -ansi -pedantic-errors
CXXFLAGS = ${CXXFLAGS_M} ${CXFLAGS_W}
all: main
./main
This allows you to run make, make all and make main and get the program main built. If you use either of the first two, the program will also be run. It will only recompile the program if the source has changed since it was last compiled. If you have other programs in the directory, say 'exercise2.cpp' and 'exercise3.cpp', then you'd be able to say make exercise2 exercise3 and those would now be compiled in much the same way that main is.
If you really wanted to run the program after building it (probably not something you'd do in the long-term), then you'd probably rewrite the compilation rule (assuming GNU Make):
% : %.cpp
${CXX} ${CXXFLAGS} -o $# $*.cpp
./$#
If you have a classic or POSIX variant of make, you'd write:
.cpp:
${CXX} ${CXXFLAGS} -o $# $*.cpp
./$#
The notation using '%' is more flexible when it is available.