Skip to content

Instantly share code, notes, and snippets.

@dive
Last active April 16, 2022 23:29
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save dive/da0a696f2d51a1cbef04762c3a216192 to your computer and use it in GitHub Desktop.
Save dive/da0a696f2d51a1cbef04762c3a216192 to your computer and use it in GitHub Desktop.
How to get the current selected Xcode and list installed

How to get the current selected Xcode and list installed

Current Selected Xcode

xcode-select

This is the most common way to get the path to the selected instance:

xcrun xcode-select --print-path
# Output
% xcrun xcode-select --print-path
/Volumes/Extended/Archives/Xcode_12.5.app/Contents/Developer

According to the documentation:

Prints the path to the currently selected developer directory. This is useful for inspection, but scripts and other tools should use xcrun(1) to locate tool inside the active developer directory.

Note: If you wonder why I prefix the xcode-select with xcrun command, please, check the Multiple Xcode versions or Why xcrun is your friend article.

readlink

There is a trick to get the current selected Xcode version without the xcode-select tool. It can be helpful in some cases, but I recommend using xcode-select if you have no additional requirements. To check the current selected Xcode version without xcode-select, evaluate the following command:

readlink /private/var/db/xcode_select_link
# Output
% readlink /private/var/db/xcode_select_link
/Volumes/Extended/Archives/Xcode_12.5.app/Contents/Developer

Every time you switch the default Xcode, xcode-select changes the link to the selected version. Perhaps, this is the fastest way to obtain the path, but it is not documented, and Apple can break it with any following Xcode release.

List of installed Xcode versions

Spotlight

The easiest way to get the list of installed Xcode versions is to ask the Spotlight with the following command:

mdfind "kMDItemCFBundleIdentifier = 'com.apple.dt.Xcode'"
# Output
% mdfind "kMDItemCFBundleIdentifier = 'com.apple.dt.Xcode'"
/Volumes/Extended/Archives/Xcode_12.5.app
/Volumes/Extended/Archives/Xcode_12.4.app
/Volumes/Extended/Archives/Xcode_12.1.app
/Volumes/Extended/Archives/Xcode_12.3.app
/Volumes/Extended/Archives/Xcode_12.2.app

Note: This approach is usually not suitable for CI/Remote Builds because this is a popular option to disable Spotlight to improve performance.

system_profile

The less obvious way to get the list of installed Xcode versions is to use the system_profiler. It registers all the versions immediately when you extract them from the xip file.

system_profiler -json SPDeveloperToolsDataType

The problem here is the output. It is vast and looks like the following for each installed version:

{
  "SPDeveloperToolsDataType" : [
    {
      "_name" : "spdevtools_info",
      "spdevtools_apps" : {
        "spinstruments_app" : "12.5 (64544.130)",
        "spxcode_app" : "12.5 (18205)"
      },
      "spdevtools_path" : "/Volumes/Extended/Archives/Xcode_12.5.app",
      "spdevtools_sdks" : {
        "iOS" : {
          "14.5" : "(18E182)"
        },
        "iOS Simulator" : {
          "14.5" : "(18E182)"
        },
        "macOS" : {
          "11.3" : "(20E214)",
          "20.4" : ""
        },
        "tvOS" : {
          "14.5" : "(18L191)"
        },
        "tvOS Simulator" : {
          "14.5" : "(18L191)"
        },
        "watchOS" : {
          "7.4" : "(18T187)"
        },
        "watchOS Simulator" : {
          "7.4" : "(18T187)"
        }
      },
      "spdevtools_version" : "12.5 (12E262)"
    },
...
}

Parse the system_profiler output with jq

You have to parse the system_profiler output to provide meaningful information. One option is to use jq – a lightweight and flexible command-line JSON processor. For example, if you want to list paths:

system_profiler -json SPDeveloperToolsDataType | jq '.SPDeveloperToolsDataType[].spdevtools_path'
# Output
% system_profiler -json SPDeveloperToolsDataType | jq '.SPDeveloperToolsDataType[].spdevtools_path'
"/Volumes/Extended/Archives/Xcode_12.5.app"
"/Volumes/Extended/Archives/Xcode_12.4.app"
"/Volumes/Extended/Archives/Xcode_12.3.app"
"/Volumes/Extended/Archives/Xcode_12.2.app"
"/Volumes/Extended/Archives/Xcode_12.1.app"

Or for installed versions:

system_profiler -json SPDeveloperToolsDataType | jq '.SPDeveloperToolsDataType[].spdevtools_apps.spxcode_app'
# Output
% system_profiler -json SPDeveloperToolsDataType | jq '.SPDeveloperToolsDataType[].spdevtools_apps.spxcode_app'
"12.5 (18205)"
"12.4 (17801)"
"12.3 (17715)"
"12.2 (17535)"
"12.1 (17222)"

Tips & Tricks

How to get the installed Xcode version

When you have the path to the current selected Xcode, then you can use the following function to extract CFBundleShortVersionString or ProductBuildVersion:

#!/bin/sh -e

function xcodeBundleVersion() {
    defaults read "${1}/../version.plist" "CFBundleShortVersionString"
}

function xcodeBuildVersion() {
    defaults read "${1}/../version.plist" "ProductBuildVersion"
}

function xcodeVersion() {
    BUNDLE_VERSION=$(xcodeBundleVersion ${1})
    BUILD_VERSION=$(xcodeBuildVersion ${1})
    echo "Xcode ${BUNDLE_VERSION} (${BUILD_VERSION})"
}

# Note that you can replace the `xcode-select` call with other methods to extract the path
XCODE_VERSION=$(xcodeVersion $(xcrun xcode-select --print-path))
echo $XCODE_VERSION

Faster Xcode secure-archive expansion (xip)

When you download a xip secure archive, you can expand it from CLI with xip tool. In this case, the validation of the archive will not be attempted. On Mac mini M1, it takes around four minutes to expand it.

% du -h Xcode_12.0.1.xip
  10G    Xcode_12.0.1.xip

% time xip --expand Xcode_12.0.1.xip
xip: signing certificate was "Development Update" (validation not attempted)
xip: expanded items from "/Users/dive/Downloads/Xcode_12.0.1.xip"
xip --expand Xcode_12.0.1.xip  901.47s user 139.39s system 420% cpu 4:07.79 total

xcodes – a command-line tool to install and switch between multiple versions of Xcode

I can recommend xcodes as a tool to manage your Xcode installation. The tool itself has a few benefits:

  • When aria2 (a lightweight multi-protocol & multi-source command-line download utility) installed, then xcodes will default to use it for downloads. It uses up to 16 connections to download Xcode 3-5x faster than usual
  • xcodes written in Swift. Improve, fix and evolve if you need something from the tool
% xcodes installed 
12.1 (12A7403)           /Volumes/Extended/Archives/Xcode_12.1.app
12.2 (12B45b)            /Volumes/Extended/Archives/Xcode_12.2.app
12.3 (12C33)             /Volumes/Extended/Archives/Xcode_12.3.app
12.4 (12D4e)             /Volumes/Extended/Archives/Xcode_12.4.app
12.5 (12E262) (Selected) /Volumes/Extended/Archives/Xcode_12.5.app

It relies on xcodereleases.com data (JSON), so you can expect delays between releases and the tool updates. But usually, it takes 10-20 minutes for an update.

Note: The tool downloads Xcode versions directly from the Apple Developer Portal. And this is the only way to do so. Please, do not download Xcode versions from third-party storages.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment