Hi there! I want to package GitHub - n4n0GH/hello: the complete KDE theme. First for my personal configuration and if it comes out good, I can see myself making a PR to nixpkgs
or package it for the NUR
.
My derivation looks like this atm:
(pkgs.libsForQt5.callPackage({mkDerivation}: mkDerivation) {} rec {
name = "hello";
version = "Hidden Hedgehog";
src = pkgs.fetchFromGitHub {
owner = "n4n0GH";
repo = "hello";
rev = "master";
sha256 = "sha256:1898swsq07rwnd3gdff7v153hzyv9k1hf5817z7a7gr8rphbn3km";
};
nativeBuildInputs = with pkgs; [
cmake
];
buildInputs = with pkgs; [
extra-cmake-modules
epoxy
xorg.libXdmcp
libsForQt5.kconfig
libsForQt5.kconfigwidgets
libsForQt5.kcrash
libsForQt5.kglobalaccel
libsForQt5.kio
libsForQt5.kinit
libsForQt5.kwin
libsForQt5.knotifications
libsForQt5.qt5.qtbase
libsForQt5.qt5.qttools
libsForQt5.qt5.qtx11extras
];
configurePhase = "mkdir build && cd build && cmake -DCMAKE_INSTALL_PREFIX=$out/usr/ ..";
buildPhase = "make -j 4";
installPhase = "make install";
})
I’m particularily uncertain about the install-prefix. It’s /usr
in the README of the GitHub-page linked above; however I thought I would have to add $out
to that, so that it gets added to the nix-store.
The actual error says, that it can’t create the directories, that are specified in the Makefile
, and that it maybe needs privileges. I don’t think that privileges are the problem, since I already run it as root (package is built on nixos-rebuild switch
).
Here is the error on which the build-process failed:
Install the project...
-- Install configuration: ""
-- Installing: /nix/store/nciszr4vcyg3zzyikzxdzh7iqzlh26gd-hello/usr/share/color-schemes/HelloDark.colors
-- Installing: /nix/store/nciszr4vcyg3zzyikzxdzh7iqzlh26gd-hello/usr/share/color-schemes/HelloLight.colors
CMake Error at kwin-effects/cmake_install.cmake:60 (file):
file cannot create directory:
/nix/store/z07clcr9p0zx91b69bmy1k17j1sjalvj-kdelibs4support-5.79.0/lib/qt-5.15.2/plugins/kwin/effects/plugins.
Maybe need administrative privileges.
Call Stack (most recent call first):
cmake_install.cmake:48 (include)
make: *** [Makefile:105: install] Error 1
builder for '/nix/store/f5jz9s4zbp2ramnjs6ah8xfwg6cdffw1-hello.drv' failed with exit code 2
cannot build derivation '/nix/store/syc1kfwy53jaybblclw8v7n0wyj49k5l-system-path.drv': 1 dependencies couldn't be built
cannot build derivation '/nix/store/6y09rlrhfy3j0vf7jpcw38bzv6k1n0dx-nixos-system-nixos-21.05pre283367.0a5f5bab0e0.drv': 1 dependencies couldn't be built
error: build of '/nix/store/6y09rlrhfy3j0vf7jpcw38bzv6k1n0dx-nixos-system-nixos-21.05pre283367.0a5f5bab0e0.drv' failed
Did anyone encounter a similar thing before or know how to resolve this? I’m still quite new to Nix and NixOS, so please forgive me, if I overlooked a basic thing.
Ohhh, of course. It’s not trying to install it in $out
, it’s trying to install it into the $out
of another package. Yeah, that’s illegal in nix. I’m not sure why it needs to do that (nor am I at all familiar with Qt infrastructure). But yeah, that’s your problem. It’s trying to install something into another package’s output path.
This gets it to compile for me (added the preCompile
hook). But I have two disclaimers:
- The package might not actually work. I don’t know if the files that I redirected actually needed to be where they were being put.
- This is just a kludge to get it working. For instance, hard-coding
qt-5.15.2
is almost certainly not good practice.
(pkgs.libsForQt5.callPackage({mkDerivation}: mkDerivation) {} rec {
name = "hello";
version = "Hidden Hedgehog";
src = pkgs.fetchFromGitHub {
owner = "n4n0GH";
repo = "hello";
rev = "master";
sha256 = "sha256:1898swsq07rwnd3gdff7v153hzyv9k1hf5817z7a7gr8rphbn3km";
};
nativeBuildInputs = with pkgs; [
cmake
];
buildInputs = with pkgs; [
extra-cmake-modules
epoxy
xorg.libXdmcp
libsForQt5.kconfig
libsForQt5.kconfigwidgets
libsForQt5.kcrash
libsForQt5.kglobalaccel
libsForQt5.kio
libsForQt5.kinit
libsForQt5.kwin
libsForQt5.knotifications
libsForQt5.qt5.qtbase
libsForQt5.qt5.qttools
libsForQt5.qt5.qtx11extras
];
preConfigure = ''
substituteInPlace kwin-effects/CMakeLists.txt \
--replace "\''${MODULEPATH}" "$out/qt-5.15.2/plugins" \
--replace "\''${DATAPATH}" "$out/share"
'';
})
Why does it do that? Isn’t $out
supposed to be usable to the derivation at hand? Why would it make sense to let $out
point to another package?
It’s not that $out
points to a different package. If you look in the kwin-effects/CMakeLists.txt
file, you’ll see:
execute_process(COMMAND kf5-config --install module OUTPUT_VARIABLE MODULEPATH OUTPUT_STRIP_TRAILING_WHITESPACE)
This sets the cmake variable MODULEPATH
to the output of the kf5-config --install module
command. This command looks up where to install modules, but it does it wrong for Nix’s purposes, and finds a path in another package.
Later on, that variable is used as follows:
install(TARGETS ${HELLOSHADERS} DESTINATION ${MODULEPATH}/kwin/effects/plugins)
So what I’ve done in the preConfigure
step is just replace that ${MODULEPATH}
with the equivalent path in $out
. There’s a similar thing happening for DATAPATH
Ah, ok got it. Thanks for the great explanation!
So basically the last thing to change is to make it more general; i.e. not depend on paths like qt-5.12.2
I can confirm, that at least the package is functional, when building it the way you showed it!
Great!
Yeah, that’s what I’d do. My first question would be: "is this a common issue that Qt applications / libraries run into when people try to package them for Nix? If so, is there a standard way to deal with it? For instance, I can imagine some kind of kf5-config
replacement shim that gives the right path to programs. Or maybe there’s some kind of automated patch script (like patchShebangs
) that will adjust the CMake files.
Looking around packages that use kdelibs4support
(which, by the way, is where kf5-config
comes from, so now it makes sense that it’s looking in it’s own out path, instead of the current package’s), it looks like almost none of them need this kind of adjustment, so it seems like there isn’t a standard / simple solution.
I did find qtcurve, which seems to do something similar:
So you’re probably good with the changes I put in. Maybe this preConfigure
instead:
# kwin-effects tries to put things in kdelibs4support's out path.
# this redirects it to our $out, but keeps the same directory structure
preConfigure = ''
local modulepath=$(kf5-config --install module)
local datapath=$(kf5-config --install data)
substituteInPlace kwin-effects/CMakeLists.txt \
--replace "\''${MODULEPATH}" "$out/''${modulepath#/nix/store/*/}" \
--replace "\''${DATAPATH}" "$out/''${datapath#/nix/store/*/}"
'';
Instead of hard-coding the paths, it uses the same method that the CMakeLists.txt is using (kf5-config
) and then stripping the /nix/store/*/
prefix and replacing it with the proper $out
prefix. It’s a little ugly, but I can’t think of a cleaner solution.