Setting flake for avr targets

I’m trying to figure out how to, with modern NixOS tooling, set up a flake that I can use to build programs for avr processors. While I have no problems getting a clang compiler that will happily target an avr processor, I can’t figure out how to get the header files into the environment.

Here’s my flake:

{
  description = "avr";

  inputs = {
    nixpkgs.url = "nixpkgs/nixos-21.11";
  };

  outputs = { self, nixpkgs }:
    let 
      version = builtins.string 0 8 self.lastModifiedDate;
      supportedSystems = [ "x86_64-linux" "avr-none" ];
    in
    {
      devShell."x86_64-linux" =
        let
          pkgs = import nixpkgs { system = "x86_64-linux"; config.allowUnsupportedSystem = true; };
        in
        pkgs.mkShell {
          name = "avr-shell";
          buildInputs = [
            pkgs.clang_14
            pkgs.avrdude
            pkgs.avrlibc
          ];
        };
    };
}

But the error I get is this:

error: builder for '/nix/store/cq7q7jmyppfzvzm7njm0zl6pdry7l8dg-avr-libc-2.0.0.drv' failed with exit code 1;
       last 10 log lines:
       > configure flags: --disable-dependency-tracking --prefix=/nix/store/amsw42qn701h75kdawp9bp59dqf249f5-avr-libc-2.0.0
       > checking build system type... x86_64-unknown-linux-gnu
       > checking host system type... x86_64-unknown-linux-gnu
       > checking if configuring for cross compile... no
       > configure: WARNING:
       > configure: WARNING: AVR-LIBC must be built using an avr cross-compiler.
       > configure: WARNING: Try configuring with:
       > configure: WARNING: "./configure --build=`./config.guess` --host=avr"
       > configure: WARNING:
       > configure: error: aborting configure
       For full logs, run 'nix log /nix/store/cq7q7jmyppfzvzm7njm0zl6pdry7l8dg-avr-libc-2.0.0.drv'.
error: 1 dependencies of derivation '/nix/store/j7jr4h87bmdz26j8lvy92fxc16qscf66-Wearables-shell-env.drv' failed to build

So, yeah, it makes sense that avr-libc can’t be compiled with an x86_64-linux target, but how can I tell the avrlibc package to just build for avr, instead?

Okay, this is a working devshell:

{
  description = "Wearables";

  inputs = {
    nixpkgs.url = "nixpkgs/nixos-21.11";
  };

  outputs = { self, nixpkgs }:
    let 
      version = builtins.string 0 8 self.lastModifiedDate;
      supportedSystems = [ "x86_64-linux" "avr-none" ];
    in
    {
      devShell."x86_64-linux" =
        let
          pkgs = import nixpkgs { system = "x86_64-linux"; };
          avr = with pkgs.pkgsCross.avr.buildPackages; [
            binutils
            gcc
            avrdude
          ];
        in
        pkgs.mkShell {
          name = "Wearables-shell";
          buildInputs = avr;
        };
    };
}

Seems that the AVR derivation can’t be built with clang, so the pkgsCross option is the only one available right now.

Some additions:

  • supportedSystems shouldn’t contain avr-none, as it relates to the derivation’s system attribute which is the system a derivation is realized on.
  • clang is wrapped for nixpkgs’ purposes because we do consistent packages sets with a single host platform for our cross-platform. That’s why you can’t use -target to freely retarget clang. Using clang-unwrapped is making it unnecessarily hard for yourself, since that won’t find libs, compiler rt etc.
  • You should use mkShell of the cross package set. That way $CC will be your cross compiler, all necessary bintools available automatically etc. If you start using extra libs they’ll just work as well (maybe not as relevant for avr).

So the following would already work as expected:

pkgs.pkgsCross.avr.mkShell { name = "wearables-shell"; }

If you want to try to get a clang-based toolchain, you could try the following, although I’m not sure if it actually works for the avr target, I’ve never tried:

let
  avrCrossPkgs = import nixpkgs {
    crossSystem = {
      config = "avr";
      useLLVM = true;
      linker = "lld"; # alternatively, "bfd" for GNU binutils' standard ld.bfd
     };
   };
in

avrCrossPkgs.mkShell { name = "wearables-clang-shell"; }