Cross-compile cups for armv6l-linux

Hello, I want to enable printing on a armv6l-linux sd image which is build on x86_64-linux, but I get some compile errors because the host parameter is not set correctly.

My build flake looks like this:

{
  description = "Build image";
  inputs.nixpkgs.url = "github:nixos/nixpkgs/nixos-23.11";
  outputs = { self, nixpkgs }: rec {
    nixosConfigurations.rpi2 = nixpkgs.lib.nixosSystem {
      modules = [
        "${nixpkgs}/nixos/modules/installer/sd-card/sd-image-raspberrypi.nix"
        ({ lib, pkgs, modulesPath, ... }: {
          nixpkgs.config.allowUnsupportedSystem = true;
          nixpkgs.hostPlatform.system = "armv6l-linux";
          nixpkgs.buildPlatform.system = "x86_64-linux"; #If you build on x86 other wise changes this.
          system.stateVersion = "23.11";
          # [...]

          # configure printing service
          services.printing = {
            enable = true;
            listenAddresses = [ "*:631" ];
            allowFrom = [ "all" ];
            browsing = true;
            defaultShared = true;
            openFirewall = true;
          };
        })
      ];
    };
    images.rpi2 = nixosConfigurations.rpi2.config.system.build.sdImage;
  };
}

This is the output of the failing build job:

@nix { "action": "setPhase", "phase": "unpackPhase" }
unpacking sources
unpacking source archive /nix/store/vb663kybnnwv3y2yid6dpk67kwh0nrk9-jbig2dec-0.20.tar.gz
source root is jbig2dec-0.20
setting SOURCE_DATE_EPOCH to timestamp 1693395286 of file jbig2dec-0.20/test_jbig2dec.py
@nix { "action": "setPhase", "phase": "patchPhase" }
patching sources
patching script interpreter paths in test_jbig2dec.py
@nix { "action": "setPhase", "phase": "updateAutotoolsGnuConfigScriptsPhase" }
updateAutotoolsGnuConfigScriptsPhase
@nix { "action": "setPhase", "phase": "updateAutotoolsGnuConfigScriptsPhase" }
updateAutotoolsGnuConfigScriptsPhase
@nix { "action": "setPhase", "phase": "configurePhase" }
configuring
checking for autoconf...
checking for automake 1.7 or later...
Checking for libtoolize... libtoolize
Generating configuration files for jbig2dec, please wait....
  aclocal
  libtoolize
libtoolize: putting auxiliary files in '.'.
libtoolize: copying file './ltmain.sh'
libtoolize: putting macros in 'm4'.
libtoolize: copying file 'm4/libtool.m4'
libtoolize: copying file 'm4/ltoptions.m4'
libtoolize: copying file 'm4/ltsugar.m4'
libtoolize: copying file 'm4/ltversion.m4'
libtoolize: copying file 'm4/lt~obsolete.m4'
libtoolize: Consider adding 'AC_CONFIG_MACRO_DIRS([m4])' to configure.ac,
libtoolize: and rerunning libtoolize and aclocal.
  autoheader
  creating config_types.h.in
  automake --add-missing
configure.ac:25: installing './ar-lib'
configure.ac:23: installing './compile'
configure.ac:26: installing './config.guess'
configure.ac:26: installing './config.sub'
configure.ac:8: installing './install-sh'
configure.ac:8: installing './missing'
Makefile.am: installing './depcomp'
parallel-tests: installing './test-driver'
  autoconf
configure.ac:9: warning: 'AM_CONFIG_HEADER': this macro is obsolete.
configure.ac:9: You should use the 'AC_CONFIG_HEADERS' macro instead.
./lib/autoconf/general.m4:2434: AC_DIAGNOSE is expanded from...
aclocal.m4:9866: AM_CONFIG_HEADER is expanded from...
configure.ac:9: the top level
configure.ac:26: warning: The macro `AC_LIBTOOL_WIN32_DLL' is obsolete.
configure.ac:26: You should run autoupdate.
...skipping...
parallel-tests: installing './test-driver'
  autoconf
configure.ac:9: warning: 'AM_CONFIG_HEADER': this macro is obsolete.
configure.ac:9: You should use the 'AC_CONFIG_HEADERS' macro instead.
./lib/autoconf/general.m4:2434: AC_DIAGNOSE is expanded from...
aclocal.m4:9866: AM_CONFIG_HEADER is expanded from...
configure.ac:9: the top level
configure.ac:26: warning: The macro `AC_LIBTOOL_WIN32_DLL' is obsolete.
configure.ac:26: You should run autoupdate.
aclocal.m4:8546: AC_LIBTOOL_WIN32_DLL is expanded from...
configure.ac:26: the top level
configure.ac:26: warning: AC_LIBTOOL_WIN32_DLL: Remove this warning and the call to _LT_SET_OPTION when you
configure.ac:26: put the 'win32-dll' option into LT_INIT's first parameter.
./lib/autoconf/general.m4:2434: AC_DIAGNOSE is expanded from...
aclocal.m4:8546: AC_LIBTOOL_WIN32_DLL is expanded from...
configure.ac:26: the top level
configure.ac:27: warning: The macro `AC_PROG_LIBTOOL' is obsolete.
configure.ac:27: You should run autoupdate.
aclocal.m4:122: AC_PROG_LIBTOOL is expanded from...
configure.ac:27: the top level
configure.ac:37: warning: The macro `AC_HELP_STRING' is obsolete.
configure.ac:37: You should run autoupdate.
./lib/autoconf/general.m4:204: AC_HELP_STRING is expanded from...
configure.ac:37: the top level
configure.ac:68: warning: The macro `AC_HEADER_STDC' is obsolete.
configure.ac:68: You should run autoupdate.
./lib/autoconf/headers.m4:704: AC_HEADER_STDC is expanded from...
configure.ac:68: the top level
configure.ac:103: warning: The macro `AC_TRY_COMPILE' is obsolete.
configure.ac:103: You should run autoupdate.
./lib/autoconf/general.m4:2847: AC_TRY_COMPILE is expanded from...
configure.ac:103: the top level
I am going to run ./configure with no arguments - if you wish
to pass any to it, please specify them on the ./autogen.sh command line.
checking whether make supports nested variables... yes
checking for a BSD-compatible install... /nix/store/bblyj5b3ii8n6v4ra0nb37cmi3lf8rz9-coreutils-9.3/bin/install -c
checking whether build environment is sane... yes
checking for a race-free mkdir -p... /nix/store/bblyj5b3ii8n6v4ra0nb37cmi3lf8rz9-coreutils-9.3/bin/mkdir -p
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking for gcc... armv6l-unknown-linux-gnueabihf-gcc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables...
checking whether we are cross compiling... configure: error: in `/build/jbig2dec-0.20':
configure: error: cannot run C compiled programs.
If you meant to cross compile, use `--host'.
See `config.log' for more details
/nix/store/ipg73dk1xw6zpi0v07010hbgy9hpp43x-stdenv-linux/setup: line 131: pop_var_context: head of shell_variables not a function context

From my understanding the --host parameter should already be set due to this line, and this in the stdenv source ?

Searching with sudo find / -name config.log | grep cups for the mentioned config.log file reveals nothing.

I then tried to manually override the host parameter with an overlay like this (weirdly sepecifying only one of the lat two overrides has no effect):

          nixpkgs.overlays = [
            (final: super: {
              cups = super.cups.overrideAttrs (old: {
                configurePlatforms =  [];
                configureFlags = old.configureFlags ++ [ "--host=armv6l-linux" "--target=armv6l-linux" ];
                NIX_CFLAGS_COMPILE = (old.NIX_CFLAGS_COMPILE or "") + " --host=armv6l-linux";
              });
            })
          ];

The error of the failed build job now looks like this:

@nix { "action": "setPhase", "phase": "unpackPhase" }
unpacking sources
unpacking source archive /nix/store/z0w3l90hw9gi23vy7w5q2l3slr8bji4y-cups-2.4.7-source.tar.gz
source root is cups-2.4.7
setting SOURCE_DATE_EPOCH to timestamp 1695216378 of file cups-2.4.7/packaging/cups.spec
@nix { "action": "setPhase", "phase": "patchPhase" }
patching sources
@nix { "action": "setPhase", "phase": "updateAutotoolsGnuConfigScriptsPhase" }
updateAutotoolsGnuConfigScriptsPhase
Updating Autotools / GNU config script to a newer upstream version: ./config.sub
Updating Autotools / GNU config script to a newer upstream version: ./config.guess
@nix { "action": "setPhase", "phase": "configurePhase" }
configuring
configure flags: --disable-static --prefix=/nix/store/fq35ajcfmp6q2lf08m66lhd0c579sw8w-cups-2.4.7 --bindir=/nix/store/fq35ajcfmp6q2lf08m66lhd0c579sw8w-cups-2.4.7/bin --sbindir=/nix/store/fq35ajcfmp6q2lf08m66lhd0c579sw8w-cups-2.4.7/sbin --includedir=/nix/store/cn7paa45x2wxqc1ssxqkyq8fw879a541-cups-2.4.7-dev/include --oldincludedir=/nix/store/cn7paa45x2wxqc1ssxqkyq8fw879a541-cups-2.4.7-dev/include --mandir=/nix/store/ys9cyw1b9h80hfyzs2nkgnv049dp2jnw-cups-2.4.7-man/share/man --infodir=/nix/store/fq35ajcfmp6q2lf08m66lhd0c579sw8w-cups-2.4.7/share/info --docdir=/nix/store/fq35ajcfmp6q2lf08m66lhd0c579sw8w-cups-2.4.7/share/doc/cups --libdir=/nix/store/wjx4qrhnkgln1vx1j2vq8lss9f5xbqdq-cups-2.4.7-lib/lib --libexecdir=/nix/store/wjx4qrhnkgln1vx1j2vq8lss9f5xbqdq-cups-2.4.7-lib/libexec --localedir=/nix/store/wjx4qrhnkgln1vx1j2vq8lss9f5xbqdq-cups-2.4.7-lib/share/locale --localstatedir=/var --sysconfdir=/etc --enable-raw-printing --enable-threads --enable-dbus --enable-pam --with-dbusdir=/nix/store/fq35ajcfmp6q2lf08m66lhd0c579sw8w-cups-2.4.7/share/dbus-1 --enable-libusb --enable-ssl --enable-avahi --enable-libpaper --host=armv6l-linux --target=armv6l-linux --prefix=/nix/store/wjx4qrhnkgln1vx1j2vq8lss9f5xbqdq-cups-2.4.7-lib --datadir=/nix/store/fq35ajcfmp6q2lf08m66lhd0c579sw8w-cups-2.4.7/share --localedir=/nix/store/wjx4qrhnkgln1vx1j2vq8lss9f5xbqdq-cups-2.4.7-lib/share/locale --with-systemd=/nix/store/fq35ajcfmp6q2lf08m66lhd0c579sw8w-cups-2.4.7/lib/systemd/system
configure: WARNING: unrecognized options: --enable-threads, --enable-ssl, --enable-avahi
checking build system type... x86_64-pc-linux-gnu
checking host system type... armv6l-unknown-linux-gnu
checking for codesign... no
checking for true... /nix/store/bblyj5b3ii8n6v4ra0nb37cmi3lf8rz9-coreutils-9.3/bin/true
checking for gawk... gawk
checking for armv6l-linux-gcc... gcc
checking whether the C compiler works... no
configure: error: in `/build/cups-2.4.7':
configure: error: C compiler cannot create executables
See `config.log' for more details

Again searching for a config.log reveals nothing.

Not sure if its related, but to build the armv6l-linux image I already have the following overrides in my flake:

          nixpkgs.overlays = [
            (final: super: {
              llvmPackages = super.llvmPackages_14;
              cmake = super.cmake.overrideAttrs (old: { env.NIX_CFLAGS_COMPILE = "-latomic"; });
            })
          ];

I’d be happy if someone could please help me on how I can fix these compiler errors and successfully cross compile cups for armv6l-linux.

TL;DR

Adding the following overlays fixes the cups build to armv6l-linux for me:

          nixpkgs.overlays = [
            (final: super: {
              llvmPackages = super.llvmPackages_14;
              cmake = super.cmake.overrideAttrs (old: { env.NIX_CFLAGS_COMPILE = "-latomic"; });
              jbig2dec = super.jbig2dec.overrideAttrs (old: { configureScript = "./autogen.sh"; preConfigure = ""; });
              cups-filters = super.cups-filters.overrideAttrs (old: {
                configureFlags = old.configureFlags ++ [ "--with-cups-config=${pkgs.cups.dev}/bin/cups-config" ];
                nativeBuildInputs = old.nativeBuildInputs ++ [ pkgs.glib ];
              });
            })
          ];

Detailed explaination

After a lot of debugging and trial and error I found out:

  1. That not the cups package was the issue, but the jbig2dec. I then looked at the git history of that nix pkg and found out, that this issue was recently patched in f4c5149 and 3d69cf4. So I added the following overlay:

    jbig2dec = super.jbig2dec.overrideAttrs (old: { configureScript = "./autogen.sh"; preConfigure = ""; });
    
  2. The build process then continues and the following error appeared:

    checking for CFLocaleCopyCurrent... no
    checking for GNU gettext in libc... yes
    checking whether to use NLS... yes
    checking where the gettext function comes from... libc
    checking for armv6l-unknown-linux-gnueabihf-cups-config... no
    checking for cups-config... no
    configure: error: Required cups-config is missing. Please install CUPS developer packages.
    

    After looking at the cups configure script I found out, that cups-config is a utility that is used by cups-filters to extract the correct cups version and much more. But from the error message it seemed like it is not installed. I then discovered the --with-cups-config parameter and tried out to manually pass the correct path to the cups-config binary.

    cups-filters = super.cups-filters.overrideAttrs (old: { configureFlags = old.configureFlags ++ [ "--with-cups-config=${pkgs.cups.dev}/bin/cups-config" ]; });
    
  3. Then the configure for cups-filters finished and I got this error in the build phase:

    @nix { "action": "setPhase", "phase": "buildPhase" }
    building
    build flags: -j6 SHELL=/nix/store/q1c2flcykgr4wwg5a6h450hxbk4ch589-bash-5.2-p15/bin/bash CUPS_SERVERBIN=\$\(out\)/lib/cups CUPS_DATADIR=\$\(out\)/share/cups CUPS_SERVERROOT=\$\(out\)/etc/cups
    gdbus-codegen \
        --interface-prefix org.cups.cupsd \
        --c-namespace Cups \
        --generate-c-code cups-notifier \
        utils/org.cups.cupsd.Notifier.xml
    gdbus-codegen \
        --interface-prefix org.cups.cupsd \
        --c-namespace Cups \
        --generate-c-code cups-notifier \
        utils/org.cups.cupsd.Notifier.xml
    /nix/store/q1c2flcykgr4wwg5a6h450hxbk4ch589-bash-5.2-p15/bin/bash: line 2: gdbus-codegen: command not found
    make: *** [Makefile:5832: cups-notifier.c] Error 127
    make: *** Waiting for unfinished jobs....
    /nix/store/q1c2flcykgr4wwg5a6h450hxbk4ch589-bash-5.2-p15/bin/bash: line 2: gdbus-codegen: command not found
    make: *** [Makefile:5832: cups-notifier.h] Error 127
    

    After a lot of googling I found out, that gdbus-codegen was not installed for building, so adding the following finally fixed the build:

    cups-filters = super.cups-filters.overrideAttrs (old: { nativeBuildInputs = old.nativeBuildInputs ++ [ pkgs.glib ]; });