By paul ~ April 4th, 2009. Filed under: Resources.
Download the current version of the template by clicking here. The rest of this is the "what" and "why" for first timers.
I’m having so much fun coding, I’m having trouble finding the time to blog. I promised the folks over on the Oolong list that I’d post some info on setting up an Xcode workspace for an Oolong project, though, so here it is. Keep in mind that I’m new to XCode, so you guys that have been around longer please straighten me out on anything that looks incorrect.
First, let me explain why this matters. Oolong is currently organized as a source tree with the examples embedded. The examples simply refer directly to the Oolong files of interest by relative paths. One would naturally like to use the examples as templates for new projects, but it’s difficult to get it to work unless you embed your project within Oolong alongside the examples. Further, we’d like to put Oolong into our own SCM system (this makes managing updates easier, especially when local changes to Oolong are required) and we might have other "libraries" that we want to use as well. Ideally, we’d like to create a project organization that looks something like this:
Where MyLibrary and MyProj1 & 2 are dependent on the shared Oolong and possibly OtherLibrary, all of this managed in our SCM.
Here’s what I did, in a nutshell, with a few details to follow:
- First, I put Oolong and MyLibrary into our SCM alongside each other, as shown above.
- I pointed Xcode to these two "Source Trees", which effectively adds the equivalent of good old "environment variables" which can be referenced by your projects. More on how to do this in a moment as it was not obvious.
- I created a project template from one of the Oolong examples, modifying it such that Oolong and MyLibrary are referenced through the environment variables.
There are several benefits to this approach. First, my project isn’t in the Oolong tree, which is important to me. Secondly, I can create any number of projects from my template and put them anywhere on my system and they’ll still be able to find Oolong and MyLibrary via the Source Tree references. Thirdly, it makes setting up a new team member very easy. They just check out the source to whatever folders they like, setup the Source Trees in Xcode, and away they go.
Here’s how to setup your Source Trees in Xcode.
- Open XCode->Preferences and then click on the Source Trees button at the top.
- Add (‘+’ button under list box)
- Choose a name for the tree (this name is a string that will be used an identifier, like an environment variable, I used "OOLONG_ROOT"), then "Oolong Root" as the Display Name (a human friendly name), then the path to your Oolong tree (/Users/paul/Sandbox/Oolong in my case.) Note that these settings are available to all your projects as they’re part of the Xcode preferences, not project settings. Each team member will have to set these up in their Xcode preferences as they are not shared.
- Do the same thing for any other libraries (like MyLibrary in my example.)
Now that you’ve set up your source trees, you can reference them from your project. There are two places where you’ll want to do this. The first is in the folders (Xcode calls them "Groups") containing the sources. The second is in the build settings where you’ll use them in header and, if necessary, library search paths.
Note that in the following, I’m assuming you’re starting with an Oolong example, such as "skeleton."
- I would start by changing the Oolong folder name from "Classes" to "Oolong" or something.
- Select the Oolong folder/group and click on the info button. On the General tab, select the "Relative to Oolong Root" item from the Path Type chooser.
- Click on "Choose" for the Path and select the folder where Oolong resides. If everything is setup correctly, the path setting should change to "None" (because the path is relative to Oolong.)
- The folders under the Oolong folder should be corrected as necessary. I found that the "group" organization in the examples didn’t always match the organization on the file system, so I changed it to match the file system. As a result, each folder and file path can be "Relative to Enclosing Group" and the Path will then match the file system folder name. It just seems cleaner to me.
Note that as an alternative to these steps, you could also just delete the Classes folder in the example and use Add Existing Files to re-add it (choose recurse and set the reference relative to the OOLONG_ROOT source tree.) If you use this approach, you will need to go through the Oolong hierarchy and delete stuff you don’t want in there (the compiler will help you identify this…)
Now, change the header search path:
- From the Project menu select Edit Project Settings .
- On the Build tab, select "All Configurations" and "All Settings".
- Scroll down to "Search Paths"
- In the Header Search Path field, change all the search paths that reference the Oolong location (probably by relative path, like ../../..) to "$(OOLONG_ROOT)" . Here’s what mine looks like "$(OOLONG_ROOT)" "$(OOLONG_ROOT)/Bullet/src" "$(OOLONG_ROOT)/Math" "$(OOLONG_ROOT)/Include"
- There really aren’t any libraries in Oolong that are used (currently everything’s just compiled together), but you could make similar changes to the Library Search Path.
- Note that you’ll need to do the same thing for the Target. What I would recommend is to set these at the Project level (as described), and for the target, simply use the value $(inherited).
Now, for the moment of truth: Build and see what smokes. I would highly recommend starting with a project that you’ve already built successfully within Oolong (like one of the simpler examples.) Build it and satisfy yourself that it works, then pull it out to the side and make the changes described above and build again. (Be sure to do a Clean before you build so that there’s no old junk lying around.) It’s hard for me to predict what kinds of problems you might run into, but hopefully you’ll be able to sort it out based on the error messages. If not, leave a comment to this post with the question and I (or some other kind soul) will try to help.
Once you’ve got the project working, clean everything up and use it as a template from which to create other projects. I’ve found that I can quickly create a new project from such a template by:
- Copying the template and renaming the copy to newProjName.
- Rename the *.xcodeproj file to newProjName.xcodeproj.
- In Xcode, open the new project, edit the build settings and for all configurations change the Product Name (under Packaging ) to newProjName.
- Edit the build settings for the target and make the same change.
- Under the Groups & Files window, rename the Targets as appropriate.
4/7/2009: I have created a template from the FallingCubes example. This template follows the rules above and can be used as a starting point for your projects. The template also includes the necessary additional frameworks for audio. Instructions for using the template are contained in the ReadMe.txt file. I hope this will save you some time mucking with Xcode.
4/27/2009: Updated template, removing the Graphics Services framework from the Frameworks group. The Graphics Services framework is a private framework and may not be used in applications released to the AppStore. Fortunately, it’s not needed!
4/30/2009: After some great discussion on performance tuning on the Oolong mailing list, I’ve updated the template with the "right" (or is it "better"?) compiler flags. Be sure to check out the Oolong Performance thread for the last two days. Also, if you’re interested in iPhone performance, be sure to check out this thread on the DevForum .
It would be best if Oolong were built as a "Framework" (pre-compiled sources in .a files with accompanying header files like the Apple frameworks) but I haven’t gone that far yet. For the moment, the approach above is sufficient for my needs. However, if the internal source organization of upcoming Oolong releases change, we’re toast. We’ll have to monkey with the structure of all of the projects that use Oolong. Therefore, a logical "next step" is to make Oolong a Framework. In fact, it would be great if the next release of Oolong was setup to build itself as a framework. I’m willing to help…
I feel like I’ve probably made some errors and left things out. Please don’t hesitate to correct me or let me know when there’s yet a better way!