doesn’t work (though the overlay works (tested with hellox))
It says: error: attribute 'xcode_15_2' missing.
Did I do something wrong in the override of the darwin attribute in the overlay?
I tried to take a shortcut and directly do the derivation inline in buildInputs with the requireFile expression etc. from xcode.nix for my specific xcode version, but couldn’t get it to work, probably due to making mistakes in the chaining of expressions.
As a workaround I can get xcode working in a devShell flake without overlay by just doing the appleSDK thing in the below flake.
{
description = "flutter shell";
inputs = {
# nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
flake-utils.url = "github:numtide/flake-utils";
};
outputs = { self, flake-utils, nixpkgs }:
flake-utils.lib.eachDefaultSystem (system: {
devShell =
let
pkgs = import nixpkgs {
inherit system;
config.allowUnfree = true;
overlays =
[ (import ./.nix/overlay) ]; # somehow doesn't work as expected?
};
inherit (pkgs) lib;
appleSDK =
if pkgs.stdenv.isDarwin then
(pkgs.darwin.callPackage ./.nix/overlay/xcode.nix { }).xcode_15_2
else
{ };
myllvm = pkgs.llvmPackages_15;
libs = with pkgs;
if stdenv.isLinux then [
atk
at-spi2-core.dev
dbus.dev
gtk3
pango
cairo
harfbuzz
gdk-pixbuf
glib # these are transitive but explicit here for the LD_LIBRARY_PATH
fontconfig
libdatrie
libselinux
libsepol
pcre
libthai
libxkbcommon
pcre2
util-linux.dev
xorg.libX11.dev
xorg.libXdmcp
xorg.libXtst
libappindicator.dev
libepoxy
libdeflate
gnome.zenity
] else if stdenv.isDarwin then
[
# libs needed for darwin
]
else
builtins.throw "Unsupported system (not Linux or Darwin)";
in
(pkgs.mkShell.override {
stdenv =
if pkgs.stdenv.isDarwin then
pkgs.stdenv
else
myllvm.stdenv;
}) {
nativeBuildInputs = with pkgs;
[ pkg-config ninja cmake dart flutter319 go envsubst ]
++ lib.optionals stdenv.isLinux [
myllvm.bintools # https://matklad.github.io/2022/03/14/rpath-or-why-lld-doesnt-work-on-nixos.html
];
buildInputs = libs ++ lib.optionals pkgs.stdenv.isLinux
(with myllvm; [ libcxxClang libunwind ])
++ lib.optionals pkgs.stdenv.isDarwin (with pkgs;
[
# this whole stuff is prepared as follows:
# https://github.com/NixOS/nixpkgs/blob/032324fd20e3be4124ffefd00da5bd66b0550e8c/pkgs/os-specific/darwin/xcode/default.nix#L23-L32
appleSDK
]);
shellHook =
if pkgs.stdenv.isDarwin then ''
# PATH=${appleSDK}/Contents/Developer/usr/bin:${appleSDK}/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin:$PATH
PATH=${appleSDK}/Contents/Developer/usr/bin:$PATH
SDKROOT=${appleSDK}/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk
'' else
"";
};
});
}
That even makes the flutter part of my project work.
BUT: depending on which PATH I set in the shellHook a go library I link into the flutter app won’t compile.
If I don’t set clang to the env’s Xcode (from Toolchain), I get
clang-16: error: cannot use 'cpp-output' output with multiple -arch options
and if I set the path I get
# runtime/cgo
_cgo_export.c:3:10: fatal error: 'stdlib.h' file not found
Anyway it seems that setting the paths for the stdenv by setting PATH in a shellHook is very hacky, is there a “natural” way to force the actually installed apple SDK?
(If I don’t set any paths I get the ancient SDK version 11). I guess that would more naturally solve library resolution?
If I recall correctly I gave up and just manually installed flutter for the gitlab-runner user on the mac, to compile my flutter code for mac in gitlab-ci. I haven’t touched it for some time now, but it appears to be working reliably enough.
TBH I’m not really satisfied with the state of stdenv on darwin, the fact that SDK version 11 is still the (hardcoded) default with no documented way to override has become a PITA, so I have all but given up on doing serious stuff with nix on darwin. (It’s still ok for occasional devshells and a partial nix-darwin and HM user config, but even for the latter I still have to use some packages from brew (via the nix-darwin module, which makes it better)
24.11 changed the way SDKs work on Darwin. The SDK used in the stdenv can be overridden by adding the appropriate apple-sdk package to buildInputs. This is documented extensively in the manual in the Darwin section.
The announcement from last fall when these changes landed goes into detail about what changed as well as what the changes enable. (I think the Flutter situation probably still sucks, but someone motivated to do so should be able to fix it.)
I ended up using stdenvNoCc for stdenv package and instead of using xcrun and the Xcode SDK from Nix, I ended up using the ones from the XCode installation by setting this:
Darwin had been stuck in a bad state for a long time, so I don’t fault people for assuming it hadn’t gotten better. There have been some growing pains (particularly with dev shells that mix Nix-built and native dependencies), but it’s generally in a better state now and should be able to keep up with updates in the future.
to the shellHook = the Flutter command isn’t found anymore.
My flake.nix works - but I would like to setup Xcode more idiomatic, if there is a recommended way. Currently I am using this workaround in shellHook = :
# installs or checks for the right xcode version
echo "installing xcode ${xcode_version}"
xcodes install ${xcode_version} --experimental-unxip # --directory "$PWD/.xcode"
xcodes select ${xcode_version}
This is my complete flake.nix file
{
description = "Flutter toolchain. Installs all tools needed for flutter, with versions pinned for this project. Rust's own tooling handles the rust toolchain.";
# nix flutter doesn't work: https://github.com/NixOS/nixpkgs/issues/243448
# thus using a local installation
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
flake-utils.url = "github:numtide/flake-utils";
android-nixpkgs = {
url = "github:tadfisher/android-nixpkgs";
inputs = {
flake-utils.follows = "flake-utils";
nixpkgs.follows = "nixpkgs";
devshell.follows = "devshell";
};
};
devshell = {
url = "github:numtide/devshell";
inputs = {
nixpkgs.follows = "nixpkgs";
};
};
# share rust configuration with nix ... not really needed!
# rust-overlay = {
# url = "github:oxalica/rust-overlay";
# inputs = {
# nixpkgs.follows = "nixpkgs";
# flake-utils.follows = "flake-utils";
# };
# };
};
# Use this to create an android emulator
# however, this is not needed, as VSCode's Flutter Plugin can create emulators as well
# AVD_package = "system-images;android-34;aosp_atd;arm64-v8a";
# local_toolchain_path = "$PWD/.toolchain";
# local_SDK_path = "${local_toolchain_path}/android";
# local_AVD_path = "${local_SDK_path}/AVD";
# avdmanager create avd --name android-34-pixel_8 --package '${AVD_package}' --device "pixel_8"
shellHook = ''
# export PATH=$(echo $PATH | sd "${pkgs.xcbuild.xcrun}/bin" "")
# unset DEVELOPER_DIR
# uncomment to enable flutter-rust-bridge-codegen logging
# export RUST_BACKTRACE=1
# export RUST_LOG="debug"
# installs or checks for the right xcode version
echo "installing xcode ${xcode_version}"
xcodes install ${xcode_version} --experimental-unxip # --directory "$PWD/.xcode"
xcodes select ${xcode_version}
echo
# GRADLE_USER_HOME=$HOME/gradle-user-home
# GRADLE_HOME=$HOME/gradle-home
'';
# GRADLE_USER_HOME = " /home/admin0101/.gradle ";
# GRADLE_OPTS = " - Dorg.gradle.project.android.aapt2FromMavenOverride=${androidCustomPackage}/share/android-sdk/build-tools/34.0.0/aapt2";
};
}
);
}
Note that I am using nix only on my Mac - thus I don’t have any if Darwin (which I should …). I am using it system wide as well, with flake and home-manager. But that should not really matter here …
Hi @tharakadesilva many thanks - highly appreciated that you took my flake and posted the fixed version!
And sorry for the late answer - I had/still have troubles with the rust compilation that broke … but I left the out for now to to realize why your changes (still) did not work for me:
I did not have ‘sd’ installed. To be pure, that would need to be added to the ‘buildInputs’. Without that the shellHook just quietly overwrites PATH with nothing!
Sorry for the left reference to the flutter_rust_bridge_codegen file. You (or anyone reading this) can see my latest flake.nix and nix/flutter_rust_bridge_codegen.nix in my example project.
I will play around with this way to integrate Xcode … or better to let the system wide Xcode “leak in”. I am not a big fan of this setup. I understand that Xcode cannot be installed by nix directly, but I think going back to PATH might have too much side effects and be too system dependent. I guess that my rust-building problems are because some lib formerly being in DEVELOPER_DIR and not in PATH is missing.
Nevermind this specific problem though.
Anyways, thanks for showing your implementation and help so I could get that work!
I took a brief look into integrating Xcode with pkgs.darwin.xcode
but that requires to install Xcode manually into the store, even though it is locally already present:
> ***
> Unfortunately, we cannot download Xcode.app automatically.
> Please go to https://developer.apple.com/services-account/download?path=/Developer_Tools/Xcode_16.2/Xcode_16.2.xip
> to download it yourself, and add it to the Nix store by running the following commands.
> Note: download (~ 5GB), extraction and storing of Xcode will take a while
>
> open -W Xcode_16.2.xip
> rm -rf Xcode_16.2.xip
>
> nix-store --add-fixed --recursive sha256 Xcode.app
> rm -rf Xcode.app
>
> ***
>
For full logs, run 'nix log /nix/store/wlh1dchi1lb6dk5jfkmadfrhr0h0xwh4-Xcode.app.drv'.
Fair enough, but I prefer to stick with my original way of using xcodes to do that all for me. Should be more convenient especially when switching version …
If you want to expose the system Xcode in your dev shell, you can use xcodeenv.composeXcodeWrapper. That doesn’t require you to copy Xcode to your store.
How can one do that? My nix knowledge is not good enough to understand … I cannot get xcodeenv into my flake.
I actually have a huge problem: I cannot get Rust and Flutter working in one flake!
My tries are in the history of my flake.nix file.
Any help is appreciated!
I thought in between that it works - but either ‘cargo test’ works (=doesn’t miss iconv) or flutter run does - but not both.
Strangely ++ lib.optionals stdenv.isDarwin [libiconv] doesn’t work, rust works only when adding clang, which is too old and leads flutter to invalid argument '-mmacos-version-min=11.3' not allowed with '-mios-simulator-version-min=12.0
and
both integrations
lead to a flutter build ios error
github:oxalica/rust-overlay: “Error (Xcode): Unknown option: -Xlinker”
github:nix-community/fenix: “Error (Xcode): invalid argument ‘-mmacos-version-min=11.3’ not allowed with ‘-miphoneos-version-min=12.0’”
In fact, mkShellNoCC binds outdated sdks to this variable, like SDKROOT does.
I used xcodes to install specific Xcode versions - which works well, but is not embedded in nix. I only executed it within nix.
Nixpkgs’ Xcode can be used to copy Xcode into the nix/store … but I opted for using xcodeenv, as recommended in the documentation (and by @reckenrode), which is creating symlinks in the nix/store to the Xcode installation.
Ultimately, IMHO, not using the latest Xcode suiting the MacOS version leads to problems … and thus I opted for leaving Xcode as-is and using nix around it.
So, the final version of my flake, and my recommendation to integrate Xcode in a nix flake, is: