Applescripting Xcode
Posted By Quentin Carnicelli on March 11th, 2005
As I don’t like to fall too far behind with the times, today I decided to start updating our code base to use the new Objective-C @try/@catch exception handling system, replacing the old NS_HANDLER macros.To do this however, you need to enable the -fobjc-exceptions build option on each project that needs it. This wouldn’t be so terrible, except we have 20 some odd different project files in our repository currently. Updating each one by hand, which I’ve done in the past, gets to be real painful after about the third one.Luckily, Xcode has an amazingly complete AppleScript dictionary:
This seems to be a little known fact about Xcode, but it’s a real life saver in situations like this. Instead of spending the day manually clicking checkboxes, I just wrote the following Batch Updater script:Download XcodeProjectBatchUpdater.scpt(* Xcode Project Batch Updater *** (C) Copyright 2005, Rogue Amoeba Software, LLC Configuration Options: RelaunchXcodeForEachProject - Quit and relaunch Xcode for each project (or leave it open)*)property RelaunchXcodeForEachProject : trueon _updateProjectDocument(aPrjDoc) tell application "Xcode" repeat with aTarget in (every target of aPrjDoc) --set newBuildSettings to {|GCC_ENABLE_OBJC_EXCEPTIONS|:"YES"} --set build settings of aTarget to ((build settings of aTarget) & newBuildSettings) end repeat end tellend _updateProjectDocumenton _updateProjectAtPath(aPrjPath) set aPrjAlias to (POSIX file aPrjPath) as alias tell application "Xcode" open aPrjAlias --set aPrjDoc to first item of (every project document whose path starts with aPrjPath set aPrjDoc to current project document my _updateProjectDocument(aPrjDoc) if not RelaunchXcodeForEachProject then close window of aPrjDoc end if end tell end _updateProjectAtPathon _gatherUserAcceptedProjects(aSearchPath) set allPrjs to _gatherAllProjects(aSearchPath) return choose from list allPrjs with prompt "Choose the projects to update:" default items allPrjs OK button name "Update" with multiple selections allowed end _gatherUserAcceptedProjectson _gatherAllProjects(aSearchPath) set cmd to "find " & aSearchPath & " -type d \\( \\( -not \\( \\( -name .svn -and -prune \\) -or \\( -name build -and -prune \\) \\) \\) -and \\( -name '*.xcode' \\) \\) -print" set results to do shell script cmd set text item delimiters to ASCII character 13 return text items of resultsend _gatherAllProjectson run set searchRootPath to POSIX path of (choose folder with prompt "Search for projects in:" default location (path to home folder)) if searchRootPath ends with "/" then set text item delimiters to "" set searchRootPath to (items 1 thru ((length of searchRootPath) - 1) of searchRootPath as list) as string end if repeat with aPrjPath in _gatherUserAcceptedProjects(searchRootPath) if RelaunchXcodeForEachProject then tell application "Xcode" to quit delay 1 else tell application "Xcode" to close every window end if try _updateProjectAtPath(aPrjPath) on error set reply to display dialog "Failed to update project: '" & aPrjPath & "'" with icon caution buttons {"Stop", "Skip"} default button 2 if button returned of reply is not "Skip" then return end if end try end repeat if RelaunchXcodeForEachProject then tell application "Xcode" to quit end if end runHeres a brief walkthrough of the script, since you need to modify the script to do anything useful with it.1. The run handler first prompts you for a folder in which to look for project files in (and below of, it’s recursive).2. _gatherAllProjects() uses do shell script and `find` to locate the project files.3. _gatherUserAcceptedProjects() prompts for which projects to update, since odds are there are some that shouldn’t be updated.4. _updateProjectAtPath() opens the project(s) in Xcode, and finds the “project document” reference and hands it off to _updateProjectDocument()5. _updateProjectDocument() does actual work on the project. In our example script above, it would turn the GCC_ENABLE_OBJC_EXCEPTIONS build setting on. This is probably the only handler you’ll need to modify.There is one bug workaround in the script, RelaunchXcodeForEachProject. I found that if you try and keep Xcode open the entire time, after about the 4th or 5th project, it would start throwing Internal Errors. Quitting and relaunching it for each and every project alleviates the problem (most of the time, anyhow).As with any batch update system, I advise to take some caution with using it, as you can quickly mangle all your projects. Having a version control system or recent backups in place before hacking away, is highly recommended.