Search code examples
xcodemacoscocoaxcode4.3nsbundle

Xcode: How to Archive a Mac App with embedded Plug-in Bundles that use -bundle_loader for linking?


My Setup:

Mac OS X 10.7.4
Xcode 4.3.2

I have a Mac OS X Application that loads embedded Cocoa Loadable Bundles to use as Plug-ins. The Plug-ins are included in the Mac App's .app bundle in the standard location (MyApp.app/Contents/PlugIns) and are loaded via the standard Cocoa NSBundle API. The Plug-ins are copied into the final Mac App bundle in a standard "Copy Files" Build Phase with the destination set to PlugIns. I would describe it as a standard Cocoa Plug-in setup for a Mac App.

However, one thing is slightly unusual. I am using the -bundle_loader option to link the Plug-in Bundles against the public symbols in my main app at build time. I originally set this up in Xcode 3, and it has always worked fine.

Here's how Xcode describes -bundle_loader:

Bundle Loader
BUNDLE_LOADER
Specifies the executable that will be loading the bundle output file being linked. Undefined symbols from the bundle are checked against the specified executable like it was one of the dynamic libraries the bundle was linked with. [BUNDLE_LOADER, -bundle_loader]

In Xcode 4, I can still build and run my Mac App successfully in both the Debug and Release Build Configurations. No problem. (I do this by setting the Build Configuration of the default Run Action to either Debug or Release). Both configurations build and run just fine.

Here's my problem: In Xcode 4, I cannot successfully Archive my Mac App. The Plug-in Bundles will not link to the main App executable at Link time (immediately after compilation in the build process).

My Archive Action is set to build using the Release Build Configuration (of course). As I mentioned, there is no problem building with the Release Build Configuration using the Run Action. The problem only occurs when executing the Archive action.

Here is the Link error I receive when trying to Archive (this occurs immediately after compiling the source of the first Plug-in Bundle):

Ld /Users/<myusername>/Library/Developer/Xcode/DerivedData/Fluidium-ajljctlwoiqpcodskkcwxrxngeyo/Build/Intermediates/ArchiveIntermediates/Fake/InstallationBuildProductsLocation/Users/<myusername>/Library/Developer/Xcode/DerivedData/Fluidium-ajljctlwoiqpcodskkcwxrxngeyo/Build/Intermediates/ArchiveIntermediates/Fake/BuildProductsPath/Release/Fake.app/Contents/PlugIns/Tabs.fluidplugin/Contents/MacOS/Tabs normal x86_64
    cd /Volumes/SystemY/Users/<myusername>/work/fluidium/trunk/Fluidium
    setenv MACOSX_DEPLOYMENT_TARGET 10.6
    /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -arch x86_64 -bundle -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.6.sdk -L/Users/<myusername>/Library/Developer/Xcode/DerivedData/Fluidium-ajljctlwoiqpcodskkcwxrxngeyo/Build/Intermediates/ArchiveIntermediates/Fake/BuildProductsPath/Release -F/Users/<myusername>/Library/Developer/Xcode/DerivedData/Fluidium-ajljctlwoiqpcodskkcwxrxngeyo/Build/Intermediates/ArchiveIntermediates/Fake/BuildProductsPath/Release -filelist /Users/<myusername>/Library/Developer/Xcode/DerivedData/Fluidium-ajljctlwoiqpcodskkcwxrxngeyo/Build/Intermediates/ArchiveIntermediates/Fake/IntermediateBuildFilesPath/Fluidium.build/Release/TabsPlugIn.build/Objects-normal/x86_64/Tabs.LinkFileList -mmacosx-version-min=10.6 -bundle_loader /Users/<myusername>/Library/Developer/Xcode/DerivedData/Fluidium-ajljctlwoiqpcodskkcwxrxngeyo/Build/Intermediates/ArchiveIntermediates/Fake/BuildProductsPath/Release/FluidApp.app/Contents/MacOS/FluidApp /Users/<myusername>/Library/Developer/Xcode/DerivedData/Fluidium-ajljctlwoiqpcodskkcwxrxngeyo/Build/Intermediates/ArchiveIntermediates/Fake/BuildProductsPath/Release/TDAppKit.framework/TDAppKit -framework Quartz -framework WebKit -framework Cocoa -o /Users/<myusername>/Library/Developer/Xcode/DerivedData/Fluidium-ajljctlwoiqpcodskkcwxrxngeyo/Build/Intermediates/ArchiveIntermediates/Fake/InstallationBuildProductsLocation/Users/<myusername>/Library/Developer/Xcode/DerivedData/Fluidium-ajljctlwoiqpcodskkcwxrxngeyo/Build/Intermediates/ArchiveIntermediates/Fake/BuildProductsPath/Release/Fake.app/Contents/PlugIns/Tabs.fluidplugin/Contents/MacOS/Tabs

Undefined symbols for architecture x86_64:
  "_OBJC_IVAR_$_FUPlugIn.aboutInfoDictionary", referenced from:
      -[FUTabsPlugIn aboutInfoDictionary] in FUTabsPlugIn.o
  "_OBJC_CLASS_$_FUPlugIn", referenced from:
      _OBJC_CLASS_$_FUTabsPlugIn in FUTabsPlugIn.o
  "_OBJC_METACLASS_$_FUPlugIn", referenced from:
      _OBJC_METACLASS_$_FUTabsPlugIn in FUTabsPlugIn.o
  "_FUTabControllerProgressDidStartNotification", referenced from:
      -[FUTabsViewController startObserveringTabController:] in FUTabsViewController.o
      -[FUTabsViewController stopObserveringTabController:] in FUTabsViewController.o
  "_FUTabControllerProgressDidChangeNotification", referenced from:
      -[FUTabsViewController startObserveringTabController:] in FUTabsViewController.o
      -[FUTabsViewController stopObserveringTabController:] in FUTabsViewController.o
  "_FUTabControllerProgressDidFinishNotification", referenced from:
      -[FUTabsViewController startObserveringTabController:] in FUTabsViewController.o
      -[FUTabsViewController stopObserveringTabController:] in FUTabsViewController.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

One final note: I have the following Build Settings set on the Mac App target that serves as the "bundle loader":

Strip Debug Symbols During Copy : NO (for both Debug and Release)
Symbols Hidden By Default : NO (for both Debug and Release)


Solution

  • SOLVED!

    When Building for Release, there was no "Strip" phase executed on my main App Target. However, when Archiving, there was as "Strip" phase executed on my main App Target. (dunno why this is different since both are building via the Release Build Configuration, but it is).

    That strip phase when Archiving is why the PlugIns could not be linked via bundle_loader: the symbols had been stripped from the main App's binary.

    The solution was to the set the following setting in the Build Settings of my main App (the one that serves as the bundle loader):

    Strip Style: Debugging Symbols