Prefix Static Library iOS - ios

I'm building an iOS static library (as per https://github.com/jverkoey/iOS-Framework). I depend on SBJson and AFNetworking. I would like to include these libraries to avoid version issues and for installation simplicity; to do so, I need to prefix these libraries to avoid naming conflicts.
How can I prefix other static libraries in a simple way?
Ideally, it would be part of my build process. Less ideally, but acceptable, are tips on how to refactor and rename in a sane manner.

The only safe solution (other than not doing this at all) is to build any dependencies with a prefix on all symbols.
The easiest method of prefixing is the classic "find-and-replace". This is error-prone, so it's a good idea to hit the .a with nm -a and scour the results for any non-prefixed symbols.
A second, much safer method is to use a two-pass compilation process.
The first pass builds the dependent project and runs nm to dump all symbols into a header file.
The second pass builds the dependent project again, but this time with the generated prefix header file imported in the precompiled header. This prefix header must be used anywhere you reference symbols from the dependency in your framework in order to properly refer to the renamed symbols.
For reference, we use this with Nimbus to generate the Nimbus prefix headers:
https://github.com/jverkoey/nimbus/blob/master/scripts/generate_namespace_header
This allows you to distribute a .framework with a prefixed version of Nimbus embedded.
You can now link the resulting .a into your framework and safely avoid any linker conflicts when a third party developer inevitably links their own version of the dependency into their project.

Related

How do you compile a static library that has a 3rd party dependency without including the dependency?

TL;DR
How do I build a static library without including a third party library that I'm referencing?
Hi,
Before I begin, I know how to compile a static library in Xcode targeted for iOS devices and simulators. However, this time around I have a dependency on a third party library that I do not want to include in the static library. I simply want to reference it. However, whenever I am building my static library I get a lexical or preprocessor error, which I know is common when the library is missing from the project. The error occurs because I removed the library from the project, because I didn't want to have it built into the static library.
The library in question is AFNetworking. I will be using CocoaPods to explicitly have the dependency installed when installing my static library.
Thank you.
When you reference external code, you will always need to have the headers accessible by your project, otherwise the compiler wouldn’t be able to tell you if you are referencing the external code in a proper manner. E.g. does the method exist, are you providing the right types, etc.
The duplicate symbol problem only exists when you actually define a symbol multiple times. For instance, defining class related Objective-C symbols only happens in a #implementation...#end block, not in a #interface...#end block. The latter is only for the compiler to make sense of things.
(This is also why you can define a #interface for e.g. a private class and use it as normal and not cause duplicate symbols.)
Therefore, you can include such ‘clean’ headers multiple times without having to worry about it. Note that I said ‘clean’, because you can actually define symbols in headers by, for instance, defining C functions in headers or even a Objective-C #implementation, if you feel especially wicked. But you will simply have to test this.
The linker will complain when you finally link the 3rd-party dependency and yours and there were duplicate symbols after all. In that case, be sure to look into tools such as nm which list the symbols in an archive.
you can add the lib.a and lib.h into your project.

Avoid duplicate symbols with static library and cocoapods

I'm using OpenCV through cocoapods and libharu, both are using libpng, I wasn't able to include the opencv.framework on libharu static library to use libpng.
Do I need rename every symbol or there is a way to use the same libpng?
Third party static libraries should never link other third party static libraries themselves. All libraries should be linked together at the end by the final application link step. If the cocoapod spec is calling for one static library to include another, then it is incorrect and needs to be fixed.
For more on this, see this question, as well as the questions it links:
ObjC: How to compile static library that includes optional classes that depend on a third party library
Starting with libpng-1.6.0, you can configure libpng (when using the
"configure" script) to prefix all exported symbols by means of the
configuration option "--with-libpng-prefix=FOO_", where FOO_ can be any
string beginning with a letter and containing only uppercase
and lowercase letters, digits, and the underscore (i.e., a C language
identifier). This creates a set of macros in pnglibconf.h, so this is
transparent to applications; their function calls get transformed by
the macros to use the modified names.
Essentially, it renames every exported symbol for you while building
your own libpng.
I have not personally tested this feature.

Compile with header in dylib

I'm trying to make a library and want to copy the header file to the dylib, but when I put libAC.h in libAC_FILES, I get this error when I compile
*** No rule to make target `obj/libAC.h.f3cc93fd.o', needed by `obj/libAC.dylib.ba964c90.unsigned'. Stop.
I want it to be that when I make a different application, I can do #include <libAC.h> and use the methods from that library, but I can't find any examples on how to do this. This is for a jailbroken device, by the way. I'm using the library template in theos, and using make package install to make the library and install it to my phone, if it helps.
What im trying to do is install the header file for my dylib to /usr/include
Headers are not supposed to get bundled into a library binary. A dylib is a shared library that is binary only.
A dylib is not the same thing as a framework (which is a bundle of a library and its headers) - I guess that is where your confusion comes from.
For allowing you to include the headers needed for using functions of your library, you will need to put those into the header-search-path of your compiler. You may certainly also extend that path towards any folder that contains your header/s.
Since you are using some packaging script as it seems, check with the documentation of that script (or simply analyse it).
And as a final note, do not use the sharp brackets (<, >) for delimiting custom header includes. Only system headers are supposed to get those. Use standard quote marks instead (").

How to use open source iOS libraries without collisions?

I'm writing an iOS library (SDK) and I need JSON decoding support. There are lots of choices, but the problem is upstream collisions.
If I add, say, JSONKit to my library, and another third party library does the same, then the upstream user who wants to use both my library and the other library will experience a collision.
It would appear then that it's impossible for me to add any third party libraries into my library because of the risk of collisions. How can I use iOS libraries as dependencies of mine without causing collisions for upstream developers?
How can I use iOS libraries as dependencies of mine without causing collisions for upstream developers?
Just specify that that third party library is a dependency of your library, provide appropriate links to the project, and any necessary instructions, version info, etc..
If that package/distro is not well-suited for distribution (e.g. they just have a pile o' source files), then create a public project (fork) which includes a proper static library target.
We're having this same issue. Here's my thoughts on how to solve it (perhaps we can figure out a robust solution together). For versioning control, we're using Git:
One option is simply to prefix all classes within your library with your own identifier. In such, even if the class is part of JSONKit, I'd still prefix it with my own identifier ("JG") to get the classname "JGJSONKit.h". In this manner, it's much less likely that a collision would occur.
This method has the drawback that should a third party repository (such as JSONKit) be updated, however, it's more difficult to pull these changes into our library's version of JSONKit.
This may be acceptable, however, if this code is intended to be exported as a static library (as you'd still maintain full control over the code, and you'd be able to manually pull changes to third party repositories and rename them appropriately, if you should so choose to do such in future updates of the static library).
Another option I've considered is using Git submodules. This solution seems to be better should your library be open source (or at least open source to the developers that have access to it -- not necessarily available publicly). In such, developers could choose to simply not include any submodule that they were already using within their own project.
Ideas?
Edit:
Here's the solution that we came up with:
1) We encapsulated our shared code (which we'd written- not a third party) into a project with a static library target and our shared resources (xibs and images) into a bundle following this tutorial:
https://github.com/jverkoey/iOS-Framework
2) We created a Git repository that included said static library and bundle.
3) We forked all desired third party libraries (so we could make changes to them if desired) and also added the original repos as another remote within each forked repo (so that should changes be made upstream, we could easily pull them into our own fork)
4) We added -objc to the "other linker" flags (important) so that all categories would work correctly during runtime.
All in all, the solution is near perfect for us:
We avoid collisions by either hiding the third party libraries (not including them in the public headers but private instead), or we warn that those libraries are used within the project for publicly exposed headers and that developers should not add them again (they can use the already included code instead, which is kept up-to-date via the simplicity of including them via said Git submodule method)
I hope this helps your efforts too!
I had a look at JSONKit and i see that it isn't a Static Library, it is a src file to copy into your project.
All Classes, etc. in your project must be prefixed with your (cough) globally unique two letter prefix, including classes you copy and paste off the internet.
You would be better off if JSONKit was a library. Your library would depend on JSONKit, but not contain it, and it would be up to whoever building an app with your library to make sure JSONKit was also included and linked against - no collisions (although distributing a library that is dependent on other third party libraries that aren't yours to distribute is inherently somewhat tricky).
If other people are pasting this JSONKit file into their libraries and then distributing them you have only two options*
Modify JSONKit.h & .m, prefixing all symbols (you must do this with any code you include as source)
or choose something else (NSJSONSerialization?).
This doesn't mean you can't have third party library dependencies (or that doing so is dangerous), just that copying a source file into your project is not the same as adding a library dependency.
*arghh, ok 3.. you could weak link all the symbols from JSONKit and leave it up to the library user to supply JSONKit.m, but then still the problem is the other libraries..
TLDR.. avoid JSONKit, it isn't suitable to use 'as is' in a library that you want to distribute.

Conflict between static libraries used in Xcode project

I am using RestKit, GData and Facebook API.
All of them has a JSON files, many of them share the same name, enums etc.
When i compile I get an error on duplicates.
How can i prevent the conflicts?
Thanks
Shani
This is my best guess. It would be helpful to post the errors you get on compile.
If you are using the -all_load linker flag, turn it off. If your libraries require that you use this option, try using -force_load option on the specific libraries that require it. As an absolute last resort, build the libraries that you can from source, renaming colliding symbols.
The question below might provide some more insight on the all_load issues:
Objective-C categories in static library
I ran into this issue because the new Facebook SDK 3.0 is now a static framework which also includes SBJSON, I also have another static framework which also includes the same class. Originally I would just go in and edit the source files of the Facebook SDK and apply a custom prefix to the SBJSON classes. This no longer works.
Here is an outside the box solution.
Navigate to FacebookSDK.framework->Versions->Current
Open the compiled FacebookSDK library file with the best IDE, textedit will do!
Search case sensitive and replace all occurrences of "SBJson" with "FBJson"
Search case sensitive and replace all occurrences of "SBJSON" with "FBJSON"
Save, clean, compile.
Note: Some would say, why replace with FBJson and not FBSBJson? I determined it would be best to keep it the same character length to be safe.
Note: If you are attempting this with other frameworks, be sure to search the header files for any references to the conflicting class that you are renaming. In this case the class being renamed was not referenced in any of the header files. If it had been, I would have made sure to rename it in the header files.

Resources