Cross compilation in Nixpkgs help

Is there a way to have same derivation hashes for the same application built for the same host system which are known to build exactly the same application but built on different systems if the derivation is not a FOD?

Why is the target system a whole nixpkgs level thing and not just an option you (or stdenv) override for gcc, clang, rustc, etc.?
Example: You are on x86_64-linux and you cross compile hello from aarch64-linux Nixpkgs.
If I’m understanding this correctly and if pkgs.gcc supported it, pkgs.stdenv could just use pkgs.gcc.override { targetSystem = "aarch64-linux"; } instead of pkgs.gcc + global variables.

Hi and welcome to the forum!

This has something to do with how Nix itself works, and the Nixpkgs stdenv is only a thin abstraction in that regard: as you probably already know, derivation hashes that aren’t fixed-output are determined by their inputs, and the system string is one of them. That parameter, as you will find in the linked reference documentation, determines the system type on which Nix will build the derivation locally. Nix itself has no notion of cross compilation, this is only introduced in stdenv, at the layer of the builder executable which in this case is a Bash script cobbled together from a pile of things such as compiler flags, the entirety of which will again constitute an input to the resulting derivation. But even mkDerivation has to set system on the underlying call to builtins.derivation, since that build has to run in some execution environment.

Therefore, without FOD or content-addressed derivations, you will necessarily get a different hash if you change parameters.


Thank you very much for your reply!

In the dependency implementation section of the Nixpkgs manual, it says the following.

Nixpkgs is now structured so that each deps<host><target> is automatically taken from pkgs<host><target>. (These pkgs<host><target>s are quite new, so there is no special case for nativeBuildInputs and buildInputs.)

I have couple of questions

  1. Could somebody explain more about what is said in the paranthesis?

  2. Does stdenv.mkDerivation do black magic behind the scenes and swap out inputs of packages or for the example, the overridable functions around derivations?

    { lib, # This is the "overridable function" I'm referring to
    stdenv.mkDerivation {
      buildInputs = [ # or depsHostTarget for that matter
        openssl # I'm guessing this comes from raw pkgs without any tricks
      nativeBuildInputs = [ # or depsBuildHost
        dtc # Is this the same as putting `dtc.override pkgsBuildHost` in buildInputs or as a store path in buildPhase?
      preBuildPhase = ''
        echo ${openssl} # Is this from raw pkgs aka pkgsHostTarget?
  3. Is the “default target system” the same as the host system of Nixpkgs? How and where in Nixpkgs code does the target system get overridden when cross-compiling?

  4. A depends on B in nativeBuildInputs, let’s say as a compiler.
    B’s host system has to be A’s build system and B’s target system has to be A’s host system.
    When making the hash for B, how does Nix decide its build system?

  5. Another example: If I build hello (and stdenv has no other dependencies than gcc) its hash depends on up to three systems?

    • Gcc’s build system
    • My (build) system
    • Hello’s host/run system
1 Like