Compiling with old glibc

The question is: how do I compile with / link against an older version of glibc?

I’m trying using flakes to compile something with nix against an older version of glibc so that it will run on older OS-es. I’ve tried pinning a second version of nixpkgs and snagging the glibc from there with an overlay:

import nixpkgs {
    inherit system;
    glibc = (import nixpkgs-old {inherit system;}).glibc;
}

but I’m getting “error: output ‘/nix/store/nh67hajlsxdj7lglvn2fyjnfxl67z2py-stdenv-linux’ is not allowed to refer to the following paths: /nix/store/1q6v2661bkkzjx48q4n1d3q2ahlsha9q-linux-headers-4.4.10”
I also tried overriding the existing glibc and changing the src to point to an older version of glibc, but the patches aren’t compatible.

I’ve run into related issues with glibc in the past, and am also curious about the answer to this.

My own weak suggestion: instead of using an overlay, can you simply use the pinned nixpkgs’s glibc as a build input for your package? (Then perhaps the mismatched glibc version won’t wreak havoc with the rest of nixpkgs.)

I’d love it if that were sufficient, but I need to rebuild all the dependencies with the old glibc as well. Including libgomp.so.1, which is found in the gcc package, so very far down in the build chain.

right now I’m trying to override it by replacing all of the relevant attributes, so something along the lines of:

glibc = super.glibc.overrideAttrs (attrs: 
  let old-glibc = (import nixpkgs-old {inherit system;}).glibc;
  in {
    inherit (old-glibc) name src postPatch patches;
    <other minor tweaks>
  }
);

I’ll let you know how it goes

It works! This is the code that I used. Bear in mind that it’s designed to fit into a flake, so it will require some modification. nixpkgs refers to current master (though I’m hoping this is somewhat flexible) and nixpkgs-old refers to nixpkgs 16.09 (which used glibc 2.24).

Soon I’m going to add this to my pull request for nix-bundle (revamp appimage functionality by Radvendii · Pull Request #76 · matthewbauer/nix-bundle · GitHub), if you want an easy way to pull it in to your flake. It’ll be nix-bundle.overlays.glibc_2_24.${system} (once the pull request is merged).

{ system
, nixpkgs
, nixpkgs-old
}:
self: super:
  let
    # takes in a *string* name of a glibc package e.g. "glibcInfo"
    #
    # the general idea is to mix the attributes from the old glibc an from the
    # the new glibc in a way that gets us an older version of glibc but is
    # compatible with the new gcc and the changes to nixpkgs. this took a lot of
    # trial and error, and will probably have to be updated as nixpkgs
    # progresses.
    glibcAdapter = glibcPkg: super.${glibcPkg}.overrideAttrs (attrs:
      let
        oldGlibcPkg = (import nixpkgs-old { inherit system; }).${glibcPkg};
        glibcDir = "pkgs/development/libraries/glibc";
        oldGlibcDir = "${nixpkgs-old}/${glibcDir}";
        newGlibcDir = "${nixpkgs}/${glibcDir}";
      in {
        inherit (oldGlibcPkg) name src;

        # version wasn't an attribute back then, so we can't inherit
        version = "2.24";

        patches = oldGlibcPkg.patches ++ [
          # from current glibc (can't use fetchurl from here)
          ./locale-C.diff

          # has to do with new gcc not new glibc
          "${newGlibcDir}/fix-x64-abi.patch"

          # newer ld does something different with .symver
          ./common-symbol.patch

          # update to allow a special case empty string
          ./ld-monetary.patch
        ];

      postPatch =
        oldGlibcPkg.postPatch
        # from current glibc
        + ''
          # Needed for glibc to build with the gnumake 3.82
          # http://comments.gmane.org/gmane.linux.lfs.support/31227
          sed -i 's/ot \$/ot:\n\ttouch $@\n$/' manual/Makefile
          # nscd needs libgcc, and we don't want it dynamically linked
          # because we don't want it to depend on bootstrap-tools libs.
          echo "LDFLAGS-nscd += -static-libgcc" >> nscd/Makefile
        '';

      # modifications from old glibc
      configureFlags =
        # we can maintain compatiblity with older kernel (see below)
        super.lib.remove "--enable-kernel=3.2.0" (attrs.configureFlags or [])
        ++ [ "--enable-obsolete-rpc" ]
        ++ super.lib.optionals
          # (we don't have access to withLinuxHeaders from here)
          (attrs.linuxHeaders != null) [
            "--enable-kernel=2.6.32"
          ];

      NIX_CFLAGS_COMPILE =
        (attrs.NIX_CFLAGS_COMPILE or "")
        # from old glibc
        + " -Wno-error=strict-prototypes"
        # new gcc introduces new warnings which we must disable
        # (see https://github.com/NixOS/nixpkgs/pull/71480)
        + " -Wno-error=stringop-truncation -Wno-error=attribute-alias"
        # I also had to disable these <.< >.>
        + " -Wno-error=multistatement-macros"
        + " -Wno-error=int-in-bool-context"
        + " -Wno-error=format-truncation"
        + " -Wno-error=nonnull"
        + " -Wno-error=restrict"
        + " -Wno-error=unused-const-variable"
        + " -Wno-error=int-conversion"
        + " -Wno-error=unused-function";
      }
    );
  in {
    glibc = glibcAdapter "glibc";
    glibcLocales = glibcAdapter "glibcLocales";
    glibcInfo = glibcAdapter "glibcInfo";
    llvmPackages_11.llvm = super.llvmPackages_11.llvm.overrideAttrs (attrs: {
      doCheck = false; # test fails: intrinsics.ll
    });
  }
4 Likes