ifdef __AVR__ in my library

I have a my own library which is working good, but I have some problems compiling for different boards.

I have findout there is a problem with this block:

#ifndef __AVR__
typedef std::function<void(void)> timer_callback;  //good for arduino, nano and similar
#else
typedef void (*timer_callback)();  //good for ESP8266
#endif // __AVR__

First “typedef” is compiling for Arduino-family boards, but is not for ESP8266-family.
Second “typedef” is opposite, compiling for ESP8266 family, but is not good for Arduino-family.

Seems like line “#ifndef AVR” is not doing its work, probably, because variable “AVR” is not suited in this case. But what should I use instead? And where these variables, describing board, are declared?

You have your logic backwards. #ifndef is the same as #if ! defined() but that's not what you want. Use #ifdef instead.

Alternately, if you want to restrict the typedef only to ESP8266, do this:

#ifdef ESP8266
typedef void (*timer_callback)();  //good for ESP8266
#else
typedef std::function<void(void)> timer_callback;  //good for arduino, nano and similar
#endif // ESP8266

pert:
You have your logic backwards. #ifndef is the same as #if ! defined() but that’s not what you want. Use #ifdef instead.

Thank you, I have just realized there is #ifndef there, not a #ifdef. Will check again.
Is “AVR” defined for ESP?

In general - how to findout which board you compile for, using #ifdef?
Are there any list of boards and matching variables?

SergeS:
Is "AVR" defined for ESP?

No, only for microcontrollers that use the AVR architecture (Uno, Nano, Mega, Leonardo, etc.).

SergeS:
In general - how to findout which board you compile for, using #ifdef?

What do you mean by "board"? Are you talking about the architecture of the board in general (e.g. AVR, ESP8266, SAM, SAMD) or do you mean the specific Arduino IDE Tools > Board menu selection (e.g. Arduino/Genuino Uno, WeMos D1 R2 & Mini, Arduino/Genuino MKR1000)?

You can use the OneWire library as an example: https://github.com/PaulStoffregen/OneWire/blob/master/util/OneWire_direct_gpio.h.
There are a lot of #elif and at the very bottom there is a fallback mode with #else.

pert:
No, only for microcontrollers that use the AVR architecture (Uno, Nano, Mega, Leonardo, etc.).
What do you mean by "board"? Are you talking about the architecture of the board in general (e.g. AVR, ESP8266, SAM, SAMD) or do you mean the specific Arduino IDE Tools > Board menu selection (e.g. Arduino/Genuino Uno, WeMos D1 R2 & Mini, Arduino/Genuino MKR1000)?

I mean architecture.

P.S. in my specific case seems like it fixed, I do not need #ifdef at all, line
typedef void (*timer_callback)();

seems like to be good for both, arduino and esp8266.

AVR is defined in AVR LibC:
https://www.microchip.com/webdoc/avrlibcreferencemanual/using_tools_1using_avr_gcc_mach_opt.html

the preprocessor will define the macros __AVR and AVR (to the value 1) when compiling for an AVR target.

ESP8266 is defined by the ESP8266 core for Arduino:

# This can be overriden in boards.txt
build.extra_flags=-DESP8266

I haven't found a more low level architecture specific macro for ESP8266. Actually, as you can see from the comment, that one is a bit fragile. I don't know why they would use build.extra_flags for that purpose as it is intended to be an external interface.

Arduino has set a convention of defining the macro ARDUINO_ARCH_{build.arch}

where build.arch is determined by the architecture folder of the hardware package for the selected board. This relies on the package author actually implementing that convention in their compiler flags.

Koepel:
You can use the OneWire library as an example: https://github.com/PaulStoffregen/OneWire/blob/master/util/OneWire_direct_gpio.h.
There are a lot of #elif and at the very bottom there is a fallback mode with #else.

Wow! There are really a lot :-), thank you.

So the real question is what is the issue?
Is it an issue related to

  • board (which is mainly pin mapping issues)
  • processor (which can be processor specific instructions or registers)
  • Arduino core (which can be processor or compiler tools related issues)

The three are different and some are much harder (sometimes impossible) to detect than others
depending on the IDE version and core being used.

--- bill

SergeS,
Having spent quite a bit of time and effort dealing with and maintaining library code (openGLCD) that must be aware of board specific differences, my advice is try very very hard to avoid having to do that. It is an endless hole you can get sucked down into that depending on your needs, can get complicated and difficult to maintain.
Try very very hard not to base things based on board type - use something else whenever possible.
You must make sure to have reliable defines that are at the appropriate level to detect the differences and those defines can vary depending on the IDE, the core and the board.

If you must detect differences, try to use the highest level define possible,
i.e. favor using a processor architecture over a specific processor type, and try at all costs not to depend on an Arduino board type.
If possible try to use a define that is not defined by the Arduino IDE
i.e. try to use internal gcc defines whenever possible.
AVR is an example of a gcc define.

For example, there can be some major issues when trying to play games or automate things using a processor architecture type when the differences are actually within a processor type.
For example board specific pin mappings can vary withing the same processor architecture and even within the same processor type, so using a processor architecture or processor type for that purpose generally has issues.

Trying to automate things for pin mappings is the most difficult since the pin mappings are really controlled by the variant not the board/board-type.
i.e. multiple boards can use the same variant for the pin mappings and the user can add his own board types.
So using board type defines for the purpose of detecting pin mappings will fail should the user create his own board types.
You also can't use processor type or core to know the pin mappings since different boards can have different variants with different pin mappings.

And while the IDE knows the variant, it does not offer that information to the source being compiled. It only offers a define based on the board. For pin mappings, you really want to know the variant at compile time and that information is simply not available from the IDE.
It can usually be detected in other ways, but it is a bit ugly/messy and complicated.

Also, keep in mind that several of these types of architecture/board/core type defines that are defined by the IDE have varied though time in various IDE versions.
In some versions of the IDE a define may be non existent or not useful at all.
Like at one point there was a single define that was defined depending on the board type. That is not useful since there is no way
to do a compile time check on the value of define when it is a string.
This is why I recommend using non IDE defines when possible.

Things have settled down quite a bit with recent IDEs but when creating a library, especially if it is intended to run on multiple
versions of the IDE and multiple cores, you must take all this into consideration.
There also is the consideration if the library will be used in environments that build code using alternate tools (without the Arduino IDE). In that case some of the IDE specific defines may not exist.

What can help identify the defines that the Arduino IDE defines is to turn on the debugging output and look at the command line executions to see what defines the IDE is setting and see what changes when you change cores and boards.
There are other processor specific gcc defines as well that get set based on the specific version of gcc, and processor, but you won't see those on the command line from the IDE as they are set internally by gcc.

I will stress again, try very hard to avoid having to do special things, like conditional compilation, based on the target environment.
If it is required, try to use the highest level define possible and if possible use an internal gcc define vs an IDE define.
And try to avoid using a board define as it will fail when a user creates his own board types.

--- bill