{
  stdenv,
  fetchurl,
  lib,
  antiword,
  aspell,
  bison,
  catdoc,
  catdvi,
  chmlib,
  djvulibre,
  file,
  gawk,
  ghostscript,
  gnugrep,
  gnused,
  gnutar,
  groff,
  gzip,
  libiconv,
  libwpd,
  libxslt,
  lyx,
  makeWrapper,
  meson,
  ninja,
  perl,
  perlPackages,
  pkg-config,
  poppler-utils,
  python3Packages,
  libsForQt5,
  unrtf,
  untex,
  unzip,
  which,
  xapian,
  zlib,
  withGui ? true,
  withPython ? with stdenv; buildPlatform.canExecute hostPlatform,
}:

let
  filters = {
    # "binary-name = package" where:
    #  - "${package}/bin/${binary-name}" is the full path to the binary
    #  - occurrences of `"${binary-name}"` in recoll's filters should be fixed up
    awk = gawk;
    antiword = antiword;
    catppt = catdoc;
    catdvi = catdvi;
    djvused = djvulibre;
    djvutxt = djvulibre;
    egrep = gnugrep;
    groff = groff;
    gunzip = gzip;
    iconv = libiconv;
    pdftotext = poppler-utils;
    ps2ascii = ghostscript;
    sed = gnused;
    tar = gnutar;
    unzip = unzip;
    xls2csv = catdoc;
    xsltproc = libxslt;
    unrtf = unrtf;
    untex = untex;
    wpd2html = libwpd;
    perl = perl.passthru.withPackages (p: [ p.ImageExifTool ]);
  };
  filterPath = lib.makeBinPath (map lib.getBin (builtins.attrValues filters));
  useInotify = if stdenv.hostPlatform.isLinux then "true" else "false";
in

stdenv.mkDerivation rec {
  pname = "recoll";
  version = "1.43.9";

  src = fetchurl {
    url = "https://www.recoll.org/${pname}-${version}.tar.gz";
    hash = "sha256-irloDtMO9CBvtI+oEicUOy2myrGskieWoqNk5eapzU8=";
  };

  mesonFlags = [
    "-Drecollq=true"
    "-Dwebkit=false"
    "-Dsystemd=false"

    # this leaks into the final `librecoll-*.so` binary, so we need
    # to be sure it is taken from `pkgs.file` rather than `stdenv`,
    # especially when cross-compiling
    "-Dfile-command=${file}/bin/file"

  ]
  ++ lib.optionals (!withPython) [
    "-Dpython-module=false"
    "-Dpython-chm=false"
  ]
  ++ lib.optionals (!withGui) [
    "-Dqtgui=false"
    "-Dx11mon=false"
  ]
  ++ [
    "-Dinotify=${useInotify}"
  ];

  env.NIX_CFLAGS_COMPILE = toString [
    "-fpermissive" # libxml2-2.12 changed const qualifiers
  ];

  patches = [
    # use the same configure based build for darwin as linux
    ./0001-no-qtgui-darwin-bundle.patch
  ];

  nativeBuildInputs = [
    makeWrapper
    meson
    ninja
    pkg-config
    which
    libsForQt5.wrapQtAppsHook
  ]
  ++ lib.optionals withGui [
    libsForQt5.qtbase
    libsForQt5.qttools
  ]
  ++ lib.optionals withPython [
    python3Packages.setuptools
  ];

  buildInputs = [
    aspell
    bison
    chmlib
  ]
  ++ lib.optionals withPython [
    python3Packages.python
    python3Packages.mutagen
  ]
  ++ [
    xapian
    zlib
    file
  ]
  ++ lib.optionals withGui [
    libsForQt5.qtbase
  ]
  ++ lib.optionals stdenv.hostPlatform.isDarwin [
    libiconv
  ];

  qtWrapperArgs = [
    "--prefix PATH : ${filterPath}"
  ];

  # the filters search through ${PATH} using a sh proc 'checkcmds' for the
  # filtering utils. Short circuit this by replacing the filtering command with
  # the absolute path to the filtering command.
  postInstall = ''
    substituteInPlace $out/lib/*/site-packages/recoll/rclconfig.py --replace /usr/share/recoll $out/share/recoll
    substituteInPlace $out/share/recoll/filters/rclconfig.py       --replace /usr/share/recoll $out/share/recoll
    for f in $out/share/recoll/filters/* ; do
      if [[ ! "$f" =~ \.zip$ ]]; then
  ''
  + lib.concatStrings (
    lib.mapAttrsToList (k: v: ''
      substituteInPlace $f --replace '"${k}"'  '"${lib.getBin v}/bin/${k}"'
    '') filters
  )
  + ''
        substituteInPlace $f --replace '"pstotext"'  '"${lib.getBin ghostscript}/bin/ps2ascii"'
        substituteInPlace $f --replace /usr/bin/perl   ${
          lib.getBin (perl.passthru.withPackages (p: [ p.ImageExifTool ]))
        }/bin/perl
      fi
    done
    wrapProgram $out/share/recoll/filters/rclaudio.py \
      --prefix PYTHONPATH : $PYTHONPATH
    wrapProgram $out/share/recoll/filters/rcljoplin.py \
      --prefix PYTHONPATH : $out/${python3Packages.python.sitePackages}
    wrapProgram $out/share/recoll/filters/rclimg \
      --prefix PERL5LIB : "${with perlPackages; makeFullPerlPath [ ImageExifTool ]}"
  ''
  + lib.optionalString stdenv.hostPlatform.isLinux ''
    substituteInPlace  $f --replace '"lyx"' '"${lib.getBin lyx}/bin/lyx"'
  ''
  + lib.optionalString (stdenv.hostPlatform.isDarwin && withGui) ''
    mkdir $out/Applications
    mv $out/bin/recoll.app $out/Applications
  '';

  # create symlink after fixup to prevent double wrapping of recoll
  postFixup = lib.optionalString (stdenv.hostPlatform.isDarwin && withGui) ''
    ln -s ../Applications/recoll.app/Contents/MacOS/recoll $out/bin/recoll
  '';

  enableParallelBuilding = false; # XXX: -j44 tried linking befoire librecoll had been created

  meta = {
    description = "Full-text search tool";
    longDescription = ''
      Recoll is an Xapian frontend that can search through files, archive
      members, email attachments.
    '';
    homepage = "https://www.recoll.org";
    changelog = "https://www.recoll.org/pages/release-history.html";
    license = lib.licenses.gpl2Plus;
    platforms = lib.platforms.unix;
    maintainers = with lib.maintainers; [
      jcumming
    ];

    # `Makefile.am` assumes the ability to run the hostPlatform's python binary at build time
    broken = withPython && (with stdenv; !buildPlatform.canExecute hostPlatform);
  };
}
