Cross-platform building of `runCommand` drv

I want to build a runCommand drv whose output is fixed (i.e. with specified outputHash). With --system argument set to a different platform from the build platform, it throws an error building it:

$ nix-build --system aarch64-darwin -E 'with import <nixpkgs> {}; runCommand "test" { outputHashAlgo = "sha256"; outputHashMode = "recursive"; outputHash = "u7BJjFENJ+zP7ZrHvFzxfwCJrLMDz0sE60YmzCBQsy8="; } "mkdir -p $out; echo test > $out/test"'
this derivation will be built:
  /nix/store/91bz16ljz52cs7sasv8rwqvmf3qsbfs7-test.drv
error: a 'aarch64-darwin' with features {} is required to build '/nix/store/91bz16ljz52cs7sasv8rwqvmf3qsbfs7-test.drv', but I am a 'x86_64-linux' with features {benchmark, big-parallel, kvm, nixos-test}

How to tell it just not to care about the host platform?

You can in general not build darwin from linux, you have to get a real Mac to build your thing.

This is for getting new hash in an update script.

Also technically it is not “for mac” because it is fixed output. I want its result to be just the same as if there is no --system specified.

--system sets both build and host platforms in Nixpkgs.

The problem is also the buildPlatform, not the hostPlatform. The hostPlatform is kinda uninteresting for FODs as those rarely contain platform-specific code generated in the drv.

What’s stopping you from simply evaluating that drv for your buildPlatform?

Technically runCommand requires to run commands.

If the store path is not available, and you request this to be built under a Darwin system, Linux will refuse to do so.

Though if it’s a fod, just building as a Linux (means omitting the --system) will produce the same result.

1 Like

Well, ideally anyways. There’s always the possibility of some FOD output being platform-dependent; you’d need to know the use-case in more detail.

If the result is different, for downloading and unzipping a tarbal from the same URL, something is massively wrong, and usually depends on Mac’s FS and not on actually Mac.

The “case insensitive, but case preserving” that windows and macs default filesystems do is a pain…

1 Like

Right, that’s the typical case where we fetch some artifact from the internet but other uses of FODs are conceivable.

Not a sensible practical case of course but there’s nothing stopping you from doing uname > $out in a FOD for instance.

You could theoretically also generate code inside of a FOD. It all depends on the use-case as I said.

Sure, but that’s not fetching a tarbal from a static URL

And would even be problematic on different linux hosts.

Let’s not worry about having different output under different platforms. I claim that won’t happen (at least for this case which is just echo test > test), and ofborg eval can check that.

The --system xxx is there because update-source-version uses it when running nix-build.
The situation is that my-pkg.src is something that depends on stdenv.hostPlatform, and --system xxx changes stdenv.hostPlatform to give the desired my-pkg.src to build. And here in this case my-pkg.src is a runCommand FOD.

So the problem is that --system sets the build platform? That I can understand, because then stdenvNoCC would contain something that cannot run on the current platform. However, then why does it work if it is a fetchurl, which uses curl of the build platform?

It doesn’t. It’s the exact same problem.

If the same FOD was built once already however (no matter what platform), Nix wouldn’t attempt to build it though and that’d work.

Oh yes it indeed doesn’t build.

Thank you.