Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions pkgs/development/libraries/qt-5/5.15/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
generateSplicesForMkScope,
lib,
stdenv,
callPackages,
gcc14Stdenv,
fetchurl,
fetchgit,
Expand Down Expand Up @@ -297,6 +298,7 @@ let

wrapQtAppsHook = callPackage (
{
wrapQtAppsHook,
makeBinaryWrapper,
qtbase,
qtwayland,
Expand All @@ -308,6 +310,9 @@ let
makeBinaryWrapper
]
++ lib.optional stdenv.hostPlatform.isLinux qtwayland.dev;
passthru.tests = callPackages ../../qt-6/tests/wrap-qt-apps-hook.nix {
inherit qtbase wrapQtAppsHook;
};
meta.license = lib.licenses.mit;
} ../hooks/wrap-qt-apps-hook.sh
) { };
Expand Down
7 changes: 5 additions & 2 deletions pkgs/development/libraries/qt-5/hooks/wrap-qt-apps-hook.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@ __nix_wrapQtAppsHook=1
# wrap only once per output
declare -a qtWrapperDoneForOuputs

# Inherit arguments given in mkDerivation
qtWrapperArgs=( ${qtWrapperArgs-} )
# Normalize qtWrapperArgs to an array
declare -a _qtWrapperArgsTmp
concatTo _qtWrapperArgsTmp qtWrapperArgs
qtWrapperArgs=("${_qtWrapperArgsTmp[@]}")
unset _qtWrapperArgsTmp

qtHostPathSeen=()

Expand Down
5 changes: 5 additions & 0 deletions pkgs/development/libraries/qt-6/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
newScope,
lib,
stdenv,
callPackages,
generateSplicesForMkScope,
makeScopeWithSplicing',
fetchurl,
Expand Down Expand Up @@ -124,6 +125,7 @@ let

wrapQtAppsHook = callPackage (
{
wrapQtAppsHook,
makeBinaryWrapper,
qtwayland,
qtbase,
Expand All @@ -134,6 +136,9 @@ let
depsTargetTargetPropagated = [
(onlyPluginsAndQml qtbase)
];
passthru.tests = callPackages ./tests/wrap-qt-apps-hook.nix {
inherit qtbase wrapQtAppsHook;
};
meta.license = lib.licenses.mit;
} ./hooks/wrap-qt-apps-hook.sh
) { };
Expand Down
7 changes: 5 additions & 2 deletions pkgs/development/libraries/qt-6/hooks/wrap-qt-apps-hook.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@ if [[ -z "${__nix_wrapQtAppsHook-}" ]]; then
# wrap only once per output
declare -a qtWrapperDoneForOuputs

# Inherit arguments given in mkDerivation
qtWrapperArgs=(${qtWrapperArgs-})
# Normalize qtWrapperArgs to an array
declare -a _qtWrapperArgsTmp
concatTo _qtWrapperArgsTmp qtWrapperArgs
qtWrapperArgs=("${_qtWrapperArgsTmp[@]}")
unset _qtWrapperArgsTmp

qtHostPathSeen=()

Expand Down
174 changes: 174 additions & 0 deletions pkgs/development/libraries/qt-6/tests/wrap-qt-apps-hook.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
{
lib,
qtbase,
runCommandLocal,
stdenv,
wrapQtAppsHook,
}:
let
testProgram = stdenv.mkDerivation {
pname = "qt-wrapper-test-program";
version = "0.0.1";
__structuredAttrs = true;

dontUnpack = true;

src = /* c */ ''
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void) {
const char *wrapperTest = getenv("WRAPPER_TEST");
if (!wrapperTest || strcmp(wrapperTest, "expected") != 0) {
fprintf(stderr,
"expected WRAPPER_TEST=expected, got=%s\n",
wrapperTest);
return 1;
}

const char *plugin_path = getenv("QT_PLUGIN_PATH");
if (!plugin_path) {
fprintf(stderr, "QT_PLUGIN_PATH not set\n");
return 1;
}

if (!strstr(plugin_path,
"${qtbase}/${qtbase.qtPluginPrefix}")) {
fprintf(stderr,
"QT_PLUGIN_PATH missing Qt plugin dir:\n%s\n",
plugin_path);
return 1;
}

return 0;
}
'';

buildPhase = ''
"$CC" -x c - -o test <<<"$src"
'';

installPhase = ''
mkdir -p $out/bin
install -m755 test $out/bin/test
'';

meta.mainProgram = "test";
};

# Test that wrapQtAppsHook produces the expected qtWrapperArgs bash array
checkWrapperArgsArray =
{
name,
qtWrapperArgs,
}:
runCommandLocal "${name}-check-qtWrapperArgs"
{
inherit qtWrapperArgs;
buildInputs = [ qtbase ];
nativeBuildInputs = [ wrapQtAppsHook ];
__structuredAttrs = true;
}
''
${lib.toShellVars {
# The resulting array should start with the exact user-defined args:
userDefinedArgs = qtWrapperArgs;

# The hook's setup should also add internal flags, including:
internalArgs = [
"QT_PLUGIN_PATH"
"${qtbase}/${qtbase.qtPluginPrefix}"
];
}}

# The hook should have run its setup already, converting qtWrapperArgs
# to an array and appending internal flags.
type=$(declare -p qtWrapperArgs)
[[ "$type" == "declare -"*a* ]] || {
echo "Expected qtWrapperArgs to be an array, found: ''${type%%=*}" >&2
exit 1
}

# The start of the array should equal the user-defined args
for i in "''${!userDefinedArgs[@]}"; do
actual="''${qtWrapperArgs[$i]}"
expected="''${userDefinedArgs[$i]}"
[ "$expected" = "$actual" ] || {
echo "qtWrapperArgs[$i]: expected '$expected', found '$actual'" >&2
exit 1
}
done

# Internal args should be appended to the array
internalSlice=("''${qtWrapperArgs[@]:''${#userDefinedArgs[@]}}")
for expected in "''${internalArgs[@]}"; do
found=
for actual in "''${internalSlice[@]}"; do
if [ "$expected" = "$actual" ]; then
found=1
break
fi
done

[ -n "$found" ] || {
echo "Internal arg '$expected' not found in internal qtWrapperArgs" >&2
exit 1
}
done

# The hook should've defined the wrapQtAppsHook function
[ "$(type -t wrapQtAppsHook)" = function ] || {
echo "wrapQtAppsHook is not declared as a function" >&2
exit 1
}

touch "$out"
'';
in

lib.fix (self: {

simple = checkWrapperArgsArray {
name = "simple";
qtWrapperArgs = [
"--chdir"
"/foo"
];
};

simple-no-structuredAttrs = self.simple.overrideAttrs (prevAttrs: {
name = prevAttrs.name + "-no-structuredAttrs";
__structuredAttrs = false;
});

# Integration test: assert program is wrapped with the expected environment
runtime =
runCommandLocal "simple-wrapper-runtime"
{
qtWrapperArgs = [
"--set"
"WRAPPER_TEST"
"expected"
];

buildInputs = [ qtbase ];
nativeBuildInputs = [ wrapQtAppsHook ];
__structuredAttrs = true;
}
''
# Install the test program
mkdir -p "$out/bin"
cp ${lib.getExe testProgram} "$out/bin/test"

# Wrap and run the test
wrapQtAppsHook
"$out/bin/test"
'';

runtime-no-structuredAttrs = self.runtime.overrideAttrs (prevAttrs: {
name = prevAttrs.name + "-no-structuredAttrs";
__structuredAttrs = false;
});

})
10 changes: 10 additions & 0 deletions pkgs/test/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,16 @@ in
) pkgs.arrayUtilities
);

# Accumulate all passthru.tests from qt5 into a single attribute set.
qt5 = recurseIntoAttrs {
wrapQtAppsHook = recurseIntoAttrs pkgs.qt5.wrapQtAppsHook.passthru.tests;
};

# Accumulate all passthru.tests from qt6 into a single attribute set.
qt6 = recurseIntoAttrs {
wrapQtAppsHook = recurseIntoAttrs pkgs.qt6.wrapQtAppsHook.passthru.tests;
};

srcOnly = callPackage ../build-support/src-only/tests.nix { };

systemd = callPackage ./systemd { };
Expand Down
Loading