Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Optional Framework Not Working (CoreAudioKit not on Simulator)

To get MIDI over Bluetooth working, I need to use the CoreAudioKit framework. This works perfectly, but I am not able to compile on the simulator.

  1. Making the framework "optional" doesn't help, error is ld: framework not found CoreAudioKit

enter image description here

I think it should work according to the docs

  1. Deleting the framework allows my code to compile

I've got this in code, which is why I can delete the framework without issues.

#if !TARGET_IPHONE_SIMULATOR
#import <CoreAudioKit/CoreAudioKit.h>
#endif


How can I get this optional compilation to work?
like image 712
Dan Rosenstark Avatar asked Jul 22 '15 21:07

Dan Rosenstark


Video Answer


2 Answers

I actually would have thought that would work, but I think you can solve it another way. This worked for me:

  1. remove all references to CoreAudioKit in your target settings Build Phases (Link Binary With Libraries)

  2. make sure there's no similar settings entered in manually. for example, don't add this setting: -weak_framework CoreAudioKit in the Other Linker Flags

  3. use preprocessor flags to conditionally compile your code for the simulator:

#import "ViewController.h"

#if !TARGET_IPHONE_SIMULATOR
@import CoreAudioKit;
#endif

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
   [super viewDidLoad];
   // Do any additional setup after loading the view, typically from a nib.

#if !TARGET_IPHONE_SIMULATOR
   if ([CABTMIDICentralViewController class]) {   // maybe not needed?
      CABTMIDICentralViewController *vc = [[CABTMIDICentralViewController alloc] init];
   }
#endif
}

Note: in my example above, you might not need to test for the existence of the CABTMIDICentralViewController class. It depends on whether your app is targeting only iOS 8+, or also iOS 7.

Update

Per comments below by @Yar and @JeremyHuddlestonSequoia, note that this solution requires you to Enable Modules and Link Frameworks Automatically in project build settings. These Xcode settings now default to the proper values for this technique, but in case you're managing an older project, make sure they're enabled.

Other References

https://stackoverflow.com/a/26510640/119114

https://stackoverflow.com/a/25883210/8047

like image 140
Nate Avatar answered Nov 16 '22 03:11

Nate


In order to link something (even weakly), it needs to be present in the SDK. It doesn't matter if you don't actually use the framework; the linker will error out if instructed to include a link to a file it cannot find.

You will need to conditionally compile and link your project based on the SDK being used. Specifically, when targeting the iOS SDK, you will want to include support for and link against CoreAudioKit.framework. When targeting iOS Simulator SDK, you will want to not include this support nor linkage.

To conditionalize your code, you will want to include the header and use the TARGET_OS_SIMULATOR macro (or the deprecated TARGET_IPHONE_SIMULATOR macro for SDKs older than iOS 9.0). This header is often pulled in via other includes, but it is best to do so yourself.

Eg:

#import "MyController.h"
#import <TargetConditionals.h>

#if !TARGET_IPHONE_SIMULATOR
#import <CoreAudioKit/CoreAudioKit.h>
#endif

@implementation ViewController

- (void)viewDidLoad {
   [super viewDidLoad];

#if !TARGET_IPHONE_SIMULATOR
   // Stuff dependent on CoreAudioKit
#endif
}
@end

Xcode does not support SDK-conditional linking in the build phases for targets, so make sure you do not include CoreAudioKit.framework in Link Binary With Libraries build phase for your target. To handle linking, you basically have two options:

  1. Use automatic linking support from clang modules
  2. Use SDK-conditional linker flags

To use automatic linking, you must set Xcode's Enable Modules (C and Objective C) and Link Frameworks Automatically build settings turned on.

If you are trying to accomplish something like this with older toolchains or just like having tighter control over linking, you can still accomplish this with SDK-conditional Other Linker Flags build settings. Create SDK-conditional entries for this build setting such that you use "-framework CoreAudioKit" (or "-weak_framework CoreAudioKit") by default and nothing when targeting the simulator SDK. This screenshot should make it more clear.

build settings screenshot

If your iOS Deployment Target is older than iOS 8, you should be sure to weak link the framework because it was added in iOS 8. If targeting iOS 8 or newer, you can safely use -framework CoreAudioKit.

like image 39
Jeremy Huddleston Sequoia Avatar answered Nov 16 '22 01:11

Jeremy Huddleston Sequoia