4

I'm currently working on a project that has a class referencing the Security.h framework. Since this is a reusable class, and might be used in multiple projects, I wish to add a compile time check to check whether the Security framework has been added to the project or not. What I mean by added to the project is whether it has been added in the Link Binary With Libraries build phases for the current target.

Now, I know that questions with similar titles have been asked multiple times, and this particular question seemed to be super close to what I'm looking for, but I did not find an answer there either.

I've been using:

#ifdef __SENTINEL_VALUE_
..conditional code here..
#endif

code, but this only works if the framework header declares the sentinel value in the main header. Let me provide two examples to compare and contrast:

SystemConfiguration.framework has a framework header SystemConfiguration.h which includes all the sub headers, but also declares its own sentinel value, namely _SYSTEMCONFIGURATION_H

Thus, checking it using #ifdef _SYSTEMCONFIGURATION_H works perfectly. However, for Security.framework, the framework header, Security.h does not declare its own sentinel value. Each of its sub headers declare their own sentinel value, but since they are being imported in Security.h, the sentinel value gets defined. Therefore, even if Security.framework is not included in the project (not linked in the build phases), an #ifndef for one of its sub headers returns a false value, since the sentinel value is defined owing to its import in the Security.h file (not to mention that this approach of checking for a sub header of a framework header makes me feel a little sad).

So, my question is: For a unique case like Security.framework, what would be the appropriate compile time check to check whether the framework has been added to the Link Binary With Libraries phase (if such a check exists).

Additionally, I know of the NSClassFromString() method and the NS_CLASS_AVAILABLE macros, but I'm not looking for a run-time solution.

Thanks in advance all!

Cheers!

Community
  • 1
  • 1
codeBearer
  • 5,114
  • 4
  • 25
  • 29
  • Have you tried Product>Generate Output>Preprocessed File in xCode? – trueinViso Jul 19 '13 at 17:19
  • I have not tried it, but how will that help me with respect to a compile time check? – codeBearer Jul 19 '13 at 17:21
  • It shows you what the compiler is seeing. You can see if what you want declared is being declared in this file. Not sure if it will answer your question, but thought I'd suggest it. – trueinViso Jul 19 '13 at 17:26

2 Answers2

2

The link phase follows the compile phase, so there is no way the compiler can tell whether a framework will be linked to the project.

If your project's product is a framework, dynamic library or an executable, you just link your binary against the Security framework, and you are fine.

If your project's product is a static library, you need to confirm that the project which produces the final executable binary will link against the Security framework. The recommended way is to provide an install and usage documentation, and possibly a sample.

CouchDeveloper
  • 18,174
  • 3
  • 45
  • 67
  • Thanks for your reply. Yep, I'm aware of the fact that the linking phase comes in after the compile phase. My question is more towards whether the framework is included, and whether there's a directive to definitively check whether a symbol is defined or not. – codeBearer Jul 19 '13 at 18:54
  • Testing whether a symbol from the library is defined isn't reliable, since you could #include/#import the public headers, though a client may not link against the framework. This would result in undefined symbol errors when the final executable will be build. On the other hand, if you use any symbol in your library sources, you know that you include the header anyway, otherwise you would get compile errors. – CouchDeveloper Jul 20 '13 at 04:49
0

This might be a little too late, but for future references for whoever encounters this kind of problem try this

BOOL isFrameworkLoaded = (NSClassFromString(@"MyClassNameFromTheFramework") != nil);

Can't take the credit, here's a link to the original post

https://stackoverflow.com/a/7333589/4160199

Community
  • 1
  • 1
quant24
  • 393
  • 6
  • 22