Maven build from source or wrap binary?

Hello,
i have a program i want to package.(tinymediamanager)
My question is if i should package from source or just wrap the binary?
Why the question?
In the dev guide is this under FAQ:
image
It reads like autoPatchelfHook should only be used as a last resort.

If i use maven to build the package i am creating the binary tar.xz before unpacking it in the installPhase. Why should i create the binary with maven if i can simply download it from the site and use autoPatchelfHook? (Maven needs more time to build)

package.nix use maven to compile .tar.xz
{ copyDesktopItems
, fetchFromGitLab
, ffmpeg
, gettext
, git
, lib
, libmediainfo
, libzen
, makeWrapper
, makeDesktopItem
, maven
, openjdk17
, stdenv
, xz
, zenity
}:

let
  # Define sources for different architectures
  sources = {
    "x86_64-linux" = {
      arch = "amd64";
    };
    "aarch64-linux" = {
      arch = "arm64";
    };
  };

  # Select the source based on the current system
  sysSrc = sources.${stdenv.hostPlatform.system}
    or (throw "Unsupported system: ${stdenv.hostPlatform.system}");
in
maven.buildMavenPackage rec {
  pname = "tinyMediaManager";
  version = "5.2.11";

  src = fetchFromGitLab {
    owner = "tinyMediaManager";
    repo = "tinyMediaManager";
    rev = "tinyMediaManager-${version}";
    hash = "sha256-9Nfh9NITUXcvbrpFgLqUxqX9pVZ0a+JtP4JBPi6tx3A=";
  };

  # remove other builds from pom.xml to speed up build
  postPatch = ''
    substituteInPlace pom.xml \
      --replace-fail "<descriptor>src/assembly/windows-x64.xml</descriptor>" ""
  '';
  mvnHash = "sha256-YGkylr5MGHBY468SFbfC2pqlF7qK1TmxzJZXVDDDQFI=";

  # Fetch plugins during the dependency download phase.
  mvnDepsParameters = "-DskipTests -Pdist -DbuildNumber=${version} -Dmaven.buildNumber.skip=true";
  mvnParameters = "-DskipTests -Pdist -DbuildNumber=${version} -Dmaven.buildNumber.skip=true";

  nativeBuildInputs = [ makeWrapper git xz copyDesktopItems ];

  strictDeps = true;
  __structuredAttrs = true;

  jdk = openjdk17;
  
  desktopItems = [
    (makeDesktopItem {
      name = "tinyMediaManager";
      exec = "tinyMediaManager";
      icon = "tinyMediaManager";
      comment = "A media management tool";
      desktopName = "tinyMediaManager";
      genericName = "Media Manager";
      categories = [ "Video" "AudioVideo" ];
      terminal = false;
    })
  ];

  installPhase = ''
    runHook preInstall
    
    TARBALL="dist/tinyMediaManager-${version}-linux-${sysSrc.arch}.tar.xz"
    if [ ! -f "$TARBALL" ]; then
      echo "Error: Could not find $TARBALL"
      echo "Actual contents of dist/ directory:"
      ls -R dist/ || echo "dist/ directory not found"
      exit 5
    fi

    # Create destination directory
    mkdir -p $out/opt/tinyMediaManager $out/bin

    echo "Unpacking $TARBALL..."
    # --strip-components=1 removes the top-level folder inside the tarball 
    # so files land directly in our share directory.
    tar -xvf "$TARBALL" -C $out/opt/tinyMediaManager --strip-components=1

    cat > $out/bin/tinyMediaManager << EOF
#!/bin/sh
export LD_LIBRARY_PATH=${libzen}/lib:${libmediainfo}/lib:\$LD_LIBRARY_PATH
export PATH=${zenity}/bin:\$PATH
cd $out/opt/tinyMediaManager
exec ${jdk}/bin/java -Djava.library.path=./native -cp "tmm.jar:lib/*" org.tinymediamanager.TinyMediaManager "\$@"
EOF
    chmod +x $out/bin/tinyMediaManager

    # Handle the icon
    mkdir -p $out/share/pixmaps
    if [ -f "$out/opt/tinyMediaManager/tmm.png" ]; then
        ln -s $out/opt/tinyMediaManager/tmm.png $out/share/pixmaps/tinyMediaManager.png
    fi

    runHook postInstall

substituteInPlace $out/opt/tinyMediaManager/launcher.yml \
--replace 'jvmOpts:' "jvmOpts:
  - '-Dtmm.noupdate=true'"
  '';

  meta = with lib; {
    description = "A media management tool";
    homepage = "https://www.tinymediamanager.org/";
    changelog = "https://gitlab.com/tinyMediaManager/tinyMediaManager/-/releases/tinyMediaManager-${finalAttrs.version}#changelog";
    license = licenses.asl20;
    maintainers = with lib.maintainers; [ gamebeaker ];
    platforms = [
      "x86_64-linux"
      "aarch64-linux"
    ];
    mainProgram = "tinyMediaManager";
  };
}
package.nix wrap binary
{ stdenv
, fetchurl
, makeDesktopItem
, copyDesktopItems
, autoPatchelfHook
, unzip
, zlib
, glibc
, fontconfig
, alsa-lib
, xorg
, wayland
, gcc13
, libzen
, libmediainfo
, zenity
, zulu25
, lib
}:

let
  version = "5.2.11";

  # Define sources for different architectures
  sources = {
    "x86_64-linux" = {
      arch = "amd64";
      sha256 = "sha256-9EMKR0adbNBsVqY7pxkVuqqEEKQJzMVVIWVWN4cDAMA=";
    };
    "aarch64-linux" = {
      arch = "arm64";
      sha256 = "sha256-rXT3HKczUtvoebjmCxm0S/l1dIRkolk40qdL/FVvrK8=";
    };
  };

  # Select the source based on the current system
  sysSrc = sources.${stdenv.hostPlatform.system}
    or (throw "Unsupported system: ${stdenv.hostPlatform.system}");

  desktopItem = makeDesktopItem {
    name = "tinyMediaManager";
    exec = "tinyMediaManager";
    icon = "tinyMediaManager";
    comment = "A media management tool";
    desktopName = "tinyMediaManager";
    genericName = "Media Manager";
    categories = [ "Video" "AudioVideo" ];
    terminal = false;
  };

in
stdenv.mkDerivation {
  pname = "tinyMediaManager";
  inherit version;

  src = fetchurl {
    url = "https://archive.tinymediamanager.org/v${version}/tinyMediaManager-${version}-linux-${sysSrc.arch}.tar.xz";
    sha256 = sysSrc.sha256;
  };

  nativeBuildInputs = [
    autoPatchelfHook
    unzip
    copyDesktopItems
  ];

  buildInputs = [
    zlib
    glibc
    fontconfig
    alsa-lib
    xorg.libX11
    xorg.libXext
    xorg.libXrender
    xorg.libXtst
    xorg.libXi
    wayland
    gcc13.cc.lib
    libzen
    libmediainfo
    zenity
  ];

  strictDeps = true;
  __structuredAttrs = true;

  desktopItems = [ desktopItem ];

  installPhase = ''
    runHook preInstall

    mkdir -p $out/opt/tmm
    cp -r * $out/opt/tmm

    # Create the wrapper script
    mkdir -p $out/bin
    cat > $out/bin/tinyMediaManager << EOF
#!/bin/sh
export LD_LIBRARY_PATH=${libzen}/lib:${libmediainfo}/lib:\$LD_LIBRARY_PATH
export PATH=${zenity}/bin:\$PATH
cd $out/opt/tmm
exec ${zulu25}/bin/java -Djava.library.path=./native -cp "tmm.jar:lib/*" org.tinymediamanager.TinyMediaManager "\$@"
EOF
    chmod +x $out/bin/tinyMediaManager

    # Handle the icon
    mkdir -p $out/share/pixmaps
    if [ -f "$out/opt/tmm/tmm.png" ]; then
        ln -s $out/opt/tmm/tmm.png $out/share/pixmaps/tinyMediaManager.png
    fi

    runHook postInstall

substituteInPlace $out/opt/tmm/launcher.yml \
--replace 'jvmOpts:' "jvmOpts:
  - '-Dtmm.noupdate=true'"

  '';

  meta = with lib; {
    description = "A media management tool";
    homepage = "https://www.tinymediamanager.org/";
    changelog = "https://gitlab.com/tinyMediaManager/tinyMediaManager/-/releases/tinyMediaManager-${finalAttrs.version}#changelog";
    sourceProvenance = [ lib.sourceTypes.binaryNativeCode ];
    license = licenses.asl20;
    maintainers = with lib.maintainers; [ gamebeaker ];
    platforms = [
      "x86_64-linux"
      "aarch64-linux"
    ];
    mainProgram = "tinyMediaManager";
  };
}

If the package is for own consumption then follow your own criteria. But if it’s for contributing to Nixpkgs, then building from source is preferred.

1 Like

Because, provenance aside, users can’t patch the code (if they so choose, or perhaps need to in case of a failing build or security reasons or whatnot) unless we build from source.