nixpkgs mirror (for testing) github.com/NixOS/nixpkgs
nix
at 22.05 320 lines 11 kB view raw
1{ requireFile, autoPatchelfHook, pkgs, pkgsHostHost, pkgs_i686 2, licenseAccepted ? false 3}: 4 5{ toolsVersion ? "26.1.1" 6, platformToolsVersion ? "31.0.3" 7, buildToolsVersions ? [ "31.0.0" ] 8, includeEmulator ? false 9, emulatorVersion ? "30.9.0" 10, platformVersions ? [] 11, includeSources ? false 12, includeSystemImages ? false 13, systemImageTypes ? [ "google_apis_playstore" ] 14, abiVersions ? [ "armeabi-v7a" ] 15, cmakeVersions ? [ ] 16, includeNDK ? false 17, ndkVersion ? "22.1.7171670" 18, ndkVersions ? [ndkVersion] 19, useGoogleAPIs ? false 20, useGoogleTVAddOns ? false 21, includeExtras ? [] 22, repoJson ? ./repo.json 23, repoXmls ? null 24, extraLicenses ? [] 25}: 26 27let 28 inherit (pkgs) stdenv lib fetchurl; 29 inherit (pkgs.buildPackages) makeWrapper unzip; 30 31 # Determine the Android os identifier from Nix's system identifier 32 os = if stdenv.system == "x86_64-linux" then "linux" 33 else if stdenv.system == "x86_64-darwin" then "macosx" 34 else throw "No Android SDK tarballs are available for system architecture: ${stdenv.system}"; 35 36 # Uses mkrepo.rb to create a repo spec. 37 mkRepoJson = { packages ? [], images ? [], addons ? [] }: let 38 mkRepoRuby = (pkgs.ruby.withPackages (pkgs: with pkgs; [ slop nokogiri ])); 39 mkRepoRubyArguments = lib.lists.flatten [ 40 (builtins.map (package: ["--packages" "${package}"]) packages) 41 (builtins.map (image: ["--images" "${image}"]) images) 42 (builtins.map (addon: ["--addons" "${addon}"]) addons) 43 ]; 44 in 45 stdenv.mkDerivation { 46 name = "androidenv-repo-json"; 47 buildInputs = [ mkRepoRuby ]; 48 preferLocalBuild = true; 49 unpackPhase = "true"; 50 buildPhase = '' 51 ruby ${./mkrepo.rb} ${lib.escapeShellArgs mkRepoRubyArguments} > repo.json 52 ''; 53 installPhase = '' 54 mv repo.json $out 55 ''; 56 }; 57 58 # Reads the repo JSON. If repoXmls is provided, will build a repo JSON into the Nix store. 59 repo = if repoXmls != null then 60 let 61 repoXmlSpec = { 62 packages = repoXmls.packages or []; 63 images = repoXmls.images or []; 64 addons = repoXmls.addons or []; 65 }; 66 in 67 lib.importJSON "${mkRepoJson repoXmlSpec}" 68 else 69 lib.importJSON repoJson; 70 71 # Converts all 'archives' keys in a repo spec to fetchurl calls. 72 fetchArchives = attrSet: 73 lib.attrsets.mapAttrsRecursive 74 (path: value: 75 if (builtins.elemAt path ((builtins.length path) - 1)) == "archives" then 76 (builtins.listToAttrs 77 (builtins.map 78 (archive: lib.attrsets.nameValuePair archive.os (fetchurl { inherit (archive) url sha1; })) value)) 79 else value 80 ) 81 attrSet; 82 83 # Converts the repo attrset into fetch calls 84 packages = fetchArchives repo.packages; 85 system-images-packages = fetchArchives repo.images; 86 addons = { 87 addons = fetchArchives repo.addons; 88 extras = fetchArchives repo.extras; 89 }; 90 91 # Converts a license name to a list of license texts. 92 mkLicenses = licenseName: repo.licenses.${licenseName}; 93 94 # Converts a list of license names to a flattened list of license texts. 95 # Just used for displaying licenses. 96 mkLicenseTexts = licenseNames: 97 lib.lists.flatten 98 (builtins.map 99 (licenseName: 100 builtins.map 101 (licenseText: "--- ${licenseName} ---\n${licenseText}") 102 (mkLicenses licenseName)) 103 licenseNames); 104 105 # Converts a license name to a list of license hashes. 106 mkLicenseHashes = licenseName: 107 builtins.map 108 (licenseText: builtins.hashString "sha1" licenseText) 109 (mkLicenses licenseName); 110 111 # The list of all license names we're accepting. Put android-sdk-license there 112 # by default. 113 licenseNames = lib.lists.unique ([ 114 "android-sdk-license" 115 ] ++ extraLicenses); 116in 117rec { 118 deployAndroidPackage = import ./deploy-androidpackage.nix { 119 inherit stdenv unzip; 120 }; 121 122 platform-tools = import ./platform-tools.nix { 123 inherit deployAndroidPackage os autoPatchelfHook pkgs lib; 124 package = packages.platform-tools.${platformToolsVersion}; 125 }; 126 127 build-tools = map (version: 128 import ./build-tools.nix { 129 inherit deployAndroidPackage os autoPatchelfHook makeWrapper pkgs pkgs_i686 lib; 130 package = packages.build-tools.${version}; 131 } 132 ) buildToolsVersions; 133 134 emulator = import ./emulator.nix { 135 inherit deployAndroidPackage os autoPatchelfHook makeWrapper pkgs pkgs_i686 lib; 136 package = packages.emulator.${emulatorVersion}; 137 }; 138 139 platforms = map (version: 140 deployAndroidPackage { 141 inherit os; 142 package = packages.platforms.${version}; 143 } 144 ) platformVersions; 145 146 sources = map (version: 147 deployAndroidPackage { 148 inherit os; 149 package = packages.sources.${version}; 150 } 151 ) platformVersions; 152 153 system-images = lib.flatten (map (apiVersion: 154 map (type: 155 map (abiVersion: 156 if lib.hasAttrByPath [apiVersion type abiVersion] system-images-packages then 157 deployAndroidPackage { 158 inherit os; 159 package = system-images-packages.${apiVersion}.${type}.${abiVersion}; 160 # Patch 'google_apis' system images so they're recognized by the sdk. 161 # Without this, `android list targets` shows 'Tag/ABIs : no ABIs' instead 162 # of 'Tag/ABIs : google_apis*/*' and the emulator fails with an ABI-related error. 163 patchInstructions = lib.optionalString (lib.hasPrefix "google_apis" type) '' 164 sed -i '/^Addon.Vendor/d' source.properties 165 ''; 166 } 167 else [] 168 ) abiVersions 169 ) systemImageTypes 170 ) platformVersions); 171 172 cmake = map (version: 173 import ./cmake.nix { 174 inherit deployAndroidPackage os autoPatchelfHook pkgs lib; 175 package = packages.cmake.${version}; 176 } 177 ) cmakeVersions; 178 179 # Creates a NDK bundle. 180 makeNdkBundle = ndkVersion: 181 import ./ndk-bundle { 182 inherit deployAndroidPackage os autoPatchelfHook makeWrapper pkgs pkgsHostHost lib platform-tools; 183 package = packages.ndk-bundle.${ndkVersion}; 184 }; 185 186 # All NDK bundles. 187 ndk-bundles = if includeNDK then map makeNdkBundle ndkVersions else []; 188 189 # The "default" NDK bundle. 190 ndk-bundle = if includeNDK then lib.findFirst (x: x != null) null ndk-bundles else null; 191 192 google-apis = map (version: 193 deployAndroidPackage { 194 inherit os; 195 package = addons.addons.${version}.google_apis; 196 } 197 ) (builtins.filter (platformVersion: platformVersion < "26") platformVersions); # API level 26 and higher include Google APIs by default 198 199 google-tv-addons = map (version: 200 deployAndroidPackage { 201 inherit os; 202 package = addons.addons.${version}.google_tv_addon; 203 } 204 ) platformVersions; 205 206 # Function that automatically links all plugins for which multiple versions can coexist 207 linkPlugins = {name, plugins}: 208 lib.optionalString (plugins != []) '' 209 mkdir -p ${name} 210 ${lib.concatMapStrings (plugin: '' 211 ln -s ${plugin}/libexec/android-sdk/${name}/* ${name} 212 '') plugins} 213 ''; 214 215 # Function that automatically links all NDK plugins. 216 linkNdkPlugins = {name, plugins, rootName ? name}: 217 lib.optionalString (plugins != []) '' 218 mkdir -p ${rootName} 219 ${lib.concatMapStrings (plugin: '' 220 ln -s ${plugin}/libexec/android-sdk/${name} ${rootName}/${plugin.version} 221 '') plugins} 222 ''; 223 224 # Function that automatically links a plugin for which only one version exists 225 linkPlugin = {name, plugin, check ? true}: 226 lib.optionalString check '' 227 ln -s ${plugin}/libexec/android-sdk/* ${name} 228 ''; 229 230 # Links all plugins related to a requested platform 231 linkPlatformPlugins = {name, plugins, check}: 232 lib.optionalString check '' 233 mkdir -p ${name} 234 ${lib.concatMapStrings (plugin: '' 235 ln -s ${plugin}/libexec/android-sdk/${name}/* ${name} 236 '') plugins} 237 ''; # */ 238 239 # This derivation deploys the tools package and symlinks all the desired 240 # plugins that we want to use. If the license isn't accepted, prints all the licenses 241 # requested and throws. 242 androidsdk = if !licenseAccepted then throw '' 243 ${builtins.concatStringsSep "\n\n" (mkLicenseTexts licenseNames)} 244 245 You must accept the following licenses: 246 ${lib.concatMapStringsSep "\n" (str: " - ${str}") licenseNames} 247 248 by setting nixpkgs config option 'android_sdk.accept_license = true;'. 249 '' else import ./tools.nix { 250 inherit deployAndroidPackage requireFile packages toolsVersion autoPatchelfHook makeWrapper os pkgs pkgs_i686 lib; 251 252 postInstall = '' 253 # Symlink all requested plugins 254 ${linkPlugin { name = "platform-tools"; plugin = platform-tools; }} 255 ${linkPlugins { name = "build-tools"; plugins = build-tools; }} 256 ${linkPlugin { name = "emulator"; plugin = emulator; check = includeEmulator; }} 257 ${linkPlugins { name = "platforms"; plugins = platforms; }} 258 ${linkPlatformPlugins { name = "sources"; plugins = sources; check = includeSources; }} 259 ${linkPlugins { name = "cmake"; plugins = cmake; }} 260 ${linkNdkPlugins { name = "ndk-bundle"; rootName = "ndk"; plugins = ndk-bundles; }} 261 ${linkPlugin { name = "ndk-bundle"; plugin = ndk-bundle; check = includeNDK; }} 262 263 ${lib.optionalString includeSystemImages '' 264 mkdir -p system-images 265 ${lib.concatMapStrings (system-image: '' 266 apiVersion=$(basename $(echo ${system-image}/libexec/android-sdk/system-images/*)) 267 type=$(basename $(echo ${system-image}/libexec/android-sdk/system-images/*/*)) 268 mkdir -p system-images/$apiVersion/$type 269 ln -s ${system-image}/libexec/android-sdk/system-images/$apiVersion/$type/* system-images/$apiVersion/$type 270 '') system-images} 271 ''} 272 273 ${linkPlatformPlugins { name = "add-ons"; plugins = google-apis; check = useGoogleAPIs; }} 274 ${linkPlatformPlugins { name = "add-ons"; plugins = google-apis; check = useGoogleTVAddOns; }} 275 276 # Link extras 277 ${lib.concatMapStrings (identifier: 278 let 279 path = addons.extras.${identifier}.path; 280 addon = deployAndroidPackage { 281 inherit os; 282 package = addons.extras.${identifier}; 283 }; 284 in 285 '' 286 targetDir=$(dirname ${path}) 287 mkdir -p $targetDir 288 ln -s ${addon}/libexec/android-sdk/${path} $targetDir 289 '') includeExtras} 290 291 # Expose common executables in bin/ 292 mkdir -p $out/bin 293 find $PWD/tools -not -path '*/\.*' -type f -executable -mindepth 1 -maxdepth 1 | while read i 294 do 295 ln -s $i $out/bin 296 done 297 298 find $PWD/tools/bin -not -path '*/\.*' -type f -executable -mindepth 1 -maxdepth 1 | while read i 299 do 300 ln -s $i $out/bin 301 done 302 303 for i in ${platform-tools}/bin/* 304 do 305 ln -s $i $out/bin 306 done 307 308 # Write licenses 309 mkdir -p licenses 310 ${lib.concatMapStrings (licenseName: 311 let 312 licenseHashes = builtins.concatStringsSep "\n" (mkLicenseHashes licenseName); 313 licenseHashFile = pkgs.writeText "androidenv-${licenseName}" licenseHashes; 314 in 315 '' 316 ln -s ${licenseHashFile} licenses/${licenseName} 317 '') licenseNames} 318 ''; 319 }; 320}