why does g++ add includes differently within makefile? - makefile

I am new to make files and having an issue where the g++ command works when run on the command line but not within a make file. The following line works:
g++ -I/home/user/ml/dynet/dynet -I/home/user/ml/dynet main.cpp
but the following make file can't find the required header file
ai: main.o
g++ -I/home/user/ml/dynet/dynet -I/home/user/ml/dynet main.cpp
the main.cpp is simple
#include <iostream>
#include "dynet.h"
int main() {
std::cout << "Hello World!";
return 0;
}
when I run the make I get the error that it can't fine the
user#LAPTOP-AUOAPRL1:~/ml/ai$ make
g++ -c -o main.o main.cpp
main.cpp:3:10: fatal error: dynet.h: No such file or directory
#include "dynet.h"
Why would the same line run differently? where is it looking when run within make? Thank you

GNU Make in it's infinite wisdom has chosen to use it's built-in rules. You can run without them by make --no-builtin-rules. It's not nice to have that as a prerequisite for building your files, but it might be useful when debugging "strange behavior" as it proves whether it's the built-in rules interfering with your mental model or not.
As for the wisdom itself, you only say how to build ai from main.o - not how to build main.o. That is what you're seeing - the built-in rule for building main.o.
What I think you want to do instead is have the rule like this:
ai: main.cpp
g++ ...
A tip; you should prefer using the built-in rules and variables, as it makes the makefile a little simpler to manage:
# using built-in variables
CC := g++
CPPFLAGS := -I/home/user/ml/dynet/dynet -I/home/user/ml/dynet
# inspired by built-in rules
ai: main.o
$(CC) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $#
See https://www.gnu.org/software/make/manual/html_node/Catalogue-of-Rules.html

Related

Creating .o file with make

I'm trying to learn how to write makefiles. I have started reading the manual of gnu make: https://www.gnu.org/software/make/manual/html_node/Simple-Makefile.html#Simple-Makefile
I have 3 files in the same directory:
main.cpp: which creates a rectangle and prints some information. Therefor it includes Rectangle.h
Rectangle.h: header file for rectangle class
Rectangle.cpp: implementation of rectangle class
I am having troubles with the include of Rectangle.h in main.cpp. My makefile is:
main: main.o rectangle.o
g++ -o main.exe main.o rectangle.o
main.o: main.cpp
g++ main.cpp
rectangle.o: Rectangle.cpp
g++ Rectangle.cpp
clean:
rm main.exe main.o rectangle.o
I know something is missing to create main.o but I can't find out what it is. I tried adding various variations of Rectangle.h/.o/.cpp and finding something on the internet but I was unable to find something.
Help will be much appreciated :)
PS: The code is fine, I can compile it with the command:
g++ -o main.exe main.cpp Rectangle.cpp
man g++
When you invoke GCC, it normally does preprocessing, compilation, assembly and linking. The "overall options" allow you to stop this process at an intermediate stage. For example, the -c option says not to run the linker. Then the output consists of object files output by the assembler.

Makefile dependency file error when including it

I am finding problem when I try to include a C source file in my Makefile. This C source file contains a function which is called by the C++ code (list.cpp) through external C linkage option. I would like to know which is the right place in the Makefile to include this C source code whose function is invoked inside C++ code. If I try adding this C file in the Makefile's SOURCES variable in order to built it, then the C++ code fails to correctly resolve the function call of C and I am getting linker error: undefined reference
Following is my Makefile content:
CFLAGS =-c -g -Wall -std=c++11
SOURCES = list.cpp
OBJECTS = $(SOURCES:.cpp=.o)
EXEC = a.out
all: $(SOURCES) $(EXEC)
$(EXEC): $(OBJECTS)
#$(CXX) $(OBJECTS) -o $# && $(EXEC)
.cpp.o:
#$(CXX) $(CFLAGS) $< -o $#
Let's assume the C source file that you need in the build is bar.c,
and that it has an associated header file bar.h that you are
#include-ing in list.cpp, and that you have correctly coded the extern C
boilerplate in bar.h.
Then the following makefile will do what you need:
Makefile
CXX_SOURCES := list.cpp
C_SOURCES := bar.c
OBJECTS = $(C_SOURCES:.c=.o) $(CXX_SOURCES:.cpp=.o)
CXXFLAGS := -g -Wall -std=c++11
CFLAGS := -g -Wall
CPPFLAGS :=
LDFLAGS :=
LDLIBS :=
EXEC := a.out
.PHONY: all clean test
all: $(EXEC)
test: $(EXEC)
./$<
$(EXEC): $(OBJECTS)
$(CXX) $(LDFLAGS) $^ -o $# $(LDLIBS)
list.o: bar.h
clean:
rm -f $(EXEC) *.o
There are a lot of learning-points here:
1. Use immediate evaluation (:=) rather than recursive evaluation (=) of
make variables unless you particularly want recursive evaluation. See
6.2 The Two Flavors of Variables
2. If a target is merely a name for a task and not the name of a file that
the task will create, then it's a phony target
and you should tell make that it is a phony target, like:
.PHONY: all clean test
3. It is not normal for the make-recipe that builds a program to run the program as
well, like your:
#$(CXX) $(OBJECTS) -o $# && $(EXEC)
You don't always want to run a program just because you've built it, and
if the program is a long-running or interactive one then this approach
will make it impractial to build the program at all.
Probably, you want to run the program to test that it has been built correctly.
But building is one task, testing is another (that may take much longer and
involve additional resources); so you should provide a separate phony target
for testing. I've called it test in this makefile: often it is called check.
To build the program without testing it, just run make. To test it,
run make test - and this will also (re)build the program if it needs to be (re)built.
4. You don't need to write a rule to make name.o from a name.cpp, or
a rule to make name.o from a name.c. GNU make has builtin rules for doing
this correctly, as long as you have correctly set the make-variables that
make uses in those builtin rules:
CC: The command that invokes C compilation or linkage, e.g. gcc
CXX: The command that invokes C++ compilation or linkage, e.g. g++
CFLAGS: Options for C compilation
CXXFLAGS: Options for C++ compilation
CPPFLAGS: Options for the C/C++ preprocessor
5. Two more important make-variables that have conventional meanings are:
LDFLAGS: Options for linkage, excluding library (-l) options
LDLIBS: Library options (-l) for linkage.
In the simple makefile above, CPPFLAGS, LDFLAGS and LDLIBS are not
needed and could be ommitted. Instead, I've assigned them empty values
just to illustrate their use.
6. A makefile should have a phony target clean that deletes any files
that the makefile might have created, so that make clean gets you
ready to build anything or everything from scratch.
7.. If name.o is compiled from name.c or name.cpp, then of
course name.o depends on name.c|name.cpp, but it also depends
on every header file that is included by name.c|name.cpp, and the
makefile needs to express all those dependencies to work reliably. So
in this case you need (at least) the rule:
list.o: bar.h
so that if you change bar.h then make will see that foo.o is out of
date and will carry out its recipe for re-making foo.o. When you
start building complex programs it will become impractical for you
to figure out all these header-file dependencies yourself: then you'll need
to find out about auto dependency generation.
Here is the GNU Make manual

Define a choice of prerequisites in a pattern rule

For example, lets say I have a compiler that can build foo files from either bar or baz sources.
The rules for this might look like:
%.foo: %.bar
# commands to
# invoke compiler
%.foo: %.baz
# commands to
# invoke compiler
However, this could start getting a bit long and redundant as the number of input types and recipe commands increase. Is there any syntax available to compress this into a single rule?
%.foo: $(oneof %.bar %.baz)
# commands to
# invoke compiler
What you propose at the beginning is right: Makefiles should be clear and concise regarding building rules.
In the other hand you may take a look at Canned Recipes to try to avoid repeating the same recipes once and again:
define MAKE_FOO =
#You may use automatic variables such as $^ or $#.
mv $< $# #In this example just a file renaming.
endef
%.foo: %.bar
$(MAKE_FOO)
%.foo: %.baz
$(MAKE_FOO)
The canned recipe MAKE_FOO will expand to whatever recipes you write inside the define statement as if they were copied manually.
Here's an illustration for the concrete problem of making an .o file
from either a .c file or a .cpp file with a combined pattern rule.
An executable is also built to aid the illustration.
Makefile
.PHONY: all clean
all: test
%.o: %.c %.cpp
gcc -c $?
test: main.o hw.o
g++ -o $# $^
clean:
rm -f test *.o
where we have:
hw.c
#include <stdio.h>
void hw(void)
{
puts("Hello from C");
}
hw.cpp
#include <iostream>
extern "C" void hw()
{
std::cout << "Hello from C++" << std::endl;
}
and:
main.cpp
extern "C" void hw(void);
int main(void)
{
hw();
return 0;
}
Make from clean and run:
$ make clean && make && ./test
rm -f test *.o
g++ -c -o main.o main.cpp
gcc -c hw.c hw.cpp
g++ -o test main.o hw.o
Hello from C++
Both hw.c and hw.cpp were compiled per the pattern rule.
Each one of them was compiled to the same object file, hw.o, with the second, C++
compilation overwriting the C compilation. So the C++ object file was linked,
simply because it was the last to be built. Be clear about what you expect to
happen when the combined rule is triggered by multiple prerequisites.
Now let's update hw.c and repeat:
$ touch hw.c
$ make && ./test
gcc -c hw.c
g++ -o test main.o hw.o
Hello from C
This time, hw.o was compiled only from hw.c, and linked.
Update hw.cpp and repeat:
$ touch hw.cpp
make && ./test
gcc -c hw.cpp
g++ -o test main.o hw.o
Hello from C++
Once again, the hw.o from C++ was linked.
The key element of the combined pattern rule is $?, which
means all the prerequisites that are newer than the target

make file preprocessor directive

I am not very experienced with make files and am trying to define a preprocessor variable in my make file,in Eclipse (linux).
It turns up a non trivial task,since as it seems am missing something...
Bellow you can find my make file's structure:
var_first=g++
all:
g++ main_cell.cpp -o hello
in this way am building my code,that i want to do is to define a variable in my make files that would then be asserted with an #ifdef,#endif in my code.
I have gone through numerous combinations but am missing some steps as it seems...
Could you please give some pointers?
To add a definition while compiling, use the -D g++ option. Like this:
g++ -DMyDefine=123 main_cell.cpp -o hello
Now in main_cell.cpp you can do:
#if MyDefine == 123
doStuff();
#endif
To use makefile variables for this, do something like:
all: g++ main_cell.cpp -o hello -Dvar_first=$(var_first)
That is equivalent of #define var_first g++ in the .cpp file
If you want to pass the preprocessor variable directly to the compiler, you use a -D flag.
E.g. you want to define the variable PRE_MY_VAR to 1, you can write:
g++ -o myexecutable *.cpp -DPRE_MY_VAR=1
So in your makefile this would be:
all:
g++ main_cell.cpp -o hello -Dvar_first="g++"

make is calling g++ is always re-compiles even when I do not change the source code

I am using make which calls g++ always re-compiles the code, even when I do not change the source code. That happens for all my projects, even for simple ones such as:
[code]
all: main.cpp
g++ -std=c++11 -c main.cpp
[/code]
I believe it should compare the date/time on source and object code. Could some help me with this, I am running using GNU toolchain on Ubuntu 12.04
THX
Edit: sorry guys, I do use Makefile, I edited my question accordingly.
Simplest Makefile
It was already pointed out that your Makefile is probably wrong. The 'all' target is indeed always built (although it may result in a no-op if it has no commands and all dependencies are already satisfied). All you need in your makefile is this:
all: main
Object files
If you expect to have more source file in your build, you should consider creating intermediate object files:
all: main
main: main.o
Tweak the build
Make will automatically find the main.ccp file and turn it into main which is required per the directive above. You can use special make variables to further tweak the compilation, e.g. for debug information inclusion and for warning configuration:
CXXFLAGS = -g -Wall -Werror
all: main
main: main.o
Nitpicking
If you insist on building up the compile rule yourself, you can do it like this:
%.o: %.hpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $# -c $<
CXX: C++ compiler
CPPFLAGS: C preprocessor flags
CXXFLAGS: C++ compiler flags
$#: Target
$<: First dependency
If you don't want to use the standard variables nor pattern matching, you can build up the whole makefile explicitly:
all: main
main: main.o
gcc -o $# $^
main.o: main.c
gcc -g -Wall -Werror -o $# -c $<
$^: Use that one if you want to include all dependencies, for example if you have multiple *.o files to build one binary.
Note: It is a bad idea to write the file names directly into the command as you might forget to update them later.
all: main.cpp
g++ -std=c++11 -c main.cpp
This seems wrong. Why does the rule for all has main.cpp as its target? Shouldn't it be something.exe or something.o? Say
all: main.exe
main.exe: main.cpp
g++ -std=c++11 main.cpp -o main.exe
clean:
del main.exe
Targets are output files and cpp files are source code which should be input to the make system.
g++ would have to "recompile" in general (what happens if you change the header but not main.cpp?)
If you are concerned about long build times, you should use something like Make (which is designed specifically to avoid recompiling when the source hasn't changed)
The compiler will always compile the code. If you want to do conditional compilation (based on file times etc) you will need to use a make system such as Make, CMake, Ant, etc. For the simplest you can set up a small "Makefile" in the directory and use the command "make" to build.
Simple Makefile for compiling "myapp.exe" from "main.cpp", "file1.cpp" and "file2.cpp"
myapp.exe: main.o file1.o file2.o
g++ -o myapp.exe main.o file1.o file2.o
(make knows to use .cpp files to build .o files)
But if you also have header files, then you will need to build dependency chains, for which you may want to look into something more sophisticated like automake, cmake, ant, etc.
---- EDIT ----
Based on your updated post, the problem is that you aren't specifying a target, so Make has to assume it needs to recompile. See my example in the above answer.

Resources