I felt a little Wordly when I designed the cover for this issue. Thanks to the postal strike in the UK, I got the printer's cover proof for the magazine after the full printed magazine landed on my doormat!
Friday, 13 November 2009
Writing: Respect the Software Release Process
Monday, 9 November 2009
Book Review: iPhone Games Projects
Name: iPhone Games ProjectsThis is the second book I've reviewed in this Apress iPhone series (the first being "iPhone Cool Projects"). The book has many of the characteristics of the first: it is full-colour throughout, contains clear writing, beautiful presentation, and relatively good copy editing. It hangs together about as well as the other book, too, which is "mostly".
Author: Dave Mark PJ Cabera
Publisher: APress
Price: $39.99
Pages: 258
Reviewed by: Pete Goodliffe
Verdict: OK
It is a series of 8 distinct essays by different "expert" (a relative term on such a new platform) iPhone game developers. The tone and approach of each chapter is therefore different.
The collection of topics covered is OK, but doesn't spread over the entire broad spectrum of game topics: there are TWO essays on networking, TWO essays on optimisation, one on multi-platform development (interesting in an "iPhone" book), one on writing a design document, and a walkthough of a simple board game.
There are many more topics that might have been interesting chapters to have in this type of book: a 3D graphics primer, when/how to select a third party games engine, considerations for getting your game noticed in the app store, and more.
There are some recurring themes: a few authors suggest prefering C over Objective-C (for obvious reasons). There is some discussion of why C is "better" than C++ which is (to a C++ programmer) unbalanced, and misleading.
As ever, the source code to each project is available from the Apress website. The quality of some of the code is quite variable.
If you want to write an iPhone game this book might be an interesting read, but I wouldn't suggest that every iPhone game programmer HAS to buy it. Some sections of it have far more value than others. In fact, I think overall you'd get more milage from the "iPhone Cool Projects" book since it covers a broader range of topics. I'm left feeling that the two books rolled into one would probably have been a better product. And I'm still not convinced that the title is even gramatically correct.
Thursday, 5 November 2009
Book Review: Pro Git
Name: Pro GitAuthor: Scott ChaconPublisher: APressPrice: $34.99Pages: 265Reviewed by: Pete GoodliffeVerdict: Highly Recommended
It's not often I start a book review with glowing praise. This time, I will: if you use the git (http://git-scm.com/) version control system, or are thinking of using git in the future, get this book. It's excellent.
Pro Git available online from http://progit.org (or git clone the book's source from http://github.com/progit). This means that you can read it for free before considering a purchase. Indeed, that's where I started. However, I highly recommend the dead tree version. Apress' production quality is excellent and the paper copy is defintely a valuable thing to have.
The book is an excellent introduction to using git; it's perfect for newbies, and a good reference for existing users. It starts from first priniciples. That is, it describes what git is, and what a distributed version control system is. It briefly introduces version control in general, but that is really prerequiste information.
The text is well paced, and very clearly written. The examples are well chosen and the coverage of git's facilities is broad.
The author starts with installing/configuring git and outlines the basic git principles. He covers basic operations (check in, clone, viewing logs, tagging). Then he moves onto git's crowning glory: branching and merging. This potentially tricky topic is covered very well.
The book also covers running a git server, sensible workflows to tame distributed collaboration, useful/advanced git facilities (stashing, amending history, binary searches, subtree merging, client- and server-side hooks), and using git with other version control systems. In particular, there is good coverage of using git as a more advanced subversion client.
The final chapter is particularly useful: a great overview of git internals. This sounds relatively pointless when you've covered most git usage already. However, this is a great chapter - the author explains what's going on under the covers in such a way that you gain a much better insight into how all the high-level git operations work.
Wednesday, 21 October 2009
Book Review: iPhone Cool Projects
Name: iPhone Cool ProjectsAuthor: Gary Bennet et alPublisher: APressPrice: $39.99Pages: 209Reviewed by: Pete GoodliffeVerdict: RecommendedLink: Publisher's website
iPhone programming is one of the current "hot topics" and we're seeing an increasing number of books published on this topic. This one is a bit of a mixed bag.
This is not an introductory tome; it requires significant prior understanding of the iPhone toolset and development environment. Instead, the book presents a number of complete fully-working iPhone applications covering various core iPhone technologies. It fits into a series of other Apress iPhone titles. Not having seem the other books, I can't say how well it complements the other titles in the series.
The book is effectively a collection essays by many authors, one per chapter, all "experts" at various aspects of iPhone development. Some of them have produced very successful iPhone applications.
The topics covered are: simple game programming, peer-to-peer networking, multi threaded applications, creating multi-touch interfaces, physics and 2D animation libraries, audio streaming, and creating a location-aware application with navigation-based UI. There are no topics covered that you can't fathom relatively easily from the free Apple documentation and a bit of careful thought. However the useful piece of the jigsaw is seeing how other developers have already learnt iPhone OS and solved the common problems.
The production quality of the book is high. It has been very well presented, in full colour throughout, with many iPhone and Xcode screen shots. On the whole, the writing is good. Some chapters appear to have been better proof read than others.
Perhaps the most useful part of the book is the availability of the source code for all the sample applications (from the publisher's website), so you can run and take apart the projects at your leisure. There is no bundled CD, and I'm more than happy with that.
As with many such multi-authored books, some chapters are better than others. Each chapter is relatively short, and they all basically provide an overview of their topic - enough to pique your interest, but not enough to answer any serious questions. For some topics this works better than others.
Highlights are the first game-writing chapter, the multi-touch interface chapters, and the location-based application chapter. These present useful information about how to write a "real" iPhone application. I felt let down by the threading chapter which presents a fairly glib and un-thorough overview of the perils of writing threaded apps. The networking chapter is a very simplistic introduction; nothing it says is wrong, but to write your own serious networked application you'd really need to know a lot more about network technologies.
If you're an experienced programmer who wants a casual introduction to some more meaty iPhone projects than you've seen in the introductory tests, this book may be interesting for you. It's easy to read, fast paced, and pretty.
Friday, 25 September 2009
Code: iPhone linker error (__restore_vfp_d8_d15_regs)
In my iPhone development I encountered link errors along the lines of:
"___restore_vfp_d8_d15_regs", referenced from:
-[Blah blah:] in blah.o"___save_vfp_d8_d15_regs", referenced from:-[Blah blah:] in blah.o
Google had a little to say about it. Unfortunately, it all appeared wrong.
The issue was a subtle one. The application's "Library search paths" (LIBRARY_SEARCH_PATHS) variable has some historic cruft in it which caused the linker to pull in and old incompatible version of libstdc++, with a consequence of much hilarity and hair-pulling.
When I removed "$(SDKROOT)/usr/lib/gcc/arm-apple-darwin9/4.0.1" from the list (not sure where this had come from) the application magically linked one more, and kittens and puppies danced with my iPhone once more.
Thursday, 24 September 2009
Code: Respect the Software Release Process
Several times recently I've run into problems caused by other developers' lackadaisical approach to the construction of software releases.
Many of these were caused by the sloppy habit of creating a release of a local working directory, rather than from a clean checkout.
For example:
- An external software release was made from a local directory containing uncommitted source file changes. We have no record of exactly what went into that build. And knowing it was built like this, I have no faith in the quality of the release at all.
- An external software release was made from a local directory that wasn't up-to-date. So it was missing one feature, and some bug fixes. But the developer tagged the HEAD of the repository, and then claimed he'd build that version. The built code begged to differ.
I mean, come on! It's not that hard, is it?
Well, actually: yes it is. Creating a serious high-quality software release is actually a lot more work than just hitting "build" in your IDE and shipping whatever comes out. If you are not prepared to put in this extra work then you should not be creating releases.
Harsh. But fair.
Respect the Software Release Process
Presuming that you are writing software for the benefit of others as well as yourself, it has to get into the hands of your "users" somehow. Whether you end up rolling a software installer shipped on a CD or deploying the software on a live web server, this is the important process of creating a software release.
The software release process is a critical part of your software development regimen, just as important as design, coding, debugging, and testing. To be effective your release process must be:
- simple
- repeatable
- reliable
Get it wrong, and you will be storing up some potentially nasty problems for your future self. When you construct a release you must:
- Ensure that you can get the exact same code that built it back again from your source control system. (You do use source control, don't you?) This is the only concrete way to prove which bugs were and were not fixed in that release. Then when you have to fix a critical bug in version 1.02 of a product that's five years old, you can do so.
- Record exactly how it was built (including the compiler optimisation settings, target CPU configuration, etc). These features may have subtly affects how well your code runs, and whether certain bugs manifest.
- Capture the build log for future reference.
The bare outline of a good release process is:
- Agree that it's time to spin a new release. A formal release is treated differently to a developer's test build, and should never come from an existing working directory.
- Agree what the "name" of the release is (e.g. "5.06 Beta1" or "1.2 Release Candidate").
- Determine exactly what code will constitute this release. In most formal release processes, you will already be working on a release branch in your source control system, so it's the state of that branch right now.
- Tag the code in source control to record what is going into the release. The tag name must reflect the release name.
- Check out a virgin copy of the entire codebase at that tag. Never use an existing checkout. You may have uncommitted local changes that change the build. Always tag then checkout the tag. This will avoid many potential problems.
- Build the software. This step must not involve hand-editing any files at all, otherwise you do not have a versioned record of exactly the code you built.
- Ideally, the build should be automated: a single button press, or a single script invocation. Checking the mechanics of the build into source control with the code records unambiguously how the code was constructed. Automation reduces the potential for human error in the release process.
- Package the code (create an installer image, CD ISO images, etc). This step should also be automated for the same reason.
- Always test the newly constructed release. Yes, you tested the code already to ensure it was time to release, but now you should test this "release" version to ensure it is of suitable release quality.
- Construct a set of "Release notes" describing how the release differs from the previous release: the new features and the bugs that have been fixed.
- Store the generated artifacts and the build log for future reference.
- Deploy the release. Perhaps this involves putting the installer on your website, sending out memos or press releases to people who need to know. Update release servers as appropriate.
This is a large topic tied intimately with configuration management, testing procedures, software product management, and the like. If you have any part in releasing a software product you really must understand and respect the sanctity of the software release process.
Friday, 18 September 2009
Code: Creating a framework for the iPhone
SummaryThis article explains how to build your own framework for Apple's iPhone OS.
The problem
Apple's Xcode development environment does not let programmers create their own framework for use in iPhone OS applications. This has caused many iPhone developers great frustration, although the restriction is for fairly sensible reasons.
So why the restriction?
A framework usually contains a dynamically loaded shared library (and the associated header files to be able to access its facilities). iPhone OS keeps applications very separate from one another, and so there is no concept of a user-created dynamic library shared between applications. There is no central library install point accessible to the developer. Indeed, managing such a software pool would be rather complex on iPhone-like devices, and preventing developers from installing their own shared frameworks neatly sidesteps a whole world of painful shared library compatibility issues, and well as simplifying the application uninstall process.
Its one, fairly final, way to avoid DLL hell!
All applications may link to the blessed, system-provided frameworks. The only other libraries they may use must be standard static libraries, linked directly to the application itself.
Those of us who'd like to supply functionality to other users in library form are left at somewhat of a disadvantage, though. Most developers are used to the simplicity of dragging a framework into their application target in Xcode, and not worrying about header paths or link issues.
It's nowhere near as neat to have to provide a static library and a set of associated header files in a flat directory. This requires your clients to work out the installation in their application for themselves. It's not hard, but it is tedious. You've also got to ship a library version for each platform the developer will need (at the very least, an arm code library for use on the iPhone OS device itself, and an i386 build for them to use in the iPhone simulator).
It's clumsy.
But fear not, there is a way...
How to build your own framework
I've worked out how to create a usable Framework that you can ship to other iPhone OS application writers. You can ship libraries that are easy to incorporate into other projects, and can exploit the standard framework versioning facilities.
There is one caveat: the framework will not be a standard shared library, it will provide a statically linked library. But the application writer need not be concerned about this issue. As far as they're concerned everything will just work. We are using Apple machines, after all.
Here's how to do it:
1. Structure your framework's header files.
Let's say your library is called "MyLib". Structure your project with a
top-level directory called "Include", and inside that make a "MyLib" subdirectory. Put all your public header files in there.
To be idiomatic, you'll want to create an umbrella header file "Include/MyLib/MyLib.h" that includes all the other headers for the user's convenience.
Set up your Xcode project "Header Search Paths" build parameter to "Include".
Now your source files can happily #import <mylib/mylib.h> in the same way they'd use any other framework. Everything will include properly.
2. Put your source elsewhere
I have a "Source" directory containing subdirectories "Source/MyLib" and "Source/Tests". You can put your implementation files (and private header files) wherever you want. Just, obviously, not in the Include directory!
3. Create a static library target
Create an iPhone OS static library target that builds all your library sources. Call it MyLib, and by default it will create a static library called libMyLib.a.
4. Create the framework plist file
Create a plist file that will be placed inside your framework, describing it.
I keep mine in Resources/Framework.plist. It's a peice of XML joy that should look like this:
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><plist version="1.0"><dict><key>CFBundleDevelopmentRegion</key><string>English</string><key>CFBundleExecutable</key><string>MyLib</string><key>CFBundleIdentifier</key><string>com.MyLovelyDomain.MyLib</string><key>CFBundleInfoDictionaryVersion</key><string>6.0</string><key>CFBundlePackageType</key><string>FMWK</string><key>CFBundleSignature</key><string>????</string><key>CFBundleVersion</key><string>1.0</string></dict></plist>
5. The magic part... build your framework by hand
Create a shell script to build your framework. I have a "Scripts" directory that contains it, because I like to keep things neat like that.
The first line is the canonical hashbang:
#!/bin/bash
There are two parts to this file...
5a. Build all the configurations that you need your framework to support
This must be at least armv6 for the device, and x386 for the simulator. You'll want these to be Release configuration libraries.
xcodebuild -configuration Release -target "MyLib" -sdk iphoneos3.0xcodebuild -configuration Release -target "MyLib" -sdk iphonesimulator3.0
So that's our libraries built. Now...
5b. Piece it all together
With a little understanding of the canonical structure of a framework directory, our ability to write a plist, and the knowledge that putting a static library in the framework instead of a dynamic library works fine, you can create your framework like this (apologies that blogger has kinda killed the formatting here):
# Define these to suit your nefarious purposesFRAMEWORK_NAME=MyLibFRAMEWORK_VERSION=AFRAMEWORK_CURRENT_VERSION=1FRAMEWORK_COMPATIBILITY_VERSION=1BUILD_TYPE=Release# Where we'll put the build framework. The script presumes we're in the# project root directoryFRAMEWORK_BUILD_PATH="build/Framework"# Clean any existing framework that might be there alreadyecho "Framework: Cleaning framework..."[ -d "$FRAMEWORK_BUILD_PATH" ] && rm -rf "$FRAMEWORK_BUILD_PATH"# The full name of the framework we'll buildFRAMEWORK_DIR=$FRAMEWORK_BUILD_PATH/$FRAMEWORK_NAME.frameworkecho "Framework: Setting up directories..."mkdir -p $FRAMEWORK_DIRmkdir -p $FRAMEWORK_DIR/Versionsmkdir -p $FRAMEWORK_DIR/Versions/$FRAMEWORK_VERSIONmkdir -p $FRAMEWORK_DIR/Versions/$FRAMEWORK_VERSION/Resourcesmkdir -p $FRAMEWORK_DIR/Versions/$FRAMEWORK_VERSION/Headersecho "Framework: Creating symlinks..."ln -s $FRAMEWORK_VERSION $FRAMEWORK_DIR/Versions/Currentln -s Versions/Current/Headers $FRAMEWORK_DIR/Headersln -s Versions/Current/Resources $FRAMEWORK_DIR/Resourcesln -s Versions/Current/$FRAMEWORK_NAME $FRAMEWORK_DIR/$FRAMEWORK_NAME# Check this is what your static libraries are calledFRAMEWORK_INPUT_ARM_FILES="build/$BUILD_TYPE-iphoneos/libMyLib.a"FRAMEWORK_INPUT_I386_FILES="build/$BUILD_TYPE-iphonesimulator/libMyLib.a"# The trick for creating a fully usable library is to use lipo to glue the# different library versions together into one file. When an application is linked# to this library, the linker will extract the appropriate platform version and# use that.# The library file is given the same name as the framework with no .a extension.echo "Framework: Creating library..."lipo \-create \-arch armv6 "$FRAMEWORK_INPUT_ARM_FILES" \-arch i386 "$FRAMEWORK_INPUT_I386_FILES" \-o "$FRAMEWORK_DIR/Versions/Current/$FRAMEWORK_NAME"# Now copy the final asserts over: your library header files and a plist fileecho "Framework: Copying assets into current version..."cp Include/$FRAMEWORK_NAME/* $FRAMEWORK_DIR/Headers/cp Resources/Framework.plist $FRAMEWORK_DIR/Resources/Info.plist
That's it. Run that script and you'll create a framework in "build/Framework". In there is MyLib.framework. This directory can be shipped to your external application developers. They can incorporate it into their iPhone OS applications like any other framework.
Congratulations, you are now a hero.
Other remarks
I have presented here the most basic structure of a shell file. My production version includes more robust error handling, and other facilties that are relevant to my particular project.
I also have a build script that automatically creates documentation for the framework that I can ship with it. Indeed, I have a release script that applies versioning information to the project, build the libraries, creates a framework, assembles the documentation, compiles release notes and packages the whole thing in a pretty DMG. But that's another story.
If calling scripts from the command line scares you, you may chose to make a "Run Script Build Phase" in your Xcode project to call your framework script. Then you can create a framework without having to creep to the command line continually.
In summary, the final file layout of my project looks like this:
....Include/........MyLib/............MyLib.h............IncludeFile1.h............IncludeFile2.h....Source/........MyLib/............PrivateHeader.h............ImplFile1.m............ImplFile2.m........Tests............MyLibTest1.m............MyLibTest2.m....Scripts/........framework.sh
I hope you have found this tutorial useful. Let me know what frameworks you manage to build.
Subscribe to:
Posts (Atom)