Deleting DerivedData the right way

January 31 2020 by Jeff Johnson

I know what you're thinking: there's a wrong way to delete Xcode's DerivedData? It turns out, yes, there is! The good news is that manually moving the DerivedData folder to the trash from Finder is the right way, or a right way. The bad news is that rm -fR from the command-line is the wrong way. To see why, we need to look at another command-line tool, hidden deep within your system:

/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister

The lsregister tool gives you direct access to your Launch Services database. For convenience, I have an alias to it in my .bash_profile file:

alias 'lsregister=/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister'

Call the lsregister tool with no arguments to see its usage. The -dump argument displays the full contents of your Launch Services database. If the following command produces any lines of output, then you've been deleting DerivedData wrong. (Replace the path with your DerivedData folder. I have a symlink from ~/Library/Developer to /Users/Shared/Developer for reasons.)

lsregister -dump | grep /Users/Shared/Developer/Xcode/DerivedData

According to Apple's documentation, "macOS Launch Services is an API that enables a running app to open other apps or their document files, similar to the Finder or the Dock… Launch Services eliminates apps having to query the Finder to open an app, document, or URL for them. The macOS Finder itself uses Launch Services to perform such tasks. Because the Finder performs no additional processing beyond calling Launch Services, any client using Launch Services for these purposes behaves identically to the Finder." When you install an app on your Mac, Finder automatically registers the app with Launch Services. However, this registration doesn't happen automatically when you compile an app with Xcode. That's why the final step in the build process, which you can see in the Xcode build transcript, is RegisterWithLaunchServices. If the above lsregister command didn't produce any output, then try it again after building an app with Xcode for the Mac or for the iOS simulator.

Finder is good about automatically unregistering apps with Launch Services when you put them in the trash and empty it (but not before emptying the trash). However, the rm command-line tool bypasses the trash, and thus also bypasses Launch Services. This means that any registered apps in the removed folder remain in the Launch Services database, effectively forever! Try it and you'll see.

rm -fR /Users/Shared/Developer/Xcode/DerivedData

Fortunately, it's still possible, though tedious, to force unregister an app that has already been deleted from your Mac. Just get the app path from the Launch Services database.

lsregister -f -u "/Users/Shared/Developer/Xcode/DerivedData/LinkUnshortener-fnlhvgtizcjhthhbvextdekzeepd/Build/Products/Debug/Link Unshortener.app"

I know that a lot of developers like to use a command-line tool to delete DerivedData. So the question is, how do you do this the right way? The answer is, of course, to do it like Finder! You can use AppleScript to control Finder, and you can call AppleScript from Terminal with the osascript command-line tool.

osascript -e "tell application \"Finder\" to move POSIX file \"/Users/Shared/Developer/Xcode/DerivedData\" to trash"
osascript -e "tell application \"Finder\" to empty trash"

Again, I've written a convenient alias for this in my .bash_profile file:

alias 'deriveddata=osascript -e "tell application \"Finder\" to move POSIX file \"/Users/Shared/Developer/Xcode/DerivedData\" to trash" -e "tell application \"Finder\" to empty trash"'

The osascript tool can take multiple -e arguments, each of which is a line of AppleScript. The first time you try osascript you may see a system dialog requesting permission for Terminal to control Finder, because macOS is now Windows Vista.

Another benefit of deleting DerivedData like Finder, besides unregistering apps from Launch Services, is that you get to hear the satisfying "empty trash" sound when it's done. Or the completely unsatisfying sound on macOS Big Sur. Either way, there's a sound to notify you.

By the way, the above AppleScript will print an error message in Terminal if you have no DerivedData folder on disk, but the error is nothing to worry about. You could probably modify the script to avoid the error, but I'll leave that as an exercise for the reader. In this time of working from home, you could probably use more exercise.

Jeff Johnson (My apps, PayPal.Me)