diff options
author | Lily Foster <lily@lily.flowers> | 2023-08-18 17:09:31 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-08-18 17:09:31 -0400 |
commit | 3effe8ee6840a31048b4c0061ec39328c056cad4 (patch) | |
tree | 7725f1cd909856a58abdddb4dda840844dabb3b5 | |
parent | ea322c26623899551d98c512e285e1ffe4b4fcac (diff) | |
parent | e555a7b3d19ec4e32ee63fa7bf632f3193d08a11 (diff) | |
download | nixpkgs-3effe8ee6840a31048b4c0061ec39328c056cad4.tar nixpkgs-3effe8ee6840a31048b4c0061ec39328c056cad4.tar.gz nixpkgs-3effe8ee6840a31048b4c0061ec39328c056cad4.tar.bz2 nixpkgs-3effe8ee6840a31048b4c0061ec39328c056cad4.tar.lz nixpkgs-3effe8ee6840a31048b4c0061ec39328c056cad4.tar.xz nixpkgs-3effe8ee6840a31048b4c0061ec39328c056cad4.tar.zst nixpkgs-3effe8ee6840a31048b4c0061ec39328c056cad4.zip |
Merge pull request #177578 from Rotaerk/godot-mono
godot3: refactor, rename from godot, and add mono builds
25 files changed, 593 insertions, 172 deletions
diff --git a/maintainers/maintainer-list.nix b/maintainers/maintainer-list.nix index 07867afff25..de2e69d2d23 100644 --- a/maintainers/maintainer-list.nix +++ b/maintainers/maintainer-list.nix @@ -14659,6 +14659,12 @@ github = "RossComputerGuy"; githubId = 19699320; }; + rotaerk = { + name = "Matthew Stewart"; + email = "m.scott.stewart@gmail.com"; + github = "rotaerk"; + githubId = 17690823; + }; rowanG077 = { email = "goemansrowan@gmail.com"; github = "rowanG077"; diff --git a/pkgs/applications/editors/pixelorama/default.nix b/pkgs/applications/editors/pixelorama/default.nix index 6c01f8e05d3..dfa7a733e6a 100644 --- a/pkgs/applications/editors/pixelorama/default.nix +++ b/pkgs/applications/editors/pixelorama/default.nix @@ -1,4 +1,21 @@ -{ lib, stdenv, fetchFromGitHub, godot-headless, godot-export-templates, nix-update-script }: +{ lib +, stdenv +, alsa-lib +, autoPatchelfHook +, fetchFromGitHub +, godot3-headless +, godot3-export-templates +, libGLU +, libpulseaudio +, libX11 +, libXcursor +, libXi +, libXinerama +, libXrandr +, libXrender +, nix-update-script +, udev +}: let preset = @@ -19,7 +36,18 @@ in stdenv.mkDerivation (finalAttrs: { }; nativeBuildInputs = [ - godot-headless + autoPatchelfHook + godot3-headless + ]; + + buildInputs = [ + libGLU + libX11 + libXcursor + libXi + libXinerama + libXrandr + libXrender ]; buildPhase = '' @@ -27,10 +55,10 @@ in stdenv.mkDerivation (finalAttrs: { export HOME=$(mktemp -d) mkdir -p $HOME/.local/share/godot/ - ln -s "${godot-export-templates}/share/godot/templates" "$HOME/.local/share/godot/templates" + ln -s "${godot3-export-templates}/share/godot/templates" "$HOME/.local/share/godot/templates" mkdir -p build - godot-headless -v --export "${preset}" ./build/pixelorama - godot-headless -v --export-pack "${preset}" ./build/pixelorama.pck + godot3-headless -v --export "${preset}" ./build/pixelorama + godot3-headless -v --export-pack "${preset}" ./build/pixelorama.pck runHook postBuild ''; @@ -47,6 +75,12 @@ in stdenv.mkDerivation (finalAttrs: { runHook postInstall ''; + runtimeDependencies = map lib.getLib [ + alsa-lib + libpulseaudio + udev + ]; + passthru.updateScript = nix-update-script { }; meta = with lib; { diff --git a/pkgs/applications/graphics/lorien/default.nix b/pkgs/applications/graphics/lorien/default.nix index e3e8daf8766..c880e2e2167 100644 --- a/pkgs/applications/graphics/lorien/default.nix +++ b/pkgs/applications/graphics/lorien/default.nix @@ -2,15 +2,17 @@ , stdenv , fetchFromGitHub +, autoPatchelfHook , copyDesktopItems , makeDesktopItem -, godot-export-templates -, godot-headless +, godot3-export-templates +, godot3-headless , alsa-lib , libGL , libGLU +, libpulseaudio , libX11 , libXcursor , libXext @@ -41,8 +43,9 @@ stdenv.mkDerivation rec { }; nativeBuildInputs = [ + autoPatchelfHook copyDesktopItems - godot-headless + godot3-headless ]; buildInputs = [ @@ -83,11 +86,11 @@ stdenv.mkDerivation rec { # Link the export-templates to the expected location. The --export commands # expects the template-file at .../templates/{godot-version}.stable/linux_x11_64_release mkdir -p $HOME/.local/share/godot - ln -s ${godot-export-templates}/share/godot/templates $HOME/.local/share/godot + ln -s ${godot3-export-templates}/share/godot/templates $HOME/.local/share/godot mkdir -p $out/share/lorien - godot-headless --path lorien --export "${preset}" $out/share/lorien/lorien + godot3-headless --path lorien --export "${preset}" $out/share/lorien/lorien runHook postBuild ''; @@ -110,6 +113,12 @@ stdenv.mkDerivation rec { runHook postInstall ''; + runtimeDependencies = map lib.getLib [ + alsa-lib + libpulseaudio + udev + ]; + meta = with lib; { homepage = "https://github.com/mbrlabs/Lorien"; description = "An infinite canvas drawing/note-taking app"; diff --git a/pkgs/development/tools/gdtoolkit/default.nix b/pkgs/development/tools/gdtoolkit/default.nix index 67d98e0aa36..479b0b2c363 100644 --- a/pkgs/development/tools/gdtoolkit/default.nix +++ b/pkgs/development/tools/gdtoolkit/default.nix @@ -1,7 +1,7 @@ { lib , python3Packages , fetchFromGitHub -, godot-server +, godot3-server }: let lark080 = python3Packages.lark.overrideAttrs (old: rec { @@ -43,12 +43,12 @@ python3Packages.buildPythonApplication rec { nativeCheckInputs = with python3Packages; [ pytestCheckHook hypothesis - godot-server + godot3-server ]; preCheck = let - godotServerMajorVersion = lib.versions.major godot-server.version; + godotServerMajorVersion = lib.versions.major godot3-server.version; gdtoolkitMajorVersion = lib.versions.major version; msg = '' gdtoolkit major version ${gdtoolkitMajorVersion} does not match godot-server major version ${godotServerMajorVersion}! diff --git a/pkgs/development/tools/godot/3/debug-server.nix b/pkgs/development/tools/godot/3/debug-server.nix new file mode 100644 index 00000000000..5e134d71e1e --- /dev/null +++ b/pkgs/development/tools/godot/3/debug-server.nix @@ -0,0 +1,7 @@ +{ godot3-headless }: + +godot3-headless.overrideAttrs (self: base: { + pname = "godot3-debug-server"; + godotBuildDescription = "debug server"; + shouldBuildTools = false; +}) diff --git a/pkgs/development/tools/godot/3/default.nix b/pkgs/development/tools/godot/3/default.nix index 84b3d60ea32..c69fcfa57b4 100644 --- a/pkgs/development/tools/godot/3/default.nix +++ b/pkgs/development/tools/godot/3/default.nix @@ -1,109 +1,166 @@ -{ stdenv -, lib +{ lib +, stdenv +, alsa-lib +, alsa-plugins +, autoPatchelfHook , fetchFromGitHub -, scons -, pkg-config -, udev +, freetype +, installShellFiles +, libGLU +, libpulseaudio , libX11 , libXcursor +, libXext +, libXfixes +, libXi , libXinerama , libXrandr , libXrender -, libpulseaudio -, libXi -, libXext -, libXfixes -, freetype -, openssl -, alsa-lib -, alsa-plugins , makeWrapper -, libGLU -, zlib +, openssl +, pkg-config +, scons +, udev , yasm -, withUdev ? true +, zlib }: -let - options = { - touch = libXi != null; - pulseaudio = false; - udev = withUdev; - }; -in -stdenv.mkDerivation rec { - pname = "godot"; +stdenv.mkDerivation (self: { + pname = "godot3"; version = "3.5.2"; + godotBuildDescription = "X11 tools"; src = fetchFromGitHub { owner = "godotengine"; repo = "godot"; - rev = "${version}-stable"; + rev = "${self.version}-stable"; sha256 = "sha256-C+1J5N0ETL1qKust+2xP9uB4x9NwrMqIm8aFAivVYQw="; }; - nativeBuildInputs = [ pkg-config makeWrapper ]; - buildInputs = [ + nativeBuildInputs = [ + autoPatchelfHook + installShellFiles + makeWrapper + pkg-config scons - udev + ]; + + buildInputs = [ + alsa-lib + freetype + libGLU + libpulseaudio libX11 libXcursor + libXext + libXfixes + libXi libXinerama libXrandr libXrender - libXi - libXext - libXfixes - freetype openssl - alsa-lib - libpulseaudio - libGLU - zlib + udev yasm + zlib ]; - patches = [ ./pkg_config_additions.patch ./dont_clobber_environment.patch ]; + shouldAddLinkFlagsToPulse = true; + + patches = map (rp: ./patches + rp) [ + # The version of SConstruct in the godot source appends the OS's PATH to the Scons PATH, + # but because it is an append, the Scons PATH takes precedence. The Scons PATH contains a + # bunch of standard Linux paths like /usr/bin, so if they happen to contain versions of any + # build-time dependencies of Godot, they will be used instead of the Nix version of them. + # + # This patch simply replaces the entire Scons environment (including the PATH) with that + # of the OS. This isn't as surgical as just fixing the PATH, but it seems to work, and + # seems to be the Nix community's current strategy when using Scons. + /SConstruct/dontClobberEnvironment.patch + ]; enableParallelBuilding = true; + godotBuildPlatform = "x11"; + shouldBuildTools = true; + godotBuildTarget = "release_debug"; - sconsFlags = [ "target=release_debug" "platform=x11" ]; - preConfigure = '' - sconsFlags+=" ${ - lib.concatStringsSep " " - (lib.mapAttrsToList (k: v: "${k}=${builtins.toJSON v}") options) - }" - ''; + shouldUseLinkTimeOptimization = self.godotBuildTarget == "release"; + + sconsFlags = [ + "arch=${stdenv.hostPlatform.linuxArch}" + "platform=${self.godotBuildPlatform}" + "tools=${lib.boolToString self.shouldBuildTools}" + "target=${self.godotBuildTarget}" + "bits=${toString stdenv.hostPlatform.parsed.cpu.bits}" + "use_lto=${lib.boolToString self.shouldUseLinkTimeOptimization}" + ]; + + shouldWrapBinary = self.shouldBuildTools; + shouldInstallManual = self.shouldBuildTools; + shouldPatchBinary = self.shouldBuildTools; + shouldInstallHeaders = self.shouldBuildTools; + shouldInstallShortcut = self.shouldBuildTools && self.godotBuildPlatform != "server"; + + outputs = ["out"] ++ lib.optional self.shouldInstallManual "man" ++ lib.optional self.shouldBuildTools "dev"; - outputs = [ "out" "dev" "man" ]; + builtGodotBinNamePattern = if self.godotBuildPlatform == "server" then "godot_server.*" else "godot.*"; + + godotBinInstallPath = "bin"; + installedGodotBinName = self.pname; + installedGodotShortcutFileName = "org.godotengine.Godot3.desktop"; + installedGodotShortcutDisplayName = "Godot Engine 3"; installPhase = '' - mkdir -p "$out/bin" - cp bin/godot.* $out/bin/godot3 + runHook preInstall + + echo "Installing godot binaries." + outbin="$out/$godotBinInstallPath" + mkdir -p "$outbin" + cp -R bin/. "$outbin" + mv "$outbin"/$builtGodotBinNamePattern "$outbin/$installedGodotBinName" - wrapProgram "$out/bin/godot3" \ - --set ALSA_PLUGIN_DIR ${alsa-plugins}/lib/alsa-lib + if [ -n "$shouldWrapBinary" ]; then + wrapProgram "$outbin/$installedGodotBinName" \ + --set ALSA_PLUGIN_DIR ${alsa-plugins}/lib/alsa-lib + fi - mkdir "$dev" - cp -r modules/gdnative/include $dev + if [ -n "$shouldInstallManual" ]; then + echo "Installing godot manual." + mansrc=misc/dist/linux + mv "$mansrc"/godot.6 "$mansrc"/godot3.6 + installManPage "$mansrc"/godot3.6 + fi - mkdir -p "$man/share/man/man6" - cp misc/dist/linux/godot.6 "$man/share/man/man6/" + if [ -n "$shouldInstallHeaders" ]; then + echo "Installing godot headers." + mkdir -p "$dev" + cp -R modules/gdnative/include "$dev" + fi - mkdir -p "$out"/share/{applications,icons/hicolor/scalable/apps} - cp misc/dist/linux/org.godotengine.Godot.desktop "$out/share/applications/org.godotengine.Godot3.desktop" - cp icon.svg "$out/share/icons/hicolor/scalable/apps/godot.svg" - cp icon.png "$out/share/icons/godot.png" - substituteInPlace "$out/share/applications/org.godotengine.Godot3.desktop" \ - --replace "Exec=godot" "Exec=$out/bin/godot3" \ - --replace "Godot Engine" "Godot Engine 3" + if [ -n "$shouldInstallShortcut" ]; then + echo "Installing godot shortcut." + mkdir -p "$out"/share/{applications,icons/hicolor/scalable/apps} + cp misc/dist/linux/org.godotengine.Godot.desktop "$out"/share/applications/$installedGodotShortcutFileName + cp icon.svg "$out"/share/icons/hicolor/scalable/apps/godot.svg + cp icon.png "$out"/share/icons/godot.png + substituteInPlace "$out"/share/applications/$installedGodotShortcutFileName \ + --replace "Exec=godot" "Exec=\"$outbin/$installedGodotBinName\"" \ + --replace "Name=Godot Engine" "Name=$installedGodotShortcutDisplayName" + fi + + runHook postInstall ''; + runtimeDependencies = lib.optionals self.shouldPatchBinary (map lib.getLib [ + alsa-lib + libpulseaudio + udev + ]); + meta = with lib; { homepage = "https://godotengine.org"; - description = "Free and Open Source 2D and 3D game engine"; + description = "Free and Open Source 2D and 3D game engine (" + self.godotBuildDescription + ")"; license = licenses.mit; platforms = [ "i686-linux" "x86_64-linux" "aarch64-linux" ]; - maintainers = with maintainers; [ twey ]; + maintainers = with maintainers; [ rotaerk twey ]; }; -} +}) diff --git a/pkgs/development/tools/godot/3/export-templates.nix b/pkgs/development/tools/godot/3/export-templates.nix index 74a78573a98..714cd32869c 100644 --- a/pkgs/development/tools/godot/3/export-templates.nix +++ b/pkgs/development/tools/godot/3/export-templates.nix @@ -1,25 +1,28 @@ -{ godot, lib }: +{ godot3 }: -# https://docs.godotengine.org/en/stable/development/compiling/compiling_for_x11.html#building-export-templates -godot.overrideAttrs (oldAttrs: rec { - pname = "godot-export-templates"; - sconsFlags = [ "target=release" "platform=x11" "tools=no" ]; - installPhase = '' - # The godot export command expects the export templates at - # .../share/godot/templates/3.2.3.stable with 3.2.3 being the godot version. - mkdir -p "$out/share/godot/templates/${oldAttrs.version}.stable" - cp bin/godot.x11.opt.64 $out/share/godot/templates/${oldAttrs.version}.stable/linux_x11_64_release - ''; +godot3.overrideAttrs (self: base: { + pname = "godot3-export-templates"; + godotBuildDescription = "nix export templates"; + + # As described in default.nix, adding the link flags to pulseaudio in detect.py was necessary to + # allow the dlopen calls to succeed in Nix builds of godot. However, it seems that this *breaks* + # the export templates, resulting in programs exported from godot using these export templates to + # be unable to load this library. + shouldAddLinkFlagsToPulse = false; + + shouldBuildTools = false; + godotBuildTarget = "release"; + godotBinInstallPath = "share/godot/templates/${self.version}.stable"; + installedGodotBinName = "linux_${self.godotBuildPlatform}_64_${self.godotBuildTarget}"; # https://docs.godotengine.org/en/stable/development/compiling/optimizing_for_size.html # Stripping reduces the template size from around 500MB to 40MB for Linux. # This also impacts the size of the exported games. # This is added explicitly here because mkDerivation does not automatically # strip binaries in the template directory. - stripAllList = (oldAttrs.stripAllList or []) ++ [ "share/godot/templates" ]; + stripAllList = (base.stripAllList or []) ++ [ "share/godot/templates" ]; - outputs = [ "out" ]; - meta.description = - "Free and Open Source 2D and 3D game engine (export templates)"; - meta.maintainers = with lib.maintainers; [ twey jojosch ]; + meta = base.meta // { + homepage = "https://docs.godotengine.org/en/stable/development/compiling/compiling_for_x11.html#building-export-templates"; + }; }) diff --git a/pkgs/development/tools/godot/3/headless.nix b/pkgs/development/tools/godot/3/headless.nix index 3e43a4f27f0..85b998f3807 100644 --- a/pkgs/development/tools/godot/3/headless.nix +++ b/pkgs/development/tools/godot/3/headless.nix @@ -1,18 +1,7 @@ -{ godot, lib }: -godot.overrideAttrs (oldAttrs: rec { - pname = "godot-headless"; - sconsFlags = [ "target=release_debug" "platform=server" "tools=yes" ]; - installPhase = '' - mkdir -p "$out/bin" - cp bin/godot_server.* $out/bin/godot-headless +{ godot3 }: - mkdir "$dev" - cp -r modules/gdnative/include $dev - - mkdir -p "$man/share/man/man6" - cp misc/dist/linux/godot.6 "$man/share/man/man6/" - ''; - meta.description = - "Free and Open Source 2D and 3D game engine (headless build)"; - meta.maintainers = with lib.maintainers; [ twey yusdacra ]; +godot3.overrideAttrs (self: base: { + pname = "godot3-headless"; + godotBuildDescription = "headless"; + godotBuildPlatform = "server"; }) diff --git a/pkgs/development/tools/godot/3/mono/debug-server.nix b/pkgs/development/tools/godot/3/mono/debug-server.nix new file mode 100644 index 00000000000..28c18dbdb2b --- /dev/null +++ b/pkgs/development/tools/godot/3/mono/debug-server.nix @@ -0,0 +1,7 @@ +{ godot3-mono-headless }: + +godot3-mono-headless.overrideAttrs (self: base: { + pname = "godot3-mono-debug-server"; + godotBuildDescription = "mono debug server"; + shouldBuildTools = false; +}) diff --git a/pkgs/development/tools/godot/3/mono/default.nix b/pkgs/development/tools/godot/3/mono/default.nix new file mode 100644 index 00000000000..22e95fb0e51 --- /dev/null +++ b/pkgs/development/tools/godot/3/mono/default.nix @@ -0,0 +1,65 @@ +{ godot3 +, callPackage +, mkNugetDeps +, mkNugetSource +, mono +, dotnet-sdk +, writeText +}: + +godot3.overrideAttrs (self: base: { + pname = "godot3-mono"; + + godotBuildDescription = "mono build"; + + nativeBuildInputs = base.nativeBuildInputs ++ [ mono dotnet-sdk ]; + + glue = callPackage ./glue.nix {}; + + nugetDeps = mkNugetDeps { name = "deps"; nugetDeps = import ./deps.nix; }; + + nugetSource = + mkNugetSource { + name = "${self.pname}-nuget-source"; + description = "A Nuget source with dependencies for ${self.pname}"; + deps = [ self.nugetDeps ]; + }; + + nugetConfig = writeText "NuGet.Config" '' + <?xml version="1.0" encoding="utf-8"?> + <configuration> + <packageSources> + <add key="${self.pname}-deps" value="${self.nugetSource}/lib" /> + </packageSources> + </configuration> + ''; + + sconsFlags = base.sconsFlags ++ [ + "module_mono_enabled=true" + "mono_prefix=${mono}" + ]; + + shouldConfigureNuget = true; + + postConfigure = '' + echo "Setting up buildhome." + mkdir buildhome + export HOME="$PWD"/buildhome + + echo "Overlaying godot glue." + cp -R --no-preserve=mode "$glue"/. . + + if [ -n "$shouldConfigureNuget" ]; then + echo "Configuring NuGet." + mkdir -p ~/.nuget/NuGet + ln -s "$nugetConfig" ~/.nuget/NuGet/NuGet.Config + fi + ''; + + installedGodotShortcutFileName = "org.godotengine.GodotMono3.desktop"; + installedGodotShortcutDisplayName = "Godot Engine (Mono) 3"; + + passthru = { + make-deps = callPackage ./make-deps.nix {}; + }; +}) diff --git a/pkgs/development/tools/godot/3/mono/deps.nix b/pkgs/development/tools/godot/3/mono/deps.nix new file mode 100644 index 00000000000..ea909921b43 --- /dev/null +++ b/pkgs/development/tools/godot/3/mono/deps.nix @@ -0,0 +1,34 @@ +{ fetchNuGet }: [ + (fetchNuGet { pname = "EnvDTE"; version = "8.0.2"; sha256 = "1wdvjzdmqbqyqlaijpjc959vvdic12vqr3c5sffhbxi7m1si5k63"; }) + (fetchNuGet { pname = "GodotTools.IdeMessaging"; version = "1.1.1"; sha256 = "0v70acpw2yq9mx05jy2gmkqqdbpgj8rb29ny2f3bgvmw9g5qmq94"; }) + (fetchNuGet { pname = "JetBrains.Annotations"; version = "2019.1.3"; sha256 = "188b0qw6lih0k3ddnmimadzr3y1y6vh6ramgkjnyskqd43prjzc2"; }) + (fetchNuGet { pname = "Microsoft.Build"; version = "16.5.0"; sha256 = "0baihvnzanqhk125g0ass9hhsqgp55h770pjjmsxdvprv0aqq22i"; }) + (fetchNuGet { pname = "Microsoft.Build.Framework"; version = "16.5.0"; sha256 = "1xgr02r7s9i6s70n237hss4yi9zicssia3zd2ny6s8vyxb7jpdyb"; }) + (fetchNuGet { pname = "Microsoft.NETCore.Platforms"; version = "1.0.1"; sha256 = "01al6cfxp68dscl15z7rxfw9zvhm64dncsw09a1vmdkacsa2v6lr"; }) + (fetchNuGet { pname = "Microsoft.NETCore.Platforms"; version = "1.1.0"; sha256 = "08vh1r12g6ykjygq5d3vq09zylgb84l63k49jc4v8faw9g93iqqm"; }) + (fetchNuGet { pname = "Microsoft.NETCore.Targets"; version = "1.0.1"; sha256 = "0ppdkwy6s9p7x9jix3v4402wb171cdiibq7js7i13nxpdky7074p"; }) + (fetchNuGet { pname = "Microsoft.NETFramework.ReferenceAssemblies"; version = "1.0.0"; sha256 = "0na724xhvqm63vq9y18fl9jw9q2v99bdwr353378s5fsi11qzxp9"; }) + (fetchNuGet { pname = "Microsoft.NETFramework.ReferenceAssemblies.net472"; version = "1.0.0"; sha256 = "1bqinq2nxnpqxziypg1sqy3ly0nymxxjpn8fwkn3rl4vl6gdg3rc"; }) + (fetchNuGet { pname = "Microsoft.VisualStudio.Setup.Configuration.Interop"; version = "1.16.30"; sha256 = "14022lx03vdcqlvbbdmbsxg5pqfx1rfq2jywxlyaz9v68cvsb0g4"; }) + (fetchNuGet { pname = "Mono.Cecil"; version = "0.11.3"; sha256 = "0xcx7pk9y2n1hr15c0l1balzi69kw5gy8dk7sb8jwqyyvm35q4j3"; }) + (fetchNuGet { pname = "NETStandard.Library"; version = "2.0.3"; sha256 = "1fn9fxppfcg4jgypp2pmrpr6awl3qz1xmnri0cygpkwvyx27df1y"; }) + (fetchNuGet { pname = "Newtonsoft.Json"; version = "13.0.1"; sha256 = "0fijg0w6iwap8gvzyjnndds0q4b8anwxxvik7y8vgq97dram4srb"; }) + (fetchNuGet { pname = "Semver"; version = "2.0.6"; sha256 = "136sd6d3ys49dipvc1h3ivmp8ryd4p7fdmdrr28521cqpvkw5f1k"; }) + (fetchNuGet { pname = "stdole"; version = "7.0.3302"; sha256 = "1n8vbzlgyklazriwvb6kjyw5w0m9a1b3xsa0f0v29j03z23fx69p"; }) + (fetchNuGet { pname = "System.Buffers"; version = "4.4.0"; sha256 = "183f8063w8zqn99pv0ni0nnwh7fgx46qzxamwnans55hhs2l0g19"; }) + (fetchNuGet { pname = "System.Collections.Immutable"; version = "1.5.0"; sha256 = "1d5gjn5afnrf461jlxzawcvihz195gayqpcfbv6dd7pxa9ialn06"; }) + (fetchNuGet { pname = "System.Globalization"; version = "4.0.11"; sha256 = "070c5jbas2v7smm660zaf1gh0489xanjqymkvafcs4f8cdrs1d5d"; }) + (fetchNuGet { pname = "System.IO"; version = "4.1.0"; sha256 = "1g0yb8p11vfd0kbkyzlfsbsp5z44lwsvyc0h3dpw6vqnbi035ajp"; }) + (fetchNuGet { pname = "System.Memory"; version = "4.5.3"; sha256 = "0naqahm3wljxb5a911d37mwjqjdxv9l0b49p5dmfyijvni2ppy8a"; }) + (fetchNuGet { pname = "System.Numerics.Vectors"; version = "4.4.0"; sha256 = "0rdvma399070b0i46c4qq1h2yvjj3k013sqzkilz4bz5cwmx1rba"; }) + (fetchNuGet { pname = "System.Reflection"; version = "4.1.0"; sha256 = "1js89429pfw79mxvbzp8p3q93il6rdff332hddhzi5wqglc4gml9"; }) + (fetchNuGet { pname = "System.Reflection.Primitives"; version = "4.0.1"; sha256 = "1bangaabhsl4k9fg8khn83wm6yial8ik1sza7401621jc6jrym28"; }) + (fetchNuGet { pname = "System.Resources.ResourceManager"; version = "4.0.1"; sha256 = "0b4i7mncaf8cnai85jv3wnw6hps140cxz8vylv2bik6wyzgvz7bi"; }) + (fetchNuGet { pname = "System.Runtime"; version = "4.1.0"; sha256 = "02hdkgk13rvsd6r9yafbwzss8kr55wnj8d5c7xjnp8gqrwc8sn0m"; }) + (fetchNuGet { pname = "System.Runtime.CompilerServices.Unsafe"; version = "4.5.2"; sha256 = "1vz4275fjij8inf31np78hw50al8nqkngk04p3xv5n4fcmf1grgi"; }) + (fetchNuGet { pname = "System.Runtime.Serialization.Primitives"; version = "4.1.1"; sha256 = "042rfjixknlr6r10vx2pgf56yming8lkjikamg3g4v29ikk78h7k"; }) + (fetchNuGet { pname = "System.Text.Encoding"; version = "4.0.11"; sha256 = "1dyqv0hijg265dwxg6l7aiv74102d6xjiwplh2ar1ly6xfaa4iiw"; }) + (fetchNuGet { pname = "System.Threading.Tasks"; version = "4.0.11"; sha256 = "0nr1r41rak82qfa5m0lhk9mp0k93bvfd7bbd9sdzwx9mb36g28p5"; }) + (fetchNuGet { pname = "System.Threading.Tasks.Dataflow"; version = "4.9.0"; sha256 = "1g6s9pjg4z8iy98df60y9a01imdqy59zd767vz74rrng78jl2dk5"; }) + (fetchNuGet { pname = "System.Threading.Thread"; version = "4.0.0"; sha256 = "1gxxm5fl36pjjpnx1k688dcw8m9l7nmf802nxis6swdaw8k54jzc"; }) +] diff --git a/pkgs/development/tools/godot/3/mono/export-templates.nix b/pkgs/development/tools/godot/3/mono/export-templates.nix new file mode 100644 index 00000000000..da0d7cb2be3 --- /dev/null +++ b/pkgs/development/tools/godot/3/mono/export-templates.nix @@ -0,0 +1,28 @@ +{ godot3-mono }: + +godot3-mono.overrideAttrs (self: base: { + pname = "godot3-mono-export-templates"; + godotBuildDescription = "nix mono export templates"; + + # As described in default.nix, adding the link flags to pulseaudio in detect.py was necessary to + # allow the dlopen calls to succeed in Nix builds of godot. However, it seems that this *breaks* + # the export templates, resulting in programs exported from godot using these export templates to + # be unable to load this library. + shouldAddLinkFlagsToPulse = false; + + shouldBuildTools = false; + godotBuildTarget = "release"; + godotBinInstallPath = "share/godot/templates/${self.version}.stable.mono"; + installedGodotBinName = "linux_${self.godotBuildPlatform}_64_${self.godotBuildTarget}"; + + # https://docs.godotengine.org/en/stable/development/compiling/optimizing_for_size.html + # Stripping reduces the template size from around 500MB to 40MB for Linux. + # This also impacts the size of the exported games. + # This is added explicitly here because mkDerivation does not automatically + # strip binaries in the template directory. + stripAllList = (base.stripAllList or []) ++ [ "share/godot/templates" ]; + + meta = base.meta // { + homepage = "https://docs.godotengine.org/en/stable/development/compiling/compiling_with_mono.html#export-templates"; + }; +}) diff --git a/pkgs/development/tools/godot/3/mono/glue.nix b/pkgs/development/tools/godot/3/mono/glue.nix new file mode 100644 index 00000000000..bbd046b4af0 --- /dev/null +++ b/pkgs/development/tools/godot/3/mono/glue.nix @@ -0,0 +1,66 @@ +{ godot3, mono }: + +godot3.overrideAttrs (self: base: { + pname = "godot3-mono-glue"; + godotBuildDescription = "mono glue"; + godotBuildPlatform = "server"; + + sconsFlags = base.sconsFlags ++ [ + "module_mono_enabled=true" + "mono_glue=false" # Indicates not to expect already existing glue. + "mono_prefix=${mono}" + ]; + + nativeBuildInputs = base.nativeBuildInputs ++ [ mono ]; + + patches = + base.patches ++ + map (rp: ./patches + rp) ( + [ + # When building godot mono, a "glue version" gets baked into it, and into the mono glue code + # generated by it. Godot mono export templates are also get a glue version baked in. If you + # export a godot mono project using an export template for which the glue version doesn't + # match that of the godot mono tool itself, then the resulting game will fail with an error + # saying "The assembly 'GodotSharp' is out of sync." Thus, if we want our build of godot mono + # to be compatible with the official export templates, we need to ensure it is built with the + # same glue version as the official build. + # + # A python script in the godot source, i.e. modules/mono/build_scripts/gen_cs_glue_version.py, + # is used by the build process to generate the glue version number. The official version of it + # does so based on the latest modified time of all the C# files in the GodotSharp solution. This + # is problematic because it is difficult to reproduce the exact timestamps that the files had + # when the official build was created. This is further complicated by the fact that nix clears + # the timestamps on the source files when they're unpacked. Thus, we can't simply regenerate the + # official glue version by building from the official source. + # + # To address this, we are patching the python script with a hard-coded glue version number. This + # patch file needs to be updated for every new version of godot, so to enforce this, the godot + # version is baked in to the file name, causing the build to fail until the patch is updated. + # + # The correct glue version number for a given godot version is obtained by running the official + # build of that version of godot with the --generate-mono-glue flag. This generates the mono + # glue files. One of those files, mono_glue.gen.cpp, has a function called get_cs_glue_version() + # which contains a hard-coded number. This is the glue version to put in the patch file. + # + # For convenience, the accompanying update-glue-version.sh script automates this work. Run it by + # passing the godot version as an argument, e.g. "3.5.2". + "/gen_cs_glue_version.py/hardcodeGlueVersion_${self.version}.patch" + ] + ); + + outputs = [ "out" ]; + + installPhase = '' + runHook preInstall + + glue="$out"/modules/mono/glue + mkdir -p "$glue" + bin/godot_server.x11.opt.tools.*.mono --generate-mono-glue "$glue" + + runHook postInstall + ''; + + meta = base.meta // { + homepage = "https://docs.godotengine.org/en/stable/development/compiling/compiling_with_mono.html#generate-the-glue"; + }; +}) diff --git a/pkgs/development/tools/godot/3/mono/headless.nix b/pkgs/development/tools/godot/3/mono/headless.nix new file mode 100644 index 00000000000..fff5367e861 --- /dev/null +++ b/pkgs/development/tools/godot/3/mono/headless.nix @@ -0,0 +1,7 @@ +{ godot3-mono }: + +godot3-mono.overrideAttrs (self: base: { + pname = "godot3-mono-headless"; + godotBuildDescription = "mono headless"; + godotBuildPlatform = "server"; +}) diff --git a/pkgs/development/tools/godot/3/mono/make-deps.nix b/pkgs/development/tools/godot/3/mono/make-deps.nix new file mode 100644 index 00000000000..e47a5a68d64 --- /dev/null +++ b/pkgs/development/tools/godot/3/mono/make-deps.nix @@ -0,0 +1,59 @@ +{ godot3-mono, nuget-to-nix }: + +godot3-mono.overrideAttrs (self: base: { + pname = "godot3-mono-make-deps"; + + nativeBuildInputs = base.nativeBuildInputs ++ [ nuget-to-nix ]; + + nugetDeps = null; + nugetSource = null; + nugetConfig = null; + + shouldConfigureNuget = false; + + outputs = [ "out" ]; + buildPhase = " "; + installPhase = ''echo "No output intended. Run make-deps.sh instead." > $out''; + + # This script is used to update the accompanying deps.nix file, a nix expression listing the + # nuget packages that the godot-mono code depends on, along with their sha256 hashes. This + # file is referenced by the godot-mono derivation and needs to be updated every time the + # godot version is updated. The way it works is: + # + # 1) Creates and navigates to a temporary directory and then explicitly runs the unpack, + # patch, and configure phases from the godot-mono derivation. + # 2) Instead of building at this point, a nuget restore is performed, downloading all the + # nuget dependencies of godot-mono into a local folder. + # 3) Once these have been downloaded, the nuget-to-nix tool is used to generate a nix + # expression listing the locally obtained nuget packages, along with their sha256 hashes. + # 4) This nix expression is saved as deps.nix in the PWD. + # + # This process is impure, because it entails downloading files with unknown hashes, so it + # is run manually by the maintainer within a nix-shell environment. Running the accompanying + # make-deps.sh instead simplifies this. + makeDeps = '' + set -e + outdir="$(pwd)" + wrkdir="$(mktemp -d)" + trap 'rm -rf -- "$wrkdir"' EXIT + pushd "$wrkdir" > /dev/null + unpackPhase + cd source + patchPhase + configurePhase + + # Without RestorePackagesPath set, it restores packages to a temp directory. Specifying + # a path ensures we have a place to run nuget-to-nix. + nugetRestore() { dotnet msbuild -t:Restore -p:RestorePackagesPath=nugetPackages $1; } + + nugetRestore modules/mono/glue/GodotSharp/GodotSharp.sln + nugetRestore modules/mono/editor/GodotTools/GodotTools.sln + + nuget-to-nix nugetPackages > "$outdir"/deps.nix + popd > /dev/null + ''; + + meta = base.meta // { + description = "Derivation with no output that exists to provide an environment for make-deps.sh"; + }; +}) diff --git a/pkgs/development/tools/godot/3/mono/make-deps.sh b/pkgs/development/tools/godot/3/mono/make-deps.sh new file mode 100755 index 00000000000..746ab0de3c1 --- /dev/null +++ b/pkgs/development/tools/godot/3/mono/make-deps.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +nix-shell "$(git rev-parse --show-toplevel)" -A godot3-mono.make-deps --run 'eval "$makeDeps"' diff --git a/pkgs/development/tools/godot/3/mono/patches/gen_cs_glue_version.py/hardcodeGlueVersion_3.5.2.patch b/pkgs/development/tools/godot/3/mono/patches/gen_cs_glue_version.py/hardcodeGlueVersion_3.5.2.patch new file mode 100644 index 00000000000..d8a3460126d --- /dev/null +++ b/pkgs/development/tools/godot/3/mono/patches/gen_cs_glue_version.py/hardcodeGlueVersion_3.5.2.patch @@ -0,0 +1,22 @@ +diff --git a/modules/mono/build_scripts/gen_cs_glue_version.py b/modules/mono/build_scripts/gen_cs_glue_version.py +index 98bbb4d9be..5189f2551b 100644 +--- a/modules/mono/build_scripts/gen_cs_glue_version.py ++++ b/modules/mono/build_scripts/gen_cs_glue_version.py +@@ -1,16 +1,5 @@ + def generate_header(solution_dir, version_header_dst): +- import os +- +- latest_mtime = 0 +- for root, dirs, files in os.walk(solution_dir, topdown=True): +- dirs[:] = [d for d in dirs if d not in ["Generated"]] # Ignored generated files +- files = [f for f in files if f.endswith(".cs")] +- for file in files: +- filepath = os.path.join(root, file) +- mtime = os.path.getmtime(filepath) +- latest_mtime = mtime if mtime > latest_mtime else latest_mtime +- +- glue_version = int(latest_mtime) # The latest modified time will do for now ++ glue_version = 1678112021 + + with open(version_header_dst, "w") as version_header: + version_header.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n") diff --git a/pkgs/development/tools/godot/3/mono/server.nix b/pkgs/development/tools/godot/3/mono/server.nix new file mode 100644 index 00000000000..28049f320a0 --- /dev/null +++ b/pkgs/development/tools/godot/3/mono/server.nix @@ -0,0 +1,7 @@ +{ godot3-mono-debug-server }: + +godot3-mono-debug-server.overrideAttrs (self: base: { + pname = "godot3-mono-server"; + godotBuildDescription = "mono server"; + godotBuildTarget = "release"; +}) diff --git a/pkgs/development/tools/godot/3/mono/update-glue-version.sh b/pkgs/development/tools/godot/3/mono/update-glue-version.sh new file mode 100755 index 00000000000..bf409ae3e7c --- /dev/null +++ b/pkgs/development/tools/godot/3/mono/update-glue-version.sh @@ -0,0 +1,39 @@ +#! /usr/bin/env nix-shell +#! nix-shell -i bash -p steam-run unzip wget + +# This script updates the hard-coded glue_version in: +# +# patches/gen_cs_glue_version.py/hardcodeGlueVersionFor{version}.patch +# +# It does so by pulling it from the official build. + +set -e + +[ -z "$1" ] && echo "Godot version not specified. Exiting." && exit 1 + +gdversion=$1 + +# Download and extract the official stable 64-bit X11 mono build of Godot. +gddir="$(mktemp -d)" +trap 'rm -rf -- "$gddir"' EXIT +wget -P "$gddir" https://downloads.tuxfamily.org/godotengine/$gdversion/mono/Godot_v$gdversion-stable_mono_x11_64.zip +unzip "$gddir"/Godot_v$gdversion-stable_mono_x11_64.zip -d "$gddir" + +# Generate the mono glue from the official build. +gluedir="$(mktemp -d)" +trap 'rm -rf -- "$gluedir"' EXIT +steam-run "$gddir"/Godot_v$gdversion-stable_mono_x11_64/Godot_v$gdversion-stable_mono_x11.64 --generate-mono-glue "$gluedir" + +# Extract the glue version. +glueversion=$(grep -Po '(?<=get_cs_glue_version\(\) \{ return )[0-9]+(?=; \})' "$gluedir"/mono_glue.gen.cpp) + +patchdir=./patches/gen_cs_glue_version.py/ +patchprefix=hardcodeGlueVersion_ +newpatchname=$patchprefix$gdversion.patch + +# Update the patch with the obtained glue version. +sed -i "s/^+ glue_version = [0-9]\+$/+ glue_version = $glueversion/" $patchdir/$patchprefix*.patch + +mv $patchdir/$patchprefix*.patch $patchdir/$patchprefix$gdversion.patch + +echo "Updated $patchdir/$patchprefix$gdversion.patch with glue_version: $glueversion" diff --git a/pkgs/development/tools/godot/3/dont_clobber_environment.patch b/pkgs/development/tools/godot/3/patches/SConstruct/dontClobberEnvironment.patch index cfd3113a6aa..d72d7ed1152 100644 --- a/pkgs/development/tools/godot/3/dont_clobber_environment.patch +++ b/pkgs/development/tools/godot/3/patches/SConstruct/dontClobberEnvironment.patch @@ -1,8 +1,5 @@ -scons does not use os environment by default: - https://scons.org/doc/2.1.0/HTML/scons-user/x1750.html - -nixpkgs' cc-wrapper on the other hand relies on various NIX_* variables -to be passed through like NIX_CFLAGS_COMPILE_BEFORE. +diff --git a/SConstruct b/SConstruct +index 057ec7628c..760be89fff 100644 --- a/SConstruct +++ b/SConstruct @@ -67,14 +67,7 @@ elif platform_arg == "javascript": diff --git a/pkgs/development/tools/godot/3/pkg_config_additions.patch b/pkgs/development/tools/godot/3/pkg_config_additions.patch deleted file mode 100644 index 23506a604a9..00000000000 --- a/pkgs/development/tools/godot/3/pkg_config_additions.patch +++ /dev/null @@ -1,33 +0,0 @@ -diff --git a/platform/x11/detect.py b/platform/x11/detect.py -index 98c9ddb..0cc2bff 100644 ---- a/platform/x11/detect.py -+++ b/platform/x11/detect.py -@@ -255,6 +255,10 @@ def configure(env): - env.ParseConfig("pkg-config xrender --cflags --libs") - env.ParseConfig("pkg-config xi --cflags --libs") - -+ env.ParseConfig("pkg-config xfixes --cflags --libs") -+ env.ParseConfig("pkg-config glu --cflags --libs") -+ env.ParseConfig("pkg-config zlib --cflags --libs") -+ - if env["touch"]: - env.Append(CPPDEFINES=["TOUCH_ENABLED"]) - -@@ -359,7 +363,7 @@ def configure(env): - if os.system("pkg-config --exists alsa") == 0: # 0 means found - env["alsa"] = True - env.Append(CPPDEFINES=["ALSA_ENABLED", "ALSAMIDI_ENABLED"]) -- env.ParseConfig("pkg-config alsa --cflags") # Only cflags, we dlopen the library. -+ env.ParseConfig("pkg-config alsa --cflags --libs") - else: - print("Warning: ALSA libraries not found. Disabling the ALSA audio driver.") - -@@ -375,7 +379,7 @@ def configure(env): - if env["udev"]: - if os.system("pkg-config --exists libudev") == 0: # 0 means found - env.Append(CPPDEFINES=["UDEV_ENABLED"]) -- env.ParseConfig("pkg-config libudev --cflags") # Only cflags, we dlopen the library. -+ env.ParseConfig("pkg-config libudev --cflags --libs") - else: - print("Warning: libudev development libraries not found. Disabling controller hotplugging support.") - else: diff --git a/pkgs/development/tools/godot/3/server.nix b/pkgs/development/tools/godot/3/server.nix index 06adf1bbfeb..d2c4939167f 100644 --- a/pkgs/development/tools/godot/3/server.nix +++ b/pkgs/development/tools/godot/3/server.nix @@ -1,18 +1,7 @@ -{ godot, lib }: -godot.overrideAttrs (oldAttrs: rec { - pname = "godot-server"; - sconsFlags = [ "target=release" "platform=server" "tools=no" ]; - installPhase = '' - mkdir -p "$out/bin" - cp bin/godot_server.* $out/bin/godot-server +{ godot3-debug-server }: - mkdir "$dev" - cp -r modules/gdnative/include $dev - - mkdir -p "$man/share/man/man6" - cp misc/dist/linux/godot.6 "$man/share/man/man6/" - ''; - meta.description = - "Free and Open Source 2D and 3D game engine (server build)"; - meta.maintainers = with lib.maintainers; [ twey yusdacra ]; +godot3-debug-server.overrideAttrs (self: base: { + pname = "godot3-server"; + godotBuildDescription = "server"; + godotBuildTarget = "release"; }) diff --git a/pkgs/games/oh-my-git/default.nix b/pkgs/games/oh-my-git/default.nix index cd4fd216eaa..f2ac8b4289c 100644 --- a/pkgs/games/oh-my-git/default.nix +++ b/pkgs/games/oh-my-git/default.nix @@ -1,4 +1,5 @@ { lib +, autoPatchelfHook , copyDesktopItems , fetchFromGitHub , makeDesktopItem @@ -6,8 +7,8 @@ , alsa-lib , gcc-unwrapped , git -, godot-export-templates -, godot-headless +, godot3-export-templates +, godot3-headless , libGLU , libX11 , libXcursor @@ -36,8 +37,9 @@ stdenv.mkDerivation rec { }; nativeBuildInputs = [ + autoPatchelfHook copyDesktopItems - godot-headless + godot3-headless ]; buildInputs = [ @@ -89,10 +91,10 @@ stdenv.mkDerivation rec { # expects the template-file at .../templates/3.2.3.stable/linux_x11_64_release # with 3.2.3 being the version of godot. mkdir -p $HOME/.local/share/godot - ln -s ${godot-export-templates}/share/godot/templates $HOME/.local/share/godot + ln -s ${godot3-export-templates}/share/godot/templates $HOME/.local/share/godot mkdir -p $out/share/oh-my-git - godot-headless --export "Linux" $out/share/oh-my-git/oh-my-git + godot3-headless --export "Linux" $out/share/oh-my-git/oh-my-git runHook postBuild ''; @@ -116,6 +118,12 @@ stdenv.mkDerivation rec { runHook postInstall ''; + runtimeDependencies = map lib.getLib [ + alsa-lib + libpulseaudio + udev + ]; + meta = with lib; { homepage = "https://ohmygit.org/"; description = "An interactive Git learning game"; diff --git a/pkgs/top-level/aliases.nix b/pkgs/top-level/aliases.nix index 26d04f3f3d9..5daf03d6890 100644 --- a/pkgs/top-level/aliases.nix +++ b/pkgs/top-level/aliases.nix @@ -640,6 +640,13 @@ mapAliases ({ gnuvd = throw "gnuvd was removed because the backend service is missing"; # Added 2020-01-14 gobby5 = gobby; # Added 2021-02-01 gobjectIntrospection = throw "'gobjectIntrospection' has been renamed to/replaced by 'gobject-introspection'"; # Converted to throw 2022-02-22 + + #godot + godot = throw "godot has been renamed to godot3 to distinguish from version 4"; # Added 2023-07-16 + godot-export-templates = throw "godot-export-templates has been renamed to godot3-export-templates to distinguish from version 4"; # Added 2023-07-16 + godot-headless = throw "godot-headless has been renamed to godot3-headless to distinguish from version 4"; # Added 2023-07-16 + godot-server = throw "godot-server has been renamed to godot3-server to distinguish from version 4"; # Added 2023-07-16 + gogoclient = throw "gogoclient has been removed, because it was unmaintained"; # Added 2021-12-15 goklp = throw "goklp has been dropped due to the lack of maintenance from upstream since 2017"; # Added 2022-06-02 golly-beta = throw "golly-beta has been removed: use golly instead"; # Added 2022-03-21 diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index 1a02f74f1b7..bba95ef0ea6 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -8549,13 +8549,25 @@ with pkgs; godot_4 = callPackage ../development/tools/godot/4 { }; - godot = callPackage ../development/tools/godot/3 { }; + godot3 = callPackage ../development/tools/godot/3 { }; - godot-export-templates = callPackage ../development/tools/godot/3/export-templates.nix { }; + godot3-export-templates = callPackage ../development/tools/godot/3/export-templates.nix { }; - godot-headless = callPackage ../development/tools/godot/3/headless.nix { }; + godot3-headless = callPackage ../development/tools/godot/3/headless.nix { }; - godot-server = callPackage ../development/tools/godot/3/server.nix { }; + godot3-debug-server = callPackage ../development/tools/godot/3/debug-server.nix { }; + + godot3-server = callPackage ../development/tools/godot/3/server.nix { }; + + godot3-mono = callPackage ../development/tools/godot/3/mono {}; + + godot3-mono-export-templates = callPackage ../development/tools/godot/3/mono/export-templates.nix { }; + + godot3-mono-headless = callPackage ../development/tools/godot/3/mono/headless.nix { }; + + godot3-mono-debug-server = callPackage ../development/tools/godot/3/mono/debug-server.nix { }; + + godot3-mono-server = callPackage ../development/tools/godot/3/mono/server.nix { }; goeland = callPackage ../applications/networking/feedreaders/goeland { }; |