Plug-in built with Xcode 11 fails to load on Yosemite (10.10)

Here’s a very simple app that won’t run on 10.10 when built with the 10.15 SDK:

main.m

#import <Foundation/Foundation.h>
#import <AudioToolbox/AudioToolbox.h>

int main(int argc, const char * argv[]) {
    AudioComponent comp = NULL;

    for (;;) {
        AudioComponentDescription desc;
        memset((void*)&desc, 0, sizeof(desc));

        comp = AudioComponentFindNext(comp, &desc);
        if (comp == NULL)
            break;

        if (AudioComponentGetDescription(comp, &desc) != noErr)
            continue;

        CFStringRef cfName;
        if (AudioComponentCopyName(comp, &cfName) == noErr) {
            NSLog(@"%@", (__bridge NSString*)cfName);
            CFRelease(cfName);
        }
    }

    return 0;
}

The runtime error message is:

dyld: lazy symbol binding failed: Symbol not found: _AudioComponentFindNext
  Referenced from: /Users/tom/workspace/./AUScan
  Expected in: /System/Library/Frameworks/AudioToolbox.framework/Versions/A/AudioToolbox

dyld: Symbol not found: _AudioComponentFindNext
  Referenced from: /Users/tom/workspace/./AUScan
  Expected in: /System/Library/Frameworks/AudioToolbox.framework/Versions/A/AudioToolbox

Trace/BPT trap: 5

So it looks like there’s a mismatch between what’s present on 10.10 and what the 10.15 SDK is expecting. Running nm on /System/Library/Frameworks/AudioToolbox.framework/Versions/A/AudioToolbox on the 10.10 machine gives us

000000000000e89e T __AT_AudioComponentFindNext

If we look at the contents of MacOSX10.14.sdk/System/Library/Frameworks/AudioToolbox.framework/Versions/A/AudioToolbox.tbd then we will find an entry for _AudioComponentFindNext in the list of symbols for /System/Library/Frameworks/AudioToolbox.framework/Versions/A/AudioToolbox.

However, if we look at what’s inside MacOSX10.15.sdk/System/Library/Frameworks/AudioToolbox.framework/Versions/A/AudioToolbox.tbd then the only _AudioComponentFindNext entry is in the listings for /System/Library/PrivateFrameworks/AudioToolboxCore.framework/Versions/A/AudioToolboxCore.

I’ve not quite got the full picture, but it suggests that the location of the symbol has changed in the latest SDK and it’s broken backwards compatibility.

5 Likes

Interesting, thanks Tom! So this is most definitely an Apple issue then, right?

The example in my previous post is unrelated to JUCE.

Are you planning to notify Apple about the situation you have found here?

Yep, will do that today.

It seems that most DAW makers are building against an older SDK.

Very interesting to see Logic is built against 10.13, it could be a sign Apple considers that an acceptable vintage for notarisation in 2020 if it satisfies their internal build processes. Having to second-guess this kind of stuff is pretty frustrating.

1 Like
7 Likes

Wow… interesting fix! How did you figure out how to solve this issue? Is it a bug in the SDK?

1 Like

Thanks @t0m, can you also explain what needs to be done to solve the issue in projects not maintained with Projucer?

Apple got back to me via Feedback Assistant.

The AudioUnit framework needs to be linked before the AudioToolbox framework if you are building against the 10.15 SDK. This is not a requirement when building against any other SDK version.

2 Likes

Thanks a lot, @t0m!

Is it right and enough to reorder the frameworks in the “Link Binary With Library” phase of the Xcode project, as shown in the screenshot, or more needs to be done?

That will do it.

If you’re using a different build system then you need to make sure that -framework AudioUnit appears before -framework AudioToolbox when you invoke the linker.

2 Likes

A bit related to this, would it be possible to add those dependencies in juce_audio_plugin_client.h to the module as stated by JUCE Module Format.txt
OSXFrameworks: (Optional) A list (space or comma-separated) of OSX frameworks that are needed by this module

Right now we add manually AudioUnit and CoreAudioKit in our cmake based generator.
This is done manually in jucer_ProjectExport_Xcode.h
xcodeFrameworks.addTokens (“AudioUnit CoreAudioKit”, false);

Thanks !

3 Likes

Wow, thanks for the fix! :smiley:

Would it fix the VST3 version? In the cmake file we link to frameworks in the following order, the issue is still here:

  target_link_libraries( ${CURRENT_TARGET} PUBLIC
  "-framework AudioUnit"
  "-framework AudioToolbox"
  "-framework AVFoundation"
  "-framework AVKit"
  "-framework Carbon"
  "-framework Cocoa"
  "-framework CoreFoundation"
  "-framework CoreAudio"
  "-framework CoreMedia"
  "-framework CoreMidi"
  "-framework QuartzCore"
  "-framework IOKit"
  "-framework AGL"
  "-framework Accelerate"
  "-framework WebKit"
  "-lobjc"
)

could it be that CMAKE uses them in reverse order?

Could you please provide a few more details?

I can successfully load the AU, VST and VST3 versions of AudioPluginDemo on 10.10.

Why does your vst3 plugin link to the AudioUnit framework? In a normal vst3 Projucer-generated build file this doesn’t happen and really shouldn’t be necessary. Unless you are hosting AudioUnits inside your vst3 and then maybe that’s why it does work for AudioPluginDemo and not for you.

We are not using Projucer, we build JUCE components with cmake instead (much easier to maintain the project files). Probably there was a different issue. The fix was:

SET(CMAKE_OSX_DEPLOYMENT_TARGET 10.11)