Can you have #includes relative to the root folder?

Today at my inconvenience I learned that one has to use the "src" sub-directory for other sub-directories. I am using Arduino IDE 1.8.5 atm.

I am now having an argueing with the IDE about the #include paths. With my Keil environment I used to have all #includes be relative to the root.

A more visual explanation:
| main < folder
main.ino
| src
| basics
io.cpp
io.h
| modules
moduleX.cpp
moduleX.h

Normally I'd type for io.cpp

#include "src/basics/io.h"

And if moduleX has an IO dependancy I'd do the same thing in moduleX.cpp

#include "src/basics/io.h"

But it seems that IDE does not want to compile this. Currently I am stuck with
#include "io.h" // in io.cpp and
#include "../basics/io.h" // in moduleX.cpp

Am I doing something wrong here? Or is it ment to be like this?

AFAIK you need to give a complete path to #include.

For my own convenience I wrote a Python program to compile and upload using the Arduino command line and it expands relative paths to complete paths.

...R

When you use the double quote #include syntax, the file is first searched for relative to the location of the file that contains the #include directive. So the correct #include directive for io.h in modulex.cpp is:

#include "../basics/io.h"

If the file is not found relative to the local path, the include paths are then searched. In Keil, the root of your project folder is probably in the include path. It is intentionally not done that way in Arduino. The reason for this is Arduino feels it will cause 3rd party library authors to create less beginner friendly interfaces. "Beginner-friendly" is not a goal for Keil, so they have different motivations.

Thnx Pert, very informative :slight_smile:

Now I am curious,

pert:
... it will cause 3rd party library authors to create less beginner friendly interfaces

Why is this true? How does that work? I personally find ../ more bothersome than to enter a fixed root path.

In the past when I needed to install some 3rd party library I followed the beginner rules and put the libary where it belonged and I #included <withArrows.h>. Than Arduino knew where to look and I was good to go

How does the other include system have a negative impact on this?

A library author may want to allow the user to configure the library using preprocessor macros. With the current system, there are only two ways to do this:

  • User editing the library: this is very challenging and "scary" for the average Arduino user.
  • Library author makes it a header only-library and the user #defines the macros before the #include directive for the library: many library authors don't want to be forced to have a header-only library.

The result is that most library authors find ways to allow configuration via the sketch, such as passing configuration data to the library via a constructor or begin function, that are (in Arduino's opinion) more beginner friendly.

If the sketch folder were in the #include path, the library author could instruct the user to add a header file (say MyConfiguration.h) to the sketch folder with the #defines for all the library configuration macros, then the library could do this to access the configuration:

#include <MyConfiguration.h>

"Libraries" are compiled separately from the rest of the application, and the two meet up only during the link phase. When each library is compiled, the "current directory" is the root directory of the library, NOT the root directory of the application. So, absolute paths are completely different at compile time. This is life with the Arduino build system, and you just have to get used to it. It's quirky, but if you obey the rules, it works fine.

It would be instructive to look at the actual build directory after doing a compile, to see where all the files actually end up, and all the "massaging" the build system does to the source files before calling the compiler.

Regards,
Ray L.