Yes you are correct. The IDE uses a very primitive and dumb methodology.
In my view, this was done from ignorance and lack of understanding of how real embedded development is done.
Because of their build methodology, the IDE doesn’t truly support libraries using other libraries.
Yes, the existing hack of including the sub library’s header in the main sketch allows things to work but it was not really designed to work this way. While it has been enhanced to better handle sub libraries over the years, In reality it is a mere accident/artefact of the way the IDE searches for sketch libraries and the way it handles it’s libray include paths.
There are better ways to handle this but the Arduino team is pretty stuck on using the current build methodology.
Yes you can include a header for another library in your library. It can be done by referencing from a library that included.
That will include the header and allow your code to build, the problem is that because the IDE is using such a primitive build methodology, it won’t compile or link in the sub library.
For example, you know that the AVR core library (the only true Arduino library - which is all the built in functions like digitalWrite() ) is always on the include path when building for AVR, you can reference
SofwareSerial relatively from that.
(I think I got the relative path correct for the latest IDE - but you get the idea)
-Is there any way (using preprocessor or other) to detect at compile time if SofwtareSerial has been included in the sketch?
Usually. You have to take advantage of detecting some information created by the dumb build methodology currently used by the IDE along with some broken compiler/pre-processing handling that exists in the newer versions of gcc.
The combination of the two allow you to do this.
I do this in some of my libraries. I detect that the user hasn’t included a header that my library needs and crash the compiler with an error saying as much.
Essentially, the way this works, is that the newer versions of gcc are not properly handling #include when the target file cannot be found. Some gcc versions consider it ok to include a file that doesn’t exist and treat that ok/acceptable and just silently ignore this error and keep going like there is no issue.
Some versions spit out a warning and keep going (you won’t see them because the Arduino IDE blocks all warnings!)
The latest gcc seems to treat it as an error but appears to be so paralleled and pipelined from cpp to cc processing that they keep going for quite some time trying to continue to try to compile the code even though the #include failed. It eventually does stop with a #include error but you get lots of funky warnings/errors as well.
Regardless of which behavior you have, you can take advantage of the compiler processing your code beyond a missing #include to emit your own error.
With respect to the Arduino IDE, this works because if the sketch does not included the header for the needed sub library, then the include path will not contain the directory for the sub library. If the include path does not contain this sub library directory, then the #include in your library code will fail to locate the sub library header.
What you can do, is in your source that includes the needed sub library header, you then use a preprocessing check to see if a define exists for the sub library immediately after the include for that library.
If you don’t see the define, crash the compiler with an error.
This works because gcc continues to process code for a while/beyond a #include with a missing target file.
I have never understood why gcc does this. To me this is very broken behavior. (gcc didn’t do this going back to 1989 until just a few years ago) But you can use this behavior to your advantage when using the wimpy arduino IDE and its dumb build methodology to try to give the end user a clue as to how to get your library working.
in your code add:
#error Sketch must include SoftwareSerial.h
This will crash the compiler with your error if the SoftwareSerial.h header file can’t be found.
Because of the dumb Arduino Build methodology it won’t be found unless the user has included it in his sketch since the SofwareSerial library directory won’t be on the include path without the user including it in his sketch.
Thanks for your answers, PaulS.
I am sure there are very good reasons for this library compilation behavior, i just try to figure out how to use it in my case.
There are other better ways this could have been handled. I believe it started out as a quick and dirty way of handling it and it has now ballooned into a monster that is actually as complex if more than doing it the “normal” way REAL libraries are handled in s/w development.
Actually, the problem is not at link time, but at compile time, when i include the header SoftwareSerial.h, the compiler does not find it if it is not included in the sketch.
As shown above, you can either force the include or crash the compile depending on what you want/need.
I have had a need to both.
All this ugliness is because of the poor build methodology the IDE uses.
If you leave the IDE behind, it can be done correctly, and there are some makefile templates out there that handle libraries correctly. The problem is that if you are creating a library for other Arduino users, most of them are not very technically sophisticated and so they will struggle with using something other than the IDE, particularly users that are still using Windows since Windows wasn’t designed for s/w development and hence doesn’t come set up with many of the needed and useful tools out of the box like the *nix operating systems do.
btw, i am not sure if it would be considered a bug or just a quirk of the IDE, but if i include SoftwareSerial in the sketch, and then remove it (without changing the library code), it compiles, because the IDE does not recompile my library.
Perhaps you mean link rather than compile?
I would expect that if you removed the header from the sketch, the compile for your library should fail because the needed sub library directory would not be on the include path.
So I’m guessing that when you remove the header file, the sketch recompiles and everything links using the pre-built objects like your previously compiled library objects.
It could be considered a bug, this is intertwined with their build system.
Because they abandoned having the IDE using makefiles long ago for all dependency checking, they have now tried to do all of what make does inside the IDE. This combined with the way they handle libraries is a real mess and you get subtle issues like this one.