{ description = "Moonlight game streaming client for Android — devShell + hermetic debug-APK build"; inputs = { fleet.url = "git+https://git.oleks.space/oleks/fleet-pins"; nixpkgs.follows = "fleet/nixpkgs-projects"; }; outputs = { self, fleet, nixpkgs, }: let # Android builds run on Linux hosts; the SDK is x86_64/aarch64-linux only. systems = [ "x86_64-linux" "aarch64-linux" ]; forAllSystems = f: nixpkgs.lib.genAttrs systems ( system: f ( import nixpkgs { inherit system; config = { allowUnfree = true; # Android SDK components are unfree android_sdk.accept_license = true; }; } ) ); # Pinned to match app/build.gradle exactly. ndkVersion = "27.0.12077973"; buildToolsVersion = "34.0.0"; platformVersion = "34"; in { # Compose the Android SDK once per system, reused by devShell + package. legacyPackages = forAllSystems (pkgs: { androidComposition = pkgs.androidenv.composeAndroidPackages { platformVersions = [ platformVersion ]; buildToolsVersions = [ buildToolsVersion ]; includeNDK = true; ndkVersions = [ ndkVersion ]; includeEmulator = false; includeSystemImages = false; includeSources = false; }; }); # `nix develop` — JDK 17 + Android SDK/NDK + gradle, ready for `./gradlew`. devShells = forAllSystems ( pkgs: let androidSdk = self.legacyPackages.${pkgs.system}.androidComposition.androidsdk; sdkRoot = "${androidSdk}/libexec/android-sdk"; in { default = pkgs.mkShell { packages = [ pkgs.jdk17 pkgs.gradle androidSdk # adb/fastboot — for sideloading the built APK to a device or an # Android TV (Chromecast with Google TV) over the network. pkgs.android-tools ]; ANDROID_HOME = sdkRoot; ANDROID_SDK_ROOT = sdkRoot; ANDROID_NDK_ROOT = "${sdkRoot}/ndk/${ndkVersion}"; JAVA_HOME = pkgs.jdk17.home; # AGP downloads aapt2 from Maven; that prebuilt won't run on NixOS. # Point it at the SDK's patched aapt2 instead. GRADLE_OPTS = "-Dorg.gradle.project.android.aapt2FromMavenOverride=${sdkRoot}/build-tools/${buildToolsVersion}/aapt2"; shellHook = '' echo "Android SDK: $ANDROID_HOME" echo "NDK: $ANDROID_NDK_ROOT" echo "Build the nonRoot debug APK with: ./gradlew assembleNonRootDebug" ''; }; } ); # `nix build` — hermetic, offline debug APK build via gradle's mitm-cache. packages = forAllSystems ( pkgs: let androidSdk = self.legacyPackages.${pkgs.system}.androidComposition.androidsdk; sdkRoot = "${androidSdk}/libexec/android-sdk"; in { default = self.packages.${pkgs.system}.moonlight-android; moonlight-android = pkgs.stdenv.mkDerivation (finalAttrs: { pname = "moonlight-android"; version = "12.1"; # The repo, including the moonlight-common-c + enet submodules that must # already be checked out (git submodule update --init --recursive). src = ./.; nativeBuildInputs = [ pkgs.gradle pkgs.jdk17 androidSdk ]; # Offline Maven dependency cache. Regenerate deps.json with: # nix build .#moonlight-android.mitmCache.updateScript && ./result mitmCache = pkgs.gradle.fetchDeps { inherit (finalAttrs) pname; pkg = finalAttrs.finalPackage; data = ./deps.json; }; gradleBuildTask = "assembleNonRootDebug"; ANDROID_HOME = sdkRoot; ANDROID_SDK_ROOT = sdkRoot; ANDROID_NDK_ROOT = "${sdkRoot}/ndk/${ndkVersion}"; gradleFlags = [ "-Dorg.gradle.java.home=${pkgs.jdk17.home}" # Use the SDK's runnable aapt2 instead of the Maven prebuilt. "-Pandroid.aapt2FromMavenOverride=${sdkRoot}/build-tools/${buildToolsVersion}/aapt2" # Skip resolving androidTest/test classpaths during dependency capture # (AGP variant ambiguity on the self-referenced app project). "--init-script" "nix-deps-fixup.gradle" ]; postPatch = '' # Tell Gradle where the SDK lives without relying on env detection. echo "sdk.dir=${sdkRoot}" > local.properties ''; # The debug build type auto-signs with a debug keystore that lands in # $HOME/.android; the build sandbox's HOME is read-only, so redirect it. preBuild = '' export ANDROID_USER_HOME="$NIX_BUILD_TOP/.android" export HOME="$NIX_BUILD_TOP/home" mkdir -p "$ANDROID_USER_HOME" "$HOME" ''; doCheck = false; installPhase = '' runHook preInstall mkdir -p "$out" find app/build/outputs/apk -name '*.apk' -exec cp -v {} "$out/" \; runHook postInstall ''; meta = { description = "Moonlight game streaming client for Android (nonRoot debug APK)"; homepage = "https://github.com/moonlight-stream/moonlight-android"; license = pkgs.lib.licenses.gpl3Only; platforms = systems; }; }); } ); }; }