The bundle at … contains disallowed file 'Frameworks' - ios

I'm trying to deploy a .dylib library wrapped in a framework, and I'm experiencing the following issue: 'ERROR ITMS-90206: "Invalid Bundle. The bundle at X.app/Frameworks/PoemsRecommender.framework' contains disallowed file 'Frameworks'."
It looks like there's a framework nested in a framework:
Things I tried:
Remove "Frameworks" folder in the "Run Script" phase (it actually helps with submission but the app crashes because it can't find the dylib which is in the Frameworks folder)
Change "Frameworks" to "Shared Frameworks" in "Embed Frameworks"
Disable "Always Embed Swift.."

Reason
The error message indicates that you are trying to package a framework that has its own frameworks embedded inside.
This is not currently supported through traditional framework embedding
The fix is, unfortunately, to link all frameworks separately in your main target.
How do I know?
When you see this error X.app/Frameworks/PoemsRecommender.framework contains disallowed file 'Frameworks'."
Apple is explicitly saying that a framework that embeds a "Frameworks" folder is disallowed. There is a great discussion here that goes into a lot more detail.
Recommended Solution
Package your frameworks separately and link them all manually. Apple has good guidelines here
Not Recommended but will achieve your goal
If you must use a single framework, there is quite a bit of work involved. Effectively you want to create an Umbrella framework that will mask all underlying frameworks. This can get messy if you ever decide to link those sub-frameworks in other parts of your application. Since your question is vague on the details I cannot ascertain if this will affect you.
There are a number of resources that can guide you through the laborious process.
Effectively the steps involve creating an aggregate target that can use a build script to bind all your frameworks at runtime.
I have done this in the past and we ran into lots of issues on the way and I would not recommend this approach. In the past we had a white-labelled SDK that consisted of a number of internal frameworks that were binded by an aggregate target. More often than not it was difficult to maintain and difficult to understand by new team members. Eventually we just migrated to multiple frameworks.
I think Apple has their own tooling to support how they do it but, sadly, it is not available to us peasants.

Related

Make framework compatible for different Xcode versions

I have a specific scenario I am trying to overcome and have yet to find a solution (if one exists) to my problem.
I am building a framework that can be used inside of other applications. This framework contains static libraries.
Now, inside my framework, if I want to add classes that use APIs from Xcode12, I would also want my framework to be able to compile in Xcode11.
This could obviously lead to compilation issues as I have no control of my framework inside other applications and as my framework will already be turned into a binary file (.a). Adding any build script to the frameworks' build phases won't be relevant.
I have been trying to look for similar scenarios or solutions for this problem, but have yet to find anything substantial.
Is there any way to overcome this or am I trying to do something that is impossible?

How to build iOS framework with XCode 6

I know of familiar tutorials on this, but introduction of framework XCode 6 template has changed the game.
I already watched WWDC 2014 video about building modern frameworks but it talks more about building extensions, framework & app all inside single project. It does not specify if the framework I make with it is truly reusable across any project.
I am building framework the XCode 6 way (File->New Project->Framework and Library->Cocoa Touch Framework), but when I import it inside my test app project (separate from framework project) - I keep getting various errors.
Example: Include of non-modular header inside framework, and so on.
I know this is not what it says, and there are quite some missing steps in whatever I am doing. The older tricks may have worked for everyone, but I simply don't find which way to follow after XCode 6.
For example, there is some folder structure that a framework needs, but XCode 6 doesn't comply to it while building it. Is it right? If not, how can I change the way the XCode builds framework folder hierarchy?
Do I go back to old school or am I screwing some tiny thing in XCode 6 that I am unable to create a reusable framework?
I am not sure if you are trying to build a framework with Objective-C or Swift as your question doesn't state it. I've encountered errors you are mentioning with Swift so I'll give you my method to build Swift frameworks.
I found the process for Objective-C to be very straightforward and well documented, so I'll skip this.
As for Swift, there are a few things to consider. First, Swift static libraries are not supported, so you must exclusively use a framework (aka dynamic library) when linking an app to a library.
Here are the steps:
Create the Framework using New > Project under IOS > Framework & Library, select Cocoa Touch Framework
To avoid the "ld: warning: directory not found for option..." goto Library Search Paths in Build Settings for your target and delete the paths.
You can't mix Objective-C with Swift so don't even consider adding the Swift-Header bridge file in your code.
There are some cases in swift where you need to import code from unexposed Frameworks. I've successfully used the module-map inside the framework to deal with these case.
I also select CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES in the Build Settings to solve 'include of non-modular header inside framework module'. That seems to work
I make sure that the header file that gets generated is marked as Public (not Project). Click on the file and you'll see the selection in the inspector under 'Target Membership'
You may run into some bizarre error messages when building. Xcode has a tendency to report linker errors when your code can't compile correctly resulting in missing files the linker needs to output its binaries. Sometimes XCode won't show the errors in the files you are compiling and you need to go manually on the build output and go back to the files. Some other time, you'll get a problem where you need to delete the cache. Those issues I call XCode blues and deal with it constantly. I found this type of problems happens more often when building libraries. The rest should work as expected.

Don't we need to link framework to XCode project anymore?

Base on this question
Why don't iOS framework dependencies need to be explicitly linked to a static library
I read the selected answer and still don't understand so I made an example project
Test Project on Github
In the test project, I remove all framework from Link Binary With Libraries and File navigation for both main project and the static library (including Foundation.framework and UIKit.framework too), basically, both project link to 0 frameworks.
Questions are
In static library, it's including MapKit/MapKit.h without referencing the Mapkit.framework to the project, why is its still working?
In main project, I remove UIKit.framework and Foundation.framework from the project, why is it still working?
Since it's working for now, will there be any issue later?
Thank you for your comment.
P.S. By working, I mean I can run on the simulator and I can archive the main project without any error.
Edit 25/07/2014
I tried with the real app that I'm working on, it's the same.
I highlight Foundation, UIKit, CoreData and 10 another frameworks in File Navigation, well, all of them.
Uncheck the target in Utilities Panel --> Target Membership
Build : Pass, Run : Pass
Every functionality of my app is still working as expected. I don't get this.
Check your project build settings. Underneath LLVM 5.1 — Language — Modules you should see the option 'Link Frameworks Automatically'. In your case it sounds like it's set to 'YES', the default.
In that case, instead of producing an error when you reference a class that the compiler doesn't know, it'll figure out which Framework contains that class and link it. In your code it'll be MKMapView or one of the other MapKit classes that triggers the linkage.
EDIT: from the relevant 'What's New?' document:
Auto Linking is enabled for frameworks imported by code modules. When
a source file includes a header from a framework that supports
modules, the compiler generates extra information in the object file
to automatically link in that framework. The result is that, in most
cases, you will not need to specify a separate list of the frameworks
to link with your target when you use a framework API that supports
modules.
Another way of looking at it is that the compiler is smart enough to mutate #import to #import when the framework has been built appropriately. All system frameworks have been.
To elaborate #Tommy's answer, a framework that supports modules satisfies the following 2 conditions:
Under Build Settings > Packaging
Define Modules is set to YES
Module Map File exists.
So, if you're certain that the framework you're using in your code modularizes like that, you can choose to not explicitly add it in the link phase as it will be automatically added as long as in the project file, under Apple Clang - Language - Modules, The option Link Frameworks Automatically is set to YES.

Creating a distributable framework for iOS Applications

I am currently building a library which should be used internally in a few iOS projects but should also be distributed to customers accessing our services with the library. The Library itself consists purely of C++ code and I am basically able to create Apps with it on iOS which work fine. My problem is creating a single, easily distributable file that can be given out to customers which can easily install them, use the provided headers and don't need to have the headaches that I am currently facing when it comes to linking.
Our code depends on two other projects, namely boost and websocketpp. For boost there is the script on github which I took to generate a framework. For websocketpp, I imported it into XCode and used the scripts from this github project to build a framework. I added both frameworks to my (potential) framework as dependencies and used the same script to build one.
I have an app using my library as a sub-project working fine. Even including the framework into the project and running it on a device works fine. So far so good.
However, trying to create an archive of the App project lead to several questions and headaches.
My library did not seem to contain the code for all architectures. So I tried to archive the Framework projects, which after small modifications in the build scripts to use different locations to search for headers worked fine.
It does not seem to contain all binary code or references to local files (i.e. my specific location of boost). I gathered that from Linker errors that I still get that tell me that some boost calls could not be satisfied.
The second issue made me think that I am must be doing something fundamentally wrong and my intuition tells me that it can't be that difficult and "hackish" to create frameworks or libraries for others for iOS development.
As you probably have found out by now, I am not very experienced when it comes to iOS and I am wondering if I am missing something fundamentally. So, I am sure that this question is rather broad, so some more concrete questsions:
Is there a(nother) way to generate some kind of distributable (preferably a framework) which contains: my public headers, my binary code compiled for all platforms supported for iOS development, the binary code of dependencies?
Is the only way to do that by adding some handwritten scripts to the build process?
I have the feeling that the information I found is quite outdated since it's older than a year and mostly refers to Xcode 4.2 or 4.3 -- so has there anything changed in this regard recently?
For example one error I get is:
File is universal (2 slices) but does not contain a(n) armv7s slice: <file>
The <file> slice is the path to the file in the framework in the Products folder of a different XCode workspace (the library was build in a different workspace then the app). I dropped the framework folder into the project for this test from a completely different location.
What is going on here?
Why does it keep referencing to some internal XCode directory?
How do I properly export it?
Since I guess my setup is probably skrewed up and weird from all the different things I tried up to now: How does this setup look like in a ideal situation?
Yes, there are some questions regarding this on SO already, however, either I don't see or don't understand in those replies:
...how to handle depencies of my code to other third-party code properly.
...how to generate a distributable file.
Have you checked your project build phase under Compile Sources and Copy Files to see if you are including your framework source files in your build?
You may also try the C/C++ Library template under OSX -> Framework & Library.
Finally, there's also kstenerud’s iOS Universal Framework, which I found very useful. I wrote a few articles in my blog on using it.

Check for framework's existence at compile time?

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.
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.
I recommend reading the Mac Developer Library : Framework Programming Guide (which includes a section on Weak Linking).
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.
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.

Resources