Pages: [1]   Go Down
Author Topic: user library including another user library  (Read 872 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Jr. Member
**
Karma: 2
Posts: 83
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm finally getting back into Arduino after a bit of a vacation and a reinstallation, and have ran into an old issue from before my hiatus.

I'm trying to modularize my code by moving things into libraries, so I can avoid re-inventing the wheel or copy-pasting from one sketch to another to do things that need to be done frequently. (besides inconvenient, it means if I bugfix/update some code, I want it to immediately be updated everywhere I've used it, and with copy-paste, that's a nightmare, as well as being very unreliable)  I made a Semaphore library that's working great.  I also made a generic input debouncing library that's also working great.  But I can't use the debouncing library IN a sketchbecause I can't get the debouncing library to include the semaphore library. (for key buffering)

After considerable googling around, I seem to have encountered a known issue with the linker in Arduino, that it fails to properly recognize #include statements in user libraries, (they can only include from the bundled libraries?) and I can't simply #include <Semaphore.h>

I also saw and tried #include "Semaphore.h", which seems to work for other built-in libraries, but not mine. (what's the difference?)  The error I was getting was that the one Semaphore object defined  in the header was an unknown type.  That was the only error, and it was aborting the compile very early.

Others have suggested entering full paths to headers, or backing up.  So I tried #include <../Semaphore/Semaphore.h>.  That appeared to work, the compile proceeded and got very late in the process, I assume to the linker.  And then it dumped out a bunch of new errors, every attempt to use a Semaphore::ClassFunction were showing up as undefined.  It saw the class, but not its functions.  Very annoying.

After much angst and trial and error, I finally resigned to find Arduino's primary library, and moved Semaphore.h/cpp into there, and change my include back to just plain #include <Semaphore.h>.  And IT COMPILED 100%.

Please someone tell me there's some way to get user libraries to use other user libraries other than moving them in with the bundled ones?  (the magic folder is Arduino.app/Contents/Resources/Java/hardware/arduino/cores/arduino/, for anyone that cares)  For right now I'm keeping my library in the user library folder, and have dropped symlinks into the bundled library folder, for the sake of sanity and some thinly-veiled illusion of standardization.  I know enough C to be dangerous, but have a lot of holes, and I'm praying that I'm simply missing a bit of syntax in my header file for my Semaphore that may mitigate this problem, if it can't be solved directly.

FWIW I have found one other work-around that is also a bit less than satisfactory.  I moved the Semaphore.h/cpp into the same folder as the Debouncer library, and changed my include back to #include <Semaphore.h> and that compiles. (I did remove symlinks and relaunch IDE before testing)  So I suppose that's *slightly* better than dropping library files into the compiler bundle, but can we do better?  Id like to solve this as "by the book" as possible, with an edit to my libraries only and no filesystem shenanegans.
« Last Edit: February 02, 2014, 12:55:24 am by virtual1 » Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 611
Posts: 49101
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Are hand-waving answers suitable responses to hand-waving questions?

I suspect that you are trying to hide, from the sketch, the fact that your library needs to use another library. You can't. Get over it.

Post your library AND your sketch AND your error messages if you want us to give meaningful answers.
Logged

Offline Offline
Jr. Member
**
Karma: 2
Posts: 83
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

well you suspect wrong smiley-wink   I entirely expect, and DESIRE for libraries to use libraries.  But it's not working, at least not without a considerable amount of fight.  I don't care if the user sees one of my libraries depending on another one of my libraries, that's how it SHOULD work.  Not being able to compile without an "ugly hack" on their end however, is fast approaching unacceptable.

http://vftp.net/arduino/issues/libraries_using_libraries/

Install those two libraries, and try to run the debouncer_example sketch.  The symlinks will probably appear as zero-byte files in the Debouncer folder, you may need to remove them before attempting to compile.

I've been writing reusable code for going on 20 years, and I know the value of writing reusable code, and of making libraries so it's not necessary to edit 10 programs because I made an improvement to a bit of shared code.  Arduino does user libraries, but is making it something of a pain to allow one library to use another.  I want to be able to stack my blocks  vertically, not just horizontally, if you know what i mean.  Right now my libraries can only go one level deep, and without proper library dependency, a single composite library can quickly get out of control.

As for "hiding", one thing I strongly desire is to make my code easy for *others* to reuse, as well as myself.  While the hack of symlinking my libraries together works for me, it's not nearly as clear to others.  They should be able to download my sketch and my libraries, install them normally, and GO.  Not have to dig in and modify the libraries (likely entering commands and following instructions they're unfamiliar with) to get it to compile.  So I'm hoping someone knows a fix I can make in the code so the issue disappears from view.

ps   while the semaphore is fairly well debugged, the debouncer was just recently extracted from a sketch and transformed into a library and may still have issues.  It's kinda hard to test as a library when it doesn't work.  So I'll get on that today now that I have a hack-around.  I'm going to make a conceited effort this week to convert as much of my shared code to libraries.  I have some bits that are shared by a dozen or more sketches, and I know the code in many of them is out of date because I've fixed/improved it in one sketch and those improvements didn't get copied to other sketches.  But this process depends to a degree on stacking libraries.
« Last Edit: February 02, 2014, 10:40:24 am by virtual1 » Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 611
Posts: 49101
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
well you suspect wrong
Really?

Code:
#include <TimerOne.h>

#include <Debouncer.h>

Debouncer Guard;

void setup () {
A quick peak in Deboncer.h shows:
Code:
#include <Semaphore.h>  //  requires Semaphore.h/cpp to be in the SAME FOLDER as this library.  how annyoing.
So, it sure looks to me like you are trying to hide from the sketch the fact that Debouncer needs Semaphore.

Please explain how you see things differently.
Logged

Offline Offline
Jr. Member
**
Karma: 2
Posts: 83
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

oh, sorry I missed that, "hide from the sketch, yes that is correct.  The sketch/user shouldn't need to be any more concerned about the semaphore being used by the main library than say, math.h being used by some other library.  I could go into more detail but this is getting off topic.  Look up "programming abstraction" if you want to know more.  Well-written libraries do a good job of abstraction.

Aaaaanyway, we've done a fine song and dance around my question, can we get back to it please?   I also just noticed a lot of sketches #include <Wire.h> though they don't directly use it either, but the sketch is using a user-installed library that requires it.  So it appears I'm not the only one with this issue.  I hadn't considered including it in the main sketch.. that's an interesting solution, but I would like to find a way to abstract child libraries completely from the sketch, if it's possible?
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 611
Posts: 49101
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I could go into more detail but this is getting off topic.  Look up "programming abstraction" if you want to know more.  Well-written libraries do a good job of abstraction.
But, the Arduino IDE doesn't.

Quote
Aaaaanyway, we've done a fine song and dance around my question, can we get back to it please?
Sure. What was it?

Quote
but I would like to find a way to abstract child libraries completely from the sketch, if it's possible?
It is. But, that does NOT seem to be what you want. In your example, Semaphore is not a child of Debouncer. It is a separate library in it's own right.

If it were a child, you could create a utility folder in the Debouncer library, and put Semaphore.h and Semaphore.cpp there.
Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 62
Arduino rocks / OpenLCB rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I could go into more detail but this is getting off topic.  Look up "programming abstraction" if you want to know more.  Well-written libraries do a good job of abstraction.
But, the Arduino IDE doesn't.

Yes, and that is exactly the problem.  I, too, would like the IDE to work like other compilers -- it needs to be fixed. 
Logged

Dr. David Harris
OpenLCB Dev Team

Pages: [1]   Go Up
Jump to: