Geant4 produces shared libraries with undefined references to GLIBC

I want to create a build environment for Allpix² but I’ve hit a snag and request some help. This project requires Geant4, ROOT and Eigen3. Luckily all of these were available in nixpkgs, only that Geant4 wasn’t updated to the last version; for that I created an updated fork. I created a shell.nix for this:

with import <nixpkgs> {};

let
  tmplt = import (fetchTarball https://github.com/Tmplt/nixpkgs/archive/update-geant4-2.tar.gz) {};

  geant4 = lib.overrideDerivation ((tmplt.geant4.override {
      enableGDML = true;
      xercesc = xercesc;

      # enableG3toG4 = true;
      # enableInventor = true;
      # enableOpenGLX11 = true;
      # enableRaytracerX11 = true;
      expat = expat;
      zlib = zlib;

      enableQT = true;
      qt = qt5.qtbase;

      enableXM = true;
      motif = motif;

      libGLU_combined = libGLU_combined;
    }).v10_4_1) (attrs: {
      NIX_CFLAGS_COMPILE = "-lm";
    });
in
  stdenv.mkDerivation {
    name = "allpix2-devenv";
    buildInputs = [
      geant4
      root
      eigen3_3
      cmake

      # Convenience, if --pure is passed to nix-shell
      # TODO: add clang-tidy
      git

      # Documentation dependencies
      doxygen
      texlive.combined.scheme-basic
      pandoc
      biber
      imagemagick
      ghostscript
      poppler_utils
    ];
  }

nix-shell builds everything without problem, but when building Allpix² itself, linking fails with

/nix/store/fnaqy9rhfidaqkvhsx36qkh88ali2p0b-geant4-10.4.1/lib/libG4clhep.so: undefined reference to `expf@GLIBC_2.27'
/nix/store/fnaqy9rhfidaqkvhsx36qkh88ali2p0b-geant4-10.4.1/lib/libG4processes.so: undefined reference to `logf@GLIBC_2.27'
collect2: error: ld returned 1 exit status

I tried to fix this by appending -lm to the compile flags via NIX_CFLAGS_COMPILE but this did not help. I also tried to recreate the build process of the Arch User Repository PKGBUILD (which build working libraries on my Arch Linux system), but a CMake flag requires the X11/xpm.h header to exist and I can’t figure out which package it’s in (xorg.xlibXpm seem to only contain the libraries).

Does geant4 in nixpkgs do something weird when building the libraries that causes this?

Try xorg.libXpm.dev for the X11/xpm.h header. This is because the derivation has multiple outputs and the default is just the binary.

Thanks, I’ve updated the shell.nix to the following:

with import <nixpkgs> {};

let
  tmplt = import (fetchTarball https://github.com/Tmplt/nixpkgs/archive/update-geant4-2.tar.gz) {};

  coin = stdenv.mkDerivation rec {
    name = "coin-${version}";
    version = "3.1.3";

    src = fetchurl {
      url = "https://bitbucket.org/Coin3D/coin/downloads/Coin-${version}.tar.gz";
      sha256 = "583478c581317862aa03a19f14c527c3888478a06284b9a46a0155fa5886d417";
    };

    patches = [ ./fixed-wrong-assignment.patch ];

    postUnpack = ''
      # fix compilation
      sed -i '/^#include "fonts\/freetype.h"$/i #include <cstdlib>\n#include <cmath>' $sourceRoot/src/fonts/freetype.cpp

      # fix http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=667139
      sed -i '/^#include <Inventor\/C\/basic.h>$/i #include <Inventor/C/errors/debugerror.h>' $sourceRoot/include/Inventor/SbBasic.h
    '';

    buildInputs = [ expat ];

    propagatedBuildInputs = [ libGLU ];
  };

  soxt = stdenv.mkDerivation rec {
    name = "soxt-${version}";
    version = "1.3.0";

    src = fetchurl {
      url = "https://bitbucket.org/Coin3D/coin/downloads/SoXt-${version}.tar.gz";
      sha256= "f5443aadafe8e2222b9b5a23d1f228bb0f3e7d98949b8ea8676171b7ea5bf013";
    };

    # buildInputs = [ coin xorg.libXi xorg.libXmu xorg.libXpm motif ];
    buildInputs = [ coin motif ];

    propagatedBuildInputs = [ xlibsWrapper ];
  };

  geant4 = lib.overrideDerivation ((tmplt.geant4.override {
      enableGDML = true;
      xercesc = xercesc;

      enableG3toG4 = true;
      enableInventor = true;
      enableOpenGLX11 = true;
      enableRaytracerX11 = true;
      expat = expat;
      zlib = zlib;

      enableQT = true;
      qt = qt5.qtbase;

      enableXM = true;
      motif = motif;

      libGLU_combined = libGLU_combined;
    }).v10_4_1) (attrs: {
      buildInputs = attrs.buildInputs ++ [ soxt xorg.libXpm.dev ];

      cmakeFlags = attrs.cmakeFlags +
        "-DINVENTOR_INCLUDE_DIR=${coin}/include/" +
        "-DINVENTOR_LIBRARY_RELEASE=${coin}/lib/libCoin.so";
    });
in
  stdenv.mkDerivation {
    name = "allpix2-devenv";
    buildInputs = [
      geant4
      root
      eigen3_3
      cmake

      # Convenience, if --pure is passed to nix-shell
      # TODO: add clang-tidy
      git

      # Documentation dependencies
      doxygen
      texlive.combined.scheme-basic
      pandoc
      biber
      imagemagick
      ghostscript
      poppler_utils
    ];
  }

Configuration stage complained about not finding some header files, but that was fixed by overriding cmakeFlags. Unfortunately, compilation fails because some Inventor headers cannot be found, but these are available in INVENTOR_INCLUDE_DIR. Creating a shell.nix for geant4 directly and manually doing the cmake .. && make dance works, compilation and all. I can’t tell if some references are undefined; nm -u libG4processes.so lists a ton of entries, most of which are GLIBC and GLIBCXX functions, but I figure these are considered resolved in the linking stage of an executable? ldd libG4processes.so does after all find everything.

Now, compilation passes in a pure Nix shell, but not with the derivation in nixpkgs with the same CMake flags. What could cause this? The CMAKE_BUILD_TYPE difference?

The next thing to do would be to publish the WIP branch so others can execute and test your code. I don’t have much experience with cmake so that would have to be somebody else.

Alright. The updated branch contain changes to default.nix and fetch.nix in pkgs/development/libraries/physics/geant4. These files are available here. The shell.nix above imports this branch.

I’m currently writing my own derivation for the library to see if it helps.

Right, geant4 and Allpix² now builds without errors with the following nix.shell:

with import <nixpkgs> {};

let
  coin = stdenv.mkDerivation rec {
    name = "coin-${version}";
    version = "3.1.3";

    src = fetchurl {
      url = "https://bitbucket.org/Coin3D/coin/downloads/Coin-${version}.tar.gz";
      sha256 = "583478c581317862aa03a19f14c527c3888478a06284b9a46a0155fa5886d417";
    };

    patches = [ ./fixed-wrong-assignment.patch ];

    postUnpack = ''
      # fix compilation
      sed -i '/^#include "fonts\/freetype.h"$/i #include <cstdlib>\n#include <cmath>' $sourceRoot/src/fonts/freetype.cpp

      # fix http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=667139
      sed -i '/^#include <Inventor\/C\/basic.h>$/i #include <Inventor/C/errors/debugerror.h>' $sourceRoot/include/Inventor/SbBasic.h
    '';

    buildInputs = [ expat ];

    propagatedBuildInputs = [ libGLU ];
  };

  soxt = stdenv.mkDerivation rec {
    name = "soxt-${version}";
    version = "1.3.0";

    src = fetchurl {
      url = "https://bitbucket.org/Coin3D/coin/downloads/SoXt-${version}.tar.gz";
      sha256= "f5443aadafe8e2222b9b5a23d1f228bb0f3e7d98949b8ea8676171b7ea5bf013";
    };

    # buildInputs = [ coin xorg.libXi xorg.libXmu xorg.libXpm motif ];
    buildInputs = [ coin motif ];

    propagatedBuildInputs = [ xlibsWrapper coin ];
  };

  geant4 = stdenv.mkDerivation rec {
    name = "geant4-${version}";
    version = "10.4.1";

    src = fetchurl{
      url = "http://cern.ch/geant4-data/releases/geant4.10.04.p01.tar.gz";
      sha256 = "a3eb13e4f1217737b842d3869dc5b1fb978f761113e74bd4eaf6017307d234dd";
    };

    enableParallelBuilding = true;
    propagatedBuildInputs =
      [ cmake expat zlib xercesc qt5.qtbase motif libGLU_combined xlibsWrapper xorg.libXmu soxt xorg.libXpm.dev ];

    cmakeFlags = ''
      -DGEANT4_BUILD_MULTITHREADED=ON
      -DGEANT4_BUILD_CXXSTD=14
      -DGEANT4_INSTALL_DATA=OFF
      -DGEANT4_USE_GDML=ON
      -DGEANT4_USE_G3TOG4=ON
      -DGEANT4_USE_QT=ON
      -DGEANT4_USE_XM=ON
      -DGEANT4_USE_OPENGL_X11=ON
      -DGEANT4_USE_INVENTOR=ON
      -DGEANT4_USE_RAYTRACER_X11=ON
      -DGEANT4_USE_SYSTEM_CLHEP=OFF
      -DGEANT4_USE_SYSTEM_EXPAT=ON
      -DGEANT4_USE_SYSTEM_ZLIB=ON
      -DINVENTOR_INCLUDE_DIR=${coin}/include
      -DINVENTOR_LIBRARY_RELEASE=${coin}/lib/libCoin.so
    '';
  };
in
  stdenv.mkDerivation {
    name = "allpix2-devenv";
    buildInputs = [
      geant4
      root
      eigen3_3
      cmake

      # Convenience, if --pure is passed to nix-shell
      # TODO: add clang-tidy
      # git

      # Documentation dependencies
      # doxygen
      # texlive.combined.scheme-basic
      # pandoc
      # biber
      # imagemagick
      # ghostscript
      # poppler_utils
    ];
  }

Its difference from the previous shell.nix is the simple geant4 derivation and that coin is now a propegated build input of soxt; the latter change makes it so that ${coin} actually resolves to something in geant4.

I have yet to investigate the difference between this and what’s in nixpkgs.

1 Like

This suggests that coin should be in buildInputs of geant explicitly. Having it in propagatedBuildInputs of soxt would have the same effect, but it’s good to have it in buildInputs just for clarity. You might be also missing simage
https://www.hep.ucl.ac.uk/pbt/wiki/Software/Geant4/Installation/Coin3D

It would be nice to get updated geant in nixpkgs too. Feel free to ping me if you make a PR.

That makes sense. simage doesn’t seem to be missing, though.

I plan to update geant4 in nixpkgs, but both coin and soxt must be packaged then. Should these be committed seperately or can they be added under “updating geant4”?

I’m marking this as solved; having to install the additional libraries just to solve two seemingly simple undefined references to some GLIBC math functions feels like the wrong way around the issue, though. I have a feeling that there is just some missing -lm in a CMake file somewhere causing this.

I think it should work fine to have separate commits that fit “good commit messages” as defined in https://github.com/NixOS/nixpkgs/blob/master/.github/CONTRIBUTING.md
These can be submitted as a single Pull Request.

Alright, I’ll see about doing that. A PR of mine to geant4 has yet to be merged/commented on; I’ll add the changes to that branch.

Have the same problem with another package that requires Geant4, although in my derivation I use the updated nixpkgs Geant.

I tried using Geant4 from nixpkgs master recently now that my PR had been merged and stumbled upon the same problem, IIRC; I’ve been using the shell.nix above all this time. I’ll see about looking into the issue within the week.

Meanwhile, unless you depend on g4py, care to try geant4 overhaul by veprbl · Pull Request #40618 · NixOS/nixpkgs · GitHub out and see if that branch fixes the issue?

I think I fixed build failure in #40618 now. So the glibc problem persists? Should we reopen the issue on GH?