make file preprocessor directive - makefile

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++"

Related

why does g++ add includes differently within 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

Import variables from C preprocessor into Makefile

I want to create one Makefile for Windows and Linux builds. The problem is I have to link with different dynamic libraries for each platform. The C preprocessor may have few nice variables, for example _WIN32. How to extract this information?
The solution have to work with a cross compiler. I cannot create and then run a small program. I have only one, different variable, the CC, the environment may be the same.
The other way around is easy, the -D switch.
Similar but different questions:
Makefile that distincts between Windows and Unix-like systems
I use the same make program. Only the CC variable is different.
I don't know if you can get directly those variables but you can try this solution:
CPP=i686-w64-mingw32-cpp
CPPFLAGS= -P
WIN32=$(shell echo _WIN32 | $(CPP) $(CPPFLAGS))
iswin32:
#echo $(WIN32)
This example will output 1:
$ make iswin32
1
If you are dealing with multiple declarations consider also creating a file with all the declarations, preprocess it and include it in a makefile.
$ cat declaration
WIN32 = _WIN32
Based on answer from TTK
Create file with variables, something like this:
#ifdef _WIN32
-lgdi32 -lopengl32
#else
-lpthread -lX11 -lXxf86vm -lXcursor -lXrandr -lXinerama -lXi -lGL
#endif
And something like this to the Makefile:
A_FLAGS = $(strip $(shell $(CPP) -P $(CPPFLAGS) ./a_flags.cpp))
# or
A_FLAGS = $(strip $(shell $(CPP) -P -xc $(CPPFLAGS) ./a_flags))
$(CPP) – the C preprocessor executable, should be defined by the Make program
-P – the flag to inhibit generation of linemarkers
-xc – the flag to force preprocessor to treat file as C source
$(CPPFLAGS) – optional flags for the preprocessor defined by programmer

Do I need to pass CFLAGS explicitly to gcc?

I read a lot of tutorials about CFLAGS and also looked in the official docs. Everywhere they say CFLAGS is implicit but still pass it explicitly in their example makefile to the compiler:
CFLAGS=-O2
gcc $(CFLAGS) -c foo.c -o foo.o
So, what does the term "implicit" mean in this context? If I declare CFLAGS=-O2 in my makefile and later just say gcc -c foo.c -o foo.o, will -O2 be active or not (so, is it really implicit)? If so, why do all tutorials (including official docs) still pass it explicitly in their examples?
Everywhere they say CFLAGS is implicit but still pass it explicitly in their example makefile to the compiler.
gcc does not use CFLAGS environment variable. See Environment Variables Affecting GCC.
CFLAGS is a conventional name for a Makefile variable with C-compiler flags and it is used by implicit make rules. See Variables Used by Implicit Rules for more details.
If you use your own make rules instead of the built-in ones, you do not need to use CFLAGS at all. Although it is a useful convention to do so because people are familiar with the conventional make variable names.
I believe CFLAGS is implicitly passed to the compiler command line by the makefile via the default compilation rule... Yet the CFLAGS can be overridden with custom flags so that each compilation command will take it and use.
You can test it easily:
$ cat cflags.mak
CFLAGS = -wrong
foo.o: foo.c
$ make -f cflags.mak
cc -wrong -c -o foo.o foo.c
cc: unrecognized option '-wrong'
So you can see it used the value of CFLAGS even though it was not explicitly specified in a rule; thus it is implicit.
But if you do specify your own rule for compiling .c files, you have to include it if you want it used:
$ cat cflags.mak
CFLAGS = -wrong
foo.o: foo.c
gcc -c $<
$ make -f cflags.mak
gcc -c foo.c
Here I provided my own rule for .c files which did not include CFLAGS, so CFLAGS was not used.
So the bottom line is if you rely on the built-in make rule for compiling .c files, CFLAGS will be included implicitly. But if you override that rule, you have to include it explicitly if you still want it to be used.
It means that there are implicit make rules, that use the CFLAGS, you can use.
So you can write a one line makefile with:
CFLAGS=-O2
if you later do:
make filename
(omitting extension) it will use an implicit rule that references the CFLAGS to convert you source file .c in an executable, so you don't need to write an explicit build statement for simple builds.
E.g. if you prepared a source name file.c it will build it with an implicit rule like:
$GCC $CFLAGS file.c -o file $LDFLAGS
see: GNU make documentation

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.

Makefile for using make as gcc

Is it possible to write universal Makefile which would get any target and act like a wrapper to gcc, but with parameters? For example, this means that
make 01.c
will have the same result as
g++ -o 01.out 01.c
make already has several "implicit rules" to do what you're trying.
For example, even with no makefile,
make 01.o
Will run:
c++ -c -o 01.o 01.cpp
If it finds a file called 01.cpp in your current directory. You can set the CXXFLAGS environment variable if you want to pass more flags. If you're really set on using g++ rather than the system compiler, you can set CXX=g++, too.
Yes - You using implicit rules.
Summat like (if memory serves me right)
.cpp.o:
$(CCC) $(CFLAGS) $< -o $#
Maybe in the set of default implicit rules
You can use a wildcard - %.
However, the thing specified on the commandline is the target, not the source - what you want, not what you have.
It looks like what you want is approximately:
%.out: %.c
g++ -o $# $<
This means: to make (something).out, first make sure you have (something).c, then run g++ -o (something).out (something).c
$# is always the target file, and $< is the first prerequisite.
You will need to run make 01.out, not make 01.c

Resources