More on the Xcode project format

A 90-Second Project Parser in Ruby

Last week we looked at the overall format of Xcode project files. Here’s an easy parser written in Ruby; this one will only run on Mac OS X, because it uses Foundation from Ruby:


#!/usr/bin/ruby
# http://danwright.info/blog/xcode-pbxproject-files-2

require 'osx/cocoa'

xcodeproj = "/Users/danwr/Documents/MyProject/MyProject.xcodeproj"

projectpbxproj = "#{xcodeproj}/project.pbxproj"
data = OSX::NSData.dataWithContentsOfFile(projectpbxproj)
plist = OSX::NSPropertyListSerialization.propertyListFromData_mutabilityOption_format_errorDescription(data, 0, nil, nil)

rootObject = plist['rootObject']
objects    = plist['objects']

if ARGV.length == 0
	puts "rootObject = #{objects[rootObject]}"
else
	what = ARGV.shift
	if /^[0-9a-fA-F]{24}$/ =~ what
		puts "object #{what} = #{objects[what]}"
	else
		results = objects.keys.find_all {|key| objects[key]['isa'] == what }
		puts "isa '#{what}': #{results}"
	end
end

If you run this command without any arguments, it will show you the root object (PBXProject). If you run it with a UUID, it will display the corresponding object; if you provide it with an object class (‘isa’), it will display the UUIDs for all matching objects. For purposes of this article, I’ve hard-coded the path to a project; you can edit that to point to your own project, or modify the script to allow a path to be specified as an argument.

Wow, that’s silly-easy. If you want your script to run on another platform—Windows or Linux—you would need another solution (but it isn’t exactly difficult to write a custom parser in a modern scripting language such as Ruby, Python, or even Old Man Perl.

XCConfigurationList

An XCConfigurationList is simply a list of configurations. A configuration refers to a group of settings, and commonly we have at least two: Debug and Release, the former for debugging the project, the latter optimized for customers.


C01FCF4E08A954540054247B = {
    buildConfigurations =     (
        C01FCF4F08A954540054247B,
        C01FCF5008A954540054247B
    );
    defaultConfigurationIsVisible = 0;
    defaultConfigurationName = Release;
    isa = XCConfigurationList;
}

The defaultConfigurationName and defaultConfigurationIsVisible properties indicate which configuration is the default when building with the xcodebuild tool, as well as whether this information should be exposed in the Xcode user interface. The buildConfigurations array contains references to objects of type XCBuildConfiguration.

XCBuildConfiguration

An XCBuildConfiguration is a collection of build settings, like so:


C01FCF4F08A954540054247B = {
    buildSettings =     {
        ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
        "GCC_C_LANGUAGE_STANDARD" = gnu99;
        "GCC_OPTIMIZATION_LEVEL" = 0;
        "GCC_WARN_ABOUT_RETURN_TYPE" = YES;
        "GCC_WARN_UNUSED_VARIABLE" = YES;
        "ONLY_ACTIVE_ARCH" = YES;
        PREBINDING = NO;
        SDKROOT = "macosx10.6";
    };
    isa = XCBuildConfiguration;
    name = Debug;
}

The buildSettings property is the heart of an XCBuildConfiguration. Each build setting should look familiar: these are the same names and settings you would use in an .xcconfig file. Of course, buildSettings can be empty, as it often will be when you have an .xcconfig file specified instead.

PBXVariantGroup

A PBXVariantGroup describes a group of files that act like one; this is used to described localized files (strings and xibs).


1DDD58140DA1D0A300B32029 = {
    children =     (
        1DDD58150DA1D0A300B32029
    );
    isa = PBXVariantGroup;
    name = "MainMenu.xib";
    sourceTree = "";
}

This one describes the application’s main xib (describing the menu bar and main window). The name is the name of the file. The children contains a list of localizations; here, there is just one, for the English version. Let’s look at that child:


1DDD58150DA1D0A300B32029 = {
    isa = PBXFileReference;
    lastKnownFileType = "file.xib";
    name = English;
    path = "English.lproj/MainMenu.xib";
    sourceTree = "";
}

The path is the path of the actual .xib file (relative to the encoding group). lastKnownFileType indicates the file type.

Next time…

Next time, a look at PBXFileReference, PBXBuildFile, and PBXSourcesBuildPhase.

Tags: