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.
ΒΆ