3

Say I'm working on a library^1 to which I want to add support for SD.h^2 but knowing for a fact that many microcotrollers don't support SD.h (therefore they result in compilation errors [eg. Attiny85]) I don't want to just #include <SD.h> (or even #ifndef __SD_H__ then #include <SD.h>) in Mylibrary.h and make it totally unusable for some microcontrollers. So I was wondering, is it considered ok to just add the functionality like...

// Mylibrary.h

#ifdef SD_H // Save functionality for those including SD.h to their sketch.ino void Mylibrary::save(String filename){ SD.open(filename, FILE_WRITE) // ... } #endif

...without ever including the SD.h in Mylibrary.h and hence force the user whenever he\she wants to use some SD functionallity, to just include SD.h in his\her sketch.ino? +(it sound exhausting to do something like this for every MCU, as an alternative way)

[1] (in my case this library)
[2] (in my case something related to this)

PS. The reason I'm asking is because I don't remember seeing it anywhere being used that way and I'm slightly confused as to if this is the right or wrong thing to do so

Giorgos Xou
  • 141
  • 8

2 Answers2

7

Yes, it is in general a bad practice to use include guard define to detect if the header file is included. It will work only in a header file in a compilation unit which includes the detected header file.

In Arduino all ino files of the sketch are one compilation unit. But every C or C++ file is a separate compilations unit. They would not 'see' the include guard from an include in the ino file(s).

If you want to use the include guard define, don't relay on it exclusively. Use your own define and set it if you detect the include guard. This way user can set it if theirs SD library has a different name for the include guard.

#ifdef __SD_H__
#define XY_USE_SD_LIB
#endif

#ifdef XY_USE_SD_LIB // Save functionality for those including SD.h to their sketch.ino void Mylibrary::save(String filename){ SD.open(filename, FILE_WRITE) // ... } #endif

I use this in my popular ArduinoOTA library here.

There is other way to detect includes and it works across compilation units, but it doesn't work on all Arduino platforms. It is the __has_include 'directive'. I use it here.

Juraj
  • 18,208
  • 4
  • 30
  • 49
2

I don't think this will work, however you could try it and see. Just set the board type to something that doesn't support SD.h.

My problem would be that your library is a separate compilation unit (ie. file) that would be compiled against the things you put as header files.

If your library user uses SD.h in the main .ino file, then your library (which is compiled separately) would not know about that. In other words, it wouldn't know whether or not to implement the Mylibrary::save function.

I think a fairly simple solution would be to put a define in the include file for your library, eg.

#define USE_FILE_SAVING false

Then check that in your code. You don't need a whole list of MCUs, just inform the user that if they want file saving implemented to change that one line.


For more information see How the IDE organizes things

Nick Gammon
  • 38,883
  • 13
  • 69
  • 125