As Mac admins, the relationship with the developers in your organization working on macOS to build apps for Apple platforms is often challenging. They can be the most enthusiastic and knowledgeable about macOS, but they are also very demanding regarding tooling and configuration of their Macs or rather, insist that you get out of their way to set up everything just the right way.
The most essential tool for developers on macOS is Xcode, but deploying Xcode in a managed environment poses many challenges for Mac admins.
Note: As I am writing this, Xcode 14.3.1 is the current release version and Xcode 15 is in beta. There were some changes relevant to managed deployment of Xcode in Xcode 14 and more in Xcode 15. Because Xcode 15 is still in beta, there may be changes in behavior before its release in September.
The first challenge is to get the Xcode app installed on the Macs. Xcode is mostly a special challenge because of its sheer size. Xcode 14 expands to ~23 GB in size and Xcode 15 to ~11.7 GB. (We will look at why Xcode 15 is much smaller later.)
Mac App Store
Apple provides Xcode in the Mac App Store. For Mac admins that means we should be able to deploy Xcode through volume purchasing with Apps and Books. You can go into Apple Business Manager or Apple School Manager and “purchase” a number of free licenses for Xcode and use the app deployment functionality of your management system to push those apps. There are quite a few downsides to deploying apps this way, and they are all exacerbated by Xcode’s unusual nature and size.
With the current (macOS Ventura and earlier) MDM protocol, there is no feedback from the client to the server after the server sends the command to install an app. There is also no way for the local user to see the status of installation. The user will likely not even know that a significant download and installation is going on in the background! If the installation on the client side fails for some reason, neither the user nor the MDM server will be notified, and there are many reasons the download and installation might fail.
A user might close or sleep a laptop or move the device out of network range during the download or installation, leading to failures. This can happen with any installation, but given the size of Xcode, it is far more likely, especially since there is not way to inform the user of the status.
One advantage of using App Store installation is that you can benefit from a Mac with Content Caching enabled in your network. This should speed up the download significantly.
Apple has announced changes to the MDM protocol in iOS 17 and macOS Sonoma that should improve the workflow of managed deployment of Mac App Store apps dramatically, but it will take a while for MDM developers to adopt and implement the new features and for organizations, users and developers to adopt the new versions of Xcode and the operating systems. It might be some time before we can all benefit from these new features.
In general, Mac App Store installations work more reliably when initiated by the user through Self Service. A large part of this is that the user is aware that an installation will be happening, and that it might take some time. But (at least up to Ventura) installations through policies are more reliable than with volume purchasing through Apps and Books.
Another characteristic of app deployments through Apps and Books is that you will always receive the latest, non-beta version. Once installed, Xcode should also automatically download and apply updates, at least as long as Xcode is not open. You cannot manage deployment of older or beta versions either. Depending on your organization, this might be an advantage or a big disadvantage.
If you want to install Xcode with a Jamf policy, you need to provide an installation package or pkg with Xcode inside.
Apple provides downloads for Xcode in their developer portal. The downloads page lists (among many other things) older versions and beta versions of Xcode. You need an Apple Developer account to access this page, but the free tier is sufficient. (I also like the Xcode Releases page, which has a useful overview.)
Xcode will download as a xip archive. You can double-click the archive in Finder to expand it. Expansion will take a long time, because well, it is a big archive with more than 100,000 files inside and also because the signature and integrity of the archive is verified before expanding.
Once you have unarchived Xcode you can repackage it. You don’t need some fancy packaging tool. You can just use productbuild:
% productbuild --component /path/to/Xcode.app /Applications Xcode-14.3.1.pkg
The first path after the --component flag points to the location of the Xcode application bundle, and the second is the file path where it will be installed on the target system. The last argument is the filename of the pkg that will be created. I strongly recommend adding the version into pkg file names. Xcode does not have to be in /Applications, and it doesn’t have to be launched or configured for this re-packaging command.
This will take a long time.
Note 1: If you care about download time and file size you can save ~25% by adding the '--componentcompression auto' option. This option will take more time to compress (and more time to de-compress on the target client), with the benefit of a smaller file size. More detail in this post.
Note 2: If you require multiple different versions of Xcode installed on the same system (such as the beta and the current version), you need to disable the ‘relocatable’ flag in the installation package. You can find instructions on how to achieve that in this post, but the easiest way is with my quickpkg tool.
First launch configuration for non-admin users
The work of a Mac admin is not done after the deployment of Xcode app(s). We also have to configure Xcode to be usable by the users. When you launch a new version of Xcode for the first time on a new system, it will prompt for the installation of additional components that require administrator privileges.
When the users in your deployment have admin privileges, this should not be much of a challenge. They can authorize these steps themselves. However, some deployments use standard users which cannot authorize these steps.
There is a good argument that standard users are a relic of the past and not a good practice for many deployments any longer, mostly because with the architecture and built-in security of macOS, the security benefits of standard users are minimal. (See Graham Gilbert’s post and MacSysAdmin presentation.)
That said, some deployments, like schools and other educational setups, don’t have this choice. Some Mac admins might prefer a different choice but have to pick their arguments with management and security interests in their organization carefully. Whatever the reason, many of us have to deal with standard users.
Also, with all of that said, automating some of the configuration in the background provides a nicer experience overall, so you might want to do it, even when the users have admin privileges.
These steps that Xcode prompts for at first launch require admin privileges:
- Select the new version when multiple versions of Xcode are installed
- Accept Xcode and Apple SDKs agreement
- Install additional components
- Enable developer tools security for non-admin users
There are command line tools to perform all of these steps, so we can automate them with a script. These commands will need to run as root, such as from a post install script policy from Jamf Pro.
First, we ensure that the command line tools are using the latest Xcode we just installed with the xcode-select command. Then we use xcodebuild to accept the license, and initiate the ‘first launch’ workflow. Both of these steps require administrator privileges.
In the next step we nest the everyone group in the _developer group. This is in preparation for the next command where we enable DevToolSecurity. This allows admins or members of the _developer group to run certain debuggers or performance analysis tools without needing to authorize with their password.
By nesting the everyone group in the _developer group we have pre-emptively added every user on the system, even users that may be created after this script runs, to the group that grants the privileges. If you would rather be more restrictive, you can change the dseditgroup to only add the currently logged in user.
The processes that DevToolsSecurity enables seem to be mostly relevant for debugging and performance workflows with command line tools and scripts. If you are particularly security sensitive, you can test if your developers can use their workflows without enabling this.
Managing platform SDKs with Xcode 14 and 15
There is one more thing you want to pre-install. Over the last few years, Apple has vastly reduced the size of Xcode downloads:
- Xcode 11: 7.5 GB
- Xcode 12: 11 GB
- Xcode 13: 10 GB
- Xcode 14: 7 GB*
- Xcode 15: 3.1 GB**
* does not include watchOS and tvOS SDKs
** does not include iOS, watchOS, tvOS and visionOS SDKs
Most of these savings come from the Xcode download not including all the platform SDKs any more. (Xcode 14 comes with macOS and iOS; Xcode 15 only includes macOS.) Since the platform SDKs are necessary to build and simulate apps on the various platforms, users are prompted on first launch platforms they want to download and install.
This means the large downloads are merely deferred, not avoided. In total, Xcode 15 and all the platforms (iOS, watchOS and tvOS) add up to more than 17 GB, with visionOS nearly another 7 GB on top of that. So, there are no real download savings in the new Xcode versions, quite the opposite, but the greatly reduced size of the initial Xcode install should make installations from the Mac App Store or using Apps and Books more reliable.
The good news for managed deployment is that the Xcode user does not need to have admin privileges to download and install additional SDKs. They can choose what to download at the initial prompt, or go to the ‘Platforms’ tab in Xcode Settings to get additional platforms at a later time.
But maybe you still want to make the end user’s life a bit easier. When you are deploying Xcode in a classroom environment, you cannot waste everyone’s time with the required download. Or you might be deploying Xcode on a Mac for automated build processes with no user involved at all. In that case you want to automate the deployment of the necessary platform SDK(s).
Somewhat surprisingly, Apple has some documentation for this, which again points us to using the xcodebuild command.
There are three options in xcodebuild that are relevant for this: -downloadAllPlatforms will, well, download all available platforms. This is convenient, but we are talking more than 20 GB for all platforms for Xcode 15. -downloadAllPreviouslySelectedPlatforms should be useful after an Xcode update.
Finally, there is -downloadPlatform which downloads the designated platform. The names for the various platforms are missing from the documentation and the command help, but are mostly easy to guess: iOS, watchOS, tvOS and xrOS (for the visionOS SDK; this might still change during the beta phase?).
If you run the command again when a platform is already installed, it will notice and not download it again, so we can just add the desired platforms to the end of our configuration script:
Xcode 14 comes with the iOS SDK included, but xcodebuild detects the existing SDK and doesn’t download again. In my testing, the download used a local caching server, which sped things up significantly.
With Xcode 15, I saw a user-facing progress bar popup while it verified the download. This could be disconcerting to users when it happens without them initiating the process, but should not be a problem if this is part of your initial deployment workflow.
Xcode is an important app for many of our users. It poses some particular challenges for managed deployments. The tools and scripts shown here should help you create a great experience for you and your users.
The approach shown here has worked well for me, but is probably not the only one or even the best one for certain environments.
Have market trends, Apple updates and Jamf news delivered directly to your inbox.