Having to Link Binary With Libraries twice when using a static library in XCode - objective-c

I am trying to use a static library in a project. The static library depends on several frameworks... CoreData, CFNetwork, AddressBook, etc.
The static library also uses categories, so I am forced to use the -all_load linker option in the main project's "Other Linker Settings". When I enable this, I get 120 errors all relating to my main project not being linked with the same frameworks as my static library (CoreData, CFNetwork, AddressBook, etc).
It is very inconvenient for a developer to want to use a static library, link to it, but then still be required to link to all of the frameworks that the library links to. Is there any way to automate this process, so that the main project automatically links to all of the frameworks linked to by the static library?
I am using XCode 4.4.
edit: to be more clear, I have the following:
StaticLibrary.xcodeproj
- AFNetworking
- files...
- CoreData
- categories for NSManagedObjectContext, for convenience
- AddressBook
- convenience methods for working with contacts
This project's target is linked to the necessary frameworks under Build Phases > Link Binary With Libraries. This includes CoreData.framework, AddressBook.framework, etc.
Now what I would like to do is add this library to another project of mine. In fact, I would like to add this library to every new project I make from here on out, so I always have easy access to the convenience functions/categories that I've written. So: I add the library to my project, and then add the .a file to Build Phases > Link Binary With Libraries (of my main project). I also do everything else necessary that I know of (see comments).
What I would like to happen: the main project is now linked to the library, so it inherits all of the library's links so that the main project is now also linked to CoreData.framework, AddressBook.framework, etc.
What does happen: the main project gives me errors because it is not linked to anything that the library requires.
Is there a way to automatically add the linked frameworks from the static library to the main project, or should I split the library up into CoreDataStaticLibrary, etc, and then require the developer to add CoreData.framework as well as the static library to the project target everytime?

As I understand, you should only need -all_load if your library contains only categories. Otherwise, you can use -ObjC. That's what I use, at any rate.
Also, when you build a static library, you are just creating an archive of compiled object modules. No external dependencies are resolved in the library. Really, you should just think of it as a single collection of a bunch of object code files.
So, when you finally link your executable, it will link all your compiled code, along with the archive of pre-compiled code in your static libraries. The linker will expect to resolve all symbols, so you must tell it where to find all the libraries (frameworks) that are needed to completely resolve all the symbols.
Should XCode be able to look inside a static-library subproject and pull out the framework dependencies from that project and add them to the linker invocation for the final project? Sure. But, I'm not aware of a way to make that happen automatically.
If you want, you can create a podfile for your library, and use CocoaPods to manage your project dependencies.

The problem is you're including the same symbols several times. I've run into the same issue several times and the solution is basically to understand what the "-all_load" flag does, which is pretty well explained in this SO question: What does the all load linked flag do
Said that, you never reference frameworks from your library in that way. Since these frameworks are dynamically linked they don't really belong to your static library, there are just references pointing to them on it.
The user of such library should be responsible of adding the necessary frameworks to make it work properly. This means, you don't have to link your library to such frameworks (as such thing just doesn't make sense), just add them to project that's gonna use it. (Have a look on Restkit to see how it's done).
Also, I think you could get rid of the "all_load" flag and try to replace it with "force_load /path/to/the/library" all_load is only necessary in case your library only contains categories (no classes at all).
Let us know how it goes and happy coding!

Related

Duplicate symbols (two projects in a workspace use the same code)

A is a module project. There are some test targets and the relevant reusable code is compiled in a separate (static library) target. A uses the third party Lumberjack logging library. The Lumberjack code was simply dropped into the project.
B is a different module project, but otherwise it has the same properties as A.
C is the main project. It depends on A and B. It links the libraries of A and B.
Compiling C will result in duplicate Lumberjack symbols.
How can I have multiple separate module projects so that...
they don't know of each other,
use the same third party code,
can be compiled and tested on their own,
included in a main project without duplicate issues?
So, to elaborate on sergio's answer, I was able to succesfully build a test setup as follows.
I included the Lumberjack code in a separate project that builds Lumberjack as a static library.
I created a new project ProjectA with a static library target ModuleA and a test app target DemoA. I copied the Lumberjack project folder into the project folder of ProjectA and then added it as a subproject. I didn't make ModuleA dependent on Lumberjack or link Lumberjack in ModuleA. Instead, I made DemoA dependent on both and link both libraries. This way, I am able to compile the test target, but the library target doesn't include Lumberjack.
I created a second project ProjectB with the analogue setup as ProjectA.
In the main project, I included ProjectA, ProjectB and Lumberjack as subprojects. Unfortunately this will make Lumberjack included 3 times in the main project, which is a little bit inconvenient and ugly (for instance when selecting dependent targets, you can't really tell which one is which).
Finally, I made the main project's target dependent on Lumberjack, ModuleA and ModuleB and link all three libraries. Now, the main project can compile without duplicate symbol error and the submodules can also be compiled and tested on their own.
Since you are targeting OSX, the solution to your issue is building Lumberjack as a framework (as opposed to link the sources code in your A and B modules) and then using that framework wherever it is required (i.e., in any project using A or B modules).
Indeed, Lumberjack already includes a project that will build a Lumberjack.framework, check this: CocoaLumberjack/Xcode/LumberjackFramework/Desktop/Lumberjack.xcodeproj.
Elaborating more on this, you would define your A and B modules as you are doing now, but without dropping Lumberjack source code in it.
What you do instead is, whenever you want to use the A static library in a executable (say, your test target), you add the library to the target and also the lumberjack framework (exactly as you do with OSX SDK frameworks).
Adding the dynamic framework is just a different way to "drop the sources", if you want, but done properly.
When you want to use both A and B in a C project, you add both static libraries and your Lumberjack framework to C.
As you can see, this way of doing will comply with all your four requirements, at the expense of introducing one dependency: you need to make clear in your static libraries documentation that they depend on the Lumberjack framework. This is actually not a big issue, since the latter is available in its own project and any one will be able to build it on his own.
If you want to improve on the handling of this dependencies, cocoapods are the way to go (a cocoapod is a file associated to your library which describes its dependencies, so when you install your library, the cocoapods system will automatically install also the dependencies). But this is highly optional. One single dependency is not a big issue to document or comply with.
Hope this answers your question.
I hate to reference an existing answer but here's one solution that's cumbersome but works: What is the best way to solve an Objective-C namespace collision?
I have this same problem and I'm working on a better solution though. Another idea that might work but I'm not yet sure how to implement it I asked here: Selectively loading classes in Objective-C
A third idea I had because of something someone said on my question was to wrap one of the libraries in a framework and create functions that reference the functions you need. Then load using something like #import <myFramework/MFMyAliases.h>
Have you tried looking at the libraries with ar? If you are very lucky, running for example
ar -t libA.a
gives you a list of files like
__.SYMDEF SORTED
Afile1.o
Afile2.o
Lumberjack1.o
Lumberjack2.o
Afile3.o
SomeOtherLibrary.o
where the Lumberjack files are clearly separable from the rest. Then, you can kick them out
with
a -d Lumberjack1.o Lumberjack2.o
and link C against this trimmed library while using the full library when testing A alone.
I was trying to achieve the same thing before few months and "Easy, Modular Code Sharing Across iPhone Apps: Static Libraries and Cross-Project References" article got all what i needed. please check it out if its useful.
Are A and B binaries?
If not you could simply uncheck the compile checkbox for all *.m files of one of the projects, so as to avoid building duplicate objects.
Also if you could use A and B thorough Cocoapods it would be best.
Try this.
It is sharing libraries/modules between different projects.

How do I link multiple libraries in a Firebreath plugin?

Does anyone know where I can find a Firebreath sample (either Mac OS X or Windows) that illustrates how to create a plugin that includes 1 or more other libraries (.DLLs or .SOs) that each rely on other sub-projects built as static libraries (LIBs)?
For example, let's say that the Firebreath plugin is called PluginA, and that PluginA calls methods from DLL_B and DLL_C. DLL_B and DLL_C are C++ projects. DLL_B calls methods from another project called LIB_D, and DLL_C calls methods from a project called DLL_E.
Therefore, the final package should contain the following files:
PluginA.dll
DLL_B.dll (which also incorporates LIB_D)
DLL_C.dll
DLL_E.dll
I am currently forced to dump all source files in the pluginA solution, but this is just a bottleneck (for example I cannot call libraries written in other languages, such as Objective-C on Mac OS X).
I tried following the samples on Firebreath, but couldn't get them to work, and I found no samples from other users that claimed they were able to get it to work. I tried using CMAKE, and also running the solutions directly from X-Code, but the end result was the same (received linking errors, after deployment DLL_C couldn't find DLL_E etc.)
Any help would be appreciated - thank you,
Mihnea
You're way overthinking this.
On windows:
DLLs don't depend on a static library because if they did it would have been compiled in when they were built.
DLLs that depend on another DLL generally just need that other DLL to be present in the same location or otherwise in the DLL search path.
Those two things taken into consideration, all you need to do is locate the .lib file that either is the static library or goes with the .dll and add a target_link_library call for each one. There is a page on firebreath.org that explains how to do this.
On linux it's about the same but using the normal rules for finding .so files.

Is it worth it to create static libraries for iOS?

There is code that I want to include in most of my projects. Things like AFNetworking, categories for CoreData and unit testing, etc.
It seems logical to include all of these in a static library, and then use it in each project. I've noticed though, that many third-party libraries (like AFNetworking, and it's predecessor ASIHTTP) are included in projects by copying over all of their source files and then manually linking the necessary libraries to the project target.
This seems to me like the easiest way. It took a fair amount of time to figure out how to include an existing static library into a project. Even after I knew how, it still seems like a pain to do it for every new project. Also, the header search paths that you specify are to a local directory with the static library's files. Wouldn't it be easier, and is there a way, to copy the static library's files into the project? This is the same idea as including the class files directly like most libraries seem to do already, but it would be more organized because everything would be lumped into one library project, instead of having class files everywhere and having to include every one of them.
Static libraries feel like they should be the right way to go. Make a library that can be used with all projects that includes classes that every project will need. Makes sense. I am just conflicted because it seems like the right way to go is to leave everything out of a 'formal' library, and just copy over all of the class files instead.
I guess I am just looking for what experienced developers find to be the best option.
I would be among the first to admit that the process of referencing a static library in Xcode is not entirely intuitive. However, using a static library is the best option, without a doubt.
The main reason is maintainability: when you copy source code of a library to many places, you must remember to update all of them to the latest code when you upgrade to the next version of the library. This may be a rather error-prone process, especially when the underlying library source changes significantly (e.g. new files are added, old files are renamed, etc.)
There's a halfway solution - make an XCode project that builds your static library from source and put that into a shared repository (ie.. git submodule etc) which is included from each project's main repository.
Each of your projects would include this submodule and project. Then they get the latest source code each time they pull that submodule. If you set this up as a build dependency it will build a static library the first time you build and then XCode is smart enough just to include it each subsequent build so you get the benefit of fast build times.
You also get the advantage of having the source right there for stepping though / debugging.
If it's in a separate XCode project and a new version of a library adds or removes a source file you would only need to change that shared project - all your individual projects wouldn't change at all.
What about using CocoaPods? This tool does exactly what you want in a declarative way: you have a file (Podfile) where you declare your dependencies, and the tool downloads all the dependencies and builds a static library that gets added to your project.
I would agree that static libraries feel like they might be the correct way to go for a number of reasons, but can also introduce some issues.
The positives would be creating an easy way to add a library to a project. Although not completely intuitive, it is rather trivial to add a static library to a project after one does it a few times. Add the files, add the search path, done. This could also be useful in certain source control situations. Also, updating a library may be easier.
I think the real problem here is for the open source community. By including, say AFNetworking, for example, as a static library, you lose all access to the implementation files. This is a great feature of including source rather than a library. It lets you change code to how you see fit, and hopefully give back.

Linking to a static library that requires a frameworks

I have a main project and a few smaller sub-projects. The smaller projects contain both a self contained Cocos2d app and a static library containing only the classes that are relevant to the main project (the sub-projects all use the Cocos2D framework). The main project is dependant on the static libraries. I think this approach is theoretically sound, but in practice it is not working.
The symptom I am seeing is as follows: When the code is executed as part of the main project the pre-processor values work. When I run the app of a subproject it runs as expected.
I have set the -all_load linker option in the main target. This is because the classes in the sub-projects are only mentioned in nib files. Without -all_load the classes are 'optimized' out of the main target as the compiler incorrectly determines the code to be superfluous.
I have linked all of the sub-projects to the .frameworks that they require.
Is this fixable or is this approach doomed to fail? How else can I manage these projects without static libraries? Other developers work on the sub-projects and the static library approach prevents us from getting in each others way.
Update
Reading that question back makes me think I should have taken a break a lot earlier! The question doesn't explain the problem very well (or make much sense!). The problem relates to how to use sub-projects to organise code. I've now almost solved the issue. I'll probably write a blog post when I've fully solved it.
Since the static libraries end up "baked in" to your executable, you don't need to concern yourself with their linking anymore than you need your executable.
Just set up the project dependencies so that the dependent framework builds first (so the .framework/Headers folder gets populated properly), then the libraries, then your app. I have done this in multiple apps with great success.

Static Library using frameworks in specific projects

I have created a static library containing all my generic classes. Some of these classes use frameworks.
Now I have two projects, one that uses some classes that use frameworks, and one that doesn't use any of the classes that use frameworks.
Because Static Libraries don't support including frameworks (if I am correct). I have to include the frameworks in the project that uses them. But when I compile the project that doesn't use any of the framework-classes the compiler breaks because it still requires the frameworks. Now I know it tries to compile all the (unused) classes from the library because I use the Linker Flag '-ObjC' to prevent 'unrecognized selector' errors.
Does anyone know how to compile only the required source files per project? And prevent from all frameworks having to be included in all projects that use my static library?
First of all, you are right in that a static library cannot include any framework nor other static libraries, it is just the collection of all object files (*.obj) that make up that specific static library.
Does anyone know how to compile only the required source files per project?
The linker will by default only link in object files from the static library that contain symbols referenced by the application. So, if you have two files a.m and b.m in your static library and you only use symbols from a.m in your main program, then b.o (the object file generated from b.c) will not appear in your final executable. As a sub-case, if b.m uses a function/class c which is only declared (not implemented), then you will not get any linker errors. As soon as you include some symbols from b.m in your program, b.o will also be linked and you will get linker errors due to the missing implementation of c.
If you want this kind of selection to happen at symbol rather than at object level granularity, enable dead code stripping in Xcode. This corresponds to the gcc option -Wl,-dead_strip (= linker option -dead_strip in the Build settings Info pane for your project). This would ensure further optimization.
In your case, though, as you correctly say, it is the use of the "-ObjC" linker flag that defeats this mechanism. So this actually depends on you. If you remove the -Objc flag, you get the behavior you like for free, while losing the stricter check on selectors.
And prevent from all frameworks having to be included in all projects that use my static library?
Xcode/GCC support an linking option which is called "weak linking", which allows to lazily load a framework or static library, i.e., only when one of its symbols is actually used.
"weak linking" can be enabled either through a linker flag (see Apple doc above), or through Xcode UI (Target -> Info -> General -> Linked Libraries).
Anyhow, the framework or library must be available in all cases at compile/link time: the "weak" option only affects the moment when the framework is first loaded at runtime. Thus, I don't think this is useful for you, since you would need anyway to include the framework in all of your projects, which is what you do not want.
As a side note, weak_linking is an option that mostly make sense when using features only available on newer SDK version (say, 4.3.2) while also supporting deployment on older SDK versions (say, 3.1.3). In this case, you rely on the fact that the newer SDK frameworks will be actually available on the newer deployment devices, and you conditionally compile in the features requiring it, so that on older devices they will not be required (and will not produce thus the attempt at loading the newer version of the framework and the crash).
To make things worse, GCC does not support a feature known as "auto-linking" with Microsoft compilers, which allow to specify which library to link by means of a #pragma comment in your source file. This could offer a workaround, but is not there.
So, I am really sorry to have to say that you should use a different approach that could equally satisfy your needs:
remove the -ObjC flag;
split your static library in two or more parts according to their dependencies from external frameworks;
resort to including the source files directly.
Abour second part of your question, you can mark a linked framework as Optional :
About first part, it is not clear to me what you intend to do:
A library being declared in a project
A project declaring which files are compiled (via Target > Build phases > Compile sources)
Unless setting complex build rules to include or not files, which if I remember well can be done using .xcconfig files, I don't see any other solutions than splitting your Library. Which I would recommend, for its ease. You should even do several targets in the same project... You could also just use precompiler MACROS (#ifdef...) but that depends on what you want to do.
It sounds like you have library bloat. To keep things small I think you need to refactor your library into separate libraries with minimal dependencies. You could try turning on "Dead Code Stripping" in the "Linker Flags" section of the build target info (Xcode 3.x) to see if that does what you want (doesn't require frameworks used by classes that are dead-stripped.)
When you link against a framework on iOS I don't think that really adds any bloat since the framework is on the device and not in your application. But your library is still a bit bloated by having entire classes that never get used but are not stripped out of the library.
A static library is built before your app is compiled, and then the whole thing is linked into your app. There's no way to include some parts of the library but not others -- you get the whole enchilada.
Since you have the source code for the library, why not just add the code directly to each application? That way you can control exactly what goes into each app. You can still keep your generic classes together in the same location, and use the same code in both apps, but you avoid the hassle of using a library.