Multiple Xcode versions or Why xcrun is your friend

The story

I recently spent a few hours helping a friend of mine investigate a weird issue in their Continuous Development infrastructure. Builds were failing with different fatal errors mostly related to SDK paths and .platform directory locations. At first sight, it was clear that something is wrong with the current selected Xcode, but all our initial attempts to catch the problem failed.

In the end, we isolated the problem; one of the tools they use changes PATH silently for the environment to simplify access to Xcode tools. Due to their internal logic, the CD pipeline changes a current selected Xcode a few times on the way within the same script. In some cases, the pipeline ended with xcodebuild in the environment’s PATH that does not reflect the expected version after the xcode-select — switch command.

How? Pretty easy, actually. A simplified sequence looked like this:

xcrun — Invoke Xcode tools in a safer way

According to the documentation:

xcrun provides a means to locate or invoke developer tools from the command-line, without requiring users to modify Makefiles or otherwise take inconvenient measures to support multiple Xcode toolchains.
The tool xcode-select(1) is used to set a system default for the active developer directory and may be overridden by the DEVELOPER_DIR environment variable.

In real life, it means that you can prefix all the calls to Xcode tools with xcrun on CI/CD to avoid the situation I described in the beginning. Want to run xcodebuild — call it via xcrun xcodebuild command, need to run/invoke simulators, use the xcrun simctl command.

It can save a few hours for your RE/DevOps team at the end of the day. And, depends on the company size, from 5 to 100 hours for your engineers.

What else?

xcrun has a few additional commands.

find — enables “find” mode, in which the resolved tool path is printed instead of the tool being executed.

A few helpers to print paths/versions of the selected SDKs.

verbose option shows the logic behind the xcrun. For example, you can see that all the mappings are stored within a temporary xcrun_db and populated on the stage when you select a different Xcode version.

Side notes

- Check the previous note about xed Xcode invocation tool
- Create a minor task for your DevOps team to prefix all the calls to Xcode tools with xcrun

Principal Engineer @Bumble