Using a Single Build Directory in Xcode

Here’s an old screencast which I never got around to uploading.

It makes sense to set up a single directory in Xcode where built products and intermediate files are kept. You can blitz all the files at once if you don’t need them, you don’t have to set up manual exclusions for your version control and you can set up the files to be excluded from Time Machine backups.

This was recorded with an earlier version of Xcode, but the steps still apply. Please excuse the sound quality.

Renaming an Xcode Project

You may have occasion to rename an Xcode project.

You can find step-by-step instructions and scripts with a little bit of Googling. But there is another way. If you’re running Xcode 3.2 on Snow Leopard there is a menu item you can use instead. Have a look at the Project > Rename… menu item instead.

Project > Rename…

Three ways of excluding files from git

Almost every git user knows about adding a .gitignore file to their repository to control the visibility of files and folders. This per project configuration will apply to all repositories of the same code base. But it’s not the only way. I’m going to tell you how to get git to ignore files on a per computer and per repository basis. These could be better choices in some circumstances.

There are three types of exclude files; from highest to lowest order of precedence they are:

Per Project: .gitignore file in the repository

This is the usual way of adding an ignore file. Call it .gitignore and save it to the root of your project to apply to all the files (you can add different .gitignore files in subdirectories where they have lesser scope). It is a part of the repository, so it will need to be git-added and committed for each change. This is useful for repositories that are passed around with others who may not have a per computer exclude file, or when there are project specific files that need to be taken into account. Even easier if you have per computer file, you can copy it straight in to your project with a simple cp ~/.gitignore .gitignore and edit to handle your specific requirements.

Per Repository: in .git/info/excludes

You can exclude files on a per repository basis by editing the .git/info/excludes file in your repository. (Why it takes it from this location rather than .git/config I don’t know: add it to the list of git annoyances). These exclusions (or inclusions, you can override the higher level exclusions by prepending ! to lines that you want to include) are not shared with the working directory, so they only apply to that particular repository. This is useful when you have particular requirements because of your workflow or machine setup.

Per Computer: through ~/.gitconfig settings

There should already be a .gitconfig file in your home directory. This is where the global setting for your git installation are stored; such as the user’s name and email address. Within this you can set a path to an excludes file that will apply to all git repositories on the computer in the same way as the name and email defined in this file apply to all repositories.

For example: Most of what I do is in Xcode so I have the following ~/.gitignore file

# ~/.gitignore

*.DS_Store
*.pbxuser
*.mode1v3
*.mode2v3
*.perspectivev3

And in my .gitconfig file under the [core] section I have added the path to this file for the excludesfile key. (If you’re sharp eyed, you’ll notice that I don’t have an exclusion for /build. That’s because I don’t keep my products in my project directory, but that’s for a different post).

<snip>…
[core]
editor = /usr/bin/see -w -r -o new-window -j ‘git editor’ -m gitCommit -g 1:0
excludesfile = /Users/abizern/.gitignore
<snip>…

Now, I have a standard set of ignores that apply to all my git repositories on this machine without me having to add a specific .gitignore file to each one. This is probably most useful if you create a lot of repositories for yourself, but I recommend it to everyone. It’s lowest on the precedence scale and provides a neat catch-all.

Summary

Most of the time the first solution is quite adequate, having exclusions with a repository that is likely to have a public face is probably the most effective way of managing file visibility. But, as with most of git, there are ways of handling edge cases. You just need to know that they are there.

REFERENCE: the gitignore man page.

Some tips for lazy Xcoders

We all know what we should be doing when writing code. Each methodology you choose to use has it’s own best practices, whether it’s working from full specifications, writing unit tests first, programming in pairs, yadda, yadda. But, as developers, we’re only human, and we’re lazy. We have tools to make things easy for us. Here are a few tips that you can use to help when you’re not as rigorous in your coding as you should be.

Use a static analyser.

You can use the Clang Static Analyser in Xcode by setting a build option. This will find a whole host of errors in your code, even down to unconventionally named functions.

ClangBuildSetting.png

Now you can just code away and have the compiler pick up your mistakes when you run ‘Build and Analyze’ (Shift ⌘ A).

Find your mistakes quickly

Any real application you develop will have a large number of resources that need to be copied to your application bundle. The default projects that Xcode create for you will copy these files first before compiling.

XcodeDefault.png

But, the lazy Xcoder knows that there are probably errors in the code that need to get flagged by the compiler, so this copying is a waste of time. Reorder the build steps by dragging so that the compilation is done first.

XcodeRecommended.png

Your builds will now break early (and often!).

Don’t fear the version controller

I’m going to stick my neck out and say that if you’re not using version control you’re an idiot. The lazy Xcoder uses a powerful system that lets him or her branch easily, make lots of little changes, and lots of mistakes (that can be backed out). These changes can then be bundled into larger commits to be merged into the main branch so that your co-workers don’t see what an idiot you’ve been.

One such version control system is git. The lazy Xcoder writes a bit of code, checks it in out of habit and then compiles. The compiler picks up the mistakes, and he or she fixes them. Rather than make a new commit, and retype the commit message, just call:

git commit --amend -a -C HEAD

This will bring up the previous commit message in the editor, which you can amend if you wish. This new commit will replace the previous one. The -a option means you don’t even need to do a git add and the -C HEAD option means it will use the commit message from the last commit.

Of course, if you’re a rockstar programmer, you don’t make mistakes at this level. But I’m not, and I prefer to work with human nature rather than against it.

Integrating git with SubEthaEdit and Changes.app

A while ago, I read a nice write up about using mercurial with SubEthaEdit and Changes. Here’s how to do the same thing with git instead of mercurial, separated into two parts in case you just want to apply one set of changes.

Changes Support

Step One: Make sure chdiff is installed.

Open Changes.app and from the Changes menu select “Install terminal utility”. This will install the chdiff utility which is used by the script.

Step Two: Create a shell script to send diffs to Changes

Create a shell script with the following contents.

#!/bin/sh
[ $# -eq 7 ] && /usr/bin/env chdiff "$2" "$5"

Where you save this and what you call it is up to you. Mine is called ‘.gitchanges’, saved it at the root of my home directory. Make sure the script is executable.

Step Three: Edit the .gitconfig file to use this script to handle diffs.

Open your ~/.gitconfig file. This should already exist, at the very least it will contain you name and email. under the section called [diff] add the location and name of the file. You may have to edit this to make sure it points to the name and location you chose in Step Two. (Make sure to use the correct path in your setup)

[diff]
external = <path to file>/.gitchanges

SubEthaEdit Support

Step One: Download and install the mode file for SubEthaEdit

I wrote a SubEthaEdit mode for this which you can download from the github project page. Please feel free to fork it and send me patches.

Step Two: Edit the .gitconfig file to use SebEthaEdit as an external editor.

Open your ~/.gitconfig file. This time, under the [core] section, add the following line:

[core]
editor = /usr/bin/see -w -r -o new-window -j ‘git editor’ -m gitCommit -g 1:0

All those flags may seem daunting, but they are quite self-explanatory: the -w flag makes the Terminal wait for a response from SubEthaEdit. -r brings Terminal to the front after you’re done editing. -o new-window opens a new window for editing. I prefer this to having a new tab appear in whatever window I was working on. -j 'git editor‘ this sets the text that appears in the title bar, which you can change as you wish. -m gitCommit is what sets the mode to be used for editing. and -g 1:0 puts the caret at the beginning of the file.

Now, when git asks you to write a commit message, or pick commits when running git rebase -i a SubEthaEdit window will open as the commit message editor. Make whatever changes you need then save the file (⌘-s) and then close the window (⌘-w) for these changes to take effect.