Commit a195cdd1 authored by Yarny0's avatar Yarny0
Browse files

zoom-us: use `buildFHSEnv` for `x86_64-linux`

While the currently packages Zoom version 6.3.11.7212
is still usabe without FHS environment,
the newer version 6.4.1.587 isn't:
The dynamic loader trick of commit
3f58227a
can also be applied to `ZoomLauncher`,
making it start again.
However, `ZoomWebviewHost` won't work anymore:
Apparently it also requires the dynamic loader trick;
However, it tries to call itself, calling the dynamic loader,
which then doesn't know what to do.
The result is Zoom causing high CPU load while the main window
is visible, as it endlessly tries to start `ZoomWebviewHost`,
which is apparently needed to show the dashboard.

The commit at hand wraps Zoom in a `buildFHSEnv`.
This is the only possible way to ensure Zoom programs can be
executed without altering them with patchelf or wrapping them.

In detail:

* The derivation that was created before this
  commit is still needed (also for linus system).
  It is now moved into a let-in variable (`unpacked`)
  so it can be used for darwin (still unchanged)
  and for linux (wrapped by FHS env).

  Linux-specific wrapping is removed as we now need the
  zoom directory structure unmodified, as packaged by Zoom.
  In particular, this removes the `postFixup` section,
  or rather, keeps only the darwin-specific part.

  This part of the commit's diff is likely best
  readable with `git diff --color-words=.`.

* As a convenience for later updates, a comment is added that
  might help searching for missing library dependencies.

* The lists of dependencies (`libs` and `binPath`)
  are merged into a function `linuxGetDependencies`.

  It is no longer meaningful to keep them separate as the FHS
  environment merges all those packages into on unified tree.
  It is also not always clear whether a
  package is used as "program" or a "library"
  (e.g. pipewire, or possibly `xdg-desktop-portal`).

  As required by `buildFHSEnv`, the function
  `linuxGetDependencies` is called with `pkgs` as its
  only argument and returns a list of packages that
  will be made available in the FHS environment.
  This mechanism is meant to facilitate multi-arch packages
  (e.g. i686 running on x86-64), so zoom should work alright
  (on x86_64-linux) if we ignore `pkgs` and just provide
  our packages as before; but there is no reason to deviate
  from the mechanism that is provided by `buildFHSEnv`.
parent 69f185ed
Loading
Loading
Loading
Loading
+161 −196
Original line number Diff line number Diff line
@@ -2,46 +2,12 @@
  stdenv,
  lib,
  fetchurl,
  pipewire,
  makeWrapper,
  xar,
  cpio,
  # Dynamic libraries
  alsa-lib,
  atk,
  at-spi2-atk,
  at-spi2-core,
  cairo,
  cups,
  dbus,
  expat,
  libdrm,
  libGL,
  fontconfig,
  freetype,
  gtk3,
  gdk-pixbuf,
  glib,
  libgbm,
  nspr,
  nss,
  pango,
  qt5,
  wayland,
  xorg,
  libxkbcommon,
  udev,
  zlib,
  libkrb5,
  # Runtime
  coreutils,
  pciutils,
  procps,
  util-linux,
  pulseaudioSupport ? true,
  libpulseaudio,
  pulseaudio,
  callPackage,
  buildFHSEnv,
}:

let
@@ -72,72 +38,7 @@ let
    };
  };

  libs = lib.makeLibraryPath (
    [
      # $ LD_LIBRARY_PATH=$NIX_LD_LIBRARY_PATH:$PWD ldd zoom | grep 'not found'
      alsa-lib
      atk
      at-spi2-atk
      at-spi2-core
      cairo
      cups
      dbus
      expat
      libdrm
      libGL
      pipewire
      fontconfig
      freetype
      gtk3
      gdk-pixbuf
      glib
      libgbm
      nspr
      nss
      pango
      qt5.qt3d
      qt5.qtgamepad
      qt5.qtlottie
      qt5.qtmultimedia
      qt5.qtremoteobjects
      qt5.qtxmlpatterns
      stdenv.cc.cc
      wayland
      xorg.libX11
      xorg.libxcb
      xorg.libXcomposite
      xorg.libXdamage
      xorg.libXext
      libxkbcommon
      xorg.libXrandr
      xorg.libXrender
      xorg.libxshmfence
      xorg.xcbutilimage
      xorg.xcbutilkeysyms
      xorg.xcbutilrenderutil
      xorg.xcbutilwm
      xorg.libXfixes
      xorg.libXtst
      udev
      zlib
      libkrb5
    ]
    ++ lib.optional (pulseaudioSupport) libpulseaudio
  );

  binPath = lib.makeBinPath (
    [
      coreutils
      glib.dev
      pciutils
      pipewire
      procps
      util-linux
    ]
    ++ lib.optional pulseaudioSupport pulseaudio
  );
in
stdenv.mkDerivation {
  unpacked = stdenv.mkDerivation {
    pname = "zoom";
    version = versions.${system} or throwSystem;

@@ -149,11 +50,22 @@ stdenv.mkDerivation {
      zcat < zoomus.pkg/Payload | cpio -i
    '';

  nativeBuildInputs =
    [
    # Note: In order to uncover missing libraries
    # on x86_64-linux, add "pkgs" to this file's arguments
    # (at the top of this file), then add these attributes here:
    # > buildInputs = linuxGetDependencies pkgs;
    # > dontAutoPatchelf = true;
    # > dontWrapQtApps = true;
    # > preFixup = ''
    # >   addAutoPatchelfSearchPath $out/opt/zoom
    # >   autoPatchelf $out/opt/zoom/{cef,Qt,*.so*,aomhost,zoom,zopen,ZoomLauncher,ZoomWebviewHost}
    # > '';
    # ...and finally "pkgs.autoPatchelfHook"
    # to `nativeBuildInputs` right below.
    # Then build `zoom-us.unpacked`:
    # `autoPatchelfHook` will report missing library files.
    nativeBuildInputs = lib.optionals stdenv.hostPlatform.isDarwin [
      makeWrapper
    ]
    ++ lib.optionals stdenv.hostPlatform.isDarwin [
      xar
      cpio
    ];
@@ -179,59 +91,10 @@ stdenv.mkDerivation {
      runHook postInstall
    '';

  postFixup =
    lib.optionalString stdenv.hostPlatform.isDarwin ''
    postFixup = lib.optionalString stdenv.hostPlatform.isDarwin ''
      makeWrapper $out/Applications/zoom.us.app/Contents/MacOS/zoom.us $out/bin/zoom
    ''
    + lib.optionalString stdenv.hostPlatform.isLinux ''
      # Desktop File
      substituteInPlace $out/share/applications/Zoom.desktop \
          --replace-fail Exec={/usr/bin/,}zoom

      for i in aomhost zopen ZoomLauncher ZoomWebviewHost; do
        if [ -f $out/opt/zoom/$i ]; then
          patchelf --set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" $out/opt/zoom/$i
        fi
      done

      # ZoomLauncher sets LD_LIBRARY_PATH before execing zoom
      # IPC breaks if the executable name does not end in 'zoom'
      # zoom binary does not like being touched by patchelf
      #   => we call it indirectly via the dynamic linker
      # zoom binary inspects /proc/self/exe to find its data files
      #   => we must place a copy (not symlink) of the linker in zoom's data dir
      mv $out/opt/zoom/zoom $out/opt/zoom/.zoom
      cp "$(cat $NIX_CC/nix-support/dynamic-linker)" $out/opt/zoom/ld.so
      makeWrapper $out/opt/zoom/ld.so $out/opt/zoom/zoom \
        --add-flags $out/opt/zoom/.zoom \
        --prefix LD_LIBRARY_PATH ":" ${libs}

      rm $out/bin/zoom
      # Zoom expects "zopen" executable (needed for web login) to be present in CWD. Or does it expect
      # everybody runs Zoom only after cd to Zoom package directory? Anyway, :facepalm:
      # Clear Qt paths to prevent tripping over "foreign" Qt resources.
      # Clear Qt screen scaling settings to prevent over-scaling.
      makeWrapper $out/opt/zoom/ZoomLauncher $out/bin/zoom \
        --chdir "$out/opt/zoom" \
        --unset QML2_IMPORT_PATH \
        --unset QT_PLUGIN_PATH \
        --unset QT_SCREEN_SCALE_FACTORS \
        --prefix PATH : ${binPath} \
        --prefix LD_LIBRARY_PATH ":" ${libs}

      if [ -f $out/opt/zoom/ZoomWebviewHost ]; then
        wrapProgram $out/opt/zoom/ZoomWebviewHost \
          --unset QML2_IMPORT_PATH \
          --unset QT_PLUGIN_PATH \
          --unset QT_SCREEN_SCALE_FACTORS \
          --prefix LD_LIBRARY_PATH ":" ${libs}
      fi

      # Backwards compatibility: we used to call it zoom-us
      ln -s $out/bin/{zoom,zoom-us}
    '';

  # already done
    dontPatchELF = true;

    passthru.updateScript = ./update.sh;
@@ -250,4 +113,106 @@ stdenv.mkDerivation {
      ];
      mainProgram = "zoom";
    };
}
  };
  packages.aarch64-darwin = unpacked;
  packages.x86_64-darwin = unpacked;

  # linux definitions

  linuxGetDependencies =
    pkgs:
    [
      pkgs.alsa-lib
      pkgs.at-spi2-atk
      pkgs.at-spi2-core
      pkgs.atk
      pkgs.cairo
      pkgs.coreutils
      pkgs.cups
      pkgs.dbus
      pkgs.expat
      pkgs.fontconfig
      pkgs.freetype
      pkgs.gdk-pixbuf
      pkgs.glib
      pkgs.glib.dev
      pkgs.gtk3
      pkgs.libGL
      pkgs.libdrm
      pkgs.libgbm
      pkgs.libkrb5
      pkgs.libxkbcommon
      pkgs.nspr
      pkgs.nss
      pkgs.pango
      pkgs.pciutils
      pkgs.pipewire
      pkgs.procps
      pkgs.qt5.qt3d
      pkgs.qt5.qtgamepad
      pkgs.qt5.qtlottie
      pkgs.qt5.qtmultimedia
      pkgs.qt5.qtremoteobjects
      pkgs.qt5.qtxmlpatterns
      pkgs.stdenv.cc.cc
      pkgs.udev
      pkgs.util-linux
      pkgs.wayland
      pkgs.xorg.libX11
      pkgs.xorg.libXcomposite
      pkgs.xorg.libXdamage
      pkgs.xorg.libXext
      pkgs.xorg.libXfixes
      pkgs.xorg.libXrandr
      pkgs.xorg.libXrender
      pkgs.xorg.libXtst
      pkgs.xorg.libxcb
      pkgs.xorg.libxshmfence
      pkgs.xorg.xcbutilimage
      pkgs.xorg.xcbutilkeysyms
      pkgs.xorg.xcbutilrenderutil
      pkgs.xorg.xcbutilwm
      pkgs.zlib
    ]
    ++ lib.optionals pulseaudioSupport [
      pkgs.libpulseaudio
      pkgs.pulseaudio
    ];

  # We add the `unpacked` zoom archive to the FHS env
  # and also bind-mount its `/opt` directory.
  # This should assist Zoom in finding all its
  # files in the places where it expects them to be.
  packages.x86_64-linux = buildFHSEnv {
    pname = "zoom"; # Will also be the program's name!
    version = versions.${system} or throwSystem;

    targetPkgs = pkgs: (linuxGetDependencies pkgs) ++ [ unpacked ];
    extraPreBwrapCmds = ''
      cd ${unpacked}/opt/zoom
      unset QML2_IMPORT_PATH
      unset QT_PLUGIN_PATH
      unset QT_SCREEN_SCALE_FACTORS
    '';
    extraBwrapArgs = [ "--ro-bind ${unpacked}/opt /opt" ];
    runScript = "/opt/zoom/ZoomLauncher";

    extraInstallCommands = ''
      cp -Rt $out/ ${unpacked}/share
      substituteInPlace \
          $out/share/applications/Zoom.desktop \
          --replace-fail Exec={/usr/bin/,}zoom

      # Backwards compatibility: we used to call it zoom-us
      ln -s $out/bin/{zoom,zoom-us}
    '';

    passthru = unpacked.passthru // {
      inherit unpacked;
    };
    inherit (unpacked) meta;
  };

in

packages.${system} or throwSystem