Arduino library in a subdirectory

this "error" was discovered on the Arduino IDE 2.0.0 rc6

i have written example libraries like so:

//.INO
#include <foo.h>
Foo foo;
void setup() 
{
  Serial.begin(9600);
}
void loop() 
{
  foo.foo(1);
}
//FOO.h
#ifndef FOO_H
#define FOO_H
class Foo
{
	public :
		void foo(int);
};
#endif
//FOO.cpp
#include <Foo.h>
#include <Arduino.h>
void Foo::foo(int i)
{
	Serial.println(i);
}

both the header and the C++ source file are located in the directory:
C:\Users\*****\Documents\Arduino\libraries\foo\foo.h
C:\Users\*****\Documents\Arduino\libraries\foo\foo.cpp


my project will scale a bit, so i would like to move both the header & C++ source file to a subdirectory like so:

Arduino
   |---libraries
           |---foo
                |---src
                     |---foo.h
                     |---foo.cpp

NOTE THE ADDED SRC DIRECTORY
i have made acording changes to my files:

//.INO
#include "C:\Users\*****\Documents\Arduino\libraries\foo\foo\foo.h"
Foo foo;
void setup() 
{
  Serial.begin(9600);
}
void loop() 
{
  foo.foo(1);
}
//FOO.h
#ifndef FOO_H
#define FOO_H

class Foo
{
	public :
		void foo(int);
};

#endif
//FOO.cpp
#include "C:\Users\*****\Documents\Arduino\libraries\foo\foo\foo.h"
#include <Arduino.h> //do i have to change this to the exact file path? then where is the Arduino.h located?

void Foo::foo(int i)
{
	Serial.println(i);
}

NOTE THE CHANGE TO THE INCLUDELINE


but the compiler is trowing at the the following error:

undefined reference to `Foo::foo(int)'

to recap; the question I am asking is, how can I run header and C++ source files from a subdirectory

This is because the library is only compiled when it is used via the Arduino build system's library discovery process, as was the case previously when you had this style of #include directive:

When you specify the absolute path to the header as you are doing now:

Only the contents of the header file are included in the sketch. So the definition of Foo::foo(int) from the .cpp file is not compiled.

So the first thing you need to do is to discontinue your use of absolute paths in the #include directive.

After that, you need to know that it is mandatory for every Arduino library to contain a header file in the root of the source folder.

In the case of a "1.0 format" library as your appears to be from the directory tree, the source folder is here:

C:\Users\*****\Documents\Arduino\libraries\foo\

However, your use of the src subfolder indicates to me that you might prefer the "recursive layout" that is possible when using the "1.5 library format".

The only thing necessary to convert your library to the "1.5 format" is the addition of a metadata file:

C:\Users\*****\Documents\Arduino\libraries\foo\library.properties

Information on that here:

https://arduino.github.io/arduino-cli/latest/library-specification/#library-metadata

So as mentioned, you will need to have a header file in the root of the source folder, which would be here with the "recursive layout":

C:\Users\*****\Documents\Arduino\libraries\foo\src\

That header file will allow your library to be discovered. Discovery adds the library to the compiler include paths, so after that you are welcome to use #include directives to paths relative to the source folder root. For example, if you have a file named foo.h in the source root, then another at bar/baz.h under that source root, you can do this in the sketch:

#include <foo.h> // This one will cause the library to be discovered
#include <bar/baz.h> // You can now include files in paths relative to the discovered library root

but you can't do this:

#include <bar/baz.h>  // compilation fails because none of the include search paths contain this relative path
#include <foo.h>

Here is a tree for a valid library:

Arduino/libraries/foo/
├── library.properties
└── src/
    ├── bar/
    │   └── baz.h
    ├── foo.h
    └── qux/
        └── foo.cpp

Due to the use of the recursive layout, all source files, including ones in subfolders such as Arduino/libraries/foo/src/qux/foo.cpp will be compiled.

1 Like

I think that to use the 'src' subdirectory you are required to use the new library format which includes a "library.properties" file:

name=
version=
author=
maintainer=
sentence=Short description
paragraph=Longer description
category=
url=
architectures=avr,samd,mbed

Also note:
#include "C:\Users\*****\Documents\Arduino\libraries\foo\foo\foo.h"

is not:
#include "C:\Users\*****\Documents\Arduino\libraries\foo\src\foo.h"

@in0
I appreciate a blazing fast reply!
I think i get the gist of the problem and its solution, and shall now read provided forums and run a few tests on my own

Thank you :smiley: !

You are welcome. I'm glad if I was able to be of assistance. Please let us know if you have any questions or problems.

Also note:
#include "C:\Users\*****\Documents\Arduino\libraries\foo\foo\foo.h"

is not:
#include "C:\Users\*****\Documents\Arduino\libraries\foo\src\foo.h"

wops, a silly mistake; tough the code wouldn't run either way

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.