How to prevent a package dependency appearing in PATH

I have a problem where a dependency of the “go” package is shadowing a system command. The command in question is xcodebuild, part of Xcode. The xcodebuild installed via Xcode is version 14.2, but the version installed as part of the “go” package is 9.4.1, making it about five years out of date.

$ xcodebuild -version
Xcode 14.2
Build version 14C18
$ nix-shell -p go
[nix-shell:/tmp]$ xcodebuild -version
Xcode 9.4.1
Build version 17E189

Is there some way to fix this?

The “go” package: nixpkgs/1.19.nix at cff83d5032a21aad4f69bf284e95b5f564f4a54e · NixOS/nixpkgs · GitHub

The out-of-date “xcbuild” package: nixpkgs/default.nix at cff83d5032a21aad4f69bf284e95b5f564f4a54e · NixOS/nixpkgs · GitHub

This is the intended behaviour of nix-shell -p. It provides the setup used to build go as defined in it’s derivation.

Note that you can still reference the system command by full path and can pull it into the nix-shell environment by defining an alias.

Side remark: “xcbuild” is up-to-date as it is no longer maintained by upstream.

Thank you for your answer.

I used nix-shell -p here just for clarity, in reality I am using nix-shell with a shell.nix file. I tried to define an alias like you said, but because xcodebuild is actually called by another tool, not via the shell, it did not solve the problem.

I haven’t learned much nix yet, but it looks like the “go” derivation takes an “xcbuild” parameter (here). Is it possible to override it with an empty derivation, so that the xcodebuild binary is never installed? Here is my shell.nix:

pkgs.mkShell {
    buildInputs = [
        pkgs.go
        ...

That would also render xcodebuild unavailable to derivations depending on your patched go. That said, you can try

pkgs.mkShell {
  buildInputs = [
     (go = pkgs.go.overrideAttrs (finalAttrs: previousAttrs: {
  xcodebuild = null;
});
)
...]

(unless your go code is relying on some of the packages that require xcodebuild).

When I override its xcbuild attribute, the go derivation no longer installs a precompiled binary - it compiles from scratch, which is not ideal. It seems odd that the go derivation installs xcodebuild - which is presumably used only to build go - when the go binary is supplied precompiled.

It’s not pretty, but the solution I currently have is to remove the xcodebuild bin directory from the PATH:

    shellHook = ''
        PATH="$(
            echo "$PATH" \
            | tr ":" "\n" \
            | grep -v xcodebuild \
            | tr "\n" ":" \
            | head -c -1
        )"
        ...

Thanks for your help.

Well, you changed the propagated build inputs of the Go derivation. By the rules of nix this forces a rebuild of the derivation and thus a build of Go from source.
Further, xcodebuild is not only used for Go itself. It is in the propagated build inputs. That means it is actively provided to any packages using Go. (You can grep through nixpkgs to find quite a few.)
Altogether, the behavior you observed is correct.

That said, if your workaround server your purpose: That is perfectly fine, but beware of any issues arising from impurity.

I can’t see why a package using Go would expect Go to provide the xcodebuild command. How do you grep through nixpkgs? What packages did you find that seemed to be depending on xcbuild as a propagated build input?

Because It is a random requirement made by apple that X-Code is used in the build. To make that easier Go (as many other buildtools) propagate it, then a random go package does not need to remember to do so.

Because It is a random requirement made by apple that X-Code is used in the build.

Do you mean the build of Go itself, or of programs written in Go?

a random go package does not need to remember to do so.

Aren’t implicit dependencies frowned upon in the Nix world?

By programs assembled and linked on MacOS.

It is not implicit. Go explicitely propagates it.

I do not know the details about the whole Mac thing, though I know, it probably needs to be that way to circumvent the restrictions made by the company owning your hardware…