Unverified Commit f29c42ad authored by Philip Taron's avatar Philip Taron Committed by GitHub
Browse files

zoom-us: use `buildFHSEnv`, update, `xdg-desktop-portal`, minor improvements (#397036)

parents aa3b7a00 27f0cbcf
Loading
Loading
Loading
Loading
+144 −224
Original line number Diff line number Diff line
@@ -2,245 +2,165 @@
  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,
  wayland,
  xorg,
  libxkbcommon,
  udev,
  zlib,
  libkrb5,
  # Runtime
  coreutils,
  pciutils,
  procps,
  util-linux,
  pulseaudioSupport ? true,
  libpulseaudio,
  pulseaudio,
  xdgDesktopPortalSupport ? true,
  callPackage,
  buildFHSEnv,
}:

let
  inherit (stdenv.hostPlatform) system;
  throwSystem = throw "Unsupported system: ${system}";

  # Zoom versions are released at different times for each platform
  # and often with different versions. We write them on three lines
  # like this (rather than using {}) so that the updater script can
  # find where to edit them.
  versions.aarch64-darwin = "6.3.11.50104";
  versions.x86_64-darwin = "6.3.11.50104";
  versions.x86_64-linux = "6.3.11.7212";

  srcs = {
    aarch64-darwin = fetchurl {
      url = "https://zoom.us/client/${versions.aarch64-darwin}/zoomusInstallerFull.pkg?archType=arm64";
      name = "zoomusInstallerFull.pkg";
      hash = "sha256-RZVBq2TQcPs+8wx3YwwISVgaPvxS8hP93vxbJMpEhT0=";
    };
    x86_64-darwin = fetchurl {
      url = "https://zoom.us/client/${versions.x86_64-darwin}/zoomusInstallerFull.pkg";
      hash = "sha256-OwHVqQZVIQlasehX6UTD1fg1YZDAtvBZSdPq2Ze2JTA=";
    };
    x86_64-linux = fetchurl {
      url = "https://zoom.us/client/${versions.x86_64-linux}/zoom_x86_64.pkg.tar.xz";
      hash = "sha256-wSXb2v2qXoLXctmjOZpL0SiOP8+ySwpTDpJmPrfQQco=";
    };
  };

  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
      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 (finalAttrs: {
    pname = "zoom";
  version = versions.${system} or throwSystem;

  src = srcs.${system} or throwSystem;
    version = "6.4.6.1370";

  dontUnpack = stdenv.hostPlatform.isLinux;
  unpackPhase = lib.optionalString stdenv.hostPlatform.isDarwin ''
    xar -xf $src
    zcat < zoomus.pkg/Payload | cpio -i
  '';
    src = fetchurl {
      url = "https://zoom.us/client/${finalAttrs.version}/zoom_x86_64.pkg.tar.xz";
      hash = "sha256-Y+8garSqDcKLCVv1cTiqGEfrGKpK3UoXIq8X4E8CF+8=";
    };

  nativeBuildInputs =
    [
      makeWrapper
    ]
    ++ lib.optionals stdenv.hostPlatform.isDarwin [
      xar
      cpio
    ];
    dontUnpack = true;

    # Note: In order to uncover missing libraries,
    # 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;
    # > nativeBuildInputs = [ pkgs.autoPatchelfHook ];
    # > preFixup = ''
    # >   addAutoPatchelfSearchPath $out/opt/zoom
    # >   autoPatchelf $out/opt/zoom/{cef,Qt,*.so*,aomhost,zoom,zopen,ZoomLauncher,ZoomWebviewHost}
    # > '';
    # Then build `zoom-us.unpacked`:
    # `autoPatchelfHook` will report missing library files.

    installPhase = ''
      runHook preInstall
    ${
      rec {
        aarch64-darwin = ''
          mkdir -p $out/Applications
          cp -R zoom.us.app $out/Applications/
        '';
        # darwin steps same on both architectures
        x86_64-darwin = aarch64-darwin;
        x86_64-linux = ''
      mkdir $out
      tar -C $out -xf $src
      mv $out/usr/* $out/
        '';
      }
      .${system} or throwSystem
    }
      runHook postInstall
    '';

  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" "Exec=$out/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;
    passthru.tests.startwindow = callPackage ./test.nix { };

  meta = with lib; {
    meta = {
      homepage = "https://zoom.us/";
      changelog = "https://support.zoom.com/hc/en/article?id=zm_kb&sysparm_article=KB0061222";
      description = "zoom.us video conferencing application";
    sourceProvenance = with sourceTypes; [ binaryNativeCode ];
    license = licenses.unfree;
    platforms = builtins.attrNames srcs;
    maintainers = with maintainers; [
      sourceProvenance = with lib.sourceTypes; [ binaryNativeCode ];
      license = lib.licenses.unfree;
      platforms = [ "x86_64-linux" ];
      maintainers = with lib.maintainers; [
        danbst
        tadfisher
      ];
    mainProgram = "zoom";
    };
  });

  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
    ]
    ++ lib.optionals xdgDesktopPortalSupport [
      pkgs.kdePackages.xdg-desktop-portal-kde
      pkgs.lxqt.xdg-desktop-portal-lxqt
      pkgs.plasma5Packages.xdg-desktop-portal-kde
      pkgs.xdg-desktop-portal
      pkgs.xdg-desktop-portal-gnome
      pkgs.xdg-desktop-portal-gtk
      pkgs.xdg-desktop-portal-hyprland
      pkgs.xdg-desktop-portal-wlr
      pkgs.xdg-desktop-portal-xapp
    ];

in

# 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.
buildFHSEnv rec {
  pname = "zoom"; # Will also be the program's name!
  inherit (unpacked) version;

  targetPkgs = pkgs: (linuxGetDependencies pkgs) ++ [ unpacked ];
  extraPreBwrapCmds = "unset QT_PLUGIN_PATH";
  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;
  };
  meta = unpacked.meta // {
    mainProgram = pname;
  };
}
+3 −3
Original line number Diff line number Diff line
@@ -22,7 +22,7 @@ let
            | tee window-names
        grep -q "Zoom Workplace" window-names
      }
      # don't let zoom eat all RAM, like it did
      # Don't let zoom eat all RAM, like it did, cf.
      # https://github.com/NixOS/nixpkgs/issues/371488
      prlimit --{as,data}=$((4*2**30)):$((4*2**30)) zoom-us &
      for _ in {0..900} ; do
@@ -31,8 +31,8 @@ let
        fi
        sleep 1
      done
      # if libraries are missing, the window still appears,
      # but disappears again immediatelly; check for that too:
      # If libraries are missing, the window still appears,
      # but then disappears again immediately; check for that also.
      sleep 20
      is_zoom_window_present
    '';
+1 −29
Original line number Diff line number Diff line
@@ -3,32 +3,4 @@

set -eu -o pipefail

scriptDir=$(cd "${BASH_SOURCE[0]%/*}" && pwd)
nixpkgs=$(realpath "$scriptDir"/../../../..)

echo >&2 "=== Obtaining version data from https://zoom.us/rest/download ..."
linux_data=$(curl -Ls 'https://zoom.us/rest/download?os=linux' | jq .result.downloadVO)
mac_data=$(curl -Ls 'https://zoom.us/rest/download?os=mac' | jq .result.downloadVO)

version_aarch64_darwin=$(jq -r .zoomArm64.version <<<"$mac_data")
version_x86_64_darwin=$(jq -r .zoom.version <<<"$mac_data")
version_x86_64_linux=$(jq -r .zoom.version <<<"$linux_data")

echo >&2 "=== Downloading packages and computing hashes..."
# We precalculate the hashes before calling update-source-version
# because it attempts to calculate each architecture's package's hash
# by running `nix-build --system <architecture> -A zoom-us.src` which
# causes cross compiling headaches; using nix-prefetch-url with
# hard-coded URLs is simpler.  Keep these URLs in sync with the ones
# in package.nix where `srcs` is defined.
hash_aarch64_darwin=$(nix hash to-sri --type sha256 $(nix-prefetch-url --type sha256 "https://zoom.us/client/${version_aarch64_darwin}/zoomusInstallerFull.pkg?archType=arm64"))
hash_x86_64_darwin=$(nix hash to-sri --type sha256 $(nix-prefetch-url --type sha256 "https://zoom.us/client/${version_x86_64_darwin}/zoomusInstallerFull.pkg"))
hash_x86_64_linux=$(nix hash to-sri --type sha256 $(nix-prefetch-url --type sha256 "https://zoom.us/client/${version_x86_64_linux}/zoom_x86_64.pkg.tar.xz"))

echo >&2 "=== Updating package.nix ..."
# update-source-version expects to be at the root of nixpkgs
(cd "$nixpkgs" && update-source-version zoom-us "$version_aarch64_darwin" $hash_aarch64_darwin --system=aarch64-darwin --version-key=versions.aarch64-darwin)
(cd "$nixpkgs" && update-source-version zoom-us "$version_x86_64_darwin" $hash_x86_64_darwin --system=x86_64-darwin --version-key=versions.x86_64-darwin)
(cd "$nixpkgs" && update-source-version zoom-us "$version_x86_64_linux" $hash_x86_64_linux --system=x86_64-linux --version-key=versions.x86_64-linux)

echo >&2 "=== Done!"
update-source-version zoom-us $(curl -Ls 'https://zoom.us/rest/download?os=linux' | jq -r .result.downloadVO.zoom.version) --source-key=unpacked.src