#define and #include Directives in Arduino IDE

I have problem with #define and #include directives.
Lets suppose we have a library named testlib1 with header file#define DEF1 1in it, that has only few lines of code

#ifndef DEF1
#error def1 not defined!
#endif

Then just open new empty Arduino project and add #include directive for our test library

#include <testlib1.h>

Now try to comile the project. you'll get error message
#error def1 not defined!

What we missed is definition of DEF1, so we add a definition and now we have ino file with begining

#define DEF1 1
#include <testlib1.h>

We defined DEF1 before #include, so preprocessor undrstands it correctly and complise code without error message.

Ok, seems everything works great, but we need library to declare a class, so we add a class file. But to understand a problem a created another library testlib2 with class definition. There is hader file "testlib2.h"

#ifndef DEF1
#error def1 not defined!
#endif

class testlib2
{
  public:
	testlib2();
};

and class file "testlib2.cpp"

#include <testlib2.h>

testlib2::testlib2()
{
   //any code here
  int a=0; 
}

and ino file with begining

#define DEF1 1
#include <testlib1.h>
#include <testlib2.h>

Now in both libraries testlib1 and testlib2 uses same definition DEF1. after compilinig testlib2 gives error message

...\libraries\testlib2/testlib2.h:2:2: error: #error def1 not defined!

Why testlib2 can't see the definition DEF1 that is seen in testlib1?
I discovered just one thing, arduino creates temprorary folder build.tmp and copyes there all the files that compiler need to compile sketch (including libraries), for testlib1 it doesn't copies header file, but for testlib2 it copies testlib2.cpp. I suppose somehow that affects definition directives.
Any ideas?

When it compiles testlib2.cpp you hit "#include <testlib2.h>" that doesn't have "#define DEF1 1" above it.

You have to put "#define DEF1 1" at the top of every source file that includes testlib2.h

johnwasser:
When it compiles testlib2.cpp you hit "#include <testlib2.h>" that doesn't have "#define DEF1 1" above it.

You have to put "#define DEF1 1" at the top of every source file that includes testlib2.h

Lets suppose I need a directive in library, defined outside library.
For example DEBUGMODE definition that is defined outside the library class but used in it.

"testlib2.cpp"

#include <testlib2.h>

...some code...

#ifdef DEBUGMODE 
... some debug code here...
#endif

So I suppose, if I define DEBUGMODE in Arduino project, then I have modified class testlib2. But seems it doesn't work.

Each file is compiled separately. Putting a #define in your .ino file does not put it into the file testlib2.cpp.

The simplest approach really is to have some sort of debug flag you pass down to your class (eg. in the begin() function).

You suggest not to use preprocessor macros but due to atmega low resources I need to optimize the code in size and performance, therefore I prefer to manipulate with code before it goes to machine code rather put in it many functions and just not to call according circumstances.
The first time I ran to this problem was my project with server/client applications.
In my project I have two (actually 3, but lets say 2) types of codes, Server and Client. There are many functions and types that is used both in server in client, but there are also parts that should initialized only in proper side. If I define arrays everywhere, I ran out the memory very soon, so I made library with conditional declarations and suppose use definition flag before include of the library, but that doesn't work as I mentioned.

In that case all I can suggest if having another include file (which simply contains this debug define) which all the other files then include. That might work around this issue.

Yes, I did try exactly this way too, but somehow it didn't work. Maybe I did something wrong, I'll try it again and post exact way I'm doing.

You may be running into a mis-design of the Arduino IDE. On .ino and .pde files, the IDE is trying to 'help' the user who may not be familiar with the ins/outs of raw C++ syntax by adding prototypes for all of the functions at the beginning of the file. Unfortunately, it does not really take #if/#else/#endif in account when it puts in these prototypes. I have found it useful at times to put put a normal declaration at the beginning of the .ino/.pde file before putting in potential #defines that I may use to control the stuff coming in from #include directives.

MichaelMeissner:
You may be running into a mis-design of the Arduino IDE. On .ino and .pde files, the IDE is trying to 'help' the user who may not be familiar with the ins/outs of raw C++ syntax by adding prototypes for all of the functions at the beginning of the file. Unfortunately, it does not really take #if/#else/#endif in account when it puts in these prototypes. I have found it useful at times to put put a normal declaration at the beginning of the .ino/.pde file before putting in potential #defines that I may use to control the stuff coming in from #include directives.

I noticed that arduino IDE passes #include directives to compiler as -I parameters.
I suppose that #include in ino file isn't rally preprocessor directive, it is just IDE directive. And those directives are processed before compiler, therefore before #define directives in ino file.

I suppose that #include in ino file isn't rally preprocessor directive, it is just IDE directive.

Wrong. It IS a preprocessor directive.

I haven't noticed anything strange with the directives in the arduino IDE. It would be quite odd if there was, since the compiler used is known to be pretty good and pretty standards compliant. I think your problem is the result of this:
Normally, when you make a headerfile for a library - this is not limited to the arduino - you would (or should) use a contruction like this:

#ifndef _HEADERFILENAME_
#define _HEADERFILENAME_
 // the rest of the header's declarations and defines go here
#endif

This way you prevent problems with multiple declarations / definitions, in case a headerfile is included more than once, e.g. via another headerfile.
If you use :

#ifdef DEBUGMODE 
... some debug code here...
#endif

within the headerfile, DEBUGMODE is only evaluated the first time, and if not set, the debug code is not compiled.
if you want to make sure the debug code is compiled, define DEBUGMODE in the headerfile itself, or use a different headerfile , included from your headerfile to set DEBUGMODE.
A more elegant solution would be to put all debugging code as a macro in separate libraries, with one version of the macro to actually do something, and another one that is empty. A small change in headerfile name, and you enable/disable debugging. Best thing about this solution is that you can use it again on other projects.

Hope this clears things up.

Pieter

pbrouwer:
I haven't noticed anything strange with the directives in the arduino IDE. It would be quite odd if there was, since the compiler used is known to be pretty good and pretty standards compliant.

The IDE is doing quite a lot of mucking about behind the scenes, though, before passing the code you see in the IDE on to the underlying compiler. It guesses what set of source files you're using based on what files you #included, appends the directories that those #included files were found in to the include path and copies all the source files to a temporary directory, along with a 'main' cpp file which it generates itself by concatenating all the .ino files along with some (poorly) autogenerated function prototypes. Although it's obviously basically C++ under the covers, the semantics of #including a file, and the implicit declaration of standard types and functions, and the implicit function prototyping, means that the actual behaviour of your Arduino source is substantially different to the behaviour of standard C++.

PeterH:
The IDE is doing quite a lot of mucking about behind the scenes, though, before passing the code you see in the IDE on to the underlying compiler. It guesses what set of source files you're using based on what files you #included, appends the directories that those #included files were found in to the include path and copies all the source files to a temporary directory, along with a 'main' cpp file which it generates itself by concatenating all the .ino files along with some (poorly) autogenerated function prototypes. Although it's obviously basically C++ under the covers, the semantics of #including a file, and the implicit declaration of standard types and functions, and the implicit function prototyping, means that the actual behaviour of your Arduino source is substantially different to the behaviour of standard C++.

I know, and sometimes things get included in an order you don't want. Or files get included that you didn't know of, or expected. In a large C/C++ build this is no different. One programmer doesn't know exactly what the other programmers are up to. Hence the tip on making sure that you don't depend on how the IDE turns your code into a complete C program.

Pieter

pbrouwer:
In a large C/C++ build this is no different.

There are definitely similarities between the two problems, but I would argue that the behaviour of the Arduino pre-processing is significantly different to that of a conventional C++ compiler, even when you are dealing with a large code base with complex hierarchies of included files. The IDE is pretty arbitrary about what header files it includes on your behalf, generates prototypes for your code on your behalf (badly) and just including or not including a header file can cause source modules to be included in or excluded from your project. Just the fact that the names of included files must be globally unique and should not include relative paths is enough to trip up somebody who is used to working in a standard C++ environment.

I would argue that the behaviour of the Arduino pre-processing is significantly different

It doesn't delete any of your code, though. Not even pre-processor directives.

I noticed that arduino IDE passes #include directives to compiler as -I parameters.

I would say "the arduino IDE adds paths for #include'ed libraries to the compile."
It's not logically any different than manually modifying the PATHS in a Makefile.
(although automation is subject to mysterious problems if your happen to duplicate the name of a library's include file. (Hmm. As would be manual paths.))

having another include file (which simply contains this debug define) which all the other files then include.

This is standard practice. Call it "config.h" and no one will be surprised.

I tried again to include definition in another header file and it worked.
But I've tried before too without success, I don't know why, maybe I hasn't saved all the files before or something else but it doesn't matter now.
Now, what I did, just add a header file to the Arduino project (in Arduino project folder)
"testdef1.h"

#define DEF1 1

and main project file

#include "testdef1.h"
#include <testlib1.h>
#include <testlib2.h>
...

and it works!
That is exactly what I need.

btw, working around this problem, I noticed that there is no easy to figure out IDE and compiler behavior, is there any technical documentation that explains all process (code preparing and compiling)?

NO, I DOES NOT WORK! :frowning:
After adding

#ifndef DEF1
#error def1 not defined!
#endif

to the "testlib2.cpp"
Arduino gave error.
What is the most strange, error still exists after removing that directives from "testlib2.cpp"
No restart helps...
I'm confused...

Now, I removed definition check

#ifndef DEF1
#error def1 not defined!
#endif

from header file too "testlib2.h"

no errors, then put back that definition check to the header and no errors again.
That's funny, any ideas?
everybody can try this.

NO, it definitely DOES NOT WORK.
After restarting doesn't work, if I remove definition check it works and after puting back works too but after restarting the IDE error comes back.
Same in 0022, 1.0.1, 1.5.3

last update:
I tried also to create a separate library testdef1 with header file "testdef1.h" in it (with the DEF1 definition).
Doesn't work anyway.
Maybe some security issues prevents one library to affect another even trough preprocessor directives?

Make a .zip file which demonstrates this, rather than having us trying to reproduce exactly what you have.

You can attach it to a post.