1{
2 stdenv,
3 lib,
4 pkgArches,
5 makeSetupHook,
6 pname,
7 version,
8 src,
9 mingwGccs,
10 monos,
11 geckos,
12 platforms,
13 bison,
14 flex,
15 fontforge,
16 gettext,
17 makeWrapper,
18 pkg-config,
19 nixosTests,
20 supportFlags,
21 wineRelease,
22 patches,
23 moltenvk,
24 buildScript ? null,
25 configureFlags ? [ ],
26 mainProgram ? "wine",
27}:
28
29with import ./util.nix { inherit lib; };
30
31let
32 prevName = pname;
33 prevConfigFlags = configureFlags;
34
35 setupHookDarwin = makeSetupHook {
36 name = "darwin-mingw-hook";
37 substitutions = {
38 darwinSuffixSalt = stdenv.cc.suffixSalt;
39 mingwGccsSuffixSalts = map (gcc: gcc.suffixSalt) mingwGccs;
40 };
41 } ./setup-hook-darwin.sh;
42
43 # Using the 14.4 SDK allows Wine to use `os_sync_wait_on_address` for its futex implementation on Darwin.
44 # It does an availability check, so older systems will still work.
45 darwinFrameworks = lib.optionals stdenv.hostPlatform.isDarwin (
46 toBuildInputs pkgArches (pkgs: [ pkgs.apple-sdk_14 ])
47 );
48
49 # Building Wine with these flags isn’t supported on Darwin. Using any of them will result in an evaluation failures
50 # because they will put Darwin in `meta.badPlatforms`.
51 darwinUnsupportedFlags = [
52 "alsaSupport"
53 "cairoSupport"
54 "dbusSupport"
55 "fontconfigSupport"
56 "gtkSupport"
57 "netapiSupport"
58 "pulseaudioSupport"
59 "udevSupport"
60 "v4lSupport"
61 "vaSupport"
62 "waylandSupport"
63 "x11Support"
64 "xineramaSupport"
65 ];
66
67 badPlatforms = lib.optional (
68 !supportFlags.mingwSupport || lib.any (flag: supportFlags.${flag}) darwinUnsupportedFlags
69 ) "x86_64-darwin";
70in
71stdenv.mkDerivation (
72 finalAttrs:
73 lib.optionalAttrs (buildScript != null) { builder = buildScript; }
74 // lib.optionalAttrs stdenv.hostPlatform.isDarwin {
75 postBuild = ''
76 # The Wine preloader must _not_ be linked to any system libraries, but `NIX_LDFLAGS` will link
77 # to libintl, libiconv, and CoreFoundation no matter what. Delete the one that was built and
78 # rebuild it with empty NIX_LDFLAGS.
79 for preloader in wine-preloader wine64-preloader; do
80 rm loader/$preloader &> /dev/null \
81 && ( echo "Relinking loader/$preloader"; make loader/$preloader NIX_LDFLAGS="" NIX_LDFLAGS_${stdenv.cc.suffixSalt}="" ) \
82 || echo "loader/$preloader not built, skipping relink."
83 done
84 '';
85 }
86 // {
87 inherit version src;
88
89 pname =
90 prevName
91 + lib.optionalString (wineRelease != "stable" && wineRelease != "unstable") "-${wineRelease}";
92
93 # Fixes "Compiler cannot create executables" building wineWow with mingwSupport
94 strictDeps = true;
95
96 nativeBuildInputs =
97 with supportFlags;
98 [
99 bison
100 flex
101 fontforge
102 makeWrapper
103 pkg-config
104 ]
105 ++ lib.optional gettextSupport gettext
106 ++ lib.optionals mingwSupport (
107 mingwGccs ++ lib.optional stdenv.hostPlatform.isDarwin setupHookDarwin
108 );
109
110 buildInputs = toBuildInputs pkgArches (
111 with supportFlags;
112 (
113 pkgs:
114 [
115 pkgs.freetype
116 pkgs.perl
117 pkgs.libunwind
118 ]
119 ++ lib.optional stdenv.hostPlatform.isLinux pkgs.libcap
120 ++ lib.optional stdenv.hostPlatform.isDarwin pkgs.libinotify-kqueue
121 ++ lib.optional cupsSupport pkgs.cups
122 ++ lib.optional dbusSupport pkgs.dbus
123 ++ lib.optional cairoSupport pkgs.cairo
124 ++ lib.optional odbcSupport pkgs.unixODBC
125 ++ lib.optional netapiSupport pkgs.samba4
126 ++ lib.optional cursesSupport pkgs.ncurses
127 ++ lib.optional vaSupport pkgs.libva
128 ++ lib.optional pcapSupport pkgs.libpcap
129 ++ lib.optional v4lSupport pkgs.libv4l
130 ++ lib.optional saneSupport pkgs.sane-backends
131 ++ lib.optional gphoto2Support pkgs.libgphoto2
132 ++ lib.optional krb5Support pkgs.libkrb5
133 ++ lib.optional fontconfigSupport pkgs.fontconfig
134 ++ lib.optional alsaSupport pkgs.alsa-lib
135 ++ lib.optional pulseaudioSupport pkgs.libpulseaudio
136 ++ lib.optional (xineramaSupport && x11Support) pkgs.xorg.libXinerama
137 ++ lib.optional udevSupport pkgs.udev
138 ++ lib.optional vulkanSupport (
139 if stdenv.hostPlatform.isDarwin then moltenvk else pkgs.vulkan-loader
140 )
141 ++ lib.optional sdlSupport pkgs.SDL2
142 ++ lib.optional usbSupport pkgs.libusb1
143 ++ lib.optionals gstreamerSupport (
144 with pkgs.gst_all_1;
145 [
146 gstreamer
147 gst-plugins-base
148 gst-plugins-good
149 gst-plugins-ugly
150 gst-libav
151 gst-plugins-bad
152 ]
153 )
154 ++ lib.optionals gtkSupport [
155 pkgs.gtk3
156 pkgs.glib
157 ]
158 ++ lib.optionals openclSupport [
159 pkgs.opencl-headers
160 pkgs.ocl-icd
161 ]
162 ++ lib.optionals tlsSupport [
163 pkgs.openssl
164 pkgs.gnutls
165 ]
166 ++ lib.optionals (openglSupport && !stdenv.hostPlatform.isDarwin) [
167 pkgs.libGLU
168 pkgs.libGL
169 pkgs.libdrm
170 ]
171 ++ lib.optionals stdenv.hostPlatform.isDarwin darwinFrameworks
172 ++ lib.optionals (x11Support) (
173 with pkgs.xorg;
174 [
175 libX11
176 libXcomposite
177 libXcursor
178 libXext
179 libXfixes
180 libXi
181 libXrandr
182 libXrender
183 libXxf86vm
184 ]
185 )
186 ++ lib.optionals waylandSupport (
187 with pkgs;
188 [
189 wayland
190 wayland-scanner
191 libxkbcommon
192 wayland-protocols
193 wayland.dev
194 libxkbcommon.dev
195 libgbm
196 ]
197 )
198 )
199 );
200
201 inherit patches;
202
203 configureFlags =
204 prevConfigFlags
205 ++ lib.optionals supportFlags.waylandSupport [ "--with-wayland" ]
206 ++ lib.optionals supportFlags.vulkanSupport [ "--with-vulkan" ]
207 ++ lib.optionals (
208 (stdenv.hostPlatform.isDarwin && !supportFlags.xineramaSupport) || !supportFlags.x11Support
209 ) [ "--without-x" ];
210
211 # Wine locates a lot of libraries dynamically through dlopen(). Add
212 # them to the RPATH so that the user doesn't have to set them in
213 # LD_LIBRARY_PATH.
214 NIX_LDFLAGS = toString (
215 map (path: "-rpath " + path) (
216 map (x: "${lib.getLib x}/lib") (
217 [ stdenv.cc.cc ]
218 # Avoid adding rpath references to non-existent framework `lib` paths.
219 ++ lib.subtractLists darwinFrameworks finalAttrs.buildInputs
220 )
221 # libpulsecommon.so is linked but not found otherwise
222 ++ lib.optionals supportFlags.pulseaudioSupport (
223 map (x: "${lib.getLib x}/lib/pulseaudio") (toBuildInputs pkgArches (pkgs: [ pkgs.libpulseaudio ]))
224 )
225 ++ lib.optionals supportFlags.waylandSupport (
226 map (x: "${lib.getLib x}/share/wayland-protocols") (
227 toBuildInputs pkgArches (pkgs: [ pkgs.wayland-protocols ])
228 )
229 )
230 )
231 );
232
233 # Don't shrink the ELF RPATHs in order to keep the extra RPATH
234 # elements specified above.
235 dontPatchELF = true;
236
237 ## FIXME
238 # Add capability to ignore known failing tests
239 # and enable doCheck
240 doCheck = false;
241
242 postInstall =
243 let
244 links = prefix: pkg: "ln -s ${pkg} $out/${prefix}/${pkg.name}";
245 in
246 lib.optionalString supportFlags.embedInstallers ''
247 mkdir -p $out/share/wine/gecko $out/share/wine/mono/
248 ${lib.strings.concatStringsSep "\n" (
249 (map (links "share/wine/gecko") geckos) ++ (map (links "share/wine/mono") monos)
250 )}
251 ''
252 + lib.optionalString supportFlags.gstreamerSupport ''
253 # Wrapping Wine is tricky.
254 # https://github.com/NixOS/nixpkgs/issues/63170
255 # https://github.com/NixOS/nixpkgs/issues/28486
256 # The main problem is that wine-preloader opens and loads the wine(64) binary, and
257 # breakage occurs if it finds a shell script instead of the real binary. We solve this
258 # by setting WINELOADER to point to the original binary. Additionally, the locations
259 # of the 32-bit and 64-bit binaries must differ only by the presence of "64" at the
260 # end, due to the logic Wine uses to find the other binary (see get_alternate_loader
261 # in dlls/kernel32/process.c). Therefore we do not use wrapProgram which would move
262 # the binaries to ".wine-wrapped" and ".wine64-wrapped", but use makeWrapper directly,
263 # and move the binaries to ".wine" and ".wine64".
264 for i in wine wine64 ; do
265 prog="$out/bin/$i"
266 if [ -e "$prog" ]; then
267 hidden="$(dirname "$prog")/.$(basename "$prog")"
268 mv "$prog" "$hidden"
269 makeWrapper "$hidden" "$prog" \
270 ${lib.optionalString (lib.versionAtLeast version "10.1") "--inherit-argv0"} \
271 --set WINELOADER "$hidden" \
272 --prefix GST_PLUGIN_SYSTEM_PATH_1_0 ":" "$GST_PLUGIN_SYSTEM_PATH_1_0"
273 fi
274 done
275 '';
276
277 enableParallelBuilding = true;
278
279 # https://bugs.winehq.org/show_bug.cgi?id=43530
280 # https://github.com/NixOS/nixpkgs/issues/31989
281 hardeningDisable = [
282 "bindnow"
283 "stackclashprotection"
284 ]
285 ++ lib.optional (stdenv.hostPlatform.isDarwin) "fortify"
286 ++ lib.optional (supportFlags.mingwSupport) "format";
287
288 passthru = {
289 inherit pkgArches;
290 tests = { inherit (nixosTests) wine; };
291 updateScript = src.updateScript or null;
292 };
293 meta = {
294 inherit version;
295 homepage = "https://www.winehq.org/";
296 license = with lib.licenses; [ lgpl21Plus ];
297 sourceProvenance = with lib.sourceTypes; [
298 fromSource
299 binaryNativeCode # mono, gecko
300 ];
301 description = "Open Source implementation of the Windows API on top of X, OpenGL, and Unix";
302 inherit badPlatforms platforms;
303 maintainers = with lib.maintainers; [
304 avnik
305 bendlas
306 jmc-figueira
307 kira-bruneau
308 raskin
309 reckenrode
310 ];
311 inherit mainProgram;
312 };
313 }
314)