diff --git a/pkgs/applications/emulators/wine/base.nix b/pkgs/applications/emulators/wine/base.nix index 480fc009504e..f13e224627a9 100644 --- a/pkgs/applications/emulators/wine/base.nix +++ b/pkgs/applications/emulators/wine/base.nix @@ -1,10 +1,11 @@ -{ stdenv, lib, pkgArches, callPackage, +{ stdenv, lib, pkgArches, callPackage, makeSetupHook, name, version, src, mingwGccs, monos, geckos, platforms, bison, flex, fontforge, makeWrapper, pkg-config, autoconf, hexdump, perl, nixosTests, supportFlags, patches, vkd3dArches, + moltenvk, buildScript ? null, configureFlags ? [] }: @@ -15,9 +16,31 @@ let prevName = name; prevPlatforms = platforms; prevConfigFlags = configureFlags; + setupHookDarwin = makeSetupHook { + name = "darwin-mingw-hook"; + substitutions = { + darwinSuffixSalt = stdenv.cc.suffixSalt; + mingwGccsSuffixSalts = map (gcc: gcc.suffixSalt) mingwGccs; + }; + } ./setup-hook-darwin.sh; in stdenv.mkDerivation ((lib.optionalAttrs (buildScript != null) { builder = buildScript; +}) // (lib.optionalAttrs stdenv.isDarwin { + postConfigure = '' + # dynamic fallback, so this shouldn’t cause problems for older versions of macOS and will + # provide additional functionality on newer ones. This can be removed once the x86_64-darwin + # SDK is updated. + sed 's|/\* #undef HAVE_MTLDEVICE_REGISTRYID \*/|#define HAVE_MTLDEVICE_REGISTRYID 1|' \ + -i include/config.h + ''; + postBuild = '' + # The Wine preloader must _not_ be linked to any system libraries, but `NIX_LDFLAGS` will link + # to libintl, libiconv, and CoreFoundation no matter what. Delete the one that was built and + # rebuild it with empty NIX_LDFLAGS. + rm loader/wine64-preloader + make loader/wine64-preloader NIX_LDFLAGS="" NIX_LDFLAGS_${stdenv.cc.suffixSalt}="" + ''; }) // rec { inherit src; @@ -38,11 +61,13 @@ stdenv.mkDerivation ((lib.optionalAttrs (buildScript != null) { hexdump perl ] - ++ lib.optionals supportFlags.mingwSupport mingwGccs; + ++ lib.optionals supportFlags.mingwSupport (mingwGccs + ++ lib.optional stdenv.isDarwin setupHookDarwin); buildInputs = toBuildInputs pkgArches (with supportFlags; (pkgs: - [ pkgs.freetype pkgs.perl ] + [ pkgs.freetype pkgs.perl pkgs.libunwind ] ++ lib.optional stdenv.isLinux pkgs.libcap + ++ lib.optional stdenv.isDarwin pkgs.libinotify-kqueue ++ lib.optional cupsSupport pkgs.cups ++ lib.optional gettextSupport pkgs.gettext ++ lib.optional dbusSupport pkgs.dbus @@ -56,14 +81,16 @@ stdenv.mkDerivation ((lib.optionalAttrs (buildScript != null) { ++ lib.optional v4lSupport pkgs.libv4l ++ lib.optional saneSupport pkgs.sane-backends ++ lib.optional gphoto2Support pkgs.libgphoto2 + ++ lib.optional krb5Support pkgs.libkrb5 ++ lib.optional ldapSupport pkgs.openldap ++ lib.optional fontconfigSupport pkgs.fontconfig ++ lib.optional alsaSupport pkgs.alsa-lib ++ lib.optional pulseaudioSupport pkgs.libpulseaudio ++ lib.optional (xineramaSupport && !waylandSupport) pkgs.xorg.libXinerama ++ lib.optional udevSupport pkgs.udev - ++ lib.optional vulkanSupport pkgs.vulkan-loader + ++ lib.optional vulkanSupport (if stdenv.isDarwin then moltenvk else pkgs.vulkan-loader) ++ lib.optional sdlSupport pkgs.SDL2 + ++ lib.optional usbSupport pkgs.libusb1 ++ vkd3dArches ++ lib.optionals gstreamerSupport (with pkgs.gst_all_1; [ gstreamer gst-plugins-base gst-plugins-good gst-plugins-ugly gst-libav @@ -83,12 +110,17 @@ stdenv.mkDerivation ((lib.optionalAttrs (buildScript != null) { wayland libxkbcommon wayland-protocols wayland.dev libxkbcommon.dev ]))); - patches = [ ] ++ patches'; + patches = [ ] + # Wine requires `MTLDevice.registryID` for `winemac.drv`, but that property is not available + # in the 10.12 SDK (current SDK on x86_64-darwin). Work around that by using selector syntax. + ++ lib.optional stdenv.isDarwin ./darwin-metal-compat.patch + ++ patches'; configureFlags = prevConfigFlags ++ lib.optionals supportFlags.waylandSupport [ "--with-wayland" ] ++ lib.optionals supportFlags.vulkanSupport [ "--with-vulkan" ] - ++ lib.optionals supportFlags.vkd3dSupport [ "--with-vkd3d" ]; + ++ lib.optionals supportFlags.vkd3dSupport [ "--with-vkd3d" ] + ++ lib.optionals (stdenv.isDarwin && !supportFlags.xineramaSupport) [ "--without-x" ]; # Wine locates a lot of libraries dynamically through dlopen(). Add # them to the RPATH so that the user doesn't have to set them in diff --git a/pkgs/applications/emulators/wine/darwin-metal-compat.patch b/pkgs/applications/emulators/wine/darwin-metal-compat.patch new file mode 100644 index 000000000000..aeee7533bbd4 --- /dev/null +++ b/pkgs/applications/emulators/wine/darwin-metal-compat.patch @@ -0,0 +1,31 @@ +diff --git a/dlls/winemac.drv/cocoa_display.m b/dlls/winemac.drv/cocoa_display.m +index f64a6c0f6ad..6da0391e3fa 100644 +--- a/dlls/winemac.drv/cocoa_display.m ++++ b/dlls/winemac.drv/cocoa_display.m +@@ -289,7 +289,7 @@ static int macdrv_get_gpus_from_metal(struct macdrv_gpu** new_gpus, int* count) + * the primary GPU because we need to hide the integrated GPU for an automatic graphic switching pair to avoid apps + * using the integrated GPU. This is the behavior of Windows on a Mac. */ + primary_device = [MTLCreateSystemDefaultDevice() autorelease]; +- if (macdrv_get_gpu_info_from_registry_id(&primary_gpu, primary_device.registryID)) ++ if (macdrv_get_gpu_info_from_registry_id(&primary_gpu, (uint64_t)[primary_device registryID])) + goto done; + + /* Hide the integrated GPU if the system default device is a dedicated GPU */ +@@ -301,7 +301,7 @@ static int macdrv_get_gpus_from_metal(struct macdrv_gpu** new_gpus, int* count) + + for (i = 0; i < devices.count; i++) + { +- if (macdrv_get_gpu_info_from_registry_id(&gpus[gpu_count], devices[i].registryID)) ++ if (macdrv_get_gpu_info_from_registry_id(&gpus[gpu_count], (uint64_t)[devices[i] registryID])) + goto done; + + if (hide_integrated && devices[i].isLowPower) +@@ -354,7 +354,7 @@ static int macdrv_get_gpu_info_from_display_id_using_metal(struct macdrv_gpu* gp + + device = [CGDirectDisplayCopyCurrentMetalDevice(display_id) autorelease]; + if (device && [device respondsToSelector:@selector(registryID)]) +- ret = macdrv_get_gpu_info_from_registry_id(gpu, device.registryID); ++ ret = macdrv_get_gpu_info_from_registry_id(gpu, (uint64_t)[device registryID]); + + done: + [pool release]; diff --git a/pkgs/applications/emulators/wine/default.nix b/pkgs/applications/emulators/wine/default.nix index 191fd4b29800..37953f73c5dc 100644 --- a/pkgs/applications/emulators/wine/default.nix +++ b/pkgs/applications/emulators/wine/default.nix @@ -6,7 +6,7 @@ # }; # Make additional configurations on demand: # wine.override { wineBuild = "wine32"; wineRelease = "staging"; }; -{ lib, stdenv, callPackage, +{ lib, stdenv, callPackage, darwin, wineRelease ? "stable", wineBuild ? if stdenv.hostPlatform.system == "x86_64-linux" then "wineWow" else "wine32", gettextSupport ? false, @@ -29,6 +29,7 @@ v4lSupport ? false, saneSupport ? false, gphoto2Support ? false, + krb5Support ? false, ldapSupport ? false, pulseaudioSupport ? false, udevSupport ? false, @@ -36,9 +37,11 @@ vulkanSupport ? false, sdlSupport ? false, vkd3dSupport ? false, + usbSupport ? false, mingwSupport ? wineRelease != "stable", waylandSupport ? wineRelease == "wayland", - embedInstallers ? false # The Mono and Gecko MSI installers + embedInstallers ? false, # The Mono and Gecko MSI installers + moltenvk ? darwin.moltenvk # Allow users to override MoltenVK easily }: let wine-build = build: release: @@ -48,11 +51,12 @@ let wine-build = build: release: inherit cupsSupport gettextSupport dbusSupport openalSupport cairoSupport odbcSupport netapiSupport cursesSupport vaSupport pcapSupport - v4lSupport saneSupport gphoto2Support ldapSupport fontconfigSupport + v4lSupport saneSupport gphoto2Support krb5Support ldapSupport fontconfigSupport alsaSupport pulseaudioSupport xineramaSupport gtkSupport openclSupport tlsSupport openglSupport gstreamerSupport udevSupport vulkanSupport - sdlSupport vkd3dSupport mingwSupport waylandSupport embedInstallers; + sdlSupport usbSupport vkd3dSupport mingwSupport waylandSupport embedInstallers; }; + inherit moltenvk; }); in if wineRelease == "staging" then diff --git a/pkgs/applications/emulators/wine/packages.nix b/pkgs/applications/emulators/wine/packages.nix index cb857daef0a6..bf3f57aff0ff 100644 --- a/pkgs/applications/emulators/wine/packages.nix +++ b/pkgs/applications/emulators/wine/packages.nix @@ -1,16 +1,16 @@ -{ stdenv_32bit, lib, pkgs, pkgsi686Linux, pkgsCross, callPackage, +{ stdenv_32bit, lib, pkgs, pkgsi686Linux, pkgsCross, callPackage, moltenvk, wineRelease ? "stable", supportFlags }: let src = lib.getAttr wineRelease (callPackage ./sources.nix {}); - vkd3d = pkgs.callPackage ./vkd3d.nix {}; - vkd3d_i686 = pkgsi686Linux.callPackage ./vkd3d.nix {}; + vkd3d = pkgs.callPackage ./vkd3d.nix { inherit moltenvk; }; + vkd3d_i686 = pkgsi686Linux.callPackage ./vkd3d.nix { inherit moltenvk; }; in with src; { wine32 = pkgsi686Linux.callPackage ./base.nix { name = "wine-${version}"; - inherit src version supportFlags patches; + inherit src version supportFlags patches moltenvk; pkgArches = [ pkgsi686Linux ]; vkd3dArches = lib.optionals supportFlags.vkd3dSupport [ vkd3d_i686 ]; geckos = [ gecko32 ]; @@ -20,7 +20,7 @@ in with src; { }; wine64 = callPackage ./base.nix { name = "wine64-${version}"; - inherit src version supportFlags patches; + inherit src version supportFlags patches moltenvk; pkgArches = [ pkgs ]; vkd3dArches = lib.optionals supportFlags.vkd3dSupport [ vkd3d ]; mingwGccs = with pkgsCross; [ mingwW64.buildPackages.gcc ]; @@ -31,7 +31,7 @@ in with src; { }; wineWow = callPackage ./base.nix { name = "wine-wow-${version}"; - inherit src version supportFlags patches; + inherit src version supportFlags patches moltenvk; stdenv = stdenv_32bit; pkgArches = [ pkgs pkgsi686Linux ]; vkd3dArches = lib.optionals supportFlags.vkd3dSupport [ vkd3d vkd3d_i686 ]; diff --git a/pkgs/applications/emulators/wine/setup-hook-darwin.sh b/pkgs/applications/emulators/wine/setup-hook-darwin.sh new file mode 100644 index 000000000000..39eee193ded6 --- /dev/null +++ b/pkgs/applications/emulators/wine/setup-hook-darwin.sh @@ -0,0 +1,37 @@ + +fixupCFlagsForDarwin() { + # Because it’s getting called from a Darwin stdenv, MinGW will pick up on Darwin-specific + # flags, and the ./configure tests will fail to consider it a working cross-compiler. + # Strip them out, so Wine can use MinGW to build its DLLs instead of trying to use Clang. + # Ideally, it would be possible to build the DLLs on Windows (i.e., as part of `pkgsCross``), + # but that is not the case currently with Wine’s build system. + cflagsFilter='s|-F[^ ]*||g;s|-iframework [^ ]*||g;s|-isystem [^ ]*||g;s| *| |g' + + # libiconv and libintl aren’t needed by Wine, and having them causes linking to fail. + # The `CoreFoundation` reference is added by `linkSystemCoreFoundationFramework` in the + # Apple SDK’s setup hook. Remove that because MingW will fail due to file not found. + ldFlagsFilter='s|-lintl||g;s|-liconv||g;s|/nix/store/[^-]*-apple-framework-CoreFoundation[^ ]*||g' + + # `cc-wrapper.sh`` supports getting flags from a system-specific salt. While it is currently a + # tuple, that’s not considered a stable interface, so the Wine derivation will provide them: + # - for Darwin: The source is `stdenv.cc.suffixSalt`; and + # - for MinGW: The source is the `suffixSalt`` attribute of each of the `mingwGccs`. + export NIX_CFLAGS_COMPILE_@darwinSuffixSalt@=${NIX_CFLAGS_COMPILE-} + export NIX_LDFLAGS_@darwinSuffixSalt@=${NIX_LDFLAGS-} + for mingwSalt in @mingwGccsSuffixSalts@; do + echo removing @darwinSuffixSalt@-specific flags from NIX_CFLAGS_COMPILE for $mingwSalt + export NIX_CFLAGS_COMPILE_$mingwSalt+="$(sed "$cflagsFilter" <<< "$NIX_CFLAGS_COMPILE")" + echo removing @darwinSuffixSalt@-specific flags from NIX_LDFLAGS for $mingwSalt + export NIX_LDFLAGS_$mingwSalt+="$(sed "$ldFlagsFilter;$cflagsFilter" <<< "$NIX_LDFLAGS")" + done + + # Make sure the global flags aren’t accidentally influencing the platform-specific flags. + export NIX_CFLAGS_COMPILE="" + export NIX_LDFLAGS="" +} + +# This is pretty hacky, but this hook _must_ run after `linkSystemCoreFoundationFramework`. +function runFixupCFlagsForDarwinLast() { + preConfigureHooks+=(fixupCFlagsForDarwin) +} +postUnpackHooks+=(runFixupCFlagsForDarwinLast) diff --git a/pkgs/applications/emulators/wine/vkd3d.nix b/pkgs/applications/emulators/wine/vkd3d.nix index 303d33df217d..ac7c399cd97b 100644 --- a/pkgs/applications/emulators/wine/vkd3d.nix +++ b/pkgs/applications/emulators/wine/vkd3d.nix @@ -1,6 +1,5 @@ -{ lib, stdenv, fetchurl, vulkan-headers, spirv-headers, vulkan-loader }: +{ lib, stdenv, fetchurl, moltenvk, vulkan-headers, spirv-headers, vulkan-loader }: -#TODO: MoltenVK #TODO: unstable stdenv.mkDerivation rec { @@ -12,7 +11,8 @@ stdenv.mkDerivation rec { sha256 = "0szr1lw3xbgi9qjm13d1q4gyzzwv8i5wfxiwjg6dmwphrc7h6jxh"; }; - buildInputs = [ vulkan-headers spirv-headers vulkan-loader ]; + buildInputs = [ vulkan-headers spirv-headers ] + ++ [ (if stdenv.isDarwin then moltenvk else vulkan-loader) ]; enableParallelBuilding = true; @@ -20,7 +20,7 @@ stdenv.mkDerivation rec { description = "A 3d library build on top on Vulkan with a similar api to DirectX 12"; homepage = "https://source.winehq.org/git/vkd3d.git"; license = licenses.lgpl21; - platforms = platforms.linux; + platforms = platforms.unix; maintainers = [ maintainers.marius851000 ]; }; } diff --git a/pkgs/top-level/wine-packages.nix b/pkgs/top-level/wine-packages.nix index 62a2278bd4f1..c8bdaeb426e7 100644 --- a/pkgs/top-level/wine-packages.nix +++ b/pkgs/top-level/wine-packages.nix @@ -9,34 +9,36 @@ rec { base = minimal.override { gettextSupport = true; - fontconfigSupport = true; - alsaSupport = true; + fontconfigSupport = stdenv.isLinux; + alsaSupport = stdenv.isLinux; openglSupport = true; - vulkanSupport = stdenv.isLinux; + vulkanSupport = true; tlsSupport = true; cupsSupport = true; - dbusSupport = true; - cairoSupport = true; + dbusSupport = stdenv.isLinux; + cairoSupport = stdenv.isLinux; cursesSupport = true; - saneSupport = true; + saneSupport = stdenv.isLinux; pulseaudioSupport = config.pulseaudio or stdenv.isLinux; - udevSupport = true; - xineramaSupport = true; + udevSupport = stdenv.isLinux; + xineramaSupport = stdenv.isLinux; sdlSupport = true; mingwSupport = true; + usbSupport = true; }; full = base.override { - gtkSupport = true; + gtkSupport = stdenv.isLinux; gstreamerSupport = true; openalSupport = true; openclSupport = true; odbcSupport = true; - netapiSupport = true; - vaSupport = true; + netapiSupport = stdenv.isLinux; + vaSupport = stdenv.isLinux; pcapSupport = true; - v4lSupport = true; + v4lSupport = stdenv.isLinux; gphoto2Support = true; + krb5Support = true; ldapSupport = true; vkd3dSupport = true; embedInstallers = true;