wrapQtAppsHook: support structuredAttrs (#526277)

This commit is contained in:
K900
2026-06-04 12:12:53 +00:00
committed by GitHub
6 changed files with 204 additions and 4 deletions
@@ -10,6 +10,7 @@
generateSplicesForMkScope,
lib,
stdenv,
callPackages,
gcc14Stdenv,
fetchurl,
fetchgit,
@@ -297,6 +298,7 @@ let
wrapQtAppsHook = callPackage (
{
wrapQtAppsHook,
makeBinaryWrapper,
qtbase,
qtwayland,
@@ -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
) { };
@@ -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=()
@@ -2,6 +2,7 @@
newScope,
lib,
stdenv,
callPackages,
generateSplicesForMkScope,
makeScopeWithSplicing',
fetchurl,
@@ -124,6 +125,7 @@ let
wrapQtAppsHook = callPackage (
{
wrapQtAppsHook,
makeBinaryWrapper,
qtwayland,
qtbase,
@@ -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
) { };
@@ -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=()
@@ -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
View File
@@ -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 { };