As mentioned, each library is compiled separately, without regard to your .ino
. But they are cached per-sketch, which is important for what you're trying to do.
When any C/C++ source is compiled, a pre-computed set of {includes}
the list of include paths in the format "-I/include/path -I/another/path...."
is added to the command, comprising sometimes dozens of directories (often named 'include') under the platform's SDK. If you were to add your own sketch directory, you could have a per-sketch required header file when using any given library.
Instead of modifying {includes}
, it's easier to use an existing setting for such shenanigans. First, you'll need to locate your board's platform.txt
file, starting at the OS-specific Arduino15 directory. For example, on Linux
$ cd ~/.arduino15
$ find . -name platform.txt
./packages/arduino/hardware/avr/1.8.6/platform.txt
./packages/arduino/hardware/renesas_uno/1.2.0/platform.txt
./packages/m5stack/hardware/esp32/2.1.1/platform.txt
$ cd ./packages/arduino/hardware/renesas_uno/1.2.0
Go to that directory and verify the expected flag
$ grep -B 5 ^compiler.cpp.extra_flags platform.txt
# These can be overridden in platform.local.txt
compiler.c.extra_flags=
compiler.c.elf.extra_flags=
compiler.S.extra_flags=
compiler.cpp.extra_flags=
We'll be using the cpp
one -- unless your library uses something else? As mentioned in the comment, create platform.local.txt
as a sibling file in the same directory, with one line
compiler.cpp.extra_flags=-I{build.source.path}
The {build.source.path}
is your sketch directory. (Exercise for the reader if it contains a space.) Whenever you modify the platform files, you have to restart the IDE to the changes to take effect.
The IDE will open library headers with Go To Definition, but they are read-only. You can hover on the file's tab to get the path (or sometimes the #include
statement) to get the path. In this case you have a specific file you're supposed to edit, so use that. (Sometimes a library has a header file that is intended for users, but doesn't use it itself. It usually includes other files; you need to edit the appropriate one.)
Let's say you'll call this configuration-header "per_sketch.h
" So add (after any include guard)
#if __has_include("per_sketch.h")
#include "per_sketch.h"
#else
#error "missing per_sketch.h: explain how this works"
#endif
The __has_include
allows for a more descriptive #error
message. Otherwise, you can just try to do the #include
, and it will fail if missing.
If you try to build now, you may get the error twice: once when compiling your sketch, if it includes the library and eventually this header; and once when trying to build the library. So use the meatball menu on the right of the file tabs in the IDE to create a New Tab, "per_sketch.h
" One advantage of having the file at the root level of the sketch is that it will auto-open in the IDE. If you build again, it should build without error, or as well as it did before.
Now you can do further modifications and put that #if defined
thing in the library's header, and your #define
in the "per_sketch.h
"