diff --git a/src/modules/top-level.nix b/src/modules/top-level.nix index cc9a5732c..dab6f7c3b 100644 --- a/src/modules/top-level.nix +++ b/src/modules/top-level.nix @@ -69,7 +69,17 @@ in stdenv = lib.mkOption { type = types.package; description = "The stdenv to use for the developer environment."; - default = pkgs.stdenv; + default = + if pkgs.stdenv.isDarwin + then + pkgs.stdenv.override + (prev: { + # Remove the default apple-sdk on macOS. + # Prefer to expose the system SDK, or let the user specify the SDK in `packages`. + extraBuildInputs = + builtins.filter (x: !lib.hasPrefix "apple-sdk" x.pname) prev.extraBuildInputs; + }) + else pkgs.stdenv; defaultText = lib.literalExpression "pkgs.stdenv"; }; @@ -297,17 +307,28 @@ in ln -snf ${lib.escapeShellArg config.devenv.runtime} ${lib.escapeShellArg config.devenv.dotfile}/run ''; - shell = performAssertions ( - (pkgs.mkShell.override { stdenv = config.stdenv; }) ({ - hardeningDisable = config.hardeningDisable; - name = "devenv-shell"; - packages = config.packages; - shellHook = '' - ${lib.optionalString config.devenv.debug "set -x"} - ${config.enterShell} - ''; - } // config.env) - ); + shell = + let + # `mkShell` merges `packages` into `nativeBuildInputs`. + # This distinction is generally not important for devShells, except when it comes to setup hooks and their run order. + # On macOS, the default apple-sdk is added the stdenv via `extraBuildInputs`. + # If we don't remove it from stdenv, then it's setup hooks will clobber any SDK added to `packages`. + isAppleSDK = pkg: builtins.match ".*apple-sdk.*" (pkg.pname or "") != null; + partitionedPkgs = builtins.partition isAppleSDK config.packages; + buildInputs = partitionedPkgs.right; + nativeBuildInputs = partitionedPkgs.wrong; + in + performAssertions ( + (pkgs.mkShell.override { stdenv = config.stdenv; }) ({ + name = "devenv-shell"; + hardeningDisable = config.hardeningDisable; + inherit buildInputs nativeBuildInputs; + shellHook = '' + ${lib.optionalString config.devenv.debug "set -x"} + ${config.enterShell} + ''; + } // config.env) + ); infoSections."env" = lib.mapAttrsToList (name: value: "${name}: ${toString value}") config.env; infoSections."packages" = builtins.map (package: package.name) (builtins.filter (package: !(builtins.elem package.name (builtins.attrNames config.scripts))) config.packages); diff --git a/tests/macos-custom-apple-sdk/devenv.nix b/tests/macos-custom-apple-sdk/devenv.nix new file mode 100644 index 000000000..c2623cf69 --- /dev/null +++ b/tests/macos-custom-apple-sdk/devenv.nix @@ -0,0 +1,15 @@ +{ pkgs, ... }: + +{ + packages = [ pkgs.apple-sdk ]; + + # Test that the above SDK is picked up by xcode-select. + enterTest = '' + if [ -v "$DEVELOPER_DIR" ]; then + echo "DEVELOPER_DIR is not set." + exit 1 + fi + + xcode-select -p | grep -q /nix/store + ''; +} diff --git a/tests/macos-no-default-sdk/devenv.nix b/tests/macos-no-default-sdk/devenv.nix new file mode 100644 index 000000000..9db111b13 --- /dev/null +++ b/tests/macos-no-default-sdk/devenv.nix @@ -0,0 +1,18 @@ +{ + # Test that there is no default SDK set on macOS. + enterTest = '' + variables_to_check=( + "DEVELOPER_DIR" + "DEVELOPER_DIR_FOR_BUILD" + "SDKROOT" + "NIX_APPLE_SDK_VERSION" + ) + + for var in "''${variables_to_check[@]}"; do + if [ -v "$var" ]; then + echo "$var is set. Expected no default Apple SDK." >&2 + exit 1 + fi + done + ''; +}