Help with building qt package caesium-image compressor

Caesium homepage: GitHub - Lymphatus/caesium-image-compressor: Caesium is an image compression software that helps you store, send and share digital pictures, supporting JPG, PNG and WebP formats. You can quickly reduce the file size (and resolution, if you want) by preserving the overall quality of the image.

so in order to build it, you need qt6 SDK
and I’m also not sure where to find /path/to/Qt/version/gcc_64 mentioned in this build command :

cmake -B build_dir -DCMAKE_PREFIX_PATH=/path/to/Qt/version/gcc_64

so my solution is just using ${pkgs.qt6.qmake}/Qt/6.6.1/gcc_64, however, I’m unable to locate the exact path of it after using nix-locate

And I’m also not sure if using libsForQt5.callPackage will affect the build process, even though i specify the buildInputs and nativeBuildInputs to to use qt6 with pkgs.qt6.

anyways, the build process is not at all successful and I’m having difficulty with it. Please help me.

#file: configuration.nix
environment.systemPackages = with pkgs; [
  (libsForQt5.callPackage ./packages/caesium.nix{}).caesium
];
#file: ./packages/caesium.nix
{ lib, stdenv, pkgs, fetchFromGithub, ...}: #qtbase, wrapQtAppsHook, qmake, cmake... }:
{
caesium = stdenv.mkDerivation rec {
  pname = "caesium-image-compressor";
  version = "2.6.0";
  dontBuild = true;
  dontWrapQtApps = true;

  src = pkgs.fetchFromGitHub {
    owner = "Lymphatus";
    repo = "caesium-image-compressor";
    rev = "b7df29d37f17ec2d201f140adc76250931183221";
    sha256 = "sha256-Rkedt8E7h8sbzBuOC2roSRogf9gizzgO3YImVqJN+60=";
  };

  buildInputs = with pkgs;  [
    qt6.qtbase
  ];

  nativeBuildInputs = with pkgs; [
    qt6.qmake
    cmake
    qt6.wrapQtAppsHook
    cargo
  ];
  
  buildPhase = ''
  cmake -B $src -DCMAKE_PREFIX_PATH=${pkgs.qt6.qmake}/Qt/6.6.1/gcc_64
  cmake --build $src --config Release --target caesium_image_compressor
  '';
  
  meta = with lib; {
    description = "caesium-image-compressor";
    homepage = "https://github.com/Lymphatus/caesium-image-compressor";
    platforms = platforms.all;
    maintainers = [ maintainers.Lymphatus ];
    license = licenses.gpl3;
  };
};
}

error log:

warning: The interpretation of store paths arguments ending in `.drv` recently changed. If this command is now failing try again with '/nix/store/fhz3p6klpp8n3q5d6jjy5zg8ysriywgh-caesium-image-compressor-2.6.0.drv^*'
@nix { "action": "setPhase", "phase": "qmakePrePhase" }
Running phase: qmakePrePhase
@nix { "action": "setPhase", "phase": "qtPreHook" }
Running phase: qtPreHook
@nix { "action": "setPhase", "phase": "unpackPhase" }
Running phase: unpackPhase
unpacking source archive /nix/store/vddm2dq9da8b33nbnzs57awc7y8206zi-source
source root is source
@nix { "action": "setPhase", "phase": "patchPhase" }
Running phase: patchPhase
@nix { "action": "setPhase", "phase": "updateAutotoolsGnuConfigScriptsPhase" }
Running phase: updateAutotoolsGnuConfigScriptsPhase
@nix { "action": "setPhase", "phase": "configurePhase" }
Running phase: configurePhase
QMAKEPATH=/nix/store/k6bzgbksd210zbmazf1ax5f37nq9b92y-qtbase-5.15.12-dev:/nix/store/kzp3jyh2lrwxkvc1hhz8dxrxx6qbwzm5-qtwayland-5.15.12-dev:/nix/store/z8y7f2amviymk>
qmake PREFIX=/nix/store/68w9x2nfbcn4h6l7hgjqwg9z6ximdk0n-caesium-image-compressor-2.6.0 NIX_OUTPUT_OUT=/nix/store/68w9x2nfbcn4h6l7hgjqwg9z6ximdk0n-caesium-image-co>
Usage: qmake [mode] [options] [files]

QMake has two modes, one mode for generating project files based on
some heuristics, and the other for generating makefiles. Normally you
shouldn't need to specify a mode, as makefile generation is the default
mode for qmake, but you may use this to test qmake on an existing project

Mode:
  -project       Put qmake into project file generation mode
                 In this mode qmake interprets [files] as files to
                 be added to the .pro file. By default, all files with
                 known source extensions are added.
                 Note: The created .pro file probably will 
                 need to be edited. For example add the QT variable to 
                 specify what modules are required.
  -makefile      Put qmake into makefile generation mode (default)
                 In this mode qmake interprets files as project files to
                 be processed, if skipped qmake will try to find a project
                 file in your current working directory

Warnings Options:
  -Wnone         Turn off all warnings; specific ones may be re-enabled by
                 later -W options
  -Wall          Turn on all warnings
  -Wparser       Turn on parser warnings
  -Wlogic        Turn on logic warnings (on by default)
  -Wdeprecated   Turn on deprecation warnings (on by default)

Options:
   * You can place any variable assignment in options and it will be *
   * processed as if it was in [files]. These assignments will be    *
   * processed before [files] by default.                            *
  -o file        Write output to file
  -d             Increase debug level
  -t templ       Overrides TEMPLATE as templ
 -tp prefix     Overrides TEMPLATE so that prefix is prefixed into the value
  -help          This help
  -v             Version information
  -early         All subsequent variable assignments will be
                 parsed right before default_pre.prf
  -before        All subsequent variable assignments will be
                 parsed right before [files] (the default)
  -after         All subsequent variable assignments will be
                 parsed after [files]
  -late          All subsequent variable assignments will be
                 parsed right after default_post.prf
  -norecursive   Don't do a recursive search
  -recursive     Do a recursive search
  -set <prop> <value> Set persistent property
  -unset <prop>  Unset persistent property
  -query <prop>  Query persistent property. Show all if <prop> is empty.
  -qtconf file   Use file instead of looking for qt.conf
  -cache file    Use file as cache           [makefile mode only]
  -spec spec     Use spec as QMAKESPEC       [makefile mode only]
  -nocache       Don't use a cache file      [makefile mode only]
  -nodepend      Don't generate dependencies [makefile mode only]
  -nomoc         Don't generate moc targets  [makefile mode only]
  -nopwd         Don't look for files in pwd [project mode only]

The error log seems like i didn’t specify operands for qmake, even though i set dontBuild to true and specify ``buildPhase` commands. I’m not quite sure what’s happenning

Did you check caesium-image-compressor: init at 2.4.0 by jtojnar · Pull Request #232527 · NixOS/nixpkgs · GitHub?

thank you for the help, as always
so the topic become how do i import a package from nixpkgs commit. This is what i tried:

{
  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
    home-manager = {
      url = "github:nix-community/home-manager";
      inputs.nixpkgs.follows = "nixpkgs";
    };
    nixpkgs-caesium.url = "github:NixOS/nixpkgs/3a984f5476ea895e5757daa566990d60ec648ebe";
    nixpkgs-libcaesium.url = "github:NixOS/nixpkgs/cf0b459b36b0d1c2fd0741be8e4aa38620e7315c";
  };

  outputs = { nixpkgs, nixpkgs-caesium, nixpkgs-libcaesium, ... }@inputs:
  let
    username = "peal";
    hostname = "Windows11";
    system = "x86_64-linux";
    pkgs = import nixpkgs {
      inherit system;
      config.allowUnfree = true;
      overlays = [
        (final: prev: {
          inherit (import nixpkgs-caesium { inherit system; })
          caesium-image-compressor;
        })
        (final: prev: {
          inherit (import nixpkgs-libcaesium { inherit system; })
          libcaesium;
        })
      ];
    };

and i just put caesium-image-compressor under environment.systemPackages in configuration.nix
did i do something very wrong? it tells me undefined variable: caesium-image-compressor

{ inputs, config, lib, pkgs, ... }:
environment.systemPackages = with pkgs; [
caesium-image-compressor
];

or i could try something silly like this, basically copy your whole commit and use qt6Packages.callPackage, but it also returns an error:

error:
       … while calling the 'head' builtin

         at /nix/store/703ww0gf0h85460pd58h0mc1g33swz4y-source/lib/attrsets.nix:960:11:

          959|         || pred here (elemAt values 1) (head values) then
          960|           head values
             |           ^
          961|         else

       … while evaluating the attribute 'value'

         at /nix/store/703ww0gf0h85460pd58h0mc1g33swz4y-source/lib/modules.nix:809:9:

          808|     in warnDeprecation opt //
          809|       { value = builtins.addErrorContext "while evaluating the option `${showOption loc}':" value;
             |         ^
          810|         inherit (res.defsFinal') highestPrio;

       (stack trace truncated; use '--show-trace' to show the full trace)

       error: A definition for option `environment.systemPackages."[definition 4-entry 5]"' is not of type `package'. Definition values:
       - In `/nix/store/zzy8zw3znl972kaf01zyah652icylh9s-source/configuration.nix': <function>
# file: configuration.nix
environment.systemPackages = with pkgs; [
  qt6Packages.callPackage ./packages/caesium.nix
];
#file: ./packages/caesium.nix
{ pkgs
, stdenv
, lib
, fetchFromGitHub
, fetchpatch2
, wrapQtAppsHook
, cmake
, qtbase
, qtsvg
, qttools
, libcaesium
}:

stdenv.mkDerivation (finalAttrs: {
  pname = "caesium-image-compressor";
  version = "2.4.0";

  src = fetchFromGitHub {
    owner = "Lymphatus";
    repo = "caesium-image-compressor";
    rev = "v${finalAttrs.version}";
    hash = "sha256-TJnDHk2FhjNPM7Z1WXMlFSxZjdZO+gcX9SyaYDsj/NE=";
  };

  patches = [
    # Remove Windows-specific build code Linux
    # https://github.com/Lymphatus/caesium-image-compressor/pull/199
    (fetchpatch2 {
      url = "https://github.com/Lymphatus/caesium-image-compressor/commit/46198e3e2528df8b55ab6fb2553e83dd0f5cbaf1.patch";
      hash = "sha256-WjquVRlnaZEMyLVvvwFKF3OdRR/KSYPEsAqRq8KJFbs=";
    })
    # Install binary
    (fetchpatch2 {
      url = "https://github.com/Lymphatus/caesium-image-compressor/commit/4aec78d41edade2fec5e50c6832d9e58175c433c.patch";
      hash = "sha256-Wzd4n4ZxNZf0wzXT7F6I8VVOqnwbyUwjapk6xjIhU2E=";
    })
  ];

  nativeBuildInputs = [
    cmake
    wrapQtAppsHook
  ];

  buildInputs = [
    pkg.callPackage ./libcaesium.nix
    qtbase
    qtsvg
    qttools
  ];

  meta = with lib; {
    description = "Reduce file size while preserving the overall quality of the image";
    homepage = "https://github.com/Lymphatus/caesium-image-compressor";
    platforms = platforms.linux;
    license = licenses.gpl3Only;
    maintainers = with maintainers; [ jtojnar ];
  };
})
file: ./packages/libcaesium.nix
{ lib
, fetchFromGitHub
, rustPlatform
}:

rustPlatform.buildRustPackage rec {
  pname = "libcaesium";
  version = "0.10.2";

  src = fetchFromGitHub {
    owner = "Lymphatus";
    repo = "libcaesium";
    rev = version;
    hash = "sha256-PO/bfh9B9icpXrNozWYSxYnTNwmWAjgYvRiVvZMNS9M=";
  };

  cargoLock = {
    lockFile = ./Cargo.lock;
  };

  postPatch = ''
    cp ${./Cargo.lock} Cargo.lock
  '';

  postInstall = ''
    # Not meant for installation.
    rm "$out/bin/main"
  '';

  meta = with lib; {
    description = "Lossy/lossless image compression library";
    homepage = "https://github.com/Lymphatus/libcaesium";
    license = licenses.asl20;
    maintainers = with maintainers; [ jtojnar ];
    platforms = platforms.unix;
  };
}

How are you passing pkgs to your system?

This will not be used by anything. If you take caesium-image-compressor from a different Nixpkgs instance, it will use all its dependencies from the selfsame Nixpkgs instance.

This is because lists in Nix are space separated so you are passing two elements to environment.systemPackages, neither which is a package:

  • qt6Packages.callPackage
  • ./packages/caesium.nix

so i can solve the second one by wrapping it with brackets:

environment.systemPackages = with pkgs; [
  (qt6Packages.callPackage ./packages/caesium.nix{})
];

how about the first one where I want to have a nixpkgs commit inside my flake, how should i approach it?

thank you!

Also, i attempted to update the package by:

  • editting the version in both libcaesium.nix and caesium.nix to the latest one.
  • clone the libcaesium repo to a local directory and do cargo generate-lockfile on the terminal
  • cp the newly created lock file to the same dir as libcaesium.nix
    and i got the error:
error: builder for '/nix/store/ys06q4rcqx4bmd2869azzkdaycfdayfq-libcaesium-0.14.1.drv' failed with exit code 101;
       last 10 log lines:
       > Executing cargoSetupPostPatchHook
       > Validating consistency between /build/source/Cargo.lock and /build/cargo-vendor-dir/Cargo.lock
       > Finished cargoSetupPostPatchHook
       > Running phase: updateAutotoolsGnuConfigScriptsPhase
       > Running phase: configurePhase
       > Running phase: buildPhase
       > Executing cargoBuildHook
       > ++ env CC_X86_64_UNKNOWN_LINUX_GNU=/nix/store/4cjqvbp1jbkps185wl8qnbjpf8bdy8j9-gcc-wrapper-13.2.0/bin/cc CXX_X86_64_UNKNOWN_LINUX_GNU=/nix/store/4cjqvbp1jbkps185wl8qnbjpf8bdy8j9-gcc-wrapper-13.2.0/bin/c++ CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER=/nix/store/4cjqvbp1jbkps185wl8qnbjpf8bdy8j9-gcc-wrapper-13.2.0/bin/cc CC_X86_64_UNKNOWN_LINUX_GNU=/nix/store/4cjqvbp1jbkps185wl8qnbjpf8bdy8j9-gcc-wrapper-13.2.0/bin/cc CXX_X86_64_UNKNOWN_LINUX_GNU=/nix/store/4cjqvbp1jbkps185wl8qnbjpf8bdy8j9-gcc-wrapper-13.2.0/bin/c++ CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER=/nix/store/4cjqvbp1jbkps185wl8qnbjpf8bdy8j9-gcc-wrapper-13.2.0/bin/cc CARGO_BUILD_TARGET=x86_64-unknown-linux-gnu HOST_CC=/nix/store/4cjqvbp1jbkps185wl8qnbjpf8bdy8j9-gcc-wrapper-13.2.0/bin/cc HOST_CXX=/nix/store/4cjqvbp1jbkps185wl8qnbjpf8bdy8j9-gcc-wrapper-13.2.0/bin/c++ cargo build -j 16 --target x86_64-unknown-linux-gnu --frozen --profile release
       > error: the lock file /build/source/Cargo.lock needs to be updated but --frozen was passed to prevent this
       > If you want to try to generate the lock file without accessing the network, remove the --frozen flag and use --offline instead.

I’m pretty sure i have updated the Cargo.lock file, so why is it need to be updated?

i tried building libcaesium on the dir where i cloned it and it works fine with no error, even with --frozen flag

i don’t get what’s happening

Hard to tell without full error message and the flake code. You need to pass the pkgs with your overlays to your NixOS config, I do not see that in your flake.nix fragment – remember, Nix is pure functional language, so it only has access to what you explicitly pass.

The various fetchers like fetchFromGitHub return fixed-ouput derivations, which are cached using mostly just their hash as key. So if you just change the version attribute keeping the hash, it will find the old version of the source archive.

Oh i forgot to mention that i also updated the hash. But the problem is that it keeps telling me cargo.lock needs to be updated. Although i already did

Did you generate it from the same version of the repo as the one used in src?

Yes,to be more specific, i clone the 0.14.1 libcaesium and do cargo generate-lockfile in that dir and cp the newly created Cargo.lock to the same dir as libcaesium.nix

I just did cargo update and replace the cargo.lock file in hope that it might work and it did.

I then stopped the build and remove the paches since it is not needed anymore

However, another error yayyy:

> CMake Error at CMakeLists.txt:32 (find_program):
       >   Could not find CARGO using the following names: cargo
       >
       > 
       > -- Configuring incomplete, errors occurred!

acording to my understanding, cmake tries finding LIBCAESIUM first and only need cargo when LIBCAESIUM is not found. However, i do have libcaesium in buildInput:

#file: caesium-image-compressor.nix
buildInputs = [
    (pkgs.callPackage ./libcaesium.nix{})
];

and here’s the whole caesium-image-compressor.nix file i have currently if it helps:

{ pkgs
, stdenv
, lib
, fetchFromGitHub
, fetchpatch2
, wrapQtAppsHook
, cmake
, qtbase
, qtsvg
, qttools
#, libcaesium
}:

stdenv.mkDerivation (finalAttrs: {
  pname = "caesium-image-compressor";
  version = "2.6.0";

  src = fetchFromGitHub {
    owner = "Lymphatus";
    repo = "caesium-image-compressor";
    rev = "v${finalAttrs.version}";
    hash = "sha256-TbhcGGS22wfN47R78Ns2Nct8w7haMCNDatG8NXRXeK4=";#sha256-TJnDHk2FhjNPM7Z1WXMlFSxZjdZO+gcX9SyaYDsj/NE=";
  };
/*
  patches = [
    # Remove Windows-specific build code Linux
    # https://github.com/Lymphatus/caesium-image-compressor/pull/199
    (fetchpatch2 {
      url = "https://github.com/Lymphatus/caesium-image-compressor/commt/46198e3e2528df8b55ab6fb2553e83dd0f5cbaf1.patch";
      hash = "sha256-WjquVRlnaZEMyLVvvwFKF3OdRR/KSYPEsAqRq8KJFbs=";
    })
    # Install binary
    (fetchpatch2 {
      url = "https://github.com/Lymphatus/caesium-image-compressor/commit/4aec78d41edade2fec5e50c6832d9e58175c433c.patch";
      hash = "sha256-Wzd4n4ZxNZf0wzXT7F6I8VVOqnwbyUwjapk6xjIhU2E=";
    })
  ];
*/
  nativeBuildInputs = [
    cmake
    wrapQtAppsHook
  ];

  buildInputs = [
    (pkgs.callPackage ./libcaesium.nix{})
    qtbase
    qtsvg
    qttools
  ];

  meta = with lib; {
    description = "Reduce file size while preserving the overall quality of the image";
    homepage = "https://github.com/Lymphatus/caesium-image-compressor";
    platforms = platforms.linux;
    license = licenses.gpl3Only;
    maintainers = with maintainers; [ jtojnar ];
  };
})

I tried looking at the build system and it indeed looks like it cannot find libcaesium. After applying the following patch

--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -28,6 +28,7 @@ else ()
 endif ()
 
 find_library(LIBCAESIUM libcaesium)
+message(WARN, "***************** ${LIBCAESIUM}")
 if (NOT LIBCAESIUM)
     find_program(CARGO "cargo" REQUIRED)
 endif ()

It prints

WARN,***************** LIBCAESIUM-NOTFOUND

And looking closer at the c-i-c patches I applied in caesium-image-compressor: init at 2.4.0 by jtojnar · Pull Request #232527 · NixOS/nixpkgs · GitHub, those appear to be an older version of my patches that got merged in build: Fix Linux builds by jtojnar · Pull Request #199 · Lymphatus/caesium-image-compressor · GitHub.

c-i-c 2.4.1 contains the final versions of the patches and those do not actually appear to work. I must have tested them incorrectly when I opened the pull request.

I have opened a new pull request fixing the build and rebased the Nixpkgs pull request.

1 Like

thank you so much for the fix, really appreciate it

for people who wants caesium and need a quick answer for it:

#file: caesium.nix
{ pkgs
, stdenv
, lib
, fetchFromGitHub
, fetchpatch2
, wrapQtAppsHook
, cmake
, qtbase
, qtsvg
, qttools
#, libcaesium
}:

stdenv.mkDerivation (finalAttrs: {
  pname = "caesium-image-compressor";
  version = "2.6.0";

  src = fetchFromGitHub {
    owner = "Lymphatus";
    repo = "caesium-image-compressor";
    rev = "v${finalAttrs.version}";
    hash = "sha256-TbhcGGS22wfN47R78Ns2Nct8w7haMCNDatG8NXRXeK4=";
  };

  patches = [
    # https://github.com/Lymphatus/caesium-image-compressor/pull/260
    (fetchpatch2 {
      url = "https://github.com/Lymphatus/caesium-image-compressor/commit/4293296340e0bd497d26d9420d00f39c30b0e9e6.patch";
      hash = "sha256-n0KnHMtrlF1K1G4MfX/3+yaY7emkR4MmEX5aVx4/JPQ=";
    })
  ];

  nativeBuildInputs = [
    cmake
    wrapQtAppsHook
  ];

  buildInputs = [
    (pkgs.callPackage ./libcaesium.nix{})
    qtbase
    qtsvg
    qttools
  ];

  meta = with lib; {
    description = "Reduce file size while preserving the overall quality of the image";
    homepage = "https://github.com/Lymphatus/caesium-image-compressor";
    platforms = platforms.linux;
    license = licenses.gpl3Only;
    maintainers = with maintainers; [ jtojnar ];
  };
})
#file: libcaesium.nix
{ lib
, fetchFromGitHub
, rustPlatform
}:

rustPlatform.buildRustPackage rec {
  pname = "libcaesium";
  version = "0.14.1";

  src = fetchFromGitHub {
    owner = "Lymphatus";
    repo = "libcaesium";
    rev = version;
    hash = "sha256-DfzvH3abgTLa/CCZeXV3ypiPLfGVksJPOIr851cbRAk=";
  };

  cargoLock = {
    lockFile = ./Cargo.lock;
  };

  postPatch = ''
    cp ${./Cargo.lock} Cargo.lock
  '';

  postInstall = ''
    # Not meant for installation.
    rm "$out/bin/main"
  '';

  meta = with lib; {
    description = "Lossy/lossless image compression library";
    homepage = "https://github.com/Lymphatus/libcaesium";
    license = licenses.asl20;
    maintainers = with maintainers; [ jtojnar ];
    platforms = platforms.unix;
  };
}

You need to clone the libcaesium 0.14.1 and do cargo generate-lockfile then cp the Cargo.lock file into the same dir as libcaesium.nix

then put this in your configuration.nix:

environment.systemPackages = with pkgs; [
  (qt6Packages.callPackage ./to/your/caesium.nix{})
];

Or with flakes, you can just use nix run github:jtojnar/nixpkgs/caesium#caesium-image-compressor.

Or if someone wants it in Nixpkgs, feel free to take over the pull request and adopt the package.