Help packaging a QT application? (PenguinSubtitlePlayer)

(I have seen similar question here but there was no answer there)

I have been trying to package the qt application Penguin Subtitle Player and I have solved some of the errors (I think) but I can’t seem to get the last step of installing the app.

The following are the files I created. The directory tree looks as such:

.
├── build
│   └── myapp
│       └── default.nix
├── default.nix
└── penguin.nix

2 directories, 3 files

(The contents of the .nix files are at the end)

When I try to run the nix-build -A penguinsub, it seems the application is built but I seem to get the following error:

> make: *** No rule to make target 'install'.  Stop.

Looking into nix.dev manual for Install Phase, I believe I have to add the following lines:

# penguinsub.nix
# ...
installPhase = ''
    runHook preInstall
    mkdir -p $out/bin
    cp PenguinSubtitlePlayer $out/bin  # Not sure about this line
    runHook postInstall
  '';]
# ...

Though adding the lines continues to give me the same error. I think something in the InstallPhase needs to be different for packaging Qt apps? Can someone help me here?


(The following are the contents of the .nix files:)

# ./build/myapp/default.nix
{
  lib,
  stdenv,
  fetchFromGitHub,
  qtbase,
  wrapQtAppsHook,
}:

stdenv.mkDerivation {
  pname = "penguinsub";
  version = "v1.6.0";
  
  src = fetchFromGitHub {
    owner = "carsonip";
    repo = "Penguin-Subtitle-Player";
    rev = "v1.6.0";
    sha256 = "1gqzcrfr73bzrr0ymkmhmvwz6hnq087f2lvk24m7ivzl24vhbjf4";
  };

  buildInputs = [ qtbase ];
  nativeBuildInputs = [ wrapQtAppsHook ];
}
# ./default.nix
let
  nixpkgs = fetchTarball "https://github.com/NixOS/nixpkgs/tarball/nixos-22.11";
  pkgs = import nixpkgs { config = {}; overlays = []; };

in
{
  hello = pkgs.callPackage ./hello.nix { };
  icat = pkgs.callPackage ./icat.nix { };
  penguinsub = pkgs.libsForQt5.callPackage ./build/myapp/default.nix { };
}
# ./penguinsub.nix
{
  lib,
  stdenv,
  fetchFromGitHub,
  qtbase,
  wrapQtAppsHook,
}:

stdenv.mkDerivation {
  pname = "penguinsub";
  version = "v1.6.0";
  
  src = fetchFromGitHub {
    owner = "carsonip";
    repo = "Penguin-Subtitle-Player";
    rev = "v1.6.0";
    sha256 = "1gqzcrfr73bzrr0ymkmhmvwz6hnq087f2lvk24m7ivzl24vhbjf4";
  };

  buildInputs = [ qtbase ];
  nativeBuildInputs = [ wrapQtAppsHook qmake ];
  qtWrapperArgs = [ ''--prefix PATH : $out/bin'' ];

  installPhase = ''
    runHook preInstall
    mkdir -p $out/bin
    cp PenguinSubtitlePlayer $out/bin
    runHook postInstall
  '';
}
1 Like

I’ve finally got it working :tada:

I changed the target path from ./build/myapp/default.nix to ./penguinsub.nix for convenience. Aside from that, here are the changes from your derivation:

  • First, qmake was missing as input from the code you posted, so we fix that.

  • Next, the build fails because it tries to build the submodules, but it doesn’t find them. So, we need to also fetch them with fetchSubmodules = true;.

Note: Notice that if we add this and try to build again immediately the build will still fail. This is because the previous source is still cached in src.sha256, so we need to set src.sha256 = ""; and we re-build. After that, a new sha256 will be outputted which represents the source with all its submodules.

  • Finally, we copy the binary which is in build/release/PenguinSubtitlePlayer to the output.
# ./penguinsub.nix
{ lib
, stdenv
, fetchFromGitHub
, qtbase
, wrapQtAppsHook
, qmake
}:

stdenv.mkDerivation (finalAttrs: {
  pname = "penguinsub";
  version = "v1.6.0";

  src = fetchFromGitHub {
    owner = "carsonip";
    repo = "Penguin-Subtitle-Player";
    rev = finalAttrs.version;
    sha256 = "sha256-AhdShg/eWqF44W1r+KmcHzbGKF2TNSD/wPKj+x4oQkM=";
    fetchSubmodules = true;
  };

  buildInputs = [ qtbase ];
  nativeBuildInputs = [ wrapQtAppsHook qmake ];
  qtWrapperArgs = [ ''--prefix PATH : $out/bin'' ];

  installPhase = ''
    runHook preInstall
    mkdir -p $out/bin
    cp build/release/PenguinSubtitlePlayer $out/bin
    runHook postInstall
  '';
})

PS: When building with the nixos-22.11 version of nixpkgs, I actually get the following error:

$ ./result/bin/PenguinSubtitlePlayer
Cannot mix incompatible Qt library (5.15.12) with this library (5.15.7)

I believe this is because I’m running on nixos-unstable and the app might be trying to load my version of qt instead. However, when I build the app using my system packages it runs fine.

2 Likes

Thank you so much for the answer as well as the explanation!! :heart:

If it is okay, might I ask a few questions about your answer?

  • What does the final Attrs do?
  • how did you know the binary will be in build/release/PenguinSubtitlePlayer? (Asking because the app icat stored their binary in a different place, so I am trying to understand how to know where different apps store their binaries. Sorry if it is a dumb question :sneezing_face: )

Thank you again!! :heart:

1 Like
  • Using finalAttrs is a way to reference the attributes from inside mkDerivation. In this case it would be the version. You can read mroe about it in the Nixpkgs Manual.
    Edit: We should just use finalAttrs.version instead of "${finalAttrs.version}".

  • I entered a new shell which has the necessary packages to build the project:

$ nix-shell -A penguinsub

I then manually cloned the project in the current directory:

$ git clone --recurse-submodules https://github.com/carsonip/Penguin-Subtitle-Player
$ cd Penguin-Subtitle-Player

Finally I built the project:

$ qmake PenguinSubtitlePlayer.pro
$ make

That’s how I found out that the final program was in build/release/PenguinSubtitlePlayer

Thinking back now, I could have just looked at the PenguinSubtitlePlayer.pro which specifies the output directory:

CONFIG(debug, debug|release) {
    DESTDIR = build/debug
} else {
    DESTDIR = build/release
}

Glad this was useful, though. Looking forward to seeing this in the nixpkgs repos :grin:

1 Like

I honestly feel like I have learned so so many things here :heart: Thank you again for your answer as well the detailed explanation! :heart: I am already thinking of trying to install another qt application because this is so cool!

By the way you mentioned you were looking forward for the penguinsub app in the repos, I hope you meant you were uploading it there ,:3 Because I don’t have any idea how to push packages into nixpkgs repos ,:3

Thank you again so so much! I keep thinking of your answer and keep feeling like practicing them on other qt applications!

1 Like

You’re welcome. I’m still new to Nix/NixOS, myself, so I’m still trying my best to learn as well, but I’m glad this helped you.

Well, I don’t mind doing that, but perhaps this can be a good chance for you to learn? You can get started by reading the nixpkgs contributing guide. If you get stuck with something you can always ask of course.

Good luck with the other packages and happy nixing :snowflake:

1 Like