Tuesday, July 21, 2009

The proper way to fix linker conflict between AdWhirl and FBConnect

I was trying to integrate AdWhirl into Puri! Lite 2 yesternight but I was getting a linker error. Apparently the static library that AdWhirl is giving out already contains part of Facebook's FBConnect library and it is causing duplicated symbols with our own FBConnect library. AdWhirl's instructions page has some answers to it but it's not good enough for us, because we're using a customized FBConnect:

  1. Refactoring would work if it's done correctly. But with Objective-C's dynamic nature it's possible for grep/sed/anything relying on regular expressions to miss a few references that aren't apparent in the code. I'm sure it will work for FBConnect (which isn't too complicated a library), but I don't see it as a clean solution.
  2. Removing .m files from FBConnect until no conflict is left - this doesn't work for us because it means we're removing our own customizations.
  3. Specifically compiled .a files without Pinch Media's package (which is the package containing FBConnect libraries) - doesn't work because we want to have Pinch Media's adverts.

There's a far better way than any of the above.

AdWhirl's library is actually an .a file - a static library that can be used by the GNU linker. People who're familiar with GNU toolchain would know that an .a file is actually just an archive containing object files (.o files that are the direct products after you've compiled .c, .cpp or .m source files). Because it's just an archive, it can be opened, listed, extracted and modified.

So let's see what's inside AdWhirl's static library file:
[martinkou@martinkou AdWhirl]$ ar -t libAdWhirlDevice_1.2.0.a
__.SYMDEF SORTED
ARAdNetworkController.o
ARAdRolloController.o
ARCustomController.o
ARExternalAdNetworkController.o
ARJumpTapController.o
ARMillennialMediaController.o
ARMobclixController.o
ARQuattroController.o
ARVideoEggController.o
AdRolloCanvasController.o
AdRolloController.o
AdRolloAdContent.o
AdRolloConnectionURLDownload.o
AdRolloConnectionURLMetricsFetch.o
AdRolloImgCacheManager.o
AdRolloLocationManager.o
AdRolloAdView.o
AdRolloCanvasWebView.o
AdRolloContainerView.o
AdRolloView.o
MMAdOverlayController.o
MMAdView.o
MMAdViewPrivate.o
MMAdWebViewController.o
MMAppData.o
dgif_lib.o
gif_err.o
gif_hash.o
gifalloc.o
PLGIFImageView.o
PLGIFReader.o
ARRollerController.o
ARReachability.o
ARRollerAnalyticsUrlRequest.o
ARRollerConfigurationInfoRequest.o
ARRollerStaticInfo.o
ARRollerUrlMetricsRequest.o
ARRollerUrlRequest.o
ARCDataScanner.o
ARCDataScanner_Extensions.o
ARNSCharacterSet_Extensions.o
ARNSDictionary_JSONExtensions.o
ARNSScanner_Extensions.o
ARCJSONDeserializer.o
ARCJSONScanner.o
ARCJSONSerializer.o
ARRollerView.o
ARRollerViewInternal.o
Mobclix.o
MobclixController.o
MobclixDatabase.o
MobclixJSON.o
MobclixMessenger.o
MobclixReachability.o
MobclixAds.a
MobclixBrowser.a
MobclixFeedback.a
MobclixSocial.a
FMDatabase.o
FMDatabaseAdditions.o
FMResultSet.o
CXMLDocument.o
CXMLDocument_CreationExtensions.o
CXMLDocument_PrivateExtensions.o
CXMLElement.o
CXMLElement_CreationExtensions.o
CXMLElement_ElementTreeExtensions.o
CXMLNode.o
CXMLNode_CreationExtensions.o
CXMLNode_PrivateExtensions.o
CXMLNode_XPathExtensions.o
QWAd.o
QWAdRequestOperation.o
QWAdView.o
QWBannerAdView.o
QWCacheManager.o
QWInterstitialAdView.o
QWLog.o
QWRequestConstants.o
QWSmallBannerAdView.o
QWSubmitReportOperation.o
QWTextAdView.o
QWWebViewController.o
QWAdViewConcrete.o
QWTestMode.o
QWPrefetchOperation.o
QWURLBuilder.o
QWImageFactory.o
NSURLRequest+QWTools.o
QWRegisterAppLaunchOperation.o
AdFrameView.o
PMCDataScanner_Extensions.o
PMNSCharacterSet_Extensions.o
PMNSDictionary_JSONExtensions.o
PMNSScanner_Extensions.o
PMCJSONDeserializer.o
PMCJSONScanner.o
PMCJSONSerializer.o
PMCDataScanner.o
PMAdSizeLookup.o
PMAdViewController.o
PMStaticAdViewController.o
PMDropDownAdViewController.o
PMInterstitialAdViewController.o
PMAdView.o
PMInterstitialAdView.o
PMAd.o
PMAdServer.o
Beacon.o
BeaconDatabase.o
Reachability.o
Database.o
JSONUtils.o
CrackDetector.o
FBConnectGlobal.o
FBRequest.o
FBSession.o
FBXMLHandler.o


Notice the four object files: FBConnectGlobal.o, FBRequest.o, FBSession.o and FBXMLHandler.o at the end of the list. These four files are causing the linker conflict with our customized FBConnect library.

To remove them from AdWhirl's static library archive, use ar -d:
[martinkou@martinkou AdWhirl]$ ar -d libAdWhirlDevice_1.2.0.a \
FBConnectGlobal.o FBRequest.o FBSession.o FBXMLHandler.o

Repeat the same command for the other .a file which is for the Simulator.

After running this command the FBConnect-related object files will no longer be present in the AdWhirl static library (you can use ar -t to check), and thus you'll no longer have the linker conflicts.

The same principle can be applied to other conflicting libraries. e.g. TouchXML or FMDB in Quattro.

1 comments:

ryan.chang said...

The other option is to rename the symbols in these object files directly. binutils tools allow you to replace the symbol names.

Archive