Since I’ve mentioned it in a response to a few PRs and have been talking about it for the last six or so months on Matrix, I thought I would post an update to explain a bit what is coming for Darwin SDKs.
Disclaimer: This is a work in progress. Things could change, but it’s shaping up to be pretty good.
Background
There are currently three SDKs available for Darwin in nixpkgs: 10.12, 11.0, and 12.3. The default SDK is different between platforms, and there are several different ways of using SDKs. It is possible to cross-compile from x86_64-darwin to aarch64-darwin but not the other way around. The SDKs are built with different patterns, and updating them is difficult. There are also two ways of overriding the default SDK, and the better one is not even documented (which is my fault).
The current situation works and has served nixpkgs for many years, but it can be improved. Instead of packaging frameworks individually, which contributes to making it difficult to update the SDK and makes overriding SDKs impossible to do generally (because dependencies can be propagated in ways that are invisible to Nix, the language), the SDK can be provided as a single package.
The Solution
The solution is to add another pattern. See also: xkcd: Standards.
More seriously, yes. Native tooling on Darwin expects there to be an SDK at a standard location. It can be changed using xcode-select
, but the location can also be specified via SDKROOT
and -isysroot
. The change is to take advantage of these to implement support for a single SDK package. Hooks are also used to make sure that only one SDK can be active at a time (though technically SDKROOT_FOR_BUILD
and SDKROOT_FOR_TARGET
will also be supported).
By default, the stdenv will come both a default SDK (same as current) as xcrun
. To change the SDK used in your package, you add it to your package’s buildInputs
. The hooks will make sure that’s what you get (unless a dependency propagates a newer SDK, then you will use that). For an example of what this looks like, see this diff to psutil: psutil with the new pattern · GitHub.
I have been prototyping the new SDK pattern using a stdenv adapter. I have successfully built Wine and MoltenVK as well as pytorch with MPS support.
Supported SDKs
The following SDKs will be supported: 10.12.2, 10.13.2, 10.14.6, 10.15.6, 11.3, 12.3, 13.3, 14.4. When macOS 15 is released, the 15.0 SDK will be added once it is available.
Source releases that are built will be updated as new ones are made available. Which ones in particular and their versions will be included in the release announcement. Most of the _cmds packages will still be built as will libiconv, libresolv, and libutil. OpenBSM is also included but technically a third party project.
Also, Cross-compilation
The new SDK pattern is being written with cross-compilation in mind. Darwin to Darwin will be supported from day 1 when it is merged. I am modifying cc-wrapper.sh
to take DEVELOPER_DIR
and SDKROOT
into account (including the different role variants). Also, because the stdenv is being reworked to use the LLVM bootstrap to build, cross-compilation should stay working because anything that breaks it should also break the regular bootstrap.
Current Status
I’ve successfully completed the prototype. As mentioned above, I’ve been able to build a few packages with it. I’m currently working on building the bootstrap with the new SDKs.
Once the SDKs successfully bootstrap, I have some more work to do. I need to finish up the cross-compilation support. I also need to test the channel blockers and that packages with known issues (such as Wezterm) are able to build. I also need to update overrideSDK
to work with the new SDKs.
Oh, and write documentation. Being able to change the SDK on a package by putting it in the package’s build inputs feels like magic. The documentation is going to explain how to do that, change the deployment target, and what’s actually included (such as propagated packages).
Transition to the New Pattern
At the soonest, maybe the next staging-next cycle. It may be the one after that. This will definitely be in 24.11. The initial PR will only add the pattern and update the bootstrap (and other things as necessary). The frameworks will remain, but they will be stubs that do nothing. This is to avoid breaking existing packages.
Once the frameworks have been removed from packages in nixpkgs, they will be added to darwin-aliases.nix
. This could happen for 24.11, but it may happen afterward. For the next release, a warning will be added. The soonest the frameworks would be removed is 26.05. This is to give people enough time to update.