From 51a9f8be74d996ce05a93639dc125447b4346d49 Mon Sep 17 00:00:00 2001 From: David McFarland Date: Fri, 27 Jun 2025 12:38:18 +0000 Subject: [PATCH] godot: add darwin support --- pkgs/development/tools/godot/common.nix | 267 +++++++++++++----- .../tools/godot/fix-moltenvk-detection.patch | 16 ++ 2 files changed, 206 insertions(+), 77 deletions(-) create mode 100644 pkgs/development/tools/godot/fix-moltenvk-detection.patch diff --git a/pkgs/development/tools/godot/common.nix b/pkgs/development/tools/godot/common.nix index 5f312cdb6937..80e2c029aa1a 100644 --- a/pkgs/development/tools/godot/common.nix +++ b/pkgs/development/tools/godot/common.nix @@ -1,8 +1,10 @@ { alsa-lib, + apple-sdk_26, autoPatchelfHook, buildPackages, callPackage, + darwin, dbus, dotnetCorePackages, embree, @@ -38,6 +40,7 @@ makeWrapper, mbedtls, miniupnpc, + moltenvk, openxr-loader, pcre2, perl, @@ -49,29 +52,34 @@ speechd-minimal, stdenv, stdenvNoCC, + strip-nondeterminism, testers, udev, + unzip, updateScript, version, vulkan-loader, wayland, wayland-scanner, - withAlsa ? true, + withAlsa ? stdenv.hostPlatform.isLinux, withDbus ? true, withFontconfig ? true, withMono ? false, nugetDeps ? null, - withPlatform ? "linuxbsd", + # only linux supports builtin_ flags properly + withBuiltins ? !stdenv.hostPlatform.isLinux, + withPlatform ? if stdenv.hostPlatform.isDarwin then "macos" else "linuxbsd", withPrecision ? "single", withPulseaudio ? true, withSpeechd ? true, withTouch ? true, - withUdev ? true, + withUdev ? stdenv.hostPlatform.isLinux, # Wayland in Godot requires X11 until upstream fix is merged # https://github.com/godotengine/godot/pull/73504 - withWayland ? true, - withX11 ? true, + withWayland ? stdenv.hostPlatform.isLinux, + withX11 ? stdenv.hostPlatform.isLinux, wslay, + zip, zstd, }: assert lib.asserts.assertOneOf "withPrecision" withPrecision [ @@ -90,6 +98,8 @@ let dottedVersion = lib.replaceStrings [ "-" ] [ "." ] version + lib.optionalString withMono ".mono"; + harfbuzz-icu = harfbuzz.override { withIcu = true; }; + mkTarget = target: let @@ -116,8 +126,14 @@ let } // lib.optionalAttrs editor ( let + platform = + { + linuxbsd = "Linux"; + macos = "macOS"; + } + .${withPlatform}; project-src = - runCommand "${pkg.name}-project-src" + runCommand "${pkg.name}-6" { nativeBuildInputs = [ pkg ] ++ lib.optional (dotnet-sdk != null) dotnet-sdk; } @@ -144,12 +160,19 @@ let monoNode.owner = node '' + '' + ${""} var scene = PackedScene.new() var scenePath = "res://test.tscn" scene.pack(node) node.free() var x = ResourceSaver.save(scene, scenePath) ProjectSettings["application/run/main_scene"] = scenePath + '' + + lib.optionalString stdenv.hostPlatform.isDarwin '' + ${""} + ProjectSettings["rendering/textures/vram_compression/import_etc2_astc"] = true + '' + + '' ProjectSettings.save() quit() EOF @@ -164,13 +187,18 @@ let cat >export_presets.cfg <<'EOF' [preset.0] name="build" - platform="Linux" + platform="${platform}" runnable=true export_filter="all_resources" include_filter="" exclude_filter="" [preset.0.options] - binary_format/architecture="${arch}" + binary_format/architecture="${if stdenv.hostPlatform.isDarwin then "universal" else arch}" + '' + + lib.optionalString stdenv.hostPlatform.isDarwin '' + application/bundle_identifier="test" + '' + + '' EOF '' + lib.optionalString withMono '' @@ -224,8 +252,11 @@ let runHook preBuild export HOME=$(mktemp -d) - mkdir -p $HOME/.local/share/godot/ - ln -s "${final.export-template}"/share/godot/export_templates "$HOME"/.local/share/godot/ + local dataDir="$HOME/${ + if stdenv.hostPlatform.isDarwin then "Library/Application Support/Godot" else ".local/share/godot" + }/" + mkdir -p "$dataDir" + ln -s "${final.export-template}"/share/godot/export_templates "$dataDir" godot${suffix} --headless --build-solutions -s create-scene.gd @@ -236,7 +267,7 @@ let runHook preInstall mkdir -p "$out"/bin - godot${suffix} --headless --export-release build "$out"/bin/test + godot${suffix} --headless --export-release build "$out"/bin/test${lib.optionalString stdenv.hostPlatform.isDarwin ".app"} runHook postInstall ''; @@ -247,7 +278,7 @@ let ( set -eo pipefail HOME=$(mktemp -d) - "${final.export}"/bin/test --headless | tail -n+3 | ( + "${final.export}"/bin/test${lib.optionalString stdenv.hostPlatform.isDarwin ".app/Contents/MacOS/Unnamed"} --headless | tail -n+3 | ( '' + lib.optionalString withMono '' # indent @@ -280,9 +311,8 @@ let export-template = pkg.export-templates-bin; export = prev.export.overrideAttrs (prev: { - nativeBuildInputs = prev.nativeBuildInputs or [ ] ++ [ - autoPatchelfHook - ]; + nativeBuildInputs = + prev.nativeBuildInputs or [ ] ++ lib.optional stdenv.hostPlatform.isElf autoPatchelfHook; # stripping dlls results in: # Failed to load System.Private.CoreLib.dll (error code 0x8007000B) @@ -291,15 +321,17 @@ let runtimeDependencies = prev.runtimeDependencies or [ ] ++ map lib.getLib [ - alsa-lib libpulseaudio libX11 libXcursor libXext libXi libXrandr - udev vulkan-loader + ] + ++ lib.optionals stdenv.hostPlatform.isLinux [ + alsa-lib + udev ]; }); } @@ -359,6 +391,11 @@ let dotnet restore modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk.sln ''; + # darwin needs $HOME/.cache/clang/ModuleCache + preBuild = lib.optionalString stdenv.hostPlatform.isDarwin '' + export HOME=$(mktemp -d) + ''; + # From: https://github.com/godotengine/godot/blob/4.2.2-stable/SConstruct sconsFlags = mkSconsFlagsFromAttrSet ( { @@ -385,7 +422,8 @@ let # aliasing bugs exist with hardening+LTO # https://github.com/godotengine/godot/pull/104501 ccflags = "-fno-strict-aliasing"; - linkflags = "-Wl,--build-id"; + # on darwin: ld: unknown option: --build-id + linkflags = lib.optionalString (!stdenv.hostPlatform.isDarwin) "-Wl,--build-id"; # libraries that aren't available in nixpkgs builtin_msdfgen = true; @@ -408,12 +446,19 @@ let // lib.optionalAttrs (lib.versionAtLeast version "4.5") { redirect_build_objects = false; # Avoid copying build objects to output } + // lib.optionalAttrs stdenv.hostPlatform.isDarwin { + generate_bundle = "yes"; + } ); enableParallelBuilding = true; strictDeps = true; + propagatedSandboxProfile = lib.optionalString stdenv.hostPlatform.isDarwin '' + (allow file-read* (subpath "/System/Library/CoreServices/SystemAppearance.bundle")) + ''; + patches = [ ./Linux-fix-missing-library-with-builtin_glslang-false.patch ] @@ -431,12 +476,17 @@ let # Fix a crash in the mono test project build. It no longer seems to # happen in 4.4, but an existing fix couldn't be identified. ./CSharpLanguage-fix-crash-in-reload_assemblies-after-.patch - ]; + ] + ++ lib.optional ( + stdenv.hostPlatform.isDarwin && lib.versionAtLeast version "4.4" + ) ./fix-moltenvk-detection.patch; postPatch = '' # this stops scons from hiding e.g. NIX_CFLAGS_COMPILE perl -pi -e '{ $r += s:(env = Environment\(.*):\1\nenv["ENV"] = os.environ: } END { exit ($r != 1) }' SConstruct + '' + + lib.optionalString (!withBuiltins) '' # disable all builtin libraries by default perl -pi -e '{ $r |= s:(opts.Add\(BoolVariable\("builtin_.*, )True(\)\)):\1False\2: } END { exit ($r != 1) }' SConstruct @@ -444,9 +494,8 @@ let + lib.optionalString (lib.versionOlder version "4.6") '' substituteInPlace platform/linuxbsd/detect.py \ --replace-fail /usr/include/recastnavigation ${lib.escapeShellArg (lib.getDev recastnavigation)}/include/recastnavigation - '' - + '' + + lib.optionalString (libGL != null) '' substituteInPlace thirdparty/glad/egl.c \ --replace-fail \ 'static const char *NAMES[] = {"libEGL.so.1", "libEGL.so"}' \ @@ -461,69 +510,103 @@ let --replace-fail \ '"libGL.so.1"' \ '"${lib.getLib libGL}/lib/libGL.so"' - + '' + + '' substituteInPlace thirdparty/volk/volk.c \ --replace-fail \ 'dlopen("libvulkan.so.1"' \ 'dlopen("${lib.getLib vulkan-loader}/lib/libvulkan.so"' - ''; + '' + + lib.optionalString stdenv.hostPlatform.isDarwin ( + '' + substituteInPlace platform/macos/export/export_plugin.cpp \ + --replace-fail \ + /usr/bin/codesign \ + '${lib.getExe' darwin.sigtool "sigtool"}' + '' + # https://github.com/godotengine/godot/issues/107199 + + lib.optionalString (lib.versionAtLeast version "4.5") '' + substituteInPlace drivers/metal/SCsub \ + --replace-fail \ + 'env_metal.Append(CCFLAGS=["-fmodules", "-fcxx-modules"])' \ + "" + '' + # godot zips these files and fails if mtime < 1980 + + lib.optionalString (!editor) '' + find misc/dist/macos_template.app -exec touch {} \; + '' + ); depsBuildBuild = lib.optionals (stdenv.buildPlatform != stdenv.hostPlatform) [ buildPackages.stdenv.cc pkg-config ]; - buildInputs = [ - embree - enet - freetype - glslang - graphite2 - (harfbuzz.override { withIcu = true; }) - icu - libtheora - libwebp - mbedtls - miniupnpc - openxr-loader - pcre2 - recastnavigation - wslay - zstd - ] - ++ lib.optionals (lib.versionAtLeast version "4.5") [ - libjpeg_turbo - sdl3 - ] - ++ lib.optionals (editor && withMono) dotnet-sdk.packages - ++ lib.optional withAlsa alsa-lib - ++ lib.optional (withX11 || withWayland) libxkbcommon - ++ lib.optionals withX11 [ - libX11 - libXcursor - libXext - libXfixes - libXi - libXinerama - libXrandr - libXrender - ] - ++ lib.optionals withWayland [ - libdecor - wayland - ] - ++ lib.optionals withDbus [ - dbus - ] - ++ lib.optionals withFontconfig [ - fontconfig - ] - ++ lib.optional withPulseaudio libpulseaudio - ++ lib.optionals withSpeechd [ - speechd-minimal - glib - ] - ++ lib.optional withUdev udev; + env.NIX_CFLAGS_COMPILE = toString ( + lib.optionals stdenv.hostPlatform.isDarwin [ + "-I${lib.getDev harfbuzz-icu}/include/harfbuzz" + "-I${lib.getDev recastnavigation}/include/recastnavigation" + ] + ); + + buildInputs = + lib.optionals (!withBuiltins) ( + [ + embree + enet + freetype + glslang + graphite2 + harfbuzz-icu + icu + libtheora + libwebp + mbedtls + miniupnpc + openxr-loader + pcre2 + recastnavigation + wslay + zstd + ] + ++ lib.optionals (lib.versionAtLeast version "4.5") [ + libjpeg_turbo + sdl3 + ] + ) + ++ lib.optionals (editor && withMono) dotnet-sdk.packages + ++ lib.optional withAlsa alsa-lib + ++ lib.optional (withX11 || withWayland) libxkbcommon + ++ lib.optionals withX11 [ + libX11 + libXcursor + libXext + libXfixes + libXi + libXinerama + libXrandr + libXrender + ] + ++ lib.optionals withWayland [ + libdecor + wayland + ] + ++ lib.optionals withDbus [ + dbus + ] + ++ lib.optionals withFontconfig [ + fontconfig + ] + ++ lib.optional withPulseaudio libpulseaudio + ++ lib.optionals withSpeechd [ + speechd-minimal + glib + ] + ++ lib.optional withUdev udev + ++ lib.optionals stdenv.hostPlatform.isDarwin [ + apple-sdk_26 + moltenvk + ]; nativeBuildInputs = [ installShellFiles @@ -535,7 +618,17 @@ let ++ lib.optional (editor && withMono) [ makeWrapper dotnet-sdk - ]; + ] + ++ lib.optionals stdenv.hostPlatform.isDarwin ( + [ + darwin.sigtool + ] + ++ lib.optionals (!editor) [ + strip-nondeterminism + unzip + zip + ] + ); postBuild = lib.optionalString (editor && withMono) '' echo "Generating Glue" @@ -548,7 +641,7 @@ let runHook preInstall mkdir -p "$out"/{bin,libexec} - cp -r bin/* "$out"/libexec + cp -r bin/${binary} "$out"/libexec/ cd "$out"/bin ln -s ../libexec/${binary} godot${lib.versions.majorMinor version}${suffix} @@ -574,12 +667,17 @@ let cp icon.png "$out/share/icons/godot.png" '' + lib.optionalString withMono '' + cp -r bin/GodotSharp "$out"/libexec/ mkdir -p "$out"/share/nuget mv "$out"/libexec/GodotSharp/Tools/nupkgs "$out"/share/nuget/source wrapProgram "$out"/libexec/${binary} \ --prefix NUGET_FALLBACK_PACKAGES ';' "$out"/share/nuget/packages/ '' + + lib.optionalString stdenv.hostPlatform.isDarwin '' + mkdir -p "$out"/Applications + cp -r bin/godot_macos_editor.app "$out"/Applications/Godot.app + '' else let template = @@ -588,6 +686,7 @@ let [ { linuxbsd = "linux"; + macos = "macos"; } .${withPlatform} ] @@ -601,6 +700,15 @@ let mkdir -p "$templates" ln -s "$out"/libexec/${binary} "$templates"/${template} '' + # TODO: teach godot to use a template that isn't zipped. for now we + # just need to make it uncompressed so it doesn't break dependencies + + lib.optionalString stdenv.hostPlatform.isDarwin '' + cd bin + unzip godot_macos${lib.optionalString withMono "_mono"}.zip + zip -rq0 "$templates"/macos.zip macos_template.app + strip-nondeterminism --type zip "$templates"/macos.zip + cd - + '' ) + '' runHook postInstall @@ -639,7 +747,12 @@ let "x86_64-linux" "aarch64-linux" ] - ++ lib.optional (!withMono) "i686-linux"; + ++ lib.optional (!withMono) "i686-linux" + # 4.3 doesn't compile on darwin, and 4.4 doesn't pass tests + ++ lib.optionals (lib.versionAtLeast version "4.5") [ + "x86_64-darwin" + "aarch64-darwin" + ]; maintainers = with lib.maintainers; [ shiryel corngood diff --git a/pkgs/development/tools/godot/fix-moltenvk-detection.patch b/pkgs/development/tools/godot/fix-moltenvk-detection.patch new file mode 100644 index 000000000000..33a944c279cd --- /dev/null +++ b/pkgs/development/tools/godot/fix-moltenvk-detection.patch @@ -0,0 +1,16 @@ +diff --git a/platform/macos/detect.py b/platform/macos/detect.py +index 227738877d..5a4bfa77d9 100644 +--- a/platform/macos/detect.py ++++ b/platform/macos/detect.py +@@ -265,11 +265,6 @@ def configure(env: "SConsEnvironment"): + + if mvk_path != "": + env.Append(LINKFLAGS=["-L" + mvk_path]) +- else: +- print_error( +- "MoltenVK SDK installation directory not found, use 'vulkan_sdk_path' SCons parameter to specify SDK path." +- ) +- sys.exit(255) + + if len(extra_frameworks) > 0: + frameworks = [item for key in extra_frameworks for item in ["-framework", key]]