Xcode project object UUIDs

Continuing our discussion of the Xcode project file format

Unique Xcode object IDs using Ruby

The “UUIDs” used in project files are shorter than true UUIDs (only 12 bytes/16 characters), and have no punctuation. We can’t just use system UUID services to generate new ones, then. In practice, our UUIDs usually do not need to be universally unique; they must be unique within a project file, and ideally would be unique across all projects built or opened on a given machine. Here, nonetheless, is a quickie ruby class that generates Xcode project UUIDs:


class XcodeUUIDGenerator

    def initialize
        @num = [Time.now.to_i, Process.pid, getMAC]
    end
	
    # Get the ethernet hardware address ("MAC"). This version 
    # works on Mac OS X 10.6 (Snow Leopard); it has not been tested
    # on other versions.

    def getMAC(interface='en0')
        addrMAC = `ifconfig #{interface} ether`.split("\n")[1]
        addrMAC ? addrMAC.strip.split[1].gsub(':','').to_i(16) : 0
    end

    def generate
        @num[0] += 1
        self
    end
	
    def to_s
        "%08X%04X%012X" % @num
    end
end

Usage is simple:

    gen = XcodeUUIDGenerator.new
    id1 = gen.generate.to_s
    id2 = gen.generate.to_s
    id3 = gen.generate.to_s

PBXFileReference

A PBXFileReference is used to track every external file referenced by the project: source files, resource files, libraries, generated application files, and so on. A source file might look like this:


 29B97316FDCFA39411CA2CEA /* main.m */ = {
	isa = PBXFileReference; 
	fileEncoding = 4; 
	lastKnownFileType = sourcecode.c.objc; 
	path = main.m; 
	sourceTree = ""; 
 };

The values for lastKnownFileType may be found within Xcode itself, by selecting the file and choosing “Get Info”. A sourceTree of “” corresponds to “Relative to Enclosing Group”. A fileEncoding value of “4” is UTF-8. Here, the path is only a file name, however it can be a (longer) relative path or an absolute path (sourceTree = ““). Relative paths may also be relative to the chosen SDK, the Xcode application (rare), the project file (that is, the .xcodeproj bundle), or the built product.


 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */ = {
	isa = PBXFileReference; 
	lastKnownFileType = wrapper.framework; 
	name = Cocoa.framework; 
	path = /System/Library/Frameworks/Cocoa.framework; 
	sourceTree = ""; 
 };

Some Xcode templates contain absolute paths to some frameworks (as in the above example), however this is, arguably, “wrong”—SDK files should always use SDK-relative paths (as, indeed, Xcode 3.2.x will do if you add a framework to a project manually):


 2D04AF89126B8A7A00073224 /* AppleScriptObjC.framework */ = {
	isa = PBXFileReference; 
	lastKnownFileType = wrapper.framework; 
	name = AppleScriptObjC.framework; 
	path = System/Library/Frameworks/AppleScriptObjC.framework; 
	sourceTree = SDKROOT; 
 };

Finally, the final output of your target also has a PBXFileReference. It looks slightly different:


 8D1107320486CEB800E47090 /* MyProject.app */ = {
	isa = PBXFileReference; 
	explicitFileType = wrapper.application; 
	includeInIndex = 0; 
	path = MyProject.app; 
	sourceTree = BUILT_PRODUCTS_DIR; 
 };

Instead of lastKnownFileType, it has an explicitFileType; it also has a property includeInIndex, set to 0 (FALSE).

You can add comment to files; these are stored as a comments property on the PBXFileReference.

PBXBuildFile

Files that need to be processed in the build (for example compiled, linked, or copied) also have a PBXBuildFile. These are very simple:

 8D11072D0486CEB800E47090 /* main.m in Sources */ = {
	isa = PBXBuildFile; 
	fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; 
	settings = {ATTRIBUTES = (); }; 
};

The fileRef is the id of the PBXFileReference. The settings property is usually omitted entirely. If you specify per-file compiler flags, they will be stored in the COMPILER_FLAGS property of the settings property.

PBXSourcesBuildPhase

Projects commonly have several build phases: compiling, linking, copying resources, copying other files, and perhaps running shell scripts. PBXSourcesBuildPhase describes the compiling phase for a target.

 8D11072C0486CEB800E47090 /* Sources */ = {
    isa = PBXSourcesBuildPhase;
    buildActionMask = 2147483647;
    files = (
      8D11072D0486CEB800E47090 /* main.m in Sources */,
      256AC3DA0F4B6AC300CF3369 /* MyProjectAppDelegate.m in Sources */,
    );
    runOnlyForDeploymentPostprocessing = 0;
 };

The files property contains an array of PBXBuildFile references. buildActionMask is usually 2147483647 (that’s 0x7FFFFFFF in hexadecimal). The runOnlyForDeploymentPostprocessing property is normally 0 (FALSE).

Until next time…

That’s it for this week! Next time, we’ll look at the other build phases.

Tags: