diff --git a/docs/reference/options.md b/docs/reference/options.md index 4a7be4f32..0b671f5e8 100644 --- a/docs/reference/options.md +++ b/docs/reference/options.md @@ -602,6 +602,29 @@ string +## apple.sdk + + + +The Apple SDK to add to the developer environment on macOS. + +If set to ` null `, the system SDK can be used if the shell allows access to external environment variables. + + + +*Type:* +null or package + + + +*Default:* +` if pkgs.stdenv.isDarwin then pkgs.apple-sdk else null ` + +*Declared by:* + - [https://github.com/cachix/devenv/blob/main/src/modules/top-level.nix](https://github.com/cachix/devenv/blob/main/src/modules/top-level.nix) + + + ## aws-vault.enable @@ -2299,8 +2322,6 @@ list of (one of “commit-msg”, “post-checkout”, “post-commit”, “pos ## git-hooks.excludes - - Exclude files that were matched by these patterns. @@ -2320,6 +2341,8 @@ list of string ## git-hooks.gitPackage + + The ` git ` package to use. @@ -5136,8 +5159,6 @@ boolean ## git-hooks.hooks.autoflake.settings.binPath - - Path to autoflake binary. @@ -5161,6 +5182,8 @@ null or string ## git-hooks.hooks.autoflake.settings.flags + + Flags passed to autoflake. @@ -7009,8 +7032,6 @@ null or package ## git-hooks.hooks.clippy.packageOverrides.cargo - - The cargo package to use @@ -7025,6 +7046,8 @@ package ## git-hooks.hooks.clippy.packageOverrides.clippy + + The clippy package to use diff --git a/src/modules/top-level.nix b/src/modules/top-level.nix index cc9a5732c..ecacfdeeb 100644 --- a/src/modules/top-level.nix +++ b/src/modules/top-level.nix @@ -71,6 +71,32 @@ in description = "The stdenv to use for the developer environment."; default = pkgs.stdenv; defaultText = lib.literalExpression "pkgs.stdenv"; + + # Remove the default apple-sdk on macOS. + # Allow users to specify an optional SDK in `apple.sdk`. + apply = stdenv: + if stdenv.isDarwin + then + stdenv.override + (prev: { + extraBuildInputs = + builtins.filter (x: !lib.hasPrefix "apple-sdk" x.pname) prev.extraBuildInputs; + }) + else stdenv; + + }; + + apple = { + sdk = lib.mkOption { + type = types.nullOr types.package; + description = '' + The Apple SDK to add to the developer environment on macOS. + + If set to `null`, the system SDK can be used if the shell allows access to external environment variables. + ''; + default = if pkgs.stdenv.isDarwin then pkgs.apple-sdk else null; + defaultText = lib.literalExpression "if pkgs.stdenv.isDarwin then pkgs.apple-sdk else null"; + }; }; unsetEnvVars = lib.mkOption { @@ -258,7 +284,8 @@ in packages = [ # needed to make sure we can load libs pkgs.pkg-config - ]; + ] + ++ lib.optional (config.apple.sdk != null) config.apple.sdk; enterShell = lib.mkBefore '' export PS1="\[\e[0;34m\](devenv)\[\e[0m\] ''${PS1-}" @@ -297,17 +324,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 to stdenv via `extraBuildInputs`. + # If we don't remove it from stdenv, then its 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..082ccced7 --- /dev/null +++ b/tests/macos-custom-apple-sdk/devenv.nix @@ -0,0 +1,15 @@ +{ pkgs, ... }: + +{ + apple.sdk = 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..ef8b797bd --- /dev/null +++ b/tests/macos-no-default-sdk/devenv.nix @@ -0,0 +1,20 @@ +{ + apple.sdk = null; + + # 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 + ''; +}