Wednesday, March 16, 2011

How to Debug Webtrends.framework Linker Problems

You are trying to integrate Webtrends Analytics library as Webtrends.framework into your application and linker fails with lots of undefined symbols:

Undefined symbols:
 "_OBJC_CLASS_$_NSManagedObject", referenced from:
     _OBJC_CLASS_$_WTDCEvent in Webtrends(WTDCEvent.o)
     _OBJC_CLASS_$_WTDCVisitor in Webtrends(WTDCVisitor.o)
     _OBJC_CLASS_$_WTDCSession in Webtrends(WTDCManager.o)
 "_SCNetworkReachabilityGetFlags", referenced from:
     -[WTReachability currentReachabilityStatus] in Webtrends(WTReachability.o)
     -[WTReachability connectionRequired] in Webtrends(WTReachability.o)
 "_SCNetworkReachabilityUnscheduleFromRunLoop", referenced from:
     -[WTReachability stopNotifer] in Webtrends(WTReachability.o)
 "_NSSQLiteStoreType", referenced from:
     _NSSQLiteStoreType$non_lazy_ptr in Webtrends(WTDCManager.o)
    (maybe you meant: _NSSQLiteStoreType$non_lazy_ptr)
 "_SCNetworkReachabilityCreateWithAddress", referenced from:
     +[WTReachability reachabilityWithAddress:] in Webtrends(WTReachability.o)
 "_SCNetworkReachabilityScheduleWithRunLoop", referenced from:
     -[WTReachability startNotifer] in Webtrends(WTReachability.o)
 "_SCNetworkReachabilitySetCallback", referenced from:
     -[WTReachability startNotifer] in Webtrends(WTReachability.o)
 "_SCNetworkReachabilityCreateWithName", referenced from:
     +[WTReachability reachabilityWithHostName:] in Webtrends(WTReachability.o)
 "_OBJC_CLASS_$_NSManagedObjectModel", referenced from:
     objc-class-ref-to-NSManagedObjectModel in Webtrends(WTDCManager.o)
 "_OBJC_CLASS_$_CLLocationManager", referenced from:
     objc-class-ref-to-CLLocationManager in Webtrends(WTDCManager.o)
 "_OBJC_CLASS_$_NSPersistentStoreCoordinator", referenced from:
     objc-class-ref-to-NSPersistentStoreCoordinator in Webtrends(WTDCManager.o)
 "_OBJC_METACLASS_$_NSManagedObject", referenced from:
     _OBJC_METACLASS_$_WTDCEvent in Webtrends(WTDCEvent.o)
     _OBJC_METACLASS_$_WTDCVisitor in Webtrends(WTDCVisitor.o)
     _OBJC_METACLASS_$_WTDCSession in Webtrends(WTDCManager.o)
 "_OBJC_CLASS_$_NSManagedObjectContext", referenced from:
     objc-class-ref-to-NSManagedObjectContext in Webtrends(WTDCManager.o)
 "_kCLLocationAccuracyThreeKilometers", referenced from:
     _kCLLocationAccuracyThreeKilometers$non_lazy_ptr in Webtrends(WTDCManager.o)
    (maybe you meant: _kCLLocationAccuracyThreeKilometers$non_lazy_ptr)
 "_OBJC_CLASS_$_NSFetchRequest", referenced from:
     objc-class-ref-to-NSFetchRequest in Webtrends(WTDCManager.o)
 "_OBJC_CLASS_$_NSEntityDescription", referenced from:
     objc-class-ref-to-NSEntityDescription in Webtrends(WTDCManager.o)
ld: symbol(s) not found
collect2: ld returned 1 exit status
You check sample application once more, it still works. Of course. You compare project files at plain text with diff, see no "major differencies". Email tech support and get reply asking you to check everything again. Done, again. Browse internet and Webtrends support pages just to confirm what you knew in the first place: framework was not loaded, thus symbols were not found. That was useful... not.

Try to use linker flag -force_load and get a different set of errors. Progress, some could say. Not really. Continue experimenting with linker options, learn something new:
ld: duplicate symbol _OBJC_METACLASS_$_WTReachability in /Users/username/folder/iPhoneClient/Webtrends.framework/Webtrends(WTReachability.o) and Webtrends.framework/Webtrends(WTReachability.o)
collect2: ld returned 1 exit status
You still surf rarely visited dusty corners of internet, maybe find out that Webtrends.framework is not a framework at all, but a normal static library. No help. What to do?

Start from the beginning, once more. This time check Each and Every Step. Literally, regardless whether they make any sense to you! Problem solved. Kick yourself. Repeat. Do not send nasty email to tech support, which did receive complete linker output and could have seen in 5 seconds what was the problem, but somehow missed it. Kick yourself again. Repeat. Go out and scream your frustration away (virtually). Done, case closed.

Write a reminder blog entry, just in case you run into this again... or maybe someone else, somewhere, sometime, would suffer from same problem.

Solution? Simple RTFM.

In my case I was missing SystemConfiguration, CoreData and CoreLocation frameworks, since I didn't need them. Don't even want CoreLocation.  Seems like Webtrends static library depends on them, but somehow I managed to misinterpret "should also add ... which support Webtrends" as something you SHOULD do, instead of a hardcoded MUST level dependency. Guess I've read/written too many specs where "should" and "must" really make a difference.

Next problem: how to remove CoreLocation dependency or at least make it weak. Trouble ahead, ahoy!

6 comments:

  1. Did you try Flurry analytics in your apps? How do you compare it to WebTrends offering?

    ReplyDelete
  2. Sorry no idea, customer told that they want Webtrends and that's it. Only thing I can say is that their API looks real easy to use, but haven't done anything beyond basic tracking.

    Will check advanced tracking tomorrow!

    ReplyDelete
  3. Hi Jouni, thanks for the post. Sorry we didn't get an answer back to you quickly. And I'm glad you got it working.

    As to your points:
    1) We agree that the CoreLocation dependency is a burden. We will be removing the dependency in the next release of the Webtrends iOS SDK, while continuing to allow customers to send geo-location data when desired to Webtrends.
    2) Our main doc (http://product.webtrends.com/DC/iPhone/index.html) and readme.txt doc both avoid the word "should" as we agree that would be misleading. Where did you see the reference to "should"? We'd like to fix that documentation so it's clear for everyone.

    Feel free to drop us a line on the Webtrends Developer Network (as you've done already), or via email through developer at webtrends.com if you have any other issues.

    Thanks very much for the feedback.

    Best.

    -Eric Butler (Webtrends)

    ReplyDelete
  4. Hi Jouni, we found the location where we say "should". We'll fix that. Thanks again.

    -Eric Butler

    ReplyDelete
  5. Hi Eric, your customer service goes way beyond normal expectations! Credits to Webtrends for the extra effort :)

    Glad to hear you are planning to change CoreLocation to a weak dependency. Location tracking is something our customer wants to avoid for now (usability, legal issues).

    ReplyDelete
  6. Happy to report that WebTrends 1.1.0.370 has dropped CoreLocation dependency. Happy that I still recalled that I can now removed it from app, too!

    ReplyDelete