Xcode Index
January 25th, 2007If you use Xcode often, surely you appreciate the “Code Sense Index.” This is the magic cache of symbolic info that allows tricks like command-double-clicking a variable name to jump to its declaration, or Opt-Period to complete a function name. Indexing makes life for programmers about one bajillion times easier.
Unless. Ughh!!!!! Angst, angst, angst! It’s got crap in the index. You jump to a definition, make a load of changes, build, run, and … nothing’s changed. What on earth? You thought for sure you fixed it. Finally you stumble upon the nuanced fact that the source file you’re editing isn’t located in your project directory. In fact, looking at the full path you see fragments like “.bak” or “old” or “copy” in the hierarchy. This is some bogus copy of your source base that you moved aside, but somehow Xcode caught up with it.
I’m not exactly sure how this happens, but I suppose the recommended procedure for fixing it is to click the “Rebuild Code Sense Index” button from the Project Inspector window. Heck, for all I know this might work. But it gives no feedback – no sense of whether the reindexing has started, or when it will be done. And especially no feedback about what it chose to index. Well, truth be told you can see some vague feedback about the indexing progress if you open the “Activity Monitor” window. But it’s still not completely reassuring.
I stumbled on the “xcodeindex” command-line tool, which is a real gift. With this you can not only explicitly remove the index, but you can recreate it with a variety of debugging log levels set, to see exactly what’s going on.
But Apple really made my day by including a “dump” option. For instance:
% xcodeindex -project FlexTime.xcodeproj dump > MyIndex
Yields a tab-delimited file containing all the indexed terms that Xcode knows about for my project. Nifty!
Anatomy Of An Index Dump
The index file contains thousands of rows divided into 5 tab-delimited columns detailing the symbol name, description, type, language, and file. Let’s take a look at a sample line from my FlexTime index, column by column:
adaptPlaybackToDisappearingItem:
This is the symbolic name, what I would have to double-click on to get Xcode to wake up and notice it was an indexed term.
-[RoutineDocument(Running) adaptPlaybackToDisappearingItem:]
This is the description, which seems to be what Xcode displays for instance in the popup menu when there are more than possible choices. Clearly this description will vary based on the language the symbol happens to belong to.
Instance Method
The type is probably the most interesting column, after name. In this case I’m told it’s an instance method. Other rows in the output include types like “Instance Variable,” “Function,” and “Type.”
Objective-C
Language. Well, that’s pretty obvious.
/Users/daniel/Sources/FlexTime/RoutineDocument+Running.m
Source file. Everything has a source file, including items from the System APIs, which point into the root volume or the appropriate SDK.
Great Expectations
What’s really exciting about this index dump file is that I can read it. You can read it. We can write scripts to do nifty analysis tricks with it. Xcode’s standard project indexes are kept in some (presumably) proprietary binary format that we dno’t have easy access to, but the dump file opens things up to the masses.
For instance, sometimes I’d really like to know the answer to questions like “which of my custom classes is depended upon by the fewest of its peer classes?” I’m not sure how I would figure that out (no doubt some of you will comment with another clever solution), but I’m pretty sure I can whip up a Python script to do the trick with this dump file.
Update: Well, call off the party balloons. The index dump file is cool, but not quite as cool as I was imagining. I just realized that because the “Instance Variable” types don’t indicate the type of the variable, they’re not very useful for tracking down dependencies.
January 25th, 2007 at 2:33 pm
The reason that the index sometimes contains references to the “wrong” project is that it (per default) is located in your build directory. If you’re using a shared build directory (not the default), for example because you’re using project references, and if you have multiple branches / copies of your project that all “point” to this same build directory, the index can (or, will often) end up with references to all those different projects. If the index had contained project-relative source file references this would still not be a problem, but since they’re absolute you get the observed behaviour.
A workaround is to use the XCCodeSenseIndexBasePath preference key to instruct Xcode to store the index in the project directory. See: “Xcode > Help > Show Expert Preferences Notes” for more information about this preference key.
January 25th, 2007 at 2:57 pm
Great tips, Joar. I hadn’t thought about the shared build-folder problem but now it makes perfect sense!
January 25th, 2007 at 5:02 pm
Daniel: I think this is actually j o a r, not Joar ;-)
and I just want to say thanks too!! (to both of you…)
January 26th, 2007 at 1:56 am
How do you stumble across these insights? The design class model feature in Xcode is often overlooked, I myself haven’t had time to delve into it properly. But I do believe that as long as your instances have class declarations it will create connection. J o a r is on my list of the few people whose post I read on the cocoa list no matter what they are about as they are always insightful. I am going to bookmark this page and come back and play with my index later, as right now I have an update to concentrate on. :)
January 26th, 2007 at 7:25 am
Conor: well, it’s always something I stumble upon for a reason. In this case I was in fact motivated after being disappointed by the Xcode Class Model :) Unless somebody knows otherwise, the Class Model in Xcode only shows inheritance relationships, not instance variable dependencies.
I thought I would be able to work around that by using Xcode’s scripting interface to the “model document.” So close, yet so far! I was able able to ask for a list of all the classes in the model, and even ask for all the variables of the classes. But unfortunately again the variables are not tagged with any information about what class they point to (even though this information is available through the UI in the class model, as a list).
January 27th, 2007 at 8:26 am
I had such high hopes for the class model, I was hoping that be exactly what it would do. At least, thanks to you, I now know the solution.
April 6th, 2007 at 3:37 pm
What can I do if xcode crashes when I use the gui to rebuild my index? I have tried xcodeindex from the command line but still no luck.
I went far enough to look at the stats options and the dump option but both of these react as if there is no index at all. Any Suggestions?
April 6th, 2007 at 4:27 pm
You mean it crashes even when you rebuild it from the command line? I guess I would ask on the xcode-users mailing list and see if any of the Apple xcode team has a suggestion.