What this article will cover
This article will cover setting up an Xcode project with SDL, SDL_image, SDL_mixer, SDL_ttf, and the Boost C++ libraries (header files only) on OS X 10.6 Snow Leopard. I’ll be using Xcode version 3.2.5 and the Classic Invaders source (2 MB) files.
There were quite a few changes made to SDL 1.2.14 and it’s Xcode project templates to accommodate Snow Leopard, backward compatibility, and building 64 bit binaries. For the details of these changes check out playcontrol.net โ Big Behind-the-Scenes changes for SDL 1.2.14 on Mac OS X (Snow Leopard).
I’ll go step-by-step through the process of
- Installing SDL and the SDL project templates
- Setting up Xcode for both Debug and Release builds
- Final packaging
Installing SDL and the SDL project templates
Download both the Mac OS X Runtime Libraries and the Mac OS X Development Libraries from the SDL downloads page.
Install the SDL framework by copying SDL.framework to
/Library/Frameworks
From the devel extras package copy the three folders in the
SDL-devel-extras/XcodeTemplates/TemplatesForXcodeSnowLeopard
directory into the
/Library/Application Support/Developer/Shared/Xcode/Project Templates/Application
directory. You may have to create the destination directory.
For the documentation copy
SDL-devel-extras/Documentation/docs/XcodeDocSet/org.libsdl.sdl.docset
to
/Library/Developer/Shared/Documentation/DocSets
Setting up Xcode for both Debug and Release builds
Creating a project with the templates
Start up Xcode and go to File -> New Project, select Application under User Templates and you should see the three SDL project templates.
Select SDL Application and save this project with an appropriate name. You should be able to build the project by clicking the Build and Run icon on the Xcode toolbar or by selecting Build and Run from the Build menu. If you do this the app should launch, at this point it is just a blank screen and can be exited with a key press.
A note on using version control:
If this is your first time setting up an Xcode project and you use a version control system such as Git or Subversion you may be wondering whether or not to put the Xcode project directory under version control. I typically add the entire project directory with these exceptions
ProjectDirectory/build/ ProjectDirectory/ProjectName.xcodeproj/username.mode1v3 ProjectDirectory/ProjectName.xcodeproj/username.pbxuser
This keeps the main settings of the project in the ProjectName.xcodeproj/project.pbxproj file version controlled, while the build directory and per user settings which change frequently and aren’t part of the dataset needed to build the final program can be ignored.
Adding additional Frameworks
The game Classic Invaders also makes use of the SDL_image, SDL_mixer, and SDL_ttf libraries (for Xcode these are packaged as Frameworks) as well as the Boost libraries (headers only). Adding these additional Frameworks is simple and it’s also simple to have Xcode copy them automatically to the .app bundle for distribution.
and copy the three Frameworks to
/Library/Frameworks
In the left pane in Xcode right click Frameworks, go to Add -> Existing Frameworks and add the three Frameworks.
You’ll want to copy the Frameworks to the .app bundle for distribution. This could be done manually by copying them into a finished .app bundle, but Xcode will do it for you. The SDL project template is already setup to copy the SDL.framework folder. To have Xcode do the same thing to the Frameworks just added expand the Targets group and then the “TargetName”. Targets consist of build phases. Drag the Frameworks from the Frameworks group to the “Copy Frameworks into .app bundle” build phase as shown below.
Add Boost
If you are following along with the Classic Invaders source files (or your own project uses Boost) you will need to add the Boost libraries into the mix.
Download and unzip the Boost archive. — http://www.boost.org/
If you are using Boost or any library in multiple projects it is usually beneficial to install in one location and then add the lib to all your projects from that location (as I’m doing with the SDL libs here), that way you can update the lib in one location and all your projects will use the newer version. It’s also possible to organize things more on a per project basis (I could have copied the Frameworks into my Xcode project folder and then configured Xcode to use those Frameworks). Since Boost isn’t distributed as a Framework I am going to add the Boost headers to my project folder and then show how to use an Xcode project variable to setup the include path in the next section.
So for now I will just copy the entire boost folder from within the boost archive (this contains the headers) to an include directory that I’ll create within the Xcode project directory. I also set up my version control system not to track this external lib.
Setting up the include paths
It’s recommended to add SDL headers to your source like so
#include "SDL_ttf.h"
for portability, which is what I have done in the Classic Invaders source so we’ll have to specify to Xcode where to find the headers.
Go to Project -> Edit Project Settings. In the Project Info window that opens, select the Build tab, select All Configurations and scroll down to Search Paths.
Double click the Header Search Path line and add
/Library/Frameworks/SDL_image.framework/Headers /Library/Frameworks/SDL_mixer.framework/Headers /Library/Frameworks/SDL_ttf.framework/Headers $SRCROOT/include
Note the “$SRCROOT/include” line. This is using the Xcode project variable $SRCROOT which represents the project directory. In this directory I added an include directory and copied the boost folder into it.
XCODEPROJECTDIRECTORY/include/boost/*.hpp
Adding the source files
Delete the main.c file and import the Classic Invaders (or your own projects) source files by going to Project -> Add to Project.
The SDLMain.m file included in the Xcode project templates is coded so that when a .app bundle is launched by double clicking on it in the Finder (the way a user would typically launch it) the working directory gets set to the .app bundle’s parent directory (which is also the default when you run a program from within Xcode). However when data files are distributed with an OS X application they are usually placed inside the .app bundle itself in the Resources directory.
I prefer to have SDLMain.m set the working directory to the Resources directory when the .app bundle is launched from the Finder, this will be needed to distribute your data files in the .app bundle and I see no reason not to do it right from the start. Why will become clear when I show how to best setup the data root directory.
Replace the SDLMain.m file with this one — SDLMain.m.zip (3.8 KB).
At this point the program will build, so Xcode is finding all the required libs and headers. If you try to run it however it exits because we haven’t yet put the data in place. To see the standard output of the program go to Run -> Console.
Handling the data directory
As previously mentioned the working directory when you launch a program from within Xcode is the parent of the .app bundle which (assuming you are building a Debug configuration) is
XCODEPROJECTDIRECTORY/build/Debug
so if you put your root data directory here
XCODEPROJECTDIRECTORY/build/Debug/data
you can then access your resources relative to that directory. But putting the data directory here is typically not the ideal location, normally you have your data with the rest of your project files and you don’t want to bother having two copies of it.
You also want these data files inside the .app bundle that you will distribute.
The setup to handle these situations is as follows.
Add your root data directory to Xcode as a folder reference. This is done by going to Project -> Add to Project or right clicking the Project name in the Groups and Files pane and then go to, Add -> Existing Files
And then selecting the “Create Folder References for any added folders” option.
When you do this Xcode automatically adds this directory to the ‘Copy Bundle Resources’ build phase, so it will be copied to the Resources directory within the .app bundle which will be the working directory when the app is launched from the Finder due to the changes made to the original SDLMain.m file earlier.
To handle the situation when you are running the program from Xcode simply make a symbolic link from the active build directory to your actual root data directory. For example with the data directory located in the Xcode project directory and the active configuration set to Debug from the command line cd into the Debug directory and run
ln -s ../../data data
The steps shown up to this point take care of both Debug and Release builds. Settings for individual configurations can be set by going back to the Project Info window and selecting the desired configuration from the Configuration pop-up.
To build a specific configuration just select the active configuration from the Overview pop-up on the Xcode toolbar.
Final packaging
In this final section I’ll look at a few details that add the final polish to the Application as well as some tools to automate the Release build and .dmg creation process.
If you launch the Application and then go to the About screen from the OS X Cocoa menu you’ll see a couple of things that you will probably want to change.
The icon, the version number, the application name, and the copyright notice are all things you may want to modify.
The version number and copyright notice
The version number is currently set in two places. In the InfoPlist.strings file and in the Target settings. I prefer to remove it from the Target settings and use the one in InfoPlist.strings. To do this go to Project -> Edit Active Target, select the Properties tab and clear the Version box.
The copyright notice is also in the InfoPlist.strings file. These strings can be edited and the results will then show in the About and Get Info windows for the application.
Renaming the .app bundle
You may also want to rename the .app bundle since it appears in the Cocoa menus. To do this go to Project -> Rename, select only the Product (the .app bundle) and rename.
Adding the application icon
Img2icns is a program that can create the .icns filetype needed. Add the .icns file to the Resources group and then to the Info.plist file (the filename is the value for the ‘Icon file’ key). It will be added to the ‘Copy Bundle Resources’ build phase automatically.
Automating the Release build and .dmg creation
At this point the setup is complete and after a Release build a .dmg can be manually created. However doing this manually can be tedious and time consuming, especially if you are continually adding features and distributing new releases.
There are two tools I use to automate this process. The first is xcodebuild. xcodebuild is a command line tool that builds a target contained in an Xcode project. For information about xcodebuild check out it’s manpage.
man xcodebuild
The second program I use is called DMG Canvas. DMG Canvas builds disk images from template documents that you create. It also has a command line tool that can be used to create an automated workflow. It’s not a free program but I’ve found it to be worth the cost.
With the two tools mentioned and a little bash scripting I’ve been able to totally automate the creation of the final .dmg for Classic Invaders that I have available on this site.