Xcode 13 warning for .swiftsourceinfo - ios

I'm developing a framework for iOS, it mixes Swift and Objective-C inside, distributed in binary form without source code.
Since Xcode 13, I observe a warning when importing this framework:
'MyFramework.framework/Modules/MyFramework.swiftmodule/Project/arm64-apple-ios.swiftsourceinfo'
is either malformed or generated by a different Swift version. Note
that it uses an unstable format and may leak internal project details,
it should not be distributed alongside modules
It seems it doesn't like .swiftsourceinfo file. Maybe I should just manually remove this file from the package, but I cannot find any explanation of what it is made for.
Even when I set BUILD_LIBRARY_FOR_DISTRIBUTION=YES, Xcode builds the framework with that .swiftsourceinfo file. So why does the warning say "it should not be distributed alongside modules"?
What is the purpose of .swiftsourceinfo file? Can I safely remove it from the built framework?

How are you building your binary frameworks?
Generally, .swiftsourceinfo are not stable across different versions of Swift Compiler so shouldn't be included when distributing the framework (especially when BUILD_LIBRARY_FOR_DISTRIBUTION=YES). So they shouldn't be included in the .framework package. If you build your framework using xcodebuild archive it should not generate .swiftsourceinfo

Related

How do I build native C source code to create a library for Unity, to be used for iOs Platform?

I want to import a library from native C source code to be used Unity, for iOs. I expect to require the .a binaries and the .h header (and any other file required if I'm missing any), but I cannot find any guide around about how to build it.
I tried to build the source code directly on Xcode, but I was not able to create a library from that. XCode accepts native C only with command line project, while I need a library.
Then I tried to run this CMake command on mac terminal:
cmake . -DCMAKE_SYSTEM_NAME=iOS "-DCMAKE_OSX_ARCHITECTURES=arm64;arm64e" -DCMAKE_OSX_DEPLOYMENT_TARGET=9.3 -DENET_STATIC=1 -DENET_LZ4=1 -GXcode
This creates an Xcode project, I build it for generic IOS but the code does not work on unity when I deploy it on the device.
A good place to start is the Bonjour example from the Unity Manual. This at least gives you a working iOS plugin as a starting point.
You include the files in your Unity project, and build for iOS. You will notice that the files under Plugins/iOS are automatically included in the generated Xcode project. They will only be compiled when you build/run your Xcode project.
Careful, an iOS plugin is not the same as a MacOS plugin. For a MacOS plugin, you will need to create the bundle and include this into your UnityProject. The DllImport decorator will also be different on your C# code. For iOS it is "__Internal", but for MacOS it is the name of the bundle.
If you are trying to interface with a third party library, you may need to manually modify the library search paths of your Xcode project to correctly locate your .a and .h files when building and linking.
As a side note, when including a third party .a binary, verify that it conforms to the iOS architecture requirements, otherwise your app may be rejected when submitting to the app-store.

Can I make iOS all-in-one framework? or include private static library into my framework?

I'm a novice on XCode and I'm making an iOS Framework with Swift2, including 3rd party libraries(*.a) and frameworks.
I want to provide it as API to others, but I also want to hide the 3rd party libs and frameworks files from my framework distribution files because they are private.
Therefore I just want to open API interfaces and classes I defined.
Is it possible? How to configure my build options?
You can do that but there are some things you need to consider:
You cannot embed one framework into another one. That means if you do not have the sources to a particular framework you have to ship it alongside your own framework. If you have the sources you may consider compiling them into your framework directly.
Depending on the sources that you use in the framework you might have to do some post processing of the framework to obfuscate private headers etc. For example, if you use Objective-C or C code alongside Swift you definitely need to do some post processing of your *.framework file to hide any API that you want to keep private.
If you use Swift code in your framework please be aware that your framework can only be used by someone with the same Swift compiler version due to the absence of an ABI. That means binaries produced by one compiler version have a high likelihood of being incompatible to a newer version of the compiler.
Static linked libraries can be linked and therefore "merged" into your framework binary directly. You just need to make sure that you have a compatible binary for the architecture you want to target, e.g., you cannot use a static linked library that was build for simulator and link it against your framework that you want to build for the actual iOS device.
If you use Swift in your framework, the users of your framework need to include the Swift dylib libraries in their app bundle - either by using Swift in the app or by enabling the Embedded Content Contains Swift Code build setting.

Embedding frameworks inside closed-source Swift framework

Our company wants to distribute a closed-source SDK for iOS to our clients. I've been using Cocoapods to build the framework and built an example app making use of it. Previously the app worked fine on the simulator as well as when deployed on the device. However, I was also embedding the Pods.framework file in the app itself. One other piece of information that may be of interest is that the framework is written in Swift, the included cocoapods dependencies are both Swift and Objective-C.
I wanted to make the pods requirements easier to manage so the user doesn't need to be concerned with them and tried to embed the Pods.framework file inside of the SDK we're building - so I removed the steps to Embed Pods Frameworks and Copy Pods Resources from the example app, leaving them only in the framework, I also removed Pods.framework as a dependency of the example app, leaving it only in the SDK. This seemed to work in the simulator, but the app now crashes on mobile device with dyld: Library not loaded error.
Upon researching it, I stumbled into a few related discussions:
https://github.com/CocoaPods/CocoaPods/issues/344 https://objectpartners.com/2014/06/25/developing-private-in-house-libraries-with-cocoapods/
However, the suggested solution of using private pods does not look like it would work for us, it's my understanding that the source code in the private pod would still be open, and we can't share it with our clients.
Could someone advise on a solution that would work in this case?
OK, I finally have a more durable solution. It's a modified, cleaner version of my old one now that I understand how Xcode links in my Swift sub-frameworks better
Problem that makes distribution/compilation a bit ugly:
Since Swift standard libraries aren't bundled on the device like Obj-C, nor are they guaranteed to be stable between versions yet (stable binary interface promised in Swift 3: https://github.com/apple/swift-evolution#development-major-version--swift-30) we have to make sure the entire project is compiled against the same version of Swift. That means the guy using your closed-source framework has to be using the same version of Swift in their Xcode for their project as you did for compiling the library, even if he's not using Swift in his code because ultimately it's his version of Swift that gets bundled into the app and your SDK runs against. This is only an issue for closed-source frameworks because open-source ones will always be compiled against the same version as final project. Possible workaround is to restrict clients to same version you use or distribute multiple compilations (i.e. Swift 2.1 and Swift 2.0). To remedy this, you could provide users with copies of binaries compiled against multiple versions of Swift.
Aside from that, here is what I had to do during compilation/distribution to make a binary framework that works in Swift:
When building the framework:
In project target, make sure to add Pods.framework to Linked Frameworks and Libraries (make sure this is a pre-compiled RED version of Pods.framework, I had a black compiled Pods.framework in the same directory which built fine but then resulted in a framework that would cause the project to complain about missing armv7 architecture during linker phase in later project)
In Build Settings, under User-Defined section, add a field called BITCODE_GENERATION_MODE and set it to bitcode
DO NOT #import any frameworks in your bridging header, all instructions telling you to do that are leftover from Swift 1.0-1.2 days, you don't need it anymore and it does more harm than good (the later project will complain that it can't find these headers that aren't even exposed to it)
Change build target to Generic iOS Device, Archive and Export the framework
When building the project using the framework:
Drag and drop the framework into the project, in General tab add it to Embedded Binaries and Linked Frameworks and Libraries (you only need to add the framework itself, not the sub-frameworks or the pods file)
In Build Settings tab, add a new path to Framework Search Paths: $(PROJECT_DIR)/MyFramework.framework/Frameworks
Build the project

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.

iOS Static vs Dynamic frameworks clarifications

I have to admit that with the release of iOS 8 I am a bit confused about dynamic and static frameworks in iOS.
I am looking for a way to distribute a library that I created, and I need to support iOS 7 and above. (Note: This will be a proprietary framework. I cannot use cocoa pods, and I also cannot distribute the source). Here is what I already know:
iOS 8 introduced "embedded frameworks" for iOS, but, as I understand, they do not work for iOS 7, only for iOS 8 and above.
I have the option of distributing my library as a static library (.a file) and also distribute the headers. I know that this is a common way of dealing with the situation, but I would like to find something simpler than that (and also to bundle some resources with it, if possible).
I have also found that iOS 7 does not support dynamic .framework libraries (only static) because it doesn't support dynamic linking. But iOS 8 does, as well as static linking.
And here are my questions regarding this information:
I saw that I can create a .framework target, and make it static, by changing the Mach-O type to "static library. Would that be enough in order to support iOS 7 without any problems, and also to distribute my library as a .framework bundle? If so, why is "embedded frameworks" in iOS 8 that big of a deal, as many resources on the internet are suggesting? Am I missing something?
Is it necessary to codesign the .framework just as I do with any other application I make?
What if I need to include other resources (like Core Data or Images) with my .framework file? Will I need to make a separate .bundle file for that?
Before iOS8, Xcode only allowed the option of creating static libraries for iOS. The common problem with that was we had to ship the binary and headers separately.
Later, some developers came with the idea of creating 'static frameworks'. [the .framework is just a folder with symbolic links to the lib and the headers]. One such example is https://github.com/jverkoey/iOS-Framework
This option will work for iOS 7 or 8 or before that. Because they are just static libraries with the convenience of bundling the headers files along.
As for your questions of the resources, we would need to bundle them in '.bundle'.. For shipping them i am not sure if we can enclose them in the .framework folder.. In the past i used to ship my libs as a static framework and bundle...
However the above option will not work for you if you use Swift. Xcode does not support building static libraries that include swift code.
You must go with Dynamic frameworks if there is swift usage. In theory, Dynamic frameworks work in iOS7.. But, i think iTunes Connect will reject if the app is targeting iOS7 and uses Dynamic frameworks :-).
Hope this helps
Static vs Dynamic linking
static or dynamic in name usually points into a Linking[About] type
Frameworks can be static or dynamic[Check static or dynamic]
You can change the format of library that will have an impact on a Linker by changing Framework target -> Build Settings -> Mach-O Type[About] to Static Library or Dynamic Library. By default Xcode has Dynamic Library value.
Depends on this setting different types of binary will be generated
After you successfully configure a consumer[Link vs Embed]
Static Linker ld: at compile time will include all code from the static library into the executable object file.
Dynamic Linker dyld: at load/run time will try to find the embedded framework using #rpath[About] and link it
[Vocabulary]
With Xcode 9 onwards you can create static frameworks for Swift as well. This is possible due to ABI source compatibility. All you need to do is just change the Mach-O type under build settings of the framework target.
This technique is also applicable to Hybrid Frameworks(frameworks with Swift and Objective-C code).
I don't have all the answers but I'll try to address some of your questions here.
You will get a warning for using these frameworks in iOS 7, however that's all it is, a warning. See this answer.
You can include other resources like CoreData however you'll need to create them in code manually. Here's a tutorial showing how to create a core data model.
You have to code sign dynamic libraries for iOS.
You need to make sure your framework supports both simulator and device architectures if you're planning to distribute it.
Swift does not work in static lib. If you have to use dynamic framework, you have to set min iOS to 8.0 because AppStore reject ios 7 with dynamic framework

Resources