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.
Related
I have this project that I have done for experimentation with Qt and shared libraries. This is basically a couple of Qt Widgets from the tutorials for Qt and what I think is the right CMakeLists configuration so a MylibConfig.cmake is automatically generated from a MylibConfig.cmake.in to share the library. The problem is that I don't want the end user to add the dependencies of my library to its own CMakeLists.txt. This is, in my case, the library depends on Qt4, but I want that the end user to not have to do find_package(Qt 4 REQUIRED). Imagine that I want to provide an enclosed functionality to someone that does not need or want to know about what my library is built on. Is there a way in the automatic generation of the MylibConfig.cmake that it automatically finds all necessary packages or is the only option to add the fin package manually in the MylibConfig.cmake.in?
Thank you very much.
In fact, both mentioned projects do find of dependencies from their *Config.cmake files. And nowadays that is the only option -- CMake can't help you to do it "automatically".
So, some way or another, your config module should do the same.
The easy way is to add find_dependency() calls (cuz you know exactly what other packages, your project is based on).
A little bit harder is to do it "automatically" (writing your own helper function) -- for example by inspecting properties of your target(s), "searching" where all that libraries come from and finally generating find_dependency() calls anyway.
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!
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.
Here is what I'm looking for:
I'd like to separate pieces of functionality into modules or components of some sort to limit visibility of other classes to prevent that each class has access to every other class which over time results in spaghetti code.
In Java & Eclipse, for example, I would use packages and put each package into a separate project with a clearly defined dependency structure.
Things I have considered:
Using separate folders for source files and using Groups in Xcode:
Pros: simple to do, almost no Xcode configuration needed
Cons: no compile-time separation of functionality, i.e. access to everything is only one #import statement away
Using Frameworks:
Pros: Framework code cannot access access classes outside of framework. This enforces encapsulation and keeps things separate
Cons: Code management is cumbersome if you work on multiple Frameworks at the same time. Each Framework is a separate Xcode project with a separate window
Using Plugins:
Pros: Similar to Frameworks, Plugin code can't access code of other plugins. Clean separation at compile-time. Plugin source can be part of the same Xcode project.
Cons: Not sure. This may be the way to go...
Based on your experience, what would you choose to keep things separate while being able to edit all sources in the same project?
Edit:
I'm targeting Mac OS X
I'm really looking for a solution to enforce separation at compile time
By plugins I mean Cocoa bundles (http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/LoadingCode/Concepts/Plugins.html)
I have worked on some good-sized Mac projects (>2M SLOC in my last one in 90 xcodeproj files) and here are my thoughts on managing them:
Avoid dynamic loads like Frameworks, Bundles, or dylibs unless you are actually sharing the binaries between groups. These tend to create more complexity than they solve in my experience. Plus they don't port easily to iOS, which means maintaining multiple approaches. Worst, having lots of dynamic libraries increases the likelihood of including the same symbols twice, leading to all kinds of crazy bugs. This happens when you directly include some "helper" class directly in more than one library. If it includes a global variable, the bugs are awesome as different threads use different instances of the global.
Static libraries are the best choice in many if not most cases. They resolve everything at build time, allowing code stripping in your C/C++ and other optimizations not possible in dynamic libraries. They get rid of "hey, it loads on my system but not the customer's" (when you use the wrong value for the framework path). No need to deal with slides when computing line numbers from crash stacks. They catch duplicate symbols at build time, saving many hours of debugging pain.
Separate major components into separate xcodeproj. Really think about what "major" means here, though. My 90-project product was way too many. Just doing dependency checking can become a very non-trivial exercise. (Xcode 4 can improve this, but I left the project before we ever were able to get Xcode 4 to reliably build it, so I don't know how well it did in the end.)
Separate public from private headers. You can do this with static libs just as well as you can with Frameworks. Put the public headers in a different directory. I recommend each component have its own public include directory for this purpose.
Do not copy headers. Include them directly from the public include directory for the component. Copying headers into a shared tree seems like a great idea until you do it. Then you find that you're editing the copy rather than the real one, or you're editing the real one, but not actually copying it. In any case, it makes development a headache.
Use xcconfig files, not the build pane. The build pane will drive you crazy in these kinds of big projects. Mine tend to have lines like this:
common="../../common"
foo="$(common)/foo"
HEADER_SEARCH_PATHS = $(inherited) $(foo)/include
Within your public header path, include your own bundle name. In the example above, the path to the main header would be common/foo/include/foo/foo.h. The extra level seems a pain, but it's a real win when you import. You then always import like this: #import <foo/foo.h>. Keeps everything very clean. Don't use double-quotes to import public headers. Only use double-quotes to import private headers in your own component.
I haven't decided the best way for Xcode 4, but in Xcode 3, you should always link your own static libraries by adding the project as a subproject and dragging the ".a" target into your link step. Doing it this way ensures that you'll link the one built for the current platform and configuration. My really huge projects haven't been able to convert to Xcode 4 yet, so I don't have a strong opinion yet on the best way there.
Avoid searching for custom libraries (the -L and -l flags at the link step). If you build the library as part of the project, then use the advice above. If you pre-build it, then add the full path in LD_FLAGS. Searching for libraries includes some surprising algorithms and makes the whole thing hard to understand. Never drop a pre-built library into your link step. If you drop a pre-built libssl.a into your link step, it actually adds a -L parameter for the path and then adds -lssl. Under default search rules, even though you show libssl.a in your build pane, you'll actually link to the system libssl.so. Deleting the library will remove the -l but not the -L so you can wind up with bizarre search paths. (I hate the build pane.) Do it this way instead in xcconfig:
LD_FLAGS = "$(openssl)/lib/libssl.a"
If you have stable code that is shared between several projects, and while developing those projects you're never going to mess with this code (and don't want the source code available), then a Framework can be a reasonable approach. If you need plugins to avoid loading large amounts of unnecessary code (and you really won't load that code in most cases), then bundles may be reasonable. But in the majority of cases for application developers, one large executable linked together from static libraries is the best approach IMO. Shared libraries and frameworks only make sense if they're actually shared at runtime.
My suggestion would be:
Use Frameworks. They're the most easily reusable build artifact of the options you list, and the way you describe the structure of what you are trying to achieve sounds very much like creating a set of Frameworks.
Use a separate project for each Framework. You'll never be able to get the compiler to enforce the kind of access restrictions you want if everything is dumped into a single project. And if you can't get the compiler to enforce it, then good luck getting your developers to do so.
Upgrade to XCode4 (if you haven't already). This will allow you to work on multiple projects in a single window (pretty much like how Eclipse does it), without intermingling the projects. This pretty much eliminates the cons you listed under the Frameworks option.
And if you are targeting iOS, I very strongly recommend that you build real frameworks as opposed to the fake ones that you get by using the bundle-hack method, if you aren't building real frameworks already.
I've managed to keep my sanity working on my project which has grown over the past months to fairly large (number of classes) by forcing myself to practice Model-View-Control (MVC) diligently, plus a healthy amount of comments, and the indispensable source control (subversion, then git).
In general, I observe the following:
"Model" Classes that serialize data (doesn't matter from where, and including app's 'state') in an Objective-C 1 class subclassed from NSObject or custom "model" classes that inherits from NSObject. I chose Objective-C 1.0 more for compatibility as it's the lowest common denominator and I didn't want to be stuck in the future writing "model" classes from scratch because of dependency of Objective-C 2.0 features.
View Classes are in XIB with the XIB version set to support the oldest toolchain I need to support (so I can use a previous version Xode 3 in addition to Xcode 4). I tend to start with Apple provided Cocoa Touch API and frameworks to benefit from any optimization/enhancement Apple may introduce as these APIs evolve.
Controller Classes contain usual code that manages display/animation of views (programmatically as well as from XIBs) and data serialization of data from "model" classes.
If I find myself reusing a class a few times, I'd explore refactoring the code and optimizing (measured using Instruments) into what I call "utility" classes, or as protocols.
Hope this helps, and good luck.
This depends largely on your situation and your own specific preferences.
If you're coding "proper" object-oriented classes then you will have a class structure with methods and variables hidden from other classes where necessary. Unless your project is huge and built of hundreds of different distinguishable modules then its probably sufficient to just group classes and resources into folders/groups in XCode and work with it that way.
If you've really got a huuge project with easily distinguishable modules then by all means create a framework. I would suggest though that this would only really be necessary where you are using the same code in different applications, in which case creating a framework/extra project would be a good way to effectively copy code between projects. In practically all other cases it would probably just be overkill and much more complicated than needed.
Your last idea seems to be a mix of the first two. Plugins (as I understand you are describing - tell me if I'm wrong) are just separated classes in the same project? This is probably the best way, and should be done (to an extent) in any case. If you are creating functionality to draw graphs (for example) you should section off a new folder/group and start your classes and functionality within that, only including those classes into your main application where necessary.
Let me put it this way. There's no reason to go over the top... but, even if just for your own sanity - or the maintainability of your code - you should always endeavour to group everything up into descriptive groups/folders.
I am trying to clean up some of my projects, and one of the things that are puzzling me is how to deal with header files in static libraries that I have added as "project dependencies" (by adding the project file itself). The basic structure is like this:
MyProject.xcodeproj
Contrib
thirdPartyLibrary.xcodeproj
Classes
MyClass1.h
MyClass1.m
...
Now, the dependencies are all set up and built correctly, but how can I specify the public headers for "thirdPartyLibrary.xcodeproj" so that they are on the search path when building MyProject.xcodeproj. Right now, I have hard-coded the include directory in the thirdPartyLibrary.xcodeproj, but obviously this is clumsy and non-portable. I assume that, since the headers are public and already built to some temporary location in ~/Library (where the .a file goes as well), there is a neat way to reference this directory. Only.. how? An hour of Googling turned up blank, so any help is greatly appreciated!
If I understand correctly, I believe you want to add a path containing $(BUILT_PRODUCTS_DIR) to the HEADER_SEARCH_PATHS in your projects build settings.
As an example, I took an existing iOS project which contains a static library, which is included just in the way you describe, and set the libraries header files to public. I also noted that the PUBLIC_HEADERS_FOLDER_PATH for this project was set to "/usr/local/include" and these files are copied to $(BUILT_PRODUCTS_DIR)/usr/local/include when the parent project builds the dependent project. So, the solution was to add $(BUILT_PRODUCTS_DIR)/usr/local/include to HEADER_SEARCH_PATHS in my project's build settings.
HEADER_SEARCH_PATHS = $(BUILT_PRODUCTS_DIR)/usr/local/include
Your situation may be slightly different but the exact path your looking for can probably be found in Xcode's build settings. Also you may find it helpful to add a Run Script build phase to your target and note the values of various settings at build time with something like:
echo "BUILT_PRODUCTS_DIR " $BUILT_PRODUCTS_DIR
echo "HEADER_SEARCH_PATHS " $HEADER_SEARCH_PATHS
echo "PUBLIC_HEADERS_FOLDER_PATH " $PUBLIC_HEADERS_FOLDER_PATH
.
.
.
etc.
I think that your solution is sufficient and a generally accepted one. One alternative would be to have all header files located under an umbrella directory that can describe the interface to using the depended-on libraries and put that in your include path. I see this as being similar to /usr/include. Another alternative that I have never personally tried, but I think would work would be to create references to all the headers of thirdPartyLibrary from MyProject so that they appear to be members of the MyProject. You would do this by dragging them from some location into MyProject, and then deselecting the checkbox that says to copy them into the project's top level directory. From one perspective this seems feasible to me because it is as if you are explicitly declaring that your project depends on those specific classes, but it is not directly responsible for compiling them.
One of the things to be wary of when addressing this issue is depending on implementation-specific details of Xcode for locating libraries automatically. Doing so may seem innocuous in the meantime but the workflows that it uses to build projects are subject to change with updates and could potentially break your project in subtle and confusing ways. If they are not well-defined in some documentation, I would take any effect as being coincidental and not worth leveraging in your project when you can enforce the desired behavior by some other means. In the end, you may have to define a convention that you follow or find one that you adopt from someone else. By doing so, you can rest assured that if your solution is documented and reproducible, any developer (including yourself in the future) can pick it up and proceed without tripping over it, and that it will stand the testament of time.
The way we do it is to go into build target settings for the main project and add:
User Header Search Path = "Contrib"
and check that it searches recursively. We don't see performance problems with searching recursively even with many (10-15 in some projects) dependencies.