Not possible to create a framework with no executable code? - objective-c

Just stumbled into something strange with Xcode 4 and Cocoa frameworks. I've a meta-framework that is essentially a .h file with constants needed by a number of other frameworks I've created. I'm capable of creating and building the framework but every time I try to include it in a project Xcode would throw a hissy fit during the build phase, saying it couldn't find the framework, even though the .framework folder was there and the .h file was set to be publicly visible.
After many a hours of running in circles I decided to throw in a .m and corresponding .h files, just so I could have something binary in there and now Xcode is happy as Larry.
Can someone explain this behaviour to me? Why do I need a useless executable to make Xcode see my framework?

The hissy fit is presumably coming from the linker. (Always post your error messages! Guessing isn’t that much fun.) As far as the linker is concerned, the binary is the framework. If you just want the header, you can include the framework in your search paths and #include the header without linking to the framework.

Related

Objective-C header file not found (AFNetworking.h) [duplicate]

This question already has answers here:
AFNetworking.h file not found
(5 answers)
Closed 1 year ago.
#import <AFNetworking/AFNetworking.h>
I imported AFNetworking.h file to .m file but an error occurred like this:
'AFNetworking/AFNetworking.h' file not found
I deleted pods folder and Podfile.lock, and reinstalled Podfile but didn't solved. What should I do? (I opened the workspace file.)
Linking !== Copying.
there is C style #include ... and Objective-C style #import ...
both work almost the same..
where #import reads the header but does not include again if done once. As this can and does fail sometime (usually because mixing C,C++,Objc,Objc++ in different dialects) we often use #define rules to make sure the enclosed code is read once for sure and not again, which in turn works also when code is included and declared with #include. It would be included but not compiled twice.
#ifndef SOME_HumanReadableFlag_h
#define SOME_HumanReadableFlag_h
// ... your header code here..
#interface XyzObject : FromInheritedClass
#end
#endif
Now why does it matter?
It might happen that a #define rule enclosing the header files content hides the header from the viewpoint of other classes.. This can & does happen often when classes are not properly written with the end developers structure in mind. It might work on the workbench of the developer but not for everyone else implementing it.
Your error clearly tells "File not found .."
So first see what both import/include rules differentiate in general
#import <LibFrameworkName/LibFrameworkName.h>
means you have to link the framework or library, even if you developed one on your own in that project. The rule is relative to your project, LibFrameworkName is a Framework/Lib. Where if found somewhere #include <LibFrameworkName/LibFrameworkName.h> is not correct unless you want to c-style include this framework header into your binarys header, 2) tells you a bit about why..
#import "LibFrameworkName/LibFrameworkName.h"
means you have to copy/offer this header into your project with a subfolder with name LibFrameworkName. Once somewhere declared properly Xcode might find and apply the headers even if declared with the wrong rule later on in that specific class, you should also get a warning in the IDE then. In case of AFNetworking you dont want to copy System SDK Frameworks into your project, also not into third party frameworks unless you know what you do. This rule is relative to the files place in project structure, meaning here it would try to look out for some folder with name LibFrameworkName below the file that carries this rule.
what it says: because the Framework is not linked, the compiler tries to find it with the given name ignoring < & > so as if it where like 2) a file with that folder name, then will not find it and throws the error or warning.
To force the precompiler to parse thru some specific folders we use sometime the header search path to explicit tell where to find it. Widely used and mostly troublesome because it also hides wrongly defined rules to the developer as Xcode skips the still existing wrong import rules in code assuming it knows this headers already. Or it throws warnings while everything is actually fine. Other developers experience trouble then, the file structure and header list don't match at all. So keep in mind, when you can avoid making use of header search path lists, go for it. It also will and should not fix your issue.
'<AFNetworking/AFNetworking.h>' File not found means a Framework module is not known to your project. This header is part of a Framework.
Solution: You have to go to your Projects Settings and scroll down to Frameworks and Libraries, hit [+] below this list. It should open the dialog presenting all SDK from your choosen Project Target and all known Pods or known frameworks of your own project when you developed some. Search for the Framework or Lib by name, click it, hit "Add".. done..
From there - there are some options to get used to it..
Because Linking does not mean Copying into your Resources at compile time by default. Usually Xcode knows it does not have to copy System SDK into a projects Framework Folder, all macUsers have those Frameworks preinstalled on their system of course in the right version.. Linking against some specific folder like ${SOMEFLAGWHEREEVERTHISPOINTSTO}/AFNetworking/AFNetworking.framework/Headers is actually wrong unless someone wanted to overrule the systems framework header and maybe also binary.
So AFNetworking should not appear under Build Phases > Copy Bundle Ressources list but after the process above is done it will appear under Link Binary with Libraries, it might also be placed in Dependencies when Xcode needs to know for some Library/Framework it must have this to compile. Last mentioned option is because you could have a framework that adapts at runtime when some framework is missing or not available. So this Entry helps Xcode to figure out in which sorting it has to compile your stuff.
finding ${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking/AFNetworking.framework/Headers in Header Search Paths there must be something wrong i guess.. because the framework is very likely not copied into the Pods folder. It should be relative to your SDKs folder that come with Xcode. The Linking process told above should fix that and you can erase that entry from your header search path then.

Where is the implementation of a framework or library added to an Xcode project?

When I add a framework to a project, using Cocoapods or manually, they contain only header files. From Xcode, using "Jump to definition" there is no definition (that means that there are no .m files).
When a function in a library is called, how does the compiler get its implementation if the .m file is not in the project?
To put it in a somewhat simplistic way, building an executable usually goes through at least these two stages:
compiling, which turns source code into binary code;
linking, which "glues" chunks of binary code into an executable.
Frameworks may include implementations in binary form, already compiled. These are then linked with your compiled sources. The compiler does not touch them in any way, and only needs the .h files that describe them. It's the linker's job to stitch them together with your code.
If you'd like to know more on the subject, the answers to the following questions contain more detailed information:
How does the compilation/linking process work? (The question is about C++, but C and Objective C go through mostly the same process)
What is compiler, linker, loader?

iOS Framework With Swift and Objective-C Where the Objective-C Uses Swift C

I have a framework building where it combines both Objective-C and Swift. My issue is that some of the Objective-C code within the framework needs to use some of the Swift classes in the framework. In order to do this, I do:
#import "FrameworkName-Swift.h"
in my Objective-C code in the framework. And here the first problem arises. The -Swift.h header is not located by Xcode this way. Digging around in the Derived Data, it turns out the -Swift.h file is located in the Framework/Headers folder, which in of itself seems odd. Should the -Swift.h file really be an exposed header for the framework? The -Swift.h file is an intermediary .h file, right?
To work around this issue of not locating the -Swift.h, I tried:
#import <FrameworkName/FrameworkName-Swift.h>
BUT, while now locating the -Swift.h file, this causes a severe and compilation-fatal rash of cyclic dependencies in Xcode, with messages like:
Cyclic dependency in module 'FrameworkName'
Could not build module 'UIKit'
Here's what those look like in-situ:
Thoughts?
I have an incomplete answer to this, which is more of a partial explanation and a workaround that works for me. Here's what I think is causing the issue.
While Apple let's you call Swift code that is in the framework, from your Objective-C in the framework, if the same Objective-C class also needs to be used from Swift you run into an include/import cycle. Here's the situation I have.
Call my Objective-C class Objc with files Objc.m and Objc.h
Now, since Objc has to use Swift code it needs an import something like this:
#import <FrameworkName/FrameworkName-Swift.h>
which in my case goes in the Objc.m file.
And since the Swift code needs to use the Objc class, you need the following in the Framework umbrella .h file (the umbrella .h file is named FrameworkName.h):
#import <FrameworkName/Objc.h>
Now, if you take a look at the FrameworkName-Swift.h file that is generated by Xcode (Xcode 7.0.1 in my case), you find that it has an import of #import <FrameworkName/FrameworkName.h>, which forms a cycle back to Objc.m.
My workaround for this was no more than a situation specific hack. It turns out that in my case Objc.m didn't critically need the Swift code. It just made the code look nicer and better engineered. So, with a comment and a couple of extra lines of (Objective-C) code in Objc.m, I worked around my issue.
Very insidiously, Xcode 7 (at least) is really resistant to getting out of this issue once you are in it. That is, when you get this cyclic dependency error, it can be very difficult to have Xcode stop telling you you have it, even if you have taken the cyclic dependency out of the code. I tried many things including removing all of the Derived Data files/folders, quitting Xcode, and restarting my Mac, and found nothing that worked consistently to have Xcode stop believing it had a cyclic dependency even though I'd fixed the issue.
This resulted in the more difficult fix. I had to effectively rebuild my Framework from scratch, every step along the way building and saving to my version control system so I'd be darn sure I could recover if Xcode started being convinced I had one of these cyclic dependencies. Makes me have even less faith in Xcode. :(.
Second fix: A workaround (10/9/15)
I've found a fix that works in some other cases:
1) Clean/remove your Xcode Derived Data, including the ModuleCache
2) Build a known working copy of your Xcode project (in my case, I had a revision before I started adding the framework)
3) Now, go back to your Xcode project with the framework included and attempt a build. For me, this now works.
This is strictly a work-around, and resolves a cyclic dependency issue that appears in somewhat different framework conditions for me than I described in the present question. I'm talking to Apple engineer right now about this issue, so will see if I can get a better fix. I'd rather not have to apply this workaround.
"Final Solution": Namespace pollution (10/22/15)
I have figured out what was going on!! It was a case of include file name space pollution. I had an Objective-C class named "Assert" (note the upper case "A"), with files Assert.h and Assert.m. I have been using this Objective-C class (part of my internal debugging) for quite a while. At least a year if not more, to no apparent problem with Xcode. Now, when I started using it in conjunction with a Cocoa Touch Framework of my own construction, a problem came up. It turns out that if I cleaned the Derived Data first, that the /usr/include/assert.h file was being picked up, and not my own Assert.h
Really odd.
And, if the Derived Data was not cleaned and I'd built a non-framework version of my project first (for the specific platform, e.g., for my iPhone if I was building for that), then my own Assert.h would get picked up.
My fix was pretty simple-- took about 10 minutes. I changed the name of my file/class to SMAssert with files SMAssert.h/.m. And then changed the references to the file in the various places that imported it. Voila!

xcode import filename collision

Let's say I'm trying to use one and only one 3rd-party library in an xcode project - a pretty typical scenario, seemingly harmless.
I plug in the path location of my include files to the project's "header file search path" setting. I haven't even modified any code to make use of the code in the library yet.
It turns out that the project couldn't compile.
Xcode complained something like "Cannot find interface declaration for NSObject", which is pretty absurd. By examining the Build Result, the complained error comes from a header file of the 3rd-party library - it looks something like
So it is indicated in the Build Result that xcode is mistaken that Foundation.h is referring to the assert.h of that 3rd-party library instead of the iOS' built-in assert.h (4th sub-item)
Is there a way to fix the collision of the file names of #import include files?
(Needless to say, I'm new to obj-c -___-)

Adding GLM to project in Xcode 4

I am trying to add GLM to a project in Xcode 4, but I cannot get it to compile. I have added the glm files to my project through the add files dialog.
I get a lexical/preprocessor issue and Xcode cannot find the file <cmath>.
I am not sure what I need to tweak to get this to build.
I have seen How do I add OpenGL Mathematics (GLM) to Xcode 4? already.
All you need to do is add the files to the project and #import "glm.hpp" (for Objective-C++; for simple C++ it should just be #include "glm.hpp").
A couple things to be careful of:
The OpenGL Mathematics library, when you download it, comes with a bunch of stuff you don't need (test code, extraneous utilities). Adding these to your project will result in compile errors which I could not get rid of. The only directory you need is the glm/ directory; you can delete the test/, util/, doc/, and bench/ directories. If you were trying to follow "How do I add OpenGL Mathematics (GLM) to Xcode 4?" and were still having problems, this may be the thing which was tripping you up.
The OpenGL Mathematics documentation tells you to include the or files. In Xcode 4, you should include them like "glm.hpp" or "*.hpp". Xcode will find the files no matter where in the project they are. Supposedly you can add a user-defined build setting "USE_HEADERMAP" and set it to "NO" to disable this, but I didn't have any luck with that.
And, just in case, note that your code files using the OpenGL Mathematics library must be Objective C++ files (ending in ".mm"), not the default/plain Objective C files (ending in ".m"). It is very much a C++ library after all... :-)
I hope that help. I was just working through this myself, and I haven't had the chance to really push this (e.g. I've basically just added a mat4 object or two and made sure things still compiled), but it seems to be working.
I ran into the same problem and I solved it remaning my ViewController.m to ViewController.mm. Change the extension to .mm tells XCode that the file may contain C++ code inside. The article Write Object-C Code explains this in the Classes and Objects section.