Wednesday, September 16, 2009

Shell Script To List XCode Target Source Files

I develop a lot of c++ code on my mac for cross-platform applications, and I've often wanted a convenient way to export a list of source files belonging to a given target in an XCode project. That way when one of my colleagues wants to create a new project on another platform (e.g. Visual Studio or makefile) I can tell them which subset of the source tree to compile for a given application. I've looked several times for a solution but never had any luck. So finally last night I did what any programmer would do and I wrote my own shell script to parse this information out of the XCode pbxproj file.

I'm sharing it here because I'm not sure where else to post it, so if anyone has any suggestions let me know. I also had to learn a bit about awk and sed and I'm not a bash programmer by trade so I'm sure there is a more efficient/elegant/obfuscated way to do this - if anyone has suggestions please do share.

The pbxproj file is coded by long hex codes - so the trick was to find the section of the file that defines the names of the targets, then work forwards from there using the hex codes to find the right lines of the file and figuring out the right awk/sed commands to parse out the relevant information.

I've only tested this with XCode 3.1.3 and with only a single project, so I don't know how robust it is. It's at least a start. Thanks to for their quick source code formatter.


# Dan Swain dan.t.swain at 9/15/09

# Bash script to list the source files that are compiled for each target
# in an xcode project file.
# If an argument is specified, it is taken to be the name of the
# xcode project - the program looks for argument.xcodeproj/project.pbxproj
# If no argument is specified, the program searches for a .xcodeproject
# directory in the current directory. This probably won't work
# if there is more than one .xcodeproj directory.

# given the name of the project, this is the location of the project file
if [ $1 ]
XCODEPROJ=`find . -name '*.xcodeproj'`

# finds the lines defining the names of the targets
LINES=`sed -n '/isa = PBXNativeTarget/=' $PBXFILE`

# for each target
for LINE in $LINES
# the target name is on the previous line and is the second field
# delimited by *'s, we also remove a leading and trailing space
TARGETNAME=`awk 'NR=='$((LINE-1)) $PBXFILE | awk -F\* '{print $2}' | sed 's/^[ ]//;s/[ ]$//'`

echo Source Files for Target $TARGETNAME:
echo ====================================

# this is the hex code corresponding to the sources for this target
SOURCES=`awk 'NR=='$((LINE+4)) $PBXFILE | awk '{print $1}'`

# find the line numbers containing the hex code for the sources
# there are two of these, so this leaves us with just the last one
: # just want the last one

# the first file is 4 lines below this
# loop over the subsequent lines until the awk command fails
while [ "$OK" = "0" ]
# the source file is the third field
FILE=`awk 'NR=='$SL $PBXFILE | awk '{print $3}'`
if [ $FILE ]
echo $FILE
# next line