I just banged my head for a while and figured out a solution, but I want to make sure that I'm doing things right and that I actually know what I'm doing (I'm pretty sure I never know what I'm doing :)
I have two projects that I've been working on, each offering different functionality. I want one project (A) to be able to use the functionality of the other (B). I tried going about it by creating a workspace and putting both projects into it, but I couldn't "see" project B's files from project A (autocomplete after #import did work, but it gave a compiler error). So I tried adding it as a "sub-project" and found the same. I figured this would be easy, but guess not.
What I ended up doing was creating a new project (C) as a "Cocoa Touch Static Library" project, and put my files from Project B into it. I built it.
I then went back to project A and added project C into it as a sub-project.
Then I added the path on the filesystem of project C into the User Header Search Paths setting under Build Settings of project A.
Then I added the .a file from Project C into the Link Binary with Libraries section of Project A.
Then it worked.
But honestly I have no idea what the meaning of a static library is.
Is all this necessary? Or is there an easier way to just integrate two projects (without me having to copy the files from one project to another)?
Thanks in advance!
Jon
You were on the right track with workspaces. What I do is have three projects in the workspace. One with no targets just to hold the generic classes. A second for my iOS target Project. And a third for mac. Keep the original files in the one with no target, then drag the files to the other two projects that creates references, so when you edit one it changes all three.
Related
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.
Say you create a project. Then you want to do something else. You want to create another project that uses all the files of the previous project. You then modify it a little bit.
In vb.net it's simple. You just copy the vbproj file and that's it.
In objective-c copying the xcproj will result in a project file that won't compile.
Solution?
Note:
I do not want to do simple copy. If I do simple copy changes will not be propagated. I want if the fork change so will the original file.
As far as I know changing the project file name will make the project fail to compile. So just copying the project file doesn't work unless I do something wrong.
I think it's utterly ridiculous that there is no easy way to make the project work after changing the name of the xcodeproj file? I can't even open that xcodeproj file in textedit. In vb.net I can hack the project file straight. Why not in xcode?
There are two options which I would prefer :-
If there are classes which are constant and are not changing, you can make library which is called as Cocoa Touch Static Library
OR
Just copy folder to another location, rename application name and changes you want to do and run it!
Hope this info helps you..
I long for the day when you can simply choose "save as template" from Xcode(!)
In the meantime it might save you some headache to check out Project Duplicator from the AppStore. I haven't tried it out myself yet, but it sounds like it's designed to do exactly what you're asking for.
If you want to do it the manually way you could duplicate the folder with all corresponding files in the Finder and go about renaming everything from there.
You can create multiple targets for your project.
look at this link.
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.
An iPad project I have been working on has become bloated with a huge number of files. The application is a prototype and we are considering ways to prevent this when we rewrite it.
One of the members of our team suggests dividing all of the components into separate Xcode projects which will be included in a master Xcode project.
Is this a good idea? What are the reasons, if any, to avoid dividing features/components/controls into separate Xcode projects?
You can add a subsidiary project file to a master project file in Xcode. Just choose "Add File" and add it. When Xcode builds the master it will build the subsidiary as well if needed.
I use a similar system. I often break a project into sub projects just so I can focus on and enforce encapsulation. I write the data model first, then add the app delegate, then specific UI elements. I add each project to the next in turn. This also allows me to go back and change things without as much risk of breaking.
Really, a properly designed objective-c app should be easy to decompose into multiple project. Ideally, all the components are so encapsulate that they don't need any others save the data model.
We have put some of the code in its own project, building a framework which we link against at some of the other projects. It's sometimes annoying that you won't see the implementation files of the framework code right away in another project (by cmd+clicking or cmd+shift+D, or whatever you do normally to navigate). Xcode will only show you the header, you'll have to open the other project and find your file there manually. Not a big deal, but if you look up the code often, it will bother you.
A real problem is that you change the scope of some operations. Stuff like "Find in project" will work on a different file set, which might not be what you want sometimes (trying to find where this method is called / key is used in your whole code, or something); well, there remains Finder / find, so it might be okay. Refactoring is not - all the renaming stuff just breaks, as it will change only the code of the current project, but not of projects referencing this one. If you change interfaces often, better avoid splitting up the project.
A good thing is that you will get less conflicts on your .xcodeproj files (if stored in a shared repository) as someone removing a file from project X won't create a conflict with someone else adding a target on project Y, which where previously the same .xcodeproj (not exactly sure this is a conflict case, but there definitely are some).
Now with Xcode4 you can create a workspace and add all your projects there. Only for documentation purpose :)
To view and modify subproject implementation files, you should add the sub projects directly into the main project.
1 step - Drag and drop the .xcode project files to main project.
2 step - Go to main project TARGETS - > Build Phases. Add subproject target in Target Dependencies. You can also add binary files in Link Binary With Libraries.
3 step - Add subproject source path to main projects header search path.
Go to main project - > Build Settings - > Header Search Paths (e.g $(SRCROOT)/../CoconutKit-master/CoconutKit/Sources )
An Xcode project can have any number of build targets within it, and you can arbitrarily group source files into folders. What makes you think that multiple projects are necessary?
I'm working with xcode and I have classes associated with other projects that I want to be included in new projects. I realize that the #import will do the job technically (although what should i do if it's out of the project root folder). But what do I do if I want to include the class "properly" --basically so i can double click and edit out of the main project window where you can see all your files and such.
I guess I'm just looking for the best and/or proper way to include/import (into the project) .h and .m files that I've already created outside of the current project I'm working on. Taking into consideration that I may want to modify the class from the original without subclassing. Hopefully this makes sense.
Thanks,
Nick
Xcode project file organization doesn't reflect the data files on disk. Files can be added to a project from anywhere in the file system. When you add the files, choosing not to copy the files to the current project's directory means that the original files are used. Selecting one of these files in Xcode for editing will alter the original file in that other project. When returning to that other project, Xcode will use the edited files in any further work.
This type of use can be quite handy while working on multiple projects with some shared code. Yet, it can also cause headaches for a versioning system.
Might be worth thinking about how to make the classes into a private framework - then you can import that as another dependency each time. Alternatively you could use a separate version control system location to store the shared classes and just check that out into the project folder.