0

A question I have long had regards an interaction between #define statements and a library header include. I've seen several Arduino libraries use this rather convenient configuration system where you can write a #define statement, then include the #include header instruction and the library will change its behavior.

Does anyone know why this does or does not work? My understanding of how #include works is that it copies the file into its place in the new file and that C/C++ code with headers should thus form something of a tree shape. It would thus make sense that any lines of code present before I #include a library would have to be seen by the library when the preprocessor does its thing and copies the #include-d file.

But I've previously been told it doesn't actually work this way (despite actual examples, but by that point I had misplaced the libraries that did it). However, I've finally tracked down an example of someone doing this, and I'd like to know how this behavior works. Is it a feature of Arduino in specific or something?

Here's a library that does it: https://github.com/madpilot/mDNSResolver

2 Answers2

1

The mDNSResolver library README has

You can change a few settings by defining some constants before including the mDNSResolver header file [in the sketch]

I added "in the sketch", because it is where you include mDNSResolver header file.

This will not work because mDNSResolver.cpp, which uses the values of the defines, is compiled without any knowledge of the ino file content.

A deeper explanation would be too long and out of scope for Arduino SE.

Juraj
  • 18,264
  • 4
  • 31
  • 49
-1

In the first few lines of the library .h file you linked, it tests a symbol it has not defined, ESP32 (#if defined(ESP32)) and alters the compilation according to the definedness of that symbol.

Since the compiler input will be one long file with all the #include files already "spliced" inline, you (or a previously included .h file) have the option to pre-define that variable to alter the compilation as this library writer provided.

Update:

@RDragonflydr: I believe you are correct, that the ESP32 symbol is defined by the compiler (or more likely, the makefile) for the target processor. And to clarify my statement that "the compiler input will be one long file", I'm referring to the compilation of each module of your project, not to the entire project at once. Each library will each be compiled, separately, and each of your modules will be compiled separately, and in each of those cases, the compiler input will consist of the module code with all of the #included files "spliced" into place, the #defined symbols and macros substituted, and comments stripped out.

The library code (the .cpp) is not #included so it does not become part of the translation unit. Only the library header file is included. That is common - and necessary - to all environments, and one of the functions of the C or C++ preprocessor. This happens for each module - separately - in a multi-module compilation. The library files will have been

JRobert
  • 15,407
  • 3
  • 24
  • 51