Skip to content

Commit 2fdb8b9

Browse files
committed
separate wrapper build helper
1 parent 8ad2484 commit 2fdb8b9

File tree

9 files changed

+321
-239
lines changed

9 files changed

+321
-239
lines changed

default.nix

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ let
1111
./modules/many-wrappers.nix
1212
] ++ modules;
1313
specialArgs = {
14-
inherit pkgs;
14+
pkgs = import ./pkgs/extended.nix pkgs;
1515
} // specialArgs;
1616
};
1717
in
@@ -27,8 +27,9 @@ in
2727
module
2828
];
2929
specialArgs = {
30-
inherit pkgs;
30+
pkgs = import ./pkgs/extended.nix pkgs;
3131
};
3232
}).config.wrapped;
3333
};
34+
helpers = pkgs: import ./pkgs { inherit pkgs; };
3435
}

docs/readme.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,11 @@ https://github.com/viperML/wrapper-manager/issues
172172

173173
## Changelog
174174

175+
- 2025-07-27
176+
- Separate wrapper build helper from module system
177+
- Add `helpers` output, currently has `mkWrapper`
178+
- `wrapFlags` now read-only for access to final flags
179+
175180
- 2025-06-19
176181
- Full rewrite
177182
- `flags` has been removed in favor of `prependFlags`

modules/common-wrapper.nix renamed to modules/common-wrapper-args.nix

Lines changed: 31 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,9 @@ in
1212
{
1313
options = {
1414
wrapFlags = mkOption {
15-
type = flagsType;
16-
default = [ ];
17-
description = "Structured flags passed to makeWrapper.";
18-
example = [
19-
"--argv0"
20-
"myprog"
21-
];
15+
type = with types; separatedString " ";
16+
readOnly = true;
17+
description = "(Read-only) Final flags to wrap with";
2218
};
2319
appendFlags = mkOption {
2420
type = flagsType;
@@ -90,31 +86,34 @@ in
9086

9187
config = {
9288
wrapFlags =
93-
(flatten (
94-
map (f: [
95-
"--add-flag"
96-
f
97-
]) config.prependFlags
98-
))
99-
# Force the eval of config.flags to trigger throw
100-
++ (flatten (
101-
map (f: [
102-
"--add-flag"
103-
f
104-
]) config.flags
105-
))
106-
++ (flatten (
107-
map (f: [
108-
"--append-flag"
109-
f
110-
]) config.appendFlags
89+
(lib.escapeShellArgs (
90+
(flatten (
91+
map (f: [
92+
"--add-flag"
93+
f
94+
]) config.prependFlags
95+
))
96+
# Force the eval of config.flags to trigger throw
97+
++ (flatten (
98+
map (f: [
99+
"--add-flag"
100+
f
101+
]) config.flags
102+
))
103+
++ (flatten (
104+
map (f: [
105+
"--append-flag"
106+
f
107+
]) config.appendFlags
108+
))
109+
++ (lib.optionals (config.pathAdd != [ ]) [
110+
"--prefix"
111+
"PATH"
112+
":"
113+
(lib.makeBinPath config.pathAdd)
114+
])
115+
++ (flatten (map (e: e.asFlags) (attrValues config.env)))
111116
))
112-
++ (lib.optionals (config.pathAdd != [ ]) [
113-
"--prefix"
114-
"PATH"
115-
":"
116-
(lib.makeBinPath config.pathAdd)
117-
])
118-
++ (flatten (map (e: e.asFlags) (attrValues config.env)));
117+
+ config.extraWrapperFlags;
119118
};
120119
}

modules/wrapper-args.nix

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
{ pkgs, lib, config, ... }:
2+
let
3+
inherit (lib) mkOption types;
4+
5+
in
6+
{
7+
imports = [
8+
./common-wrapper-args.nix
9+
];
10+
11+
options = {
12+
basePackage = mkOption {
13+
type = with types; package;
14+
description = "Program to be wrapped";
15+
};
16+
17+
extraPackages = mkOption {
18+
type = with types; listOf package;
19+
default = [ ];
20+
description = "Optional extra packages to also wrap";
21+
};
22+
23+
programs = mkOption {
24+
default = { };
25+
description = "Wrap specific binaries with specific options. You may use it to skip wrapping some program.";
26+
example = lib.literalExpression ''
27+
{
28+
supervim = {
29+
target = "neovim";
30+
};
31+
32+
git = {
33+
env.GIT_CONFIG.value = ./gitconfig;
34+
};
35+
36+
# Don't wrap scalar
37+
scalar = {};
38+
}
39+
'';
40+
type = types.attrsOf (
41+
types.submoduleWith {
42+
modules = [
43+
./common-wrapper-args.nix
44+
(
45+
{ name, ... }:
46+
{
47+
options = {
48+
name = mkOption {
49+
type = types.str;
50+
default = name;
51+
description = "Name of the program";
52+
};
53+
54+
target = mkOption {
55+
type = with types; nullOr str;
56+
default = null;
57+
description = "Target of the program";
58+
};
59+
};
60+
61+
config = {
62+
wrapperType = lib.mkDefault config.wrapperType;
63+
};
64+
}
65+
)
66+
];
67+
}
68+
);
69+
};
70+
};
71+
}

modules/wrapper-impl.nix

Lines changed: 13 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,6 @@
66
}:
77
let
88
inherit (lib) mkOption types;
9-
inherit (builtins) attrValues;
10-
11-
printAndRun = cmd: ''
12-
echo ":: ${cmd}"
13-
eval "${cmd}"
14-
'';
15-
16-
hasMan = builtins.any (builtins.hasAttr "man") ([ config.basePackage ] ++ config.extraPackages);
179
in
1810
{
1911
options = {
@@ -51,137 +43,20 @@ in
5143
config = {
5244
wrapped =
5345
(
54-
(pkgs.symlinkJoin {
55-
# inherit (config.basePackage) name;
56-
pname = lib.getName config.basePackage;
57-
version = lib.getVersion config.basePackage;
58-
__intentionallyOverridingVersion = true;
59-
paths = [ config.basePackage ] ++ config.extraPackages;
60-
nativeBuildInputs = [
61-
pkgs.makeBinaryWrapper
62-
pkgs.makeWrapper
63-
];
64-
passthru = (config.basePackage.passthru or { }) // {
65-
unwrapped = config.basePackage;
66-
};
67-
outputs = [
68-
"out"
69-
] ++ (lib.optional hasMan "man");
70-
meta = (config.basePackage.meta or { }) // {
71-
outputsToInstall = [
72-
"out"
73-
] ++ (lib.optional hasMan "man");
74-
};
75-
postBuild = ''
76-
pushd "$out/bin" > /dev/null
77-
78-
echo "::: Wrapping explicit .programs ..."
79-
already_wrapped=()
80-
${lib.concatMapStringsSep "\n" (
81-
program:
82-
let
83-
name = program.name;
84-
target = if program.target == null then "" else program.target;
85-
wrapProgram = if program.wrapperType == "shell" then "wrapProgramShell" else "wrapProgramBinary";
86-
makeWrapper = if program.wrapperType == "shell" then "makeShellWrapper" else "makeBinaryWrapper";
87-
in
88-
# bash
89-
''
90-
already_wrapped+="${program.name}"
91-
92-
# If target is empty, use makeWrapper
93-
# If target is not empty, but the same as name, use makeWrapper
94-
# If target is not empty, is different from name, and doesn't exist, use wrapProgram
95-
# If target is not empty, is different from name, and exists, error out
96-
97-
cmd=()
98-
if [[ -z "${target}" ]]; then
99-
cmd=(${wrapProgram} "$out/bin/${name}")
100-
elif [[ -e "$out/bin/${name}" ]]; then
101-
echo ":: Error: Target '${name}' already exists"
102-
exit 1
103-
else
104-
cmd=(${makeWrapper} "$out/bin/${target}" '${name}')
105-
fi
106-
107-
${
108-
if program.wrapFlags == [ ] && program.extraWrapperFlags == "" then
109-
"echo ':: (${name} skipped: no wrapper configuration)'"
110-
else
111-
printAndRun "\${cmd[@]} ${lib.escapeShellArgs program.wrapFlags} ${program.extraWrapperFlags}"
112-
}
113-
''
114-
) (attrValues config.programs)}
115-
116-
echo "::: Wrapping packages in out/bin ..."
117-
118-
for file in "$out/bin/"*; do
119-
# check if $file is in $already_wrapped
120-
prog="$(basename "$file")"
121-
if [[ " ''${already_wrapped[@]} " =~ " $prog " ]]; then
122-
continue
123-
fi
124-
125-
${
126-
if config.wrapFlags == [ ] && config.extraWrapperFlags == "" then
127-
"echo \":: ($prog skipped: no wrapper configuration)\""
128-
else
129-
printAndRun (
130-
let
131-
wrapProgram = if config.wrapperType == "shell" then "wrapProgramShell" else "wrapProgramBinary";
132-
in
133-
''${wrapProgram} "$file" ${lib.escapeShellArgs config.wrapFlags} ${config.extraWrapperFlags}''
134-
)
135-
}
136-
done
137-
popd > /dev/null
138-
139-
## Fix desktop files
140-
141-
# Some derivations have nested symlinks here
142-
if [[ -d $out/share/applications && ! -w $out/share/applications ]]; then
143-
echo "Detected nested symlink, fixing"
144-
temp=$(mktemp -d)
145-
cp -v $out/share/applications/* $temp
146-
rm -vf $out/share/applications
147-
mkdir -pv $out/share/applications
148-
cp -v $temp/* $out/share/applications
149-
fi
150-
151-
pushd "$out/bin" > /dev/null
152-
for exe in *; do
153-
# Fix .desktop files
154-
# This list of fixes might not be exhaustive
155-
for file in $out/share/applications/*; do
156-
trap "set +x" ERR
157-
set -x
158-
sed -i "s#/nix/store/.*/bin/$exe #$out/bin/$exe #" "$file"
159-
sed -i -E "s#Exec=$exe([[:space:]]*)#Exec=$out/bin/$exe\1#g" "$file"
160-
sed -i -E "s#TryExec=$exe([[:space:]]*)#TryExec=$out/bin/$exe\1#g" "$file"
161-
set +x
162-
done
163-
done
164-
popd > /dev/null
165-
166-
${lib.optionalString hasMan ''
167-
mkdir -p ''${!outputMan}
168-
${lib.concatMapStringsSep "\n" (
169-
p:
170-
if p ? "man" then
171-
"${lib.getExe pkgs.xorg.lndir} -silent ${p.man} \${!outputMan}"
172-
else
173-
"echo \"No man output for ${lib.getName p}\""
174-
) ([ config.basePackage ] ++ config.extraPackages)}
175-
''}
176-
177-
${config.postBuild}
178-
'';
46+
(pkgs.mkWrapper {
47+
inherit (config)
48+
basePackage
49+
extraPackages
50+
programs
51+
prependFlags
52+
appendFlags
53+
pathAdd
54+
env
55+
extraWrapperFlags
56+
wrapperType
57+
;
17958
}).overrideAttrs
180-
(
181-
final: prev: {
182-
name = "${final.pname}-${final.version}";
183-
}
184-
)
59+
(_: prev: { buildCommand = prev.buildCommand + config.postBuild; })
18560
).overrideAttrs
18661
config.overrideAttrs;
18762
};

0 commit comments

Comments
 (0)