Missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun

George J Ficzeri
3 min readFeb 10, 2021

After upgrading to macOS Big Sur, I ran into an error sharing my tmux config:

➜ ~ grep -v ^# ~/.tmux.conf | strings | pbcopy

xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun

The fix was just a quick reinstall of the XCode command line tools.

➜ ~ sudo xcode-select --install

But why was this needed? A little process of elimination reveals the command that triggered the error was strings. But why?

The error seems to point to xcrun. A quick man xcrun says “xcrun provides a means to locate or invoke developer tools from the command-line”, which doesn’t seem relevant? What about strings? There’s no strings at that path, right?

➜ ~ find /Library/Developer/CommandLineTools -name strings
/Library/Developer/CommandLineTools/usr/bin/strings

Hmm, ok… I thought it was in /usr/bin?

➜ ~ which strings
/usr/bin/strings

😕

Back to man xcrun. “xcrun provides a means to locate or invoke developer tools from the command-line…” Ok, so xcrun is invoking strings, but from this path…?

➜ xcrun -find strings
/Library/Developer/CommandLineTools/usr/bin/strings

I’m confused. Time for some research. After a bit of reading, I found my answer in this article: https://macops.ca/developer-binaries-on-os-x-xcode-select-and-xcrun/. In it, the author explains, “The developer tool binaries actually ship with OS X as shim binaries, which use a system library to resolve a path to a “Developer” directory, where all the actual executables, libraries and support files are installed.” He demonstrates this using otool to see what a binary is linked to. Using our strings:

➜ ~ otool -L `which strings`
/usr/bin/strings:
/usr/lib/libxcselect.dylib (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1292.60.1)

He goes on to say, “Behind the scenes, if I run /usr/bin/git, this shim binary loads functions in libxcselect.dylibthat can locate the path to the real binary, depending on how the system has been configured. One part of this process is to check whether this path contains usr/lib/libxcrun.dylib, and the xcrun tool, in which case it will invoke xcrun to run the binary.” Which we discovered earlier is pointing to /Library/Developer/CommandLineTools/usr/bin/strings.

To confuse things further, According to the macOS Big Sur 11 Beta Release Notes, “the system ships with a built-in dynamic linker cache of all system-provided libraries. As part of this change, copies of dynamic libraries are no longer present on the filesystem.” i.e., if you go searching for it in the filesystem you might not find anything. If you trace strings with dtruss

➜ ~ sudo dtruss -n strings
— — — — — 8< — — — — — —
7782/0x11fd6: stat64(“/System/Library/dyld/dyld_shared_cache_x86_64h\0”, 0x7FFEE79E9058, 0x0) = 0 0
7782/0x11fd6: getpid(0x0, 0x0, 0x0) = 7782 0
7782/0x11fd6: stat64(“/Library/Developer/CommandLineTools/usr/bin/strings\0”, 0x7FFEE79E96C0, 0x0) = 0 0
7782/0x11fd6: stat64(“/System/Library/dyld/dyld_shared_cache_x86_64h\0”, 0x7FFEE79E9058, 0x0) = 0 0
7782/0x11fd6: getpid(0x0, 0x0, 0x0) = 7782 0
7782/0x11fd6: stat64(“/Library/Developer/CommandLineTools/usr/bin/strings\0”, 0x7FFEE79E96C0, 0x0) = 0 0
7782/0x11fd6: proc_info(0x2, 0x1E66, 0x1F) = 1040 0
7782/0x11fd6: stat64(“/usr/lib/libSystem.B.dylib\0”, 0x7FFEE79E8740, 0x0) = -1 2

in the wall of text returned (after running the strings command) can see that dyld_shared_cache call.

--

--

George J Ficzeri

I like coffee, standing desks, and uptime. 😬 🎧