Override kernel build dependencies

Hi!

I’m trying to build a kernel from source for aarch64 for the Orange Pi Zero2 H616 using the provided nix flake.

However after changing the source, it seems that a tool is missing mkimage:

/nix/store/wim4mqpn8lxhhr10p2kd070hyj152lil-bash-5.1-p16/bin/bash: line 1: mkimage: command not found

My experience with Nix is quite limited but it feels like a build dependencies is missing so I tried to override buildLinux to add ubootTools which contains mkimage like so:

      buildLinux.overrideAttrs(old: {
        nativeBuildInputs = old.nativeBuildInputs ++ [ nixpkgs.ubootTools ];
      }) rec
      {
        kernelPatches = [];
        src = fetchFromGitHub {
          owner = "orangepi-xunlong";
          repo = "linux-orangepi";
          rev = "orange-pi-5.16-sunxi64";
          sha256 = "sha256-VnniPfLyGXeuQRyhlq+b8QgXd7qFY52rFzG2J5WzPCg=";
        };
        version = "5.16.17";
        modDirVersion = version;
        extraMeta.branch = versions.majorMinor version;
        defconfig = "orangepi_defconfig";
      };

but this fails with error which I just don’t understand:

error: value is a function while a set was expected

       at /nix/store/1cimm8vgpgrhh03cf4awb0dgqmwirs6x-source/flake.nix:25:7:

           24|       # }));
           25|       buildLinux.overrideAttrs(old: {
             |       ^
           26|         nativeBuildInputs = old.nativeBuildInputs ++ [ nixpkgs.ubootTools ];

Have I lost myself with the syntax?
Is this the correct approach?

Here is the full flake.nix for more context:

{
  description = "Build image for OrangePi Zero 2";
  inputs = {
    nixpkgs.url = github:nixos/nixpkgs/nixos-22.11;
  };
  outputs = { self, nixpkgs }: let
    system = "aarch64-linux";

    #Build manipulation
    stateVersion = "22.11";   # NixOS Version
    useUnstableKernel = true; # Set to false to use mainline kernel
    compressImage = true;     # Set to false to disable image compressing

    pkgs = nixpkgs.legacyPackages.x86_64-linux.pkgsCross.aarch64-multiplatform;

    # Build unstable kernel
    kernel =
      with pkgs;
      with lib;
      buildLinux.overrideAttrs(old: {
        nativeBuildInputs = old.nativeBuildInputs ++ [ nixpkgs.ubootTools ];
      }) rec
      {
        kernelPatches = [
          # linuxKernel.kernelPatches.bridge_stp_helper
          # linuxKernel.kernelPatches.request_key_helper
        ];
        src = fetchFromGitHub {
          owner = "orangepi-xunlong";
          repo = "linux-orangepi";
          rev = "orange-pi-5.16-sunxi64";
          sha256 = "sha256-VnniPfLyGXeuQRyhlq+b8QgXd7qFY52rFzG2J5WzPCg=";
        };
        version = "5.16.17";
        modDirVersion = version;
        extraMeta.branch = versions.majorMinor version;
        defconfig = "orangepi_defconfig";
      };

    # Boot related configuration
    bootConfig = let
      bootloaderPackage = pkgs.ubootOrangePiZero2;
      bootloaderSubpath = "/u-boot-sunxi-with-spl.bin";
      # Disable ZFS support to prevent problems with fresh kernels.
      filesystems = pkgs.lib.mkForce [ "btrfs" "reiserfs" "vfat" "f2fs" "xfs"
                                       "ntfs" "cifs" /* "zfs" */ "ext4" "vfat"
                                     ];
    in {
      system.stateVersion = stateVersion;
      boot.kernelPackages = if useUnstableKernel
        then pkgs.linuxPackagesFor kernel
        else pkgs.linuxPackages_latest;
      boot.initrd.supportedFilesystems = filesystems;
      sdImage = {
        postBuildCommands = ''
          # Emplace bootloader to specific place in firmware file
          dd if=${bootloaderPackage}${bootloaderSubpath} of=$img    \
            bs=8 seek=1024                                          \
            conv=notrunc # prevent truncation of image
        '';
        inherit compressImage;
      };
    };

    # NixOS configuration
    nixosSystem = nixpkgs.lib.nixosSystem rec {
      inherit system;
      modules = [
        # Default aarch64 SOC System
        "${nixpkgs}/nixos/modules/installer/sd-card/sd-image-aarch64.nix"
        # Minimal configuration
        "${nixpkgs}/nixos/modules/profiles/minimal.nix"
        { config = bootConfig; }
        # Put your configuration here. e.g. ./configuration.nix
      ];
    };
  in {
    inherit system;
    # Run nix build .#images.orangePiZero2 to build image.
    images = {
      orangePiZero2 = nixosSystem.config.system.build.sdImage;
    };
  };
}
1 Like

Yes, it does seem that way.

buildLinux is a function, but you’re treating it like an attrset when you do buildLinux.overrideAttrs. Hence the error. foo.bar looks up the bar attribute in the foo attrset. If foo isn’t an attrset, you get an error like this.

overrideAttrs is an attribute of the output of buildLinux (I assume. I haven’t worked with buildLinux specifically)

I also strongly suspect overrideAttrs is unnecessary here. You can just add the attributes to the buildLinux call. buildLinux might be unusual in a way that requires this for some reason, but normally, overrideAttrs is only necessary when you want to alter the way something is created but don’t have access to easily modify the original source.

Thanks for your reply!

I understood what I was doing wrong with overrideAttrs, it’s clearer now.

However I’m not sure how to add my dependencies without override. I tried:

  • Adding nativeBuildInputs and/or depsBuildBuild to the kernel record. It didn’t change anything
  • I tried to call buildKernel THEN overrideDerivation to override configfile with overrideAttrs which contains a nativeBuildInputs and append nixpkgs.ubootTools to it. It failed because ubootTools was not in nixpkgs. I switched to pkgs.ubootTools which compiled this time but did not work because this produce an aarch64 binary on a x86_64 computer
  • I noticed this so I tried to add stdenv.hostPlatform.linux-kernel.target = "uImage" which had no effect. I then tried to redo the override chain described on the step before but this time trying to modify this in order to add my dependencies. But this did not work either because after the call to overrideDerivation on the result of buildLinux call kept saying that kernel (this) was not present

Clearly my use case seem to be handled by this but I just don’t understand how am I supposed to make this condition true…

The platform spec for aarch64-multiplatform sets target = "Image";:

I would assume they know what they’re doing, and having the target as “uImage” isn’t necessary for what you’re going for here. However, I simply don’t know enough about how kernels are done in nixpkgs to point you in the right direction. Hopefully someone else will pick up the baton.

1 Like