I have a C library whose code resides in say /repos1/clib. I build that from the command line using the latest iOS sdk to create clib.a (including a debug build for the simulator) which I copy to an iOS project say in /repos2/proj.
I have been using this setup for several years. The old C library very occasionally might require some debugging and I was pleased by the fact that Xcode simply stepped into the library code that was outside the project (inside repos1) without having to do any setup - it just worked.
But this was up until a few Xcode versions ago. I am not sure exactly when it changed - perhaps when they moved from gcc to llvm? - since I very seldom needed to debug the C code, but for a while now I only get dissasembly when I try to debug the C library from the iOS project (including at least references to the C file name & line number). For the few times I need to debug it is very inconvenient (I create a temp project that includes the C code).
So, any idea why it worked before and doesn't now? Where should I look? Could it be the way I build the C library, maybe there was a flag in gcc I was using that does not have an equivalent in llvm (I can find and post the old build command I was using if it is relevant)? Is the issue in Xcode and there is a way to tell it where to look for the sources?
Thanks!
Edit: To make it clear, I can add the C library either as the source or as a subproject in Xcode, however for reasons that are out of scope this is not helpful for this specific project. So, can it work like it used to with older Xcode versions? If not, it would still be interesting to know why not.
The recommended approach is to create a library project in Xcode, one for iOS (there is a template for it), then when you get that to build add that project to your app, make sure the lib is a dependency and gets linked. There are many tutorials on the web how to do this.
Then as iOS evolves and new architectures (armv7s) arrive you simply update both projects.
I was struggling with the same issue.
I tried resetting in library/application project all options related to symbol stripping and copy application project to same truecrypt drive as library project but it didn't help.
In my case it appeared it was an app project issue. Same library could be debugged in another app project with source code so that was a clue.
I had more than one version of the same library in app project and set only target membership to choose which should be used. Not sure if that could affect my app project somehow.
Nevertheless after deleting all libraries and copying them to app project again I was able to debug libraries with access to source code.
Related
i was making a project using sqlite in swift. I added Sqlite manually to my project like told in this tutorial
This link under Manual method
So it compiled and worked fine with my mac. But when i transferred it to other one and compiled then it said No Such Module.
But again when i manually added the framework to my xcode project in the other computer, it started working. Can you tell me how can i do it like that it does not need to be added again and again.
It took some time but here is the answer:
1. Need to download the file sqlite.swift-master.zip
Downlod from here
2. Unzip it and drag the SQLite.xcodeproj file into your own project.
3. In your target’s General tab, click the + button under Linked Frameworks and Libraries, add the sqlite framework for ios and in the Embedded Binaries the sqlite.framework.
Here is a nice video that helps:
Youtube video
This would be a great use of git for transferring between computers that way you can avoid issues like this and you will have less chance of losing work that started on one computer but forgot to transfer it to other computer.
Best practice would be to commit on major changes in code or if you are not going to be working on the code for an extend time frame. Or when you know that you need to transfer to another computer.
I use bitbucket because it allows unlimited private repositories. If you are going to do a file level copy you should always copy the full folder.
Change your deployment target of your Project and your Target to IOS 11. That should do it. Also, make sure that the swift_version of all your targets is set to Swift 4.
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
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.
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.
I'm working on an iOS app where I use third party libraries. I want to migrate my project to use ARC, but the third party libraries are still using the old memory management. So I want to separate third party code and put it in a separate project without ARC, and then somehow link that project into my iOS-app project, so that they will be built together using the same configuration.
Is this possible to do in a very simple way, or am i better of just turning off ARC for the individual files? (seems very tedious..)
Can I use a workspace? Where one project is my iOS app and the other just contains third party code?
I've played around a bit and googled a lot, but there just doesn't seem to be any simple soultion, or am I wrong?
So I figured it out myself, with a lot of help from different blogs. Something this basic should be more trivial and well documented... But here we go, this is what I did to get a library for AsiHttpRequest:
Create a new iOS project. Select the 'Cocoa Touch Static Library' template. Call it whatever you like. You don't want to tick 'Use automatic reference counting', since AsiHttpRequest does not support it.
Select a location for your library project (will matter later on).
Delete the default .h- and .m-file created by Xcode.
Drag and drop the AsiHttpRequest files into the project
You can add the frameworks that AsiHttpRequest is dependent of, but you will have to add them to your main project anyway, so it is not necessary.
Try to build the project, it should do so without errors.
Open your main project
From finder, drag your library .proj-file into your main project (in Xcode, so that it 'lands' onto the main project file)
The library project should now appear under your main project (still in XCode). It should be expandable and you should be able to see the library project files as well. If it doesn't, try closing all open projects and reopen the main project.
Select the main project, and select target. Under Build Phases - Link Binary With Libraries, click the +-sign.
In the list of frameworks you should see your library project (called something like libname.a). Select that file
The newly added file might appear red in the list of frameworks, don't worry, it works anyway. Guess it's a bug.
Still under target, go to Build Settings
Under Header Search Paths add the relative search path to where the library .h-files are. This is relative to your main projects .proj-file. (For example ../some folder/libproject/)
Hopefully your main project will build without errors and the library project will be built at the same time, using the same configuration as the main project.
I have no idea if this is a good approach or if there is some easier way to do it. However, I like this, since I can use the library project in several projects. And if I want to update the library project, I only have to do it in one place, and the other projects will be updated as well, since they all reference the same project.
Edit1:
I had some problems with library projects using objective c categories. I received unrecognized selector sent to instance errors in runtime when trying to call those methods. This problem was solved by following the answer given here.
Go to build settings of the target in the main project and add -ObjC to the entry called Other Linker Flags
Edit2:
I found this template for creating Universal frameworks. I haven't tried it, but I guess something like this would work as well.