21

I'm working on an open-source project that can optionally use a closed-source framework. If the closed-source framework is included in the project, there will be additional functionality. But if the framework isn't included in the project, the project should still compile properly.

How do I check at compile-time if the framework is included in the project?

Basically, I want to do something like this:

#ifdef _MY_FRAMEWORK_EXISTS
#import <MyFramework/MyFramework.h>
#endif

I've seen older questions from 2 years ago like this one, but no answer has surfaced so I might be missing something new now.

I DON'T want to check at run-time via NSClassFromString(), because this will fail at compile time when I try to import MyFramework and it doesn't exist.

Community
  • 1
  • 1
johngraham
  • 6,461
  • 2
  • 16
  • 22
  • Not sure you can, since all that will be evaluated after compilation, you will get linker error. But you can throw a script before compilation, in order to check dependancy. then declare macro depending on the script result. From make is feasible, from Xcode that will be far from simple. By the way you should deal with weak linking + NSClassFromString() at runtime, this is the more conveniant – Mr Bonjour Mar 26 '13 at 16:27
  • Hmm thank you for the suggestion. Ideally I'd want developers to use the open-source module with as minimal overhead as possible (e.g. not writing a custom script & macro in their project). Although this would work, it probably wouldn't be the most elegant. – johngraham Mar 26 '13 at 16:32
  • :S what area you talking about? i was kidding about script check before compilation time. You should use definitively weak linking, that's what it's made for. If library is not available, you won't get linker error. Since all your method call from client will be dynamic, you won't get symbol not found. That's why obj-c is really great – Mr Bonjour Mar 26 '13 at 16:39
  • Ok, I have two questions. (1) If the framework doesn't exist in the developer's project, how do they set it as a weakly linked? Can you provide an example? (2) And if the framework doesn't exist, won't there still be compile-time errors in the `NSClassFromString()` code that doesn't get run at run-time? – johngraham Mar 26 '13 at 17:13
  • @johngraham: could you share details if you managed to achieve your objective? I'm looking to do the same with Google' Firebase frameworks. Thanks. – batman Nov 22 '16 at 08:08
  • @johngraham here's the issue I'm running into: http://imgur.com/a/bRgQ3 – batman Nov 22 '16 at 08:17

2 Answers2

21

You can check for the presence of a header file using the __has_include language extension. http://clang.llvm.org/docs/LanguageExtensions.html#include-file-checking-macros

However, that only tells you if the header file is installed. It can't tell you if "Link Binary With Libraries" has linked to its framework.

Greg Parker
  • 7,972
  • 2
  • 24
  • 21
  • @greg-parker: how would I resolve this error: http://imgur.com/a/bRgQ3 I'm trying to do the same as the OP – batman Nov 22 '16 at 08:18
2

I recommend reading the Mac Developer Library : Framework Programming Guide (which includes a section on Weak Linking).

  1. What do you mean by "exists" or "included in the project"? Do you mean added to the "Link Binary With Libraries" build phase (as described by Including Frameworks)? All that does is affect the linking, not the compilation, build phase. To see this, build. Then, search for -framework in the build log of Xcode's Log Navigator.

    So, yes, if you want to affect the compilation of the code you provided, you could manually define the macro _MY_FRAMEWORK_EXISTS.

  2. I don't really understand what you are trying to do. Can you explain what you want at a higher level? Perhaps, there's a better way to go about it.

    "Minimal overhead" is nice, but too much magic might be confusing. For example, Xcode's magic hides what really happens when including a framework.

    I also recommend checking out how the Facebook SDK for iOS works for high & low-level ideas. It might do the kinds of things you want to do.

ma11hew28
  • 121,420
  • 116
  • 450
  • 651
  • Thanks for your response, @mattdipasquale. (1) By "exists"/"included in the project", I meant that it was added to "Link Binary With Libraries" (though I don't see anything when searching for `-framework` in the Log Navigator of that build). (2) I want to provide open-source code that optionally `#imports` & uses a framework if it can be linked to - but no matter what, the project should compile whether or not the framework was linked to. ----- So if the developer adds "libMyFramework.a" to "Link Binary With Libraries", the open-source code will have extra functionality 'automatically'. – johngraham Mar 26 '13 at 20:36
  • (1) It's there. Maybe, double click on the log before you search. Or, you can look for it under the details of the "Link" step. (2) I'd go with @Greg_Parker's answer. I didn't know you could do that. Cool. I thought you'd have to have the developer manually define the macro _MY_FRAMEWORK_EXISTS if they've included it. – ma11hew28 Mar 27 '13 at 13:07