Load bundle returns nil on Mojave (worked on High Sierra)

I make a plug-in to ą third-party app. Part of the plug-in is written in Swift.


The plug-in is stuck at Xcode 7.3.1/Swift 2.2 because of this issue in an old version of PyObjC.


In more detail, the reasons for being stuck on Swift 2.2 are:

  • The bug in the old version of PyObjC causes that if a user installs a plug-in written in Python while having our plug-in in Swift as well, the third-party app crashes on start-up.
  • Apple ships only an obsolete version of Python/PyObjC with macOS. This obsolete version does not contain a fix for this issue.
  • Instructing users to install newer version of Python/PyObjC manually is not feasible.
  • Apple does not support developing in Swift 2.2 in newer versions of Xcode.


The plug-in no longer works on Mojave.


We have the following observations:

  • The issue is limited to Mojave, everything works as expected on older macOS versions.
  • If the third-party app asks to "load this bundle" of the plug-in, it just gets nil.
  • The plug-in's init method is not called at all.
  • If I completely remove Swift 2.2 from the plug-in's code base (making in unusable), its bundle is correctly loaded.


Any ideas what might be causing this issue and how to fix it?


PS:

  • Pursuing users to install a newer version of Python/PyObjC is not feasible nor expecting Apple to bundle a newer version of Python/PyObjC with macOS (so the plug-in code base cannot be upgraded to a newer Swift version).
  • We plan to migrate the code base from Swift to Objective-C but this will not happen instantly.

Replies

It’s currently not safe to use Swift in this sort of plug-in. The problem is that the Swift runtime library is not ABI compatible, so each Swift executable is tied to a specific Swift runtime. If you have two plug-ins that use conflicting runtimes, loading them into the same address space would be bad.

I’m not sure what’s causing your specific problem; it could be the above issue but it could be something else. Regardless, the only way supported option is to remove the Swift code from your plug-in. You could do this by putting it in a separate process and communicating with that via some sort of IPC, but it might just be easier to continue with your current plan to rewrite it.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Thanks. I am aware of the ABI compatible thing (unfortunatelly, we learnt that the hard way). I guess this is not the case as it should have crashed on High Sierra as well.


This issue seems to be new and limited to Mojave. The same app with the same plug-ins works on High Sierra but not on Mojave. The issue appears even if my plug-in is the only one installed.

The problem with doing unsupported stuff is that things can break in mysterious ways. I’m not exactly sure why this has broken on 10.14 but I think that’s besides the point. You might be able to patch over this particular breakage, but that just exposes you to other potential problems down the line. IMO it’s better to spend this time addressing the fundamental problem here.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

I understand. However, I am seeking for a possibility to unblock our users to use the plug-in on Mojave before we get rid of Swift from the plug-ins code base (which will propably take several months).

I am seeking for a possibility to unblock our users …

For that you’ll have to dig deeper into some combination of the Swift, Objective-C and PyObjC runtimes. Fun!

Earlier you wrote:

If the third-party app asks to "load this bundle" of the plug-in, it just gets nil.

Presumably this

nil
is coming back from some
NSBundle
method. Which method?

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

I have managed to get the plug-in running on Mojave.


The nil was returned by a call to NSBundle's principalClass.

Based on my understanding of the official documentation, there are two ways how the principalClass is determined.

- The principal class name is specified manually in the info.plist file. As the plug-in did not have it specified here, this step should not apply.

- The principal class is the first one listed on the ld command line when linking. As the exactly same plug-in binary was used on both High Siera and Mojave, "the first one listed on the ld command line" was the same so the returned principal class should be the same on both versions.


Somehow, the principalClass call returned different value on High Sierra and Mojave. Personally, I do not see any reason why it should behave differently, as the documentation has not changed and the logic sounds to be dependent solely on what happened while compiling the plug-in not how the world context while running it.


However, after I have added NSPrincipalClass item into the info.plist file, the plug-in loads successfuly on Mojave.

Good spelunking!

With regards the load order, I always use

NSPrincipalClass
and thus I’m actually quite surprised that this load order stuff is documented as something that folks can rely on. Weird.

As the exactly same plug-in binary was used on both High Siera and Mojave, "the first one listed on the ld command line" was the same so the returned principal class should be the same on both versions.

Agreed. I’d appreciate you filing a bug about that, and then posting your bug number here, just for the record.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

What Product (problem area) should I choose?

[Quinn logs in with his ‘clean’ developer account to see what the product area list looks like these days.]

I’d recommend macOS + SDK.

Just as general advice, it is helpful to choose a good product area but you shouldn’t let the lack of a good choice prevent you from filing a bug. Each of these product areas expands to a long list of internal components, so routing your bug is a complex process. Choosing an incorrect product area slows things down a little, but only a little.

Thanks for taking the time to do this.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Bug 45696097