Unable to build MoltenVK in a nix-shell using rust-overlay on macOS

I have a nix dev shell that should include Rust. I’m unable to build part of MoltenVK (GitHub - KhronosGroup/MoltenVK: MoltenVK is a Vulkan Portability implementation. It layers a subset of the high-performance, industry-standard Vulkan graphics and compute API over Apple's Metal graphics framework, enabling Vulkan applications to run on macOS, iOS and tvOS.) using xcodebuild.

Here is my flake.nix:

{
  description = "A devShell example";

  inputs = {
    nixpkgs.url      = "github:NixOS/nixpkgs/nixos-unstable";
    rust-overlay.url = "github:oxalica/rust-overlay";
    flake-utils.url  = "github:numtide/flake-utils";
  };

  outputs = { self, nixpkgs, rust-overlay, flake-utils, ... }:
    flake-utils.lib.eachDefaultSystem (system:
      let
        overlays = [ (import rust-overlay) ];
        pkgs = import nixpkgs {
          inherit system overlays;
        };
      in
      {
        devShells.default = with pkgs; mkShellNoCC {
          buildInputs = [
            darwin.apple_sdk.frameworks.Foundation
            rust-bin.beta.latest.default
          ];
        };
      }
    );
}

Here is the xcodebuild output:

bash-5.2$ xcodebuild -project ExternalDependencies.xcodeproj/
Command line invocation:
    /Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild -project ExternalDependencies.xcodeproj/

User defaults from command line:
    IDEPackageSupportUseBuiltinSCM = YES

ComputeTargetDependencyGraph
warning: Building targets in manual order is deprecated - check "Parallelize build for command-line builds" in the project editor, or set DISABLE_MANUAL_TARGET_ORDER_BUILD_WARNING in any of the targets in the current build to suppress this warning
note: Target dependency graph (10 targets)
    Target 'ExternalDependencies' in project 'ExternalDependencies'
        ➜ Explicit dependency on target 'ExternalDependencies-macOS' in project 'ExternalDependencies'
        ➜ Explicit dependency on target 'ExternalDependencies-iOS' in project 'ExternalDependencies'
        ➜ Explicit dependency on target 'ExternalDependencies-tvOS' in project 'ExternalDependencies'
    Target 'ExternalDependencies-tvOS' in project 'ExternalDependencies'
        ➜ Explicit dependency on target 'SPIRV-Cross-tvOS' in project 'ExternalDependencies'
        ➜ Explicit dependency on target 'SPIRV-Tools-tvOS' in project 'ExternalDependencies'
    Target 'SPIRV-Tools-tvOS' in project 'ExternalDependencies' (no dependencies)
    Target 'SPIRV-Cross-tvOS' in project 'ExternalDependencies' (no dependencies)
    Target 'ExternalDependencies-iOS' in project 'ExternalDependencies'
        ➜ Explicit dependency on target 'SPIRV-Cross-iOS' in project 'ExternalDependencies'
        ➜ Explicit dependency on target 'SPIRV-Tools-iOS' in project 'ExternalDependencies'
    Target 'SPIRV-Tools-iOS' in project 'ExternalDependencies' (no dependencies)
    Target 'SPIRV-Cross-iOS' in project 'ExternalDependencies' (no dependencies)
    Target 'ExternalDependencies-macOS' in project 'ExternalDependencies'
        ➜ Explicit dependency on target 'SPIRV-Cross-macOS' in project 'ExternalDependencies'
        ➜ Explicit dependency on target 'SPIRV-Tools-macOS' in project 'ExternalDependencies'
    Target 'SPIRV-Tools-macOS' in project 'ExternalDependencies' (no dependencies)
    Target 'SPIRV-Cross-macOS' in project 'ExternalDependencies' (no dependencies)

GatherProvisioningInputs

CreateBuildDescription

ExecuteExternalTool /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool -V

Build description signature: a6ff0332f8a0873ec1551bfbdde1d492
Build description path: /Users/max/projects/MoltenVK/build/XCBuildData/a6ff0332f8a0873ec1551bfbdde1d492.xcbuilddata
note: Removed stale file '/Users/max/projects/MoltenVK/build/ExternalDependencies.build/Release/SPIRV-Cross-macOS.build/Objects-normal/arm64/82b82416624d2658e5098eb0a28c15c5-common-args.resp'

note: Removed stale file '/Users/max/projects/MoltenVK/build/ExternalDependencies.build/Release/SPIRV-Cross-macOS.build/Objects-normal/x86_64/82b82416624d2658e5098eb0a28c15c5-common-args.resp'

CompileC /Users/max/projects/MoltenVK/build/ExternalDependencies.build/Release/SPIRV-Cross-macOS.build/Objects-normal/arm64/spirv_cross.o /Users/max/projects/MoltenVK/External/SPIRV-Cross/spirv_cross.cpp normal arm64 c++ com.apple.compilers.llvm.clang.1_0.compiler (in target 'SPIRV-Cross-macOS' from project 'ExternalDependencies')
    cd /Users/max/projects/MoltenVK
    clang -x c++ -target arm64-apple-macos10.15 -fmessage-length\=236 -fdiagnostics-show-note-include-stack -fmacro-backtrace-limit\=0 -fcolor-diagnostics -std\=c++17 -stdlib\=libc++ -Wno-trigraphs -fpascal-strings -O2 -fno-common -Wmissing-field-initializers -Wmissing-prototypes -Werror\=deprecated-objc-isa-usage -Werror\=objc-root-class -Wnon-virtual-dtor -Woverloaded-virtual -Wno-exit-time-destructors -Wno-missing-braces -Wparentheses -Wswitch -Wunused-function -Wno-unused-label -Wunused-parameter -Wno-unused-variable -Wunused-value -Wempty-body -Wno-uninitialized -Wno-unknown-pragmas -Wno-shadow -Wno-four-char-constants -Wconversion -Wconstant-conversion -Wint-conversion -Wbool-conversion -Wenum-conversion -Wfloat-conversion -Wnon-literal-null-conversion -Wobjc-literal-conversion -Wno-shorten-64-to-32 -Wno-newline-eof -Wc++11-extensions -Wno-implicit-fallthrough -DNDEBUG\=1 -DSPIRV_CROSS_NAMESPACE_OVERRIDE\=MVK_spirv_cross -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.2.sdk -fstrict-aliasing -Wno-deprecated-declarations -Winvalid-offsetof -fvisibility\=hidden -fvisibility-inlines-hidden -Wno-sign-conversion -Winfinite-recursion -Wmove -Wno-comma -Wno-block-capture-autoreleasing -Wno-strict-prototypes -Wno-range-loop-analysis -Wno-semicolon-before-method-body -iquote /Users/max/projects/MoltenVK/build/ExternalDependencies.build/Release/SPIRV-Cross-macOS.build/SPIRVCross-generated-files.hmap -I/Users/max/projects/MoltenVK/build/ExternalDependencies.build/Release/SPIRV-Cross-macOS.build/SPIRVCross-own-target-headers.hmap -I/Users/max/projects/MoltenVK/build/ExternalDependencies.build/Release/SPIRV-Cross-macOS.build/SPIRVCross-all-target-headers.hmap -iquote /Users/max/projects/MoltenVK/build/ExternalDependencies.build/Release/SPIRV-Cross-macOS.build/SPIRVCross-project-headers.hmap -I/Users/max/projects/MoltenVK/build/Release/include -I/Users/max/projects/MoltenVK/build/ExternalDependencies.build/Release/SPIRV-Cross-macOS.build/DerivedSources-normal/arm64 -I/Users/max/projects/MoltenVK/build/ExternalDependencies.build/Release/SPIRV-Cross-macOS.build/DerivedSources/arm64 -I/Users/max/projects/MoltenVK/build/ExternalDependencies.build/Release/SPIRV-Cross-macOS.build/DerivedSources -F/Users/max/projects/MoltenVK/build/Release -MMD -MT dependencies -MF /Users/max/projects/MoltenVK/build/ExternalDependencies.build/Release/SPIRV-Cross-macOS.build/Objects-normal/arm64/spirv_cross.d --serialize-diagnostics /Users/max/projects/MoltenVK/build/ExternalDependencies.build/Release/SPIRV-Cross-macOS.build/Objects-normal/arm64/spirv_cross.dia -c /Users/max/projects/MoltenVK/External/SPIRV-Cross/spirv_cross.cpp -o /Users/max/projects/MoltenVK/build/ExternalDependencies.build/Release/SPIRV-Cross-macOS.build/Objects-normal/arm64/spirv_cross.o
Warning: supplying the --target argument to a nix-wrapped compiler may not work correctly - cc-wrapper is currently not designed with multi-target compilers in mind. You may want to use an un-wrapped compiler instead.
clang: warning: overriding '-mmacos-version-min=11.3' option with '-target arm64-apple-macos10.15' [-Woverriding-option]
In file included from /Users/max/projects/MoltenVK/External/SPIRV-Cross/spirv_cross.cpp:24:
In file included from /Users/max/projects/MoltenVK/External/SPIRV-Cross/spirv_cross.hpp:31:
In file included from /Users/max/projects/MoltenVK/External/SPIRV-Cross/spirv_cfg.hpp:27:
In file included from /Users/max/projects/MoltenVK/External/SPIRV-Cross/spirv_common.hpp:32:
In file included from /Users/max/projects/MoltenVK/External/SPIRV-Cross/spirv_cross_containers.hpp:27:
In file included from /Users/max/projects/MoltenVK/External/SPIRV-Cross/spirv_cross_error_handling.hpp:28:
/nix/store/cvl21fnjrwqcw59vkvhfdfl5w4d0xfaw-libcxx-19.1.6-dev/include/c++/v1/stdlib.h:143:30: error: unknown type name 'ldiv_t'
  143 | inline _LIBCPP_HIDE_FROM_ABI ldiv_t div(long __x, long __y) _NOEXCEPT { return ::ldiv(__x, __y); }
      |                              ^
/nix/store/cvl21fnjrwqcw59vkvhfdfl5w4d0xfaw-libcxx-19.1.6-dev/include/c++/v1/stdlib.h:143:82: error: no member named 'ldiv' in the global namespace
  143 | inline _LIBCPP_HIDE_FROM_ABI ldiv_t div(long __x, long __y) _NOEXCEPT { return ::ldiv(__x, __y); }
      |                                                                                ~~^
/nix/store/cvl21fnjrwqcw59vkvhfdfl5w4d0xfaw-libcxx-19.1.6-dev/include/c++/v1/stdlib.h:145:30: error: unknown type name 'lldiv_t'
  145 | inline _LIBCPP_HIDE_FROM_ABI lldiv_t div(long long __x, long long __y) _NOEXCEPT { return ::lldiv(__x, __y); }
      |                              ^
/nix/store/cvl21fnjrwqcw59vkvhfdfl5w4d0xfaw-libcxx-19.1.6-dev/include/c++/v1/stdlib.h:145:93: error: no member named 'lldiv' in the global namespace
  145 | inline _LIBCPP_HIDE_FROM_ABI lldiv_t div(long long __x, long long __y) _NOEXCEPT { return ::lldiv(__x, __y); }
      |                                                                                           ~~^
In file included from /Users/max/projects/MoltenVK/External/SPIRV-Cross/spirv_cross.cpp:24:
In file included from /Users/max/projects/MoltenVK/External/SPIRV-Cross/spirv_cross.hpp:31:
In file included from /Users/max/projects/MoltenVK/External/SPIRV-Cross/spirv_cfg.hpp:27:
In file included from /Users/max/projects/MoltenVK/External/SPIRV-Cross/spirv_common.hpp:32:
In file included from /Users/max/projects/MoltenVK/External/SPIRV-Cross/spirv_cross_containers.hpp:27:
In file included from /Users/max/projects/MoltenVK/External/SPIRV-Cross/spirv_cross_error_handling.hpp:29:
In file included from /nix/store/cvl21fnjrwqcw59vkvhfdfl5w4d0xfaw-libcxx-19.1.6-dev/include/c++/v1/string:591:
In file included from /nix/store/cvl21fnjrwqcw59vkvhfdfl5w4d0xfaw-libcxx-19.1.6-dev/include/c++/v1/__algorithm/remove.h:12:
In file included from /nix/store/cvl21fnjrwqcw59vkvhfdfl5w4d0xfaw-libcxx-19.1.6-dev/include/c++/v1/__algorithm/find.h:31:
In file included from /nix/store/cvl21fnjrwqcw59vkvhfdfl5w4d0xfaw-libcxx-19.1.6-dev/include/c++/v1/cwchar:113:
/nix/store/cvl21fnjrwqcw59vkvhfdfl5w4d0xfaw-libcxx-19.1.6-dev/include/c++/v1/wchar.h:148:20: error: use of undeclared identifier 'wcschr'
  148 |   return (wchar_t*)wcschr(__s, __c);
      |                    ^
/nix/store/cvl21fnjrwqcw59vkvhfdfl5w4d0xfaw-libcxx-19.1.6-dev/include/c++/v1/wchar.h:158:20: error: use of undeclared identifier 'wcspbrk'
  158 |   return (wchar_t*)wcspbrk(__s1, __s2);
      |                    ^
/nix/store/cvl21fnjrwqcw59vkvhfdfl5w4d0xfaw-libcxx-19.1.6-dev/include/c++/v1/wchar.h:169:20: error: use of undeclared identifier 'wcsrchr'; did you mean 'wcschr'?
  169 |   return (wchar_t*)wcsrchr(__s, __c);
      |                    ^
/nix/store/cvl21fnjrwqcw59vkvhfdfl5w4d0xfaw-libcxx-19.1.6-dev/include/c++/v1/wchar.h:150:72: note: 'wcschr' declared here
  150 | inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_PREFERRED_OVERLOAD const wchar_t* wcschr(const wchar_t* __s, wchar_t __c) {
      |                                                                        ^
/nix/store/cvl21fnjrwqcw59vkvhfdfl5w4d0xfaw-libcxx-19.1.6-dev/include/c++/v1/wchar.h:179:20: error: use of undeclared identifier 'wcsstr'; did you mean 'wcschr'?
  179 |   return (wchar_t*)wcsstr(__s1, __s2);
      |                    ^
/nix/store/cvl21fnjrwqcw59vkvhfdfl5w4d0xfaw-libcxx-19.1.6-dev/include/c++/v1/wchar.h:153:66: note: 'wcschr' declared here
  153 | inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_PREFERRED_OVERLOAD wchar_t* wcschr(wchar_t* __s, wchar_t __c) {
      |                                                                  ^
/nix/store/cvl21fnjrwqcw59vkvhfdfl5w4d0xfaw-libcxx-19.1.6-dev/include/c++/v1/wchar.h:179:20: error: no matching function for call to 'wcschr'
  153 |   return (wchar_t*)wcsstr(__s1, __s2);
      |                    ^
/nix/store/cvl21fnjrwqcw59vkvhfdfl5w4d0xfaw-libcxx-19.1.6-dev/include/c++/v1/wchar.h:153:66: note: candidate disabled: <no message provided>
  153 | inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_PREFERRED_OVERLOAD wchar_t* wcschr(wchar_t* __s, wchar_t __c) {
      |                              ~~~~~~~~~~~~~~~~~~~~~~~~~~          ^
/nix/store/cvl21fnjrwqcw59vkvhfdfl5w4d0xfaw-libcxx-19.1.6-dev/include/c++/v1/wchar.h:179:27: error: cannot initialize a parameter of type 'wchar_t *' with an lvalue of type 'const wchar_t *'
  179 |   return (wchar_t*)wcsstr(__s1, __s2);
      |                           ^~~~
/nix/store/cvl21fnjrwqcw59vkvhfdfl5w4d0xfaw-libcxx-19.1.6-dev/include/c++/v1/wchar.h:153:82: note: passing argument to parameter '__s' here
  153 | inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_PREFERRED_OVERLOAD wchar_t* wcschr(wchar_t* __s, wchar_t __c) {
      |                                                                                  ^
/nix/store/cvl21fnjrwqcw59vkvhfdfl5w4d0xfaw-libcxx-19.1.6-dev/include/c++/v1/wchar.h:190:20: error: use of undeclared identifier 'wmemchr'
  190 |   return (wchar_t*)wmemchr(__s, __c, __n);
      |                    ^
In file included from /Users/max/projects/MoltenVK/External/SPIRV-Cross/spirv_cross.cpp:24:
In file included from /Users/max/projects/MoltenVK/External/SPIRV-Cross/spirv_cross.hpp:31:
In file included from /Users/max/projects/MoltenVK/External/SPIRV-Cross/spirv_cfg.hpp:27:
In file included from /Users/max/projects/MoltenVK/External/SPIRV-Cross/spirv_common.hpp:32:
In file included from /Users/max/projects/MoltenVK/External/SPIRV-Cross/spirv_cross_containers.hpp:27:
In file included from /Users/max/projects/MoltenVK/External/SPIRV-Cross/spirv_cross_error_handling.hpp:29:
In file included from /nix/store/cvl21fnjrwqcw59vkvhfdfl5w4d0xfaw-libcxx-19.1.6-dev/include/c++/v1/string:597:
/nix/store/cvl21fnjrwqcw59vkvhfdfl5w4d0xfaw-libcxx-19.1.6-dev/include/c++/v1/__functional/hash.h:35:8: error: reference to unresolved using declaration
   35 |   std::memcpy(&__r, __p, sizeof(__r));

I can build it in a nix shell without Rust by using mkShellNoCC. However the NoCC version of mkShell will still include the nix wrapped clang. Essentially my question builds down to, how do I use xcodebuild in with nix clang OR how do I force the host clang in a nix shell when using Rust.

The errors above are ver basic. So basically the the stdlib is not working correctly. I have XCode installed:

xcodebuild -showsdks
DriverKit SDKs:
	DriverKit 24.2                	-sdk driverkit24.2

iOS SDKs:
	iOS 18.2                      	-sdk iphoneos18.2

iOS Simulator SDKs:
	Simulator - iOS 18.2          	-sdk iphonesimulator18.2

macOS SDKs:
	macOS 15.2                    	-sdk macosx15.2
	macOS 15.2                    	-sdk macosx15.2

tvOS SDKs:
	tvOS 18.2                     	-sdk appletvos18.2

tvOS Simulator SDKs:
	Simulator - tvOS 18.2         	-sdk appletvsimulator18.2

visionOS SDKs:
	visionOS 2.2                  	-sdk xros2.2

visionOS Simulator SDKs:
	Simulator - visionOS 2.2      	-sdk xrsimulator2.2

watchOS SDKs:
	watchOS 11.2                  	-sdk watchos11.2

watchOS Simulator SDKs:
	Simulator - watchOS 11.2      	-sdk watchsimulator11.2

This might be interesting, however I did not yet achieve a solution: How to override stdenv? · Issue #70 · oxalica/rust-overlay · GitHub

MoltenVK is already packaged in nixpkgs and built with the latest SDK. What are you trying to accomplish by building it yourself?

Sorry, had to delete and repost with a better answer regarding the error.

Try setting SDKROOT to the location of your SDK. The nixpkgs toolchain depends on SDKROOT to find the location of the libc headers, which seems to be the issue with missing definitions. Alternatively, you could add an SDK to your shell’s buildInputs, which will set that up for you.

Note that darwin.apple_sdk.frameworks.Foundation is an empty stub. See the manual for how to use SDKs in nixpkgs.

Also note that if the goal is to build MoltenVK for App Store deployment, you’ll need to use a native toolchain not Clang from nixpkgs. (But the easiest thing is to use the moltenvk package and probably bindgenHook to help Rust find the nixpkgs MoltenVK).

Essentialy I’m trying to use a nix shell for an existing project. A dev shell is typically great even if the project is not nix-native as getting dependencies on macOS is pain.

Also note that if the goal is to build MoltenVK for App Store deployment, you’ll need to use a native toolchain not Clang from nixpkgs.

Oh did not know that! Essentially I failed at doing this so far, because the Rust overlay overrides clang in the shell. Maybe I can change this using environment variables, however it would be great to use stdenvNoCC. Somehow this is not working with Rust as overlay.

Try setting SDKROOT to the location of your SDK. The nixpkgs toolchain depends on SDKROOT to find the location of the libc headers, which seems to be the issue with missing definitions. Alternatively, you could add an SDK to your shell’s buildInputs, which will set that up for you.

Thanks, I’m gonna try to do something like:

nativeBuildInputs = [ apple-sdk_15 ];
buildInputs = [ apple-sdk_15 ];

So overall I think there are two possibilities: Use nix wrapped clang and setup apple sdk (I failed so far doing this) or using the host clang (also failed so far due to the Rust overlay).

Setting up the apple-sdk did not change anything:

{
  description = "A devShell example";

  inputs = {
    nixpkgs.url      = "github:NixOS/nixpkgs/nixos-unstable";
    rust-overlay.url = "github:oxalica/rust-overlay";
    flake-utils.url  = "github:numtide/flake-utils";
  };

  outputs = { self, nixpkgs, rust-overlay, flake-utils, ... }:
    flake-utils.lib.eachDefaultSystem (system:
      let
        overlays = [ (import rust-overlay) ];
        pkgs = import nixpkgs {
          inherit system overlays;
        };
      in
      {
        devShells.default = with pkgs; mkShell {
          nativeBuildInputs = [ apple-sdk_15 ];
          buildInputs = [
            rust-bin.beta.latest.default
            apple-sdk_15
          ];
        };
      }
    );
}

SDKROOT:

echo $SDKROOT
/nix/store/z6fkdhmylg8xqch03ffiv9352zf8cjn0-apple-sdk-15.0/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk

I might be able to use xcbuild however I noticed some other compilation issues regarding that. Is there a way to stick with the Apple xcodebuild? However I believe that the better option is to actually use the host CC in my case. So far I failed with that though because including Rust forces a nix-wrapped clang.

Thanks for the explanations! The extra context helps. Fixing everything to build with the Nix stdenv probably won’t do what you need.

Have you looked at xcodenv? It’s targeted at iOS development, but xcodenv. composeXcodeWrapper will create a derivation that exposes Xcode as a Nix package. If you put it after Rust in your shell’s buildInputs, Xcode’s clang should win.

1 Like

Not yet but I’ll try. I think Code is not responsible for clang/cc. That comes with the command line tools installed by XCode.

Xcode ships clang, so xcodeenv.composeXcodeWrapper should link it into the resulting package.

$ xcrun --find clang # Run outside of a dev shell
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang
1 Like

Oh that sounds what I’m looking for. For some strange reason executing clang in the shell causes a hang for me and clang never really executes:

{
  description = "A devShell example";

  inputs = {
    nixpkgs.url      = "github:NixOS/nixpkgs/nixos-unstable";
    rust-overlay.url = "github:oxalica/rust-overlay";
    flake-utils.url  = "github:numtide/flake-utils";
  };

  outputs = { self, nixpkgs, rust-overlay, flake-utils, ... }:
    flake-utils.lib.eachDefaultSystem (system:
      let
        overlays = [ (import rust-overlay) ];
        pkgs = import nixpkgs {
          inherit system overlays;
          config.allowUnfree = true;
        };
          #xcodeenv = import ./xcodeenv {
          #  inherit (pkgs) stdenv;
          #};
      in
      {
        devShells.default = with pkgs; mkShell {
          nativeBuildInputs = [ 
            (pkgs.xcodeenv.composeXcodeWrapper {  })
           ];
          buildInputs = [
            rust-bin.beta.latest.default
          ];
        };
      }
    );
}

EDIT: In fact, xcrun clang hangs with no output. I can observe a lot of processes being spawned.

That problem sounds like the one fixed by xcbuild: look in native toolchain when `/usr/bin` is in path by reckenrode · Pull Request #353893 · NixOS/nixpkgs · GitHub. I assume your nixpkgs is newer than that? Can you try adding the shell hook in the following post to your dev shell? It will make sure the nixpkgs xcrun is not on PATH.

1 Like

That one sounds very similar indeed. I’d also call that a fork bomb :slight_smile:

           shellHook = ''
            #export PATH=$(echo $PATH | sd "${pkgs.xcbuild.xcrun}/bin" "")
            unset DEVELOPER_DIR
           '';

Unsetting DEVELOPER_DIR fixes it! Changing the path is not needed it seems.

Pretty wild, bug that way I think I can use the shell.

Should we patch composeXcodeWrapper?

Full dev env for reference:

{
  description = "A devShell example";

  inputs = {
    nixpkgs.url      = "github:NixOS/nixpkgs/nixos-unstable";
    rust-overlay.url = "github:oxalica/rust-overlay";
    flake-utils.url  = "github:numtide/flake-utils";
  };

  outputs = { self, nixpkgs, rust-overlay, flake-utils, ... }:
    flake-utils.lib.eachDefaultSystem (system:
      let
        overlays = [ (import rust-overlay) ];
        pkgs = import nixpkgs {
          inherit system overlays;
          config.allowUnfree = true;
        };
      in
      {
        devShells.default = with pkgs; mkShell {
          nativeBuildInputs = [ 
            sd
            (pkgs.xcodeenv.composeXcodeWrapper {  })
           ];
           shellHook = ''
            #export PATH=$(echo $PATH | sd "${pkgs.xcbuild.xcrun}/bin" "")
            unset DEVELOPER_DIR
           '';
          buildInputs = [
             #apple-sdk_15
            rust-bin.beta.latest.default
          ];
        };
      }
    );
}

It must be picking up the xcrun in the default SDK, which is weird. I’d suggest opening an issue on GitHub because there have been efforts to make it not do that, but it still is.