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.
Related
I am using GNU make to compile my C++ code, and i would like to understand how to make my compilations customizable.
I read in different places that CFLAGS, CCFLAGS and CXXFLAGS are used for this purpose. So how should i use them? If i have additional command-line arguments to the compiler, should i append them to CFLAGS or prepend them? Is there a common practice?
Why the three different variables? I suppose the C compiler should get CFLAGS and CCFLAGS, while the C++ compiler should get CFLAGS and CXXFLAGS - did i get it right?
Is the human user supposed to set these variables at all? Do any automatic tools (automake, autoconf, etc) set them? The linux system that i am supposed to use doesn't define any of these variables - is this typical?
Currently my Makefile looks like this, and i feel it's a bit dirty:
ifdef code_coverage
GCOV_FLAG := -fprofile-arcs -ftest-coverage
else
GCOV_FLAG :=
endif
WFLAGS := -Wall
INC_FLAGS := -Istuff -Imore_stuff -Ietc
CCFLAGSINT := -O3 $(WFLAGS) $(INC_FLAGS) $(CCFLAGS)
... (somewhere in the makefile, the command-line for compilation looks like this)
$(CC) $(CCFLAGSINT) -c $< -o $#
... (somewhere in the makefile, the command-line for linking looks like this)
$(CC) $(GCOV_FLAG) $(CCFLAGSINT) $(OBJLIST) $(LDFLAGS) -o $#
I am pretty sure there are no bugs here; the Makefile works very well. But is there anything that goes against conventions (like CCFLAGSINT - should i just overwrite CCFLAGS instead? Or CXXFLAGS? FUD!)
Sorry for so many questions; you will obviously not answer them all but i hope the answers will help me understand the general idea behind these settings.
As you noticed, these are Makefile {macros or variables}, not compiler options. They implement a set of conventions. (Macros is an old name for them, still used by some. GNU make doc calls them variables.)
The only reason that the names matter is the default make rules, visible via make -p, which use some of them.
If you write all your own rules, you get to pick all your own macro names.
In a vanilla gnu make, there's no such thing as CCFLAGS. There are CFLAGS, CPPFLAGS, and CXXFLAGS. CFLAGS for the C compiler, CXXFLAGS for C++, and CPPFLAGS for both.
Why is CPPFLAGS in both? Conventionally, it's the home of preprocessor flags (-D, -U) and both c and c++ use them. Now, the assumption that everyone wants the same define environment for c and c++ is perhaps questionable, but traditional.
P.S. As noted by James Moore, some projects use CPPFLAGS for flags to the C++ compiler, not flags to the C preprocessor. The Android NDK, for one huge example.
According to the GNU make manual:
CFLAGS: Extra flags to give to the C compiler.
CXXFLAGS: Extra flags to give to the C++ compiler.
CPPFLAGS: Extra flags to give to the C preprocessor and programs that use it (the C and Fortran compilers).
src: https://www.gnu.org/software/make/manual/make.html#index-CFLAGS
note: PP stands for PreProcessor (and not Plus Plus), i.e.
CPP: Program for running the C preprocessor, with results to standard output; default ‘$(CC) -E’.
These variables are used by the implicit rules of make
Compiling C programs
n.o is made automatically from n.c with a recipe of the form
‘$(CC) $(CPPFLAGS) $(CFLAGS) -c’.
Compiling C++ programs
n.o is made automatically from n.cc, n.cpp, or n.C with a recipe of the form
‘$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c’.
We encourage you to use the suffix ‘.cc’ for C++ source files instead of ‘.C’.
src: https://www.gnu.org/software/make/manual/make.html#Catalogue-of-Rules
Minimal example
And just to make what Mizux said as a minimal example:
main_c.c
#include <stdio.h>
int main(void) {
puts("hello");
}
main_cpp.cpp
#include <iostream>
int main(void) {
std::cout << "hello" << std::endl;
}
Then, without any Makefile:
make CFLAGS='-g -O3' \
CXXFLAGS='-ggdb3 -O0' \
CPPFLAGS='-DX=1 -DY=2' \
CCFLAGS='--asdf' \
main_c \
main_cpp
runs:
cc -g -O3 -DX=1 -DY=2 main_c.c -o main_c
g++ -ggdb3 -O0 -DX=1 -DY=2 main_cpp.cpp -o main_cpp
So we understand that:
make had implicit rules to make main_c and main_cpp from main_c.c and main_cpp.cpp
CFLAGS and CPPFLAGS were used as part of the implicit rule for .c compilation
CXXFLAGS and CPPFLAGS were used as part of the implicit rule for .cpp compilation
CCFLAGS is not used.
BTW, the SCons build system for example uses CCFLAGS for flags that are common to C and C++, which is a convention I sometimes follow on my custom make rules.
Those variables are only used in make's implicit rules automatically: if compilation had used our own explicit rules, then we would have to explicitly use those variables as in:
main_c: main_c.c
$(CC) $(CFLAGS) $(CPPFLAGS) -o $# $<
main_cpp: main_c.c
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -o $# $<
to achieve a similar affect to the implicit rules.
We could also name those variables however we want: but since Make already treats them magically in the implicit rules, those make good name choices.
Tested in Ubuntu 16.04, GNU Make 4.1.
Related: CFLAGS vs CPPFLAGS
This is an addition to all the existing answers, which mostly describe how these make variables affect the compilation process. In this answer, I describe a suggested way to use these variables, and any surrounding considerations. It is partly inspired by an answer to a similar question.
How should I use them? Should I append or prepend?
Compilation flags are of two types:
Those which are required to make the compilation work (example: -I, which tells the compiler where to find h-files).
Those which customize the compilation (example: -O, optimization level).
Only type 2 (customization) should go into CCFLAGS, and if the user specifies them, they should override whatever is defined in the Makefile. Use ?= syntax for that in your Makefile:
CCFLAGS ?= -O3
Type 1 settings should go into a new made-up variable, which should aggregate them all, and also include the standard variables, like CCFLAGS:
INC_FLAGS := -Istuff -Imore_stuff -Ietc
CCFLAGS_INTERNAL := $(INC_FLAGS) $(CCFLAGS)
Is there a common practice?
No, it doesn't seem so. Stuff I described above is one option, which looks good, but it's not standard.
Is the human user supposed to set these variables at all? The linux system that I use doesn't define any of these variables - is this typical?
Yes, these are for specifying options using the command line. The environment variables usually don't exist.
Is there anything that goes against conventions? (like CCFLAGSINT - should I just overwrite CCFLAGS instead? Or CXXFLAGS? FUD!)
No, the idea of this Makefile is correct: append CCFLAGS and other flags to the compiler's command-line; don't update CCFLAGS.
My directory structure looks like this:
root
|____SG
| |
| |____Makefile
| |____simple_client_main.cpp
|
|___EEE
|___my_utils.h
SG is essentially my base of operations for building "simple_client", and I'm running make from here. In simple_client_main.cpp I have the following #includes:
#include <iostream>
#include <string>
#include "my_utils.h"
So I need my makefile to know where my_utils.h is. With this in mind, I want to add the root/EEE directory as an include directory. (From where I am, that would be ../EEE.)
Following the advice suggested here, my makefile looks like this:
DIR1 = ../EEE
CXXFLAGS = $(FLAG)
OBJS = simple_client_main.o
SRCS = simple_client_main.cpp
all: simple_client
simple_client: $(OBJS)
g++ -o simple_client -I$(DIR1) $(OBJS) -lz
# [...]
depend:
makedepend -- $(CFLAGS) -- $(SRCS)
But it doesn't work:
simple_client_main.cpp:6:25: fatal error: my_utils.h: No such file or directory
compilation terminated.
Note that if I manually set the #include directive in the cpp as follows:
#include "../EEE/my_utils.h"
...everything works as expected.
What am I likely to be doing wrong here?
You need to add -I$(DIR1) to either CFLAGS or CXXFLAGS (or perhaps both), so that when the object file is compiled, the option is present in the compiler command line.
You want make to execute something similar to:
g++ -c -I../EEE simple_client_main.cpp
It should do that if you add -I../EEE to $(CXXFLAGS) or $(CFLAGS). You need to know the rules used by the make program you're using — they can vary.
When linking object files, it is too late for the -I option to be of relevance (but you should still include $(CFLAGS) or $(CXXFLAGS) in the linker command line as other options, notably -g, are of relevance when linking as well as when compiling to object code).
Here is some simple modifications to the outline makefile shown in the question.
DIR1 = ../EEE
IFLAGS = -I$(DIR1)
CXXFLAGS = $(FLAG) $(IFLAGS)
CFLAGS = $(IFLAGS)
LDFLAGS =
LDLIBS = -lz
CXX = g++
OBJS = simple_client_main.o
SRCS = simple_client_main.cpp
all: simple_client
simple_client: $(OBJS)
$(CXX) -o $# $(CXXFLAGS) $(OBJS) $(LDFLAGS) $(LDLIBS)
A makefile like this stands a modest chance of working correctly. It is not clear what you might put in the FLAG macro, so I've left it. (I use UFLAGS and UXXFLAGS for 'user-defined C (or C++) flags'; they can be set on the command line and are never set by the makefile and are included in the CFLAGS or CXXFLAGS — you may be after something similar.)
Note how the linking line is almost all macros. This is normal and desirable; macros can be changed when running make without editing the makefile, but constant text cannot be changed without editing the makefile. The -c and -o options to the C and C++ compilers are about all that should ever appear as plain text.
If there are still problems, look at the built-in rule for compiling C++ source code to an object file, and tweak definitions accordingly. (You can use make -p to print the rules — you may need that to find out what is going on, but I hope not for your sake because they tend to be complex. Using make -f /dev/null -p shows the built-in rules only; that can be useful, too.)
Note that the make depend rule may need some surgery. It uses $(CFLAGS). If $(CXXFLAGS) contains extra options that are needed by the makedepend command, then you may need that instead, or even as well. If you have only C++ source, you probably only need the $(CXXFLAGS) macro in the command line.
Is the error coming from the compile stage, or the makedepend stage?
Because what I see above is that makedepend uses $(CFLAGS), and you haven't put -I$(DIR1) into CFLAGS.
I recently learned how to use Makefiles, and I found out that GCC/G++ generates dependencies for you:
$ g++ -MM file.cpp
file.o: file.cpp file.h
I then thought that the obvious thing to do would be to use this to generate dependencies directly in the file without creating a dependency file:
CXX = g++
SRCS = $(wildcard src/*.cpp)
OBJS = $(SRCS:.cpp=.o)
OCT = $(CXX -MM $(SRCS))
OBJDIR = obj
CPPFLAGS = -Wall -I/usr/local/include -L/usr/local/lib -lGLEW -lglfw -lGL
.PHONY: all
all: $(OBJS)
$(CXX) $(CPPFLAGS) $(OBJS) -o output
$(OCT)
.PHONY: clean
clean:
rm -f obj/*
For some reason, I have never seen anyone else do this; they always generate a dependency file. Is there something wrong with this system? In my case yes -- the objects don't go to OBJDIR, they go to they location of the source file. I'm sure this could be fixed though. If anyone knows how I could fix this and why dependency files are usually generated, please let me know.
Well, the first reason people don't do this is that it's not possible to do: if you try to make your suggestion work in real life you'll see that. Your example, for instance, doesn't do anything at all. This:
OCT = $(CXX -MM $(SRCS))
(I assume you mean $($(CXX) -MM $(SRCS)) but it doesn't matter either way) is putting a reference to the make variable named, literally, CXX -MM $(SRCS) into the variable OCT: you probably are thinking that it's using the shell command invocation syntax $(...) but this is a makefile, not a shell script. So when you write:
$(OCT)
that tries to look up that make variable, which obviously does not exist, and so this expands to the empty string and nothing at all happens. If you actually try to test your makefile by touching a header etc. you'll see nothing gets rebuilt.
How can you do this? You can't do it. You can change your variable assignment like this:
OCT = $(shell $(CXX) -MM $(SRCS))
and that will actually run the compiler, which is moving you in the right direction, but the results of the shell function will change all newlines to whitespace, so this:
$(OCT)
will expand to the entire output of the compiler command on one line, and since it contains multiple colons you'll get a syntax error.
All you can do is redirect the output of the compiler to a file, and using make's include capability to include that file. But now you're basically back to the scenario suggested in the GNU make manual, except your version is less efficient because, as pointed out in the comments above, you're regenerating all the headers for all the source files every time you run make, rather than only regenerating header information for the files that have actually changed.
There are better/more efficient ways to generate headers, such as the one used by most GNU packages.
I'm extremely new to Makefiles, and I'm currently trying to build my first one on a project I'm starting.
The problem I'm having is having it automatically know how to handle all my .cpp files without defining rules for each one.
I also want my object files to all be put in one folder which is $(PLATFORM)/obj/ where PLATFORM=win32 in this case.
The follwing is what I'm using for a Makefile, executing it with mingw32-make.exe
CXX=g++
CXXFLAGS=-c -Wall -DALLEGRO_STATICLINK
LDFLAGS=
PLATFORM=win32
SOURCES=main.cpp
EXECUTABLE=app.exe
OBJDIR=$(PLATFORM)/obj/
OBJECTS= $(SOURCES:%.cpp=$(OBJDIR)%.o)
all: $(EXECUTABLE)
%.o: %.c
$(CXX) $(CXXFLAGS) $< -o $#
$(EXECUTABLE): $(OBJECTS)
$(CXX) $(OBJECTS) $(LDFLAGS) -o $(EXECUTABLE)
I'm getting the error:
mingw32-make: * No rule to make target win32/obj/main.o', needed by
app.exe' . Stop.
I'm not sure what I'm doing wrong, I've been looking around at other examples of makefiles and they seem to have a similar structure, so I'm not sure whats wrong with mine. I'm looking for an explanation of why this is happening, and advice on how to fix it.
Also, any comments on my style, suggestions for making it more clean/standardized would be great as well. While learning to make makefiles, I want to make sure I'm learning properly.
Thanks
make sees that it needs to create win32/obj/main.o, but can't see any rule to tell it how to do that.
You have three rules, one for all, one for %.o and one for $(EXECUTABLE). The first one and the last one will not tell make how to create win32/obj/main.o.
The second rule probably should, but it says this: if you want to create <something>.o, then first make sure that there's a file called <something>.c (if it doesn't exist, try to find a rule to make it). Then run the following command: $(CXX) ...
But the file <something>.c doesn't exist, because your files end with .cpp. So this rule fails. make can't find any other rule to build win32/obj/main.o, so it gives up.
In summary, you need to change the rule so that %.o depends on %.cpp, and then make will be able to run the command to create the object file. So the rule should be:
%.o: %.cpp
$(CXX) $(CXXFLAGS) $< -o $#
By the way, make also has predefined implicit rules. Because you give an explicit rule for %.o you're actually overriding the predefined rule. I suggest you try at some point not to give this rule at all (but still define CXX and CXXFLAGS) and see what happens. See this for details.
I don't want to dissuade you from using manual makefiles, but if you want to eliminate the problem altogether, there are autotools available that will generate the makefiles for you. Since you're using Windows, I suspect you're using cygwin (or perhaps MingGW). For cygwin, just download the autotools binary package. If you're using eclipse for your IDE (which I strongly promote), you can configure your environment to pick up on the autotools. This way, you just focus on writing the code. All configurability options still exist, but you don't have to know make.
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.