From f97ca76b1043ecc972187a4fcadab5dff18e9547 Mon Sep 17 00:00:00 2001 From: Morgan Jones Date: Sun, 27 Apr 2025 15:27:48 -0700 Subject: [PATCH 1/2] androidenv: support linking "latest" version of all plugins As noted in #379534, the NDK linking broke during refactoring. Add a test for that, and support linking the latest for all platform plugins that take at least one version. --- .../androidenv/compose-android-packages.nix | 73 ++++++++++++------- .../mobile/androidenv/examples/shell.nix | 14 ++++ 2 files changed, 62 insertions(+), 25 deletions(-) diff --git a/pkgs/development/mobile/androidenv/compose-android-packages.nix b/pkgs/development/mobile/androidenv/compose-android-packages.nix index aaf0dd43dc80..57a9afc8a9de 100644 --- a/pkgs/development/mobile/androidenv/compose-android-packages.nix +++ b/pkgs/development/mobile/androidenv/compose-android-packages.nix @@ -13,6 +13,16 @@ let # Coerces a string to an int. coerceInt = val: if lib.isInt val then val else lib.toIntBase10 val; + + # Parses a single version, substituting "latest" with the latest version. + parseVersion = + repo: key: version: + if version == "latest" then repo.latest.${key} else version; + + # Parses a list of versions, substituting "latest" with the latest version. + parseVersions = + repo: key: versions: + lib.unique (map (parseVersion repo key) versions); in { repoJson ? ./repo.json, @@ -74,27 +84,31 @@ in else lib.importJSON repoJson ), - cmdLineToolsVersion ? repo.latest.cmdline-tools, - toolsVersion ? repo.latest.tools, - platformToolsVersion ? repo.latest.platform-tools, - buildToolsVersions ? [ repo.latest.build-tools ], + cmdLineToolsVersion ? "latest", + toolsVersion ? "latest", + platformToolsVersion ? "latest", + buildToolsVersions ? [ "latest" ], includeEmulator ? false, - emulatorVersion ? repo.latest.emulator, + emulatorVersion ? "latest", minPlatformVersion ? null, - maxPlatformVersion ? coerceInt repo.latest.platforms, + maxPlatformVersion ? "latest", numLatestPlatformVersions ? 1, platformVersions ? if minPlatformVersion != null && maxPlatformVersion != null then let - minPlatformVersionInt = coerceInt minPlatformVersion; - maxPlatformVersionInt = coerceInt maxPlatformVersion; + minPlatformVersionInt = coerceInt (parseVersion repo "platforms" minPlatformVersion); + maxPlatformVersionInt = coerceInt (parseVersion repo "platforms" maxPlatformVersion); in lib.range (lib.min minPlatformVersionInt maxPlatformVersionInt) ( lib.max minPlatformVersionInt maxPlatformVersionInt ) else let - minPlatformVersionInt = if minPlatformVersion == null then 1 else coerceInt minPlatformVersion; + minPlatformVersionInt = + if minPlatformVersion == null then + 1 + else + coerceInt (parseVersion repo "platforms" minPlatformVersion); latestPlatformVersionInt = lib.max minPlatformVersionInt (coerceInt repo.latest.platforms); firstPlatformVersionInt = lib.max minPlatformVersionInt ( latestPlatformVersionInt - (lib.max 1 numLatestPlatformVersions) + 1 @@ -115,9 +129,9 @@ in ], # cmake has precompiles on x86_64 and Darwin platforms. Default to true there for compatibility. includeCmake ? stdenv.hostPlatform.isx86_64 || stdenv.hostPlatform.isDarwin, - cmakeVersions ? [ repo.latest.cmake ], + cmakeVersions ? [ "latest" ], includeNDK ? false, - ndkVersion ? repo.latest.ndk, + ndkVersion ? "latest", ndkVersions ? [ ndkVersion ], useGoogleAPIs ? false, useGoogleTVAddOns ? false, @@ -126,6 +140,9 @@ in }: let + # Resolve all the platform versions. + platformVersions' = map coerceInt (parseVersions repo "platforms" platformVersions); + # Determine the Android os identifier from Nix's system identifier os = { @@ -420,7 +437,9 @@ lib.recurseIntoAttrs rec { arch meta ; - package = checkVersion allArchives.packages "platform-tools" platformToolsVersion; + package = checkVersion allArchives.packages "platform-tools" ( + parseVersion repo "platform-tools" platformToolsVersion + ); }; tools = callPackage ./tools.nix { @@ -430,7 +449,7 @@ lib.recurseIntoAttrs rec { arch meta ; - package = checkVersion allArchives.packages "tools" toolsVersion; + package = checkVersion allArchives.packages "tools" (parseVersion repo "tools" toolsVersion); postInstall = '' ${linkPlugin { @@ -464,7 +483,7 @@ lib.recurseIntoAttrs rec { }} ''; } - ) buildToolsVersions; + ) (parseVersions repo "build-tools" buildToolsVersions); emulator = callPackage ./emulator.nix { inherit @@ -473,7 +492,9 @@ lib.recurseIntoAttrs rec { arch meta ; - package = checkVersion allArchives.packages "emulator" emulatorVersion; + package = checkVersion allArchives.packages "emulator" ( + parseVersion repo "emulator" emulatorVersion + ); postInstall = '' ${linkSystemImages { @@ -483,21 +504,21 @@ lib.recurseIntoAttrs rec { ''; }; - inherit platformVersions; + platformVersions = platformVersions'; platforms = map ( version: deployAndroidPackage { package = checkVersion allArchives.packages "platforms" version; } - ) platformVersions; + ) platformVersions'; sources = map ( version: deployAndroidPackage { package = checkVersion allArchives.packages "sources" version; } - ) platformVersions; + ) platformVersions'; system-images = lib.flatten ( map ( @@ -538,7 +559,7 @@ lib.recurseIntoAttrs rec { patchesInstructions = instructions; }) ) systemImageTypes - ) platformVersions + ) platformVersions' ); cmake = map ( @@ -552,7 +573,7 @@ lib.recurseIntoAttrs rec { ; package = checkVersion allArchives.packages "cmake" version; } - ) cmakeVersions; + ) (parseVersions repo "cmake" cmakeVersions); # All NDK bundles. ndk-bundles = @@ -576,11 +597,11 @@ lib.recurseIntoAttrs rec { version: let package = makeNdkBundle ( - allArchives.packages.ndk-bundle.${ndkVersion} or allArchives.packages.ndk.${ndkVersion} + allArchives.packages.ndk-bundle.${version} or allArchives.packages.ndk.${version} ); in lib.optional (shouldLink includeNDK [ package ]) package - ) ndkVersions + ) (parseVersions repo "ndk" ndkVersions) ); # The "default" NDK bundle. @@ -592,7 +613,7 @@ lib.recurseIntoAttrs rec { deployAndroidPackage { package = (checkVersion allArchives "addons" version).google_apis; } - ) (lib.filter (hasVersion allArchives "addons") platformVersions); + ) (lib.filter (hasVersion allArchives "addons") platformVersions'); # Makes a Google TV addons bundle from supported versions. google-tv-addons = map ( @@ -600,9 +621,11 @@ lib.recurseIntoAttrs rec { deployAndroidPackage { package = (checkVersion allArchives "addons" version).google_tv_addon; } - ) (lib.filter (hasVersion allArchives "addons") platformVersions); + ) (lib.filter (hasVersion allArchives "addons") platformVersions'); - cmdline-tools-package = checkVersion allArchives.packages "cmdline-tools" cmdLineToolsVersion; + cmdline-tools-package = checkVersion allArchives.packages "cmdline-tools" ( + parseVersion repo "cmdline-tools" cmdLineToolsVersion + ); # This derivation deploys the tools package and symlinks all the desired # plugins that we want to use. If the license isn't accepted, prints all the licenses diff --git a/pkgs/development/mobile/androidenv/examples/shell.nix b/pkgs/development/mobile/androidenv/examples/shell.nix index 9058e1664fe6..423753cae366 100644 --- a/pkgs/development/mobile/androidenv/examples/shell.nix +++ b/pkgs/development/mobile/androidenv/examples/shell.nix @@ -45,11 +45,19 @@ let # The head unit only works on these platforms includeAuto = pkgs.stdenv.hostPlatform.isx86_64 || pkgs.stdenv.hostPlatform.isDarwin; + ndkVersions = [ + "23.1.7779620" + "25.1.8937393" + "26.1.10909125" + "latest" + ]; + androidComposition = androidEnv.composeAndroidPackages { includeSources = true; includeSystemImages = false; includeEmulator = "if-supported"; includeNDK = "if-supported"; + inherit ndkVersions; useGoogleAPIs = true; useGoogleTVAddOns = true; @@ -191,6 +199,12 @@ pkgs.mkShell rec { fi done + num_ndk_packages="$(echo "$installed_packages_section" | grep '^ndk;' | wc -l)" + if [ $num_ndk_packages -ne ${toString (pkgs.lib.length ndkVersions)} ]; then + echo "Invalid NDK package count: $num_ndk_packages" + exit 1 + fi + touch "$out" ''; }; From 126c22792dbb48b879e533cdf5795aba4e018d17 Mon Sep 17 00:00:00 2001 From: Morgan Jones Date: Sun, 27 Apr 2025 15:53:53 -0700 Subject: [PATCH 2/2] androidenv: update docs to explain the latest version --- doc/languages-frameworks/android.section.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/languages-frameworks/android.section.md b/doc/languages-frameworks/android.section.md index f970776a9b8d..9e93d4eda36d 100644 --- a/doc/languages-frameworks/android.section.md +++ b/doc/languages-frameworks/android.section.md @@ -50,6 +50,7 @@ let platformVersions = [ "34" "35" + "latest" ]; systemImageTypes = [ "google_apis_playstore" ]; abiVersions = [ @@ -130,7 +131,8 @@ For each requested system image we can specify the following options: be included. Defaults to `armeabi-v7a` and `arm64-v8a`. Most of the function arguments have reasonable default settings, preferring the latest -versions of tools when possible. +versions of tools when possible. You can additionally specify "latest" for any plugin version +that you do not care about, and just want the latest of. You can specify license names: