Make static library for iOS with existing C code in Xcode - ios

Short version of the question:
So basically what I'm looking to do is to take an existing library written in C (https://github.com/lsalzman/enet) and turn it into a static library for iOS.
I am just looking for an easy to understand step by step of how to accomplish this in Xcode.
Long version:
I've gone over some tutorials for making a simple static library that's written in Objective-C (http://www.raywenderlich.com/41377/creating-a-static-library-in-ios-tutorial), and I generally understand what is happening there, but I'm failing to understand how to do this with existing code written in C.
I think I'm getting close, but I'm not so sure.
I start out by making a "Cocoa Touch Static Library" project in xcode.
I add all of the enet .h and .c files
make sure the enet stuff is in my "User Header Search Paths" in build settings.
hit build - it compiles!
The generated .a file is 517kb, so I'm pretty sure it's building the enet stuff in at this point.
My problem right now though is that the header file for the library is basically empty:
#import <Foundation/Foundation.h>
#interface enet_ios : NSObject
#end
I'm thinking I either need to write a wrapper in Objective-C that talks to the enet library, or I need to reconfigure my xcode project somehow so that enet.h is the 'entry point' into this library and not xcode's pre-generated .h/.m files. I'm not really sure how to do that, though. Ideally I'd just like to skip any sort of wrapper and use what the enet library is already providing me.
Thanks for taking a look!

Question, are you trying to call the functions using objective c syntax / object orient notation? Then you do need a wrapper object, no way around that.
But if you are fine calling C functions directly, which is completely acceptable in IOS/Objective C, then it is a matter of making sure your header files from the enet library (the ones in the include directory I see in the github link you shared) are also distributed with the static library. This is a limitation of the static library. You can copy them with the *.a, but they must be copied with the static library. This does differ from a Framework, which has included .H and assets, which developers are not easily able to create with Apple's tools for IOS.
I find that library management with Objective C to be painful on its own and static libraries a challenge for this and many other reasons. One more suggestion, definitely more elegant and portable but slightly overkill for personal use, would be building the project as a cocoapod. You can do this by forking the project and converting it to cocopods. There are lots of examples of how the project structure should look on cocopods and other OSS like AFNetworking. This seems to be the defacto standard way people are creating IOS libraries. See http://cocoapods.org/ for more details. This will include the source code as the pod and compiled against the target application.
This is the only way i deal with my own libraries and third party libraries. It has gotten to the point that if the library doesn't use cocoapods, i don't use the library or fork it and do make it a pod myself....

Related

How to combine fat static libraries for use in an iOS application?

I got very confused when reading about static libraries and dynamic libraries and then finally about frameworks, Cocoa Touch Frameworks and Cocoa Touch Static Libraries.
The only thing I understood is that static libraries (frameworks?) are added at compile time, whereas dynamic libraries aren't; they're loaded dynamically during runtime.
Q:
I'd like to add several static libraries (they end with ".a", universal fat binaries, compiled for a bunch of iOS architectures such like armv7 and arm64) to my iOS application. Preferably, if possible, that'd be done by combining all of those libraries together (...to a framework?).
I also want to write a Swift wrapper around those C libraries. This wrapper shall finally be used in my application. However, the wrapper shall not be part of my app, I want a separate project (again, a framework?) for that (can the libraries and the wrapper be combined together?).
What I'm currently trying to do is to write the Swift wrapper.
So I've started with a Cocoa Touch Framework (because I thought that would be the best idea), added the C libraries and headers (actually via a podspec, I don't think that matters though as I could also add them manually), added a bridging header (although some other users reported frameworks don't work with bridging headers, mine does build successfully). Is this the correct way to go?
The first article I read was this one (called "Static and Dynamic Libraries and Frameworks in iOS").
Then, I read lots of articles on stackoverflow about how to compile static libraries, how libraries & frameworks are structured, that frameworks are really just a bundle of libraries and their headers (or so).
I also feel like things have changed over the years at Apple, like they changed the names and possibilities (the Cocoa Touch Framework (is that a dynamic framework?) seems to have been introduced on the release of iOS 8 etc.), which made it even more difficult for me to understand how things work.
Don't get me wrong, I'm just saying this because I want to make clear that I have indeed done some research (quite a lot I think), but I really need some help to get everything right. Basically, I'm just looking for the next step I should take in order to import all those libraries to my app.
There two parts to this:
Creating the framework Mach-O image
Sorting out the headers
The first part should be relatively straightforward. If you create a framework target and add a bunch of static libraries to it, the resulting framework will include all of those static libraries.
The only complication is Objective-C. If any of your static libraries contain Objective-C code, the linker may end up stripping that out. There’s a linker flag, -ObjC, that disables this.
Sorting out the headers is a bit more challenging. Frameworks have their own view of how headers should be organised, and this generally doesn’t line up well with UNIX traditions (which is what you seem to have). The critical question is how your client code uses these headers. If the client code does stuff like:
#include <lib_1/----1.h>
you have to preserve that layout on disk, and there’s no obvious way to do that when working with a framework. OTOH, if you have control over the client code, and can change it to just do this:
#include <MyFramework/MyFramework.h>
you could create an umbrella header in your framework, have it include all of your public headers, and away you go.
This answer was copied from the Apple Developer Forums.

I would like to use a UNIX command-line program (Berkeleys SPICE) in an iOS app. What is the process to compile it into a usable library?

I am trying to use Berkeley's SPICE tool in an iOS app, but am having trouble compiling it for iOS.
It is a command-line program that I can call from a terminal like:
./spice3f5 <arguments>
Which works well, and I would like this functionality in my iOS app, but I don't think I can just copy the executable over to Xcode and call it from Swift.
I've done some research and found the following:
There is an updated version of SPICE called ngspice, which is relatively new (2014 release)
I'm fairly sure there are apps out there than have used either SPICE or ngspice, so I'm sure it can be done somehow.
I have read an article about a guy who says that ngspice has been compiled as a shared library(ctrl+f "ngspice"), and he made an app with it. I have emailed him but he unfortunately he has not responded.
The reason I am asking here is because when googling for "ngspice iOS", I came across this thread which has a lot of smart people trying to compile a static library, which seems way out of my scope. I learned that dynamic libraries are allowed as of iOS8. So would it be easier to compile a *.dylib than it is a static library?
How would I goabout using ngspice or SPICE in an iOS app?
Thanks
The difference between a static and a dynamic library is essentially where they live, a static library will live inside the binary of your app, and an dynamic library will live on the system (iPhone) that runs your app. there isn't much difference as far as difficulty goes. If you wanted to go the dynamic route on os x for example, you might compile a .dylib file in a separate project first. Then copy your new .dylib file into /usr/lib or a similar location that is part of your system's path. Then you would need to copy the associated header files that know how to talk to your new .dylib file into your /usr/include folder. At this point you could import said header files in xcode using angle brackets like so:
#import <my_dylib_header_file.h>
in static world however, you would simply drag your .dylib file into xcode then copy the associated header files into your source folder and then import using quotes like so:
#import "my_dylib_header_file.h"
the advantage of doing the import statically is that the library becomes baked into your final product, as opposed to a dynamic link, which will require that the dylib is installed on the system prior to the binary being able to run properly (think DLL's on windows). The disadvantage of a static import is that the final binary is larger, as it contains more code.
The advantage of a dynamic import is that the binary is smaller, and dylib can be updated without updating the binary itself.
However based on your questions I don't think any of this matters for your project. You have the source code. Which means creating a dylib is entirely unnecessary for your purpose, you can treat the source code like a static library by simply adding it to your xcode project. If I were you I would add the spice source code to my xcode project and forget about creating a dylib. From there I would import the files and make calls to them from swift. There are lots of threads out there that explain how call c functions or objective-c classes from swift so I wont go into that here, instead I'll refer you to another answer: Swift: How to call a C function loaded from a dylib

iOS: Can i create a static library with all classes (.h & .m) as public?

I have a bunch of classes that i want to share with others so i thought of creating a static library but i don't want to hide my code. I want to allow them to put change in the library if they want to.
I can share a folder of files but i want to merge all the files into a single package so it's easy to manage and maintain.
Static library generally shows only header (.h) files to users but is it possible to make implementation (.m) files also visible?
I've one more static library which is a dependency for this one. Can i put one static library inside another? or i have to add both files in my project?
I didn't do this library stuff before so am i going in a right direction? or is there any more appropriate way in iOS that can fulfil my requirement?
Thanks!
Ship the code as a framework and instead of sharing a folder, turn the library into a regular project on GitHub or anywhere else. Add what’s needed to install the library through CocoaPods or Carthage. Make proper releases with semantic versioning, write a proper Changelog.
It’s a lot of stuff to go through for the first time, but it’s a good practice that will pay off. See my simple goo.gl client for an example of such library.

iOS Framework build: what is the best practice to link with third-party libraries?

I'm build a Framework for iOS and my framework has AFNetworking as dependency.
So what is the best practice to include AFNetworing? Reading other posts (specially this question here) i came up with three options:
Copy all the .h.m files from AFNetworing in to my project and compile my framework with it. But according to this, it will possible cause a situation where some third part developer using my Framework are already using AFNetworking and will get a compile-time error that some class is declared twice.
Use CocoaPods and link AFNetworking to my Framework. This is causing this error: -lPods is not an object file (not allowed in a library).
Build something like the Aeris SDK where the third part developer using my Framework will be responsibly to add AFNetworking to their project.
I think that option 3 is the best but i don't know how to do that. How can i dev my framework calling AFNetworking classes/methods but do not include on the final framework product?
Thanks!
That's a very bad practice to use third party library in you library.
Ideally you should avoid doing that.
But if you really need it, you can define and add prefixes to class names.
Refer this article Avoiding dependency collisions in iOS static library managed by CocoaPods
Ok. I decided to go with the option 3.
A just added all the header files from any third-party lib to the my framework project (you can also add the .m files but not include them on the static library target).
And a i also documented everything, so developers using my framework will know what are the dependencies and how to include/install them on their own projects (including third-party lib versions, CocoaPods support, etc).
I decided not to go with option 1 because that will cause some situations where a project will have two copies of the same lib compiled on the final app. Even if a change the namespace for the libs on my framework code (to prevent "duplicated symbols" errors) that will still cause some other possible problems like an APP with larger size, possible bugs related to two or more instances of the same lib running together, etc...

Cocoapods - Hide implementation?

I have a iOS library that I created. Quite now I shipped this lib in a .framework file with only some .h files.
Now I would like to use Cocoapods instead of the framework.
Is it possible to hide the .m files and expose only some header files (like with the framework)?
According to this question I don't understand the relation between the podspec settings source_files and public_header_files.
I assumed that public_header_files would be my needed option, but I don't understand what this property is doing.
Edit:
I think I misunderstood the design of Cocoapods. public_header_files seems to make sense when using the use_framework! setting.
Maybe I'm trying Carthage instead.
For the Objective-C static framework, it is possible, you can try cocoapods-packager.
For Swift framework, so far it is impossible to use cocoapods-packager because of no volunteers. You can find the detailed information here:
But there is another way to Hide implementation of Swift framework when distributing it

Resources