mirror of
https://github.com/NixOS/nixpkgs.git
synced 2026-08-27 02:34:53 +00:00
Because a single abi such as x86_64 can have multiple image variants which are not distinguished by checking only the first tag. Android API 36x were particularly affected as they have both 4kb and 16kb memory page images. Remove the inconsistent use of `tag` to determine the image path and ID. Instead the path is uniquely determined from the source XML metadata's location while the `id` uses part of Google's `path` ID. The `repo.json` is updated incrementally and the last version which was not affected by these issues was `a137f263af92` so it has been regenerated based on that version.
820 lines
24 KiB
Nix
820 lines
24 KiB
Nix
{
|
|
callPackage,
|
|
stdenv,
|
|
stdenvNoCC,
|
|
lib,
|
|
fetchurl,
|
|
ruby,
|
|
writeText,
|
|
licenseAccepted ? false,
|
|
meta,
|
|
}:
|
|
|
|
let
|
|
# Coerces a string to an int.
|
|
coerceInt = val: if lib.isInt val then val else lib.toIntBase10 val;
|
|
|
|
coerceIntVersion = v: coerceInt (lib.versions.major (toString v));
|
|
|
|
# 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.sort (a: b: lib.strings.compareVersions (toString a) (toString b) > 0) (
|
|
lib.unique (map (parseVersion repo key) versions)
|
|
);
|
|
in
|
|
{
|
|
repoJson ? ./repo.json,
|
|
repoXmls ? null,
|
|
repo ? (
|
|
# Reads the repo JSON. If repoXmls is provided, will build a repo JSON into the Nix store.
|
|
if repoXmls != null then
|
|
let
|
|
# Uses update.rb to create a repo spec.
|
|
mkRepoJson =
|
|
{
|
|
packages ? [ ],
|
|
images ? [ ],
|
|
addons ? [ ],
|
|
}:
|
|
let
|
|
mkRepoRuby = (
|
|
ruby.withPackages (
|
|
pkgs: with pkgs; [
|
|
slop
|
|
curb
|
|
nokogiri
|
|
]
|
|
)
|
|
);
|
|
mkRepoRubyArguments = lib.lists.flatten [
|
|
(map (package: [
|
|
"--packages"
|
|
"${package}"
|
|
]) packages)
|
|
(map (image: [
|
|
"--images"
|
|
"${image}"
|
|
]) images)
|
|
(map (addon: [
|
|
"--addons"
|
|
"${addon}"
|
|
]) addons)
|
|
];
|
|
in
|
|
stdenvNoCC.mkDerivation {
|
|
name = "androidenv-repo-json";
|
|
buildInputs = [ mkRepoRuby ];
|
|
preferLocalBuild = true;
|
|
unpackPhase = "true";
|
|
buildPhase = ''
|
|
env ruby -e 'load "${./update.rb}"' -- ${lib.escapeShellArgs mkRepoRubyArguments} --input /dev/null --output repo.json
|
|
'';
|
|
installPhase = ''
|
|
mv repo.json $out
|
|
'';
|
|
};
|
|
repoXmlSpec = {
|
|
packages = repoXmls.packages or [ ];
|
|
images = repoXmls.images or [ ];
|
|
addons = repoXmls.addons or [ ];
|
|
};
|
|
in
|
|
lib.importJSON "${mkRepoJson repoXmlSpec}"
|
|
else
|
|
lib.importJSON repoJson
|
|
),
|
|
cmdLineToolsVersion ? "latest",
|
|
toolsVersion ? "latest",
|
|
platformToolsVersion ? "latest",
|
|
buildToolsVersions ? [ "latest" ],
|
|
includeEmulator ? false,
|
|
emulatorVersion ? "latest",
|
|
minPlatformVersion ? null,
|
|
maxPlatformVersion ? "latest",
|
|
numLatestPlatformVersions ? 1,
|
|
platformVersions ?
|
|
if minPlatformVersion != null && maxPlatformVersion != null then
|
|
# Range between min and max, inclusive.
|
|
let
|
|
minPlatformVersion' = parseVersion repo "platforms" minPlatformVersion;
|
|
maxPlatformVersion' = parseVersion repo "platforms" maxPlatformVersion;
|
|
minPlatformVersionInt = coerceIntVersion minPlatformVersion';
|
|
maxPlatformVersionInt = coerceIntVersion maxPlatformVersion';
|
|
range = lib.range (lib.min minPlatformVersionInt maxPlatformVersionInt) (
|
|
lib.max minPlatformVersionInt maxPlatformVersionInt
|
|
);
|
|
in
|
|
# Don't use the actual latest version in lieu of the rounded version here,
|
|
# since when Google upgrades it would have the nasty side effect of being
|
|
# unstable and picking 35 -> 36 -> 37 instead of 35 -> 36.1 -> 37.
|
|
# Best to stay consistent.
|
|
#
|
|
# However, if only one platform is requested and it's the latest (which is the default),
|
|
# we should use it.
|
|
if lib.length range == 1 then lib.singleton maxPlatformVersion' else range
|
|
else
|
|
# Use numLatestPlatformVersions with a lower cutoff of minPlatformVersion (defaulting to 1)
|
|
# to determine how many of the latest *major* versions we should pick.
|
|
let
|
|
minPlatformVersionInt =
|
|
if minPlatformVersion == null then
|
|
1
|
|
else
|
|
coerceIntVersion (parseVersion repo "platforms" minPlatformVersion);
|
|
latestPlatformVersionInt = lib.max minPlatformVersionInt (coerceIntVersion repo.latest.platforms);
|
|
firstPlatformVersionInt = lib.max minPlatformVersionInt (
|
|
latestPlatformVersionInt - (lib.max 1 numLatestPlatformVersions) + 1
|
|
);
|
|
range = lib.range firstPlatformVersionInt latestPlatformVersionInt;
|
|
in
|
|
# Ditto, see above.
|
|
if lib.length range == 1 then lib.singleton repo.latest.platforms else range,
|
|
includeSources ? false,
|
|
includeSystemImages ? false,
|
|
systemImageTypes ? [
|
|
"google_apis"
|
|
"google_apis_playstore"
|
|
"google_apis_ps16k"
|
|
"google_apis_playstore_ps16k"
|
|
],
|
|
abiVersions ? [
|
|
"x86"
|
|
"x86_64"
|
|
"armeabi-v7a"
|
|
"arm64-v8a"
|
|
],
|
|
# cmake has precompiles on x86_64 and Darwin platforms. Default to true there for compatibility.
|
|
includeCmake ? stdenv.hostPlatform.isx86_64 || stdenv.hostPlatform.isDarwin,
|
|
cmakeVersions ? [ "latest" ],
|
|
includeNDK ? false,
|
|
ndkVersion ? "latest",
|
|
ndkVersions ? [ ndkVersion ],
|
|
useGoogleAPIs ? false,
|
|
useGoogleTVAddOns ? false,
|
|
includeExtras ? [ ],
|
|
extraLicenses ? [ ],
|
|
}:
|
|
|
|
let
|
|
# Resolve all the platform versions.
|
|
platformVersions' = parseVersions repo "platforms" platformVersions;
|
|
|
|
# Determine the Android os identifier from Nix's system identifier
|
|
os =
|
|
{
|
|
x86_64-linux = "linux";
|
|
aarch64-linux = "linux";
|
|
aarch64-darwin = "macosx";
|
|
}
|
|
.${stdenv.hostPlatform.system} or "all";
|
|
|
|
# Determine the Android arch identifier from Nix's system identifier
|
|
arch =
|
|
{
|
|
x86_64-linux = "x64";
|
|
aarch64-linux = "aarch64";
|
|
aarch64-darwin = "aarch64";
|
|
}
|
|
.${stdenv.hostPlatform.system} or "all";
|
|
|
|
# Converts all 'archives' keys in a repo spec to fetchurl calls.
|
|
fetchArchives =
|
|
attrSet:
|
|
lib.attrsets.mapAttrsRecursive (
|
|
path: value:
|
|
if (builtins.elemAt path (builtins.length path - 1)) == "archives" then
|
|
let
|
|
validArchives = builtins.filter (
|
|
archive:
|
|
let
|
|
isTargetOs =
|
|
if builtins.hasAttr "os" archive then archive.os == os || archive.os == "all" else true;
|
|
isTargetArch =
|
|
if builtins.hasAttr "arch" archive then archive.arch == arch || archive.arch == "all" else true;
|
|
in
|
|
isTargetOs && isTargetArch
|
|
) value;
|
|
packageInfo = lib.attrByPath (lib.sublist 0 (builtins.length path - 1) path) null attrSet;
|
|
in
|
|
lib.optionals (builtins.length validArchives > 0) (
|
|
lib.last (
|
|
map (
|
|
archive:
|
|
(fetchurl {
|
|
pname = packageInfo.name;
|
|
version = packageInfo.revision;
|
|
inherit (archive) url sha1;
|
|
inherit meta;
|
|
passthru = {
|
|
info = packageInfo;
|
|
};
|
|
}).overrideAttrs
|
|
(
|
|
finalAttrs: previousAttrs: {
|
|
# fetchurl prioritize `pname` and `version` over the specified `name`,
|
|
# so specify custom `name` in an override.
|
|
name = baseNameOf (lib.head (finalAttrs.urls));
|
|
}
|
|
)
|
|
) validArchives
|
|
)
|
|
)
|
|
else
|
|
value
|
|
) attrSet;
|
|
|
|
# Converts the repo attrset into fetch calls.
|
|
allArchives = {
|
|
packages = fetchArchives repo.packages;
|
|
system-images = fetchArchives repo.images;
|
|
addons = fetchArchives repo.addons;
|
|
extras = fetchArchives repo.extras;
|
|
};
|
|
|
|
# Lift the archives to the package level for easy search,
|
|
# and add recurseIntoAttrs to all of them.
|
|
allPackages =
|
|
let
|
|
liftedArchives = lib.attrsets.mapAttrsRecursiveCond (value: !(builtins.hasAttr "archives" value)) (
|
|
path: value:
|
|
if (value.archives or null) != null && (value.archives or [ ]) != [ ] then
|
|
lib.dontRecurseIntoAttrs value.archives
|
|
else
|
|
null
|
|
) allArchives;
|
|
|
|
# Creates a version key from a name.
|
|
# Converts things like 'extras;google;auto' to 'extras-google-auto'
|
|
toVersionKey =
|
|
name:
|
|
let
|
|
normalizedName = lib.replaceStrings [ ";" "." ] [ "-" "_" ] name;
|
|
versionParts = lib.match "^([0-9][0-9\\.]*)(.*)$" normalizedName;
|
|
in
|
|
if versionParts == null then normalizedName else "v" + lib.concatStrings versionParts;
|
|
|
|
recurse = lib.mapAttrs' (
|
|
name: value:
|
|
if builtins.isAttrs value && (value.recurseForDerivations or true) then
|
|
lib.nameValuePair (toVersionKey name) (lib.recurseIntoAttrs (recurse value))
|
|
else
|
|
lib.nameValuePair (toVersionKey name) value
|
|
);
|
|
in
|
|
lib.recurseIntoAttrs (recurse liftedArchives);
|
|
|
|
# Converts a license name to a list of license texts.
|
|
mkLicenses = licenseName: repo.licenses.${licenseName};
|
|
|
|
# Converts a list of license names to a flattened list of license texts.
|
|
# Just used for displaying licenses.
|
|
mkLicenseTexts =
|
|
licenseNames:
|
|
lib.lists.flatten (
|
|
map (
|
|
licenseName: map (licenseText: "--- ${licenseName} ---\n${licenseText}") (mkLicenses licenseName)
|
|
) licenseNames
|
|
);
|
|
|
|
# Converts a license name to a list of license hashes.
|
|
mkLicenseHashes =
|
|
licenseName: map (licenseText: builtins.hashString "sha1" licenseText) (mkLicenses licenseName);
|
|
|
|
# The list of all license names we're accepting. Put android-sdk-license there
|
|
# by default.
|
|
licenseNames = lib.lists.unique (
|
|
[
|
|
"android-sdk-license"
|
|
]
|
|
++ extraLicenses
|
|
);
|
|
|
|
# Returns true if the given version exists.
|
|
hasVersion =
|
|
packages: package: version:
|
|
lib.hasAttrByPath [ package (toString version) ] packages
|
|
|| lib.hasAttrByPath [ package "${(toString version)}.0" ] packages;
|
|
|
|
# Displays a nice error message that includes the available options if a version doesn't exist.
|
|
# Note that allPackages can be a list of package sets, or a single package set. Pass a list if
|
|
# you want to prioritize elements to the left (e.g. for passing a platform major version).
|
|
checkVersion =
|
|
allPackages: package: version:
|
|
let
|
|
# Convert the package sets to a list.
|
|
allPackages' = if lib.isList allPackages then allPackages else lib.singleton allPackages;
|
|
|
|
# Pick the first package set where we have the version.
|
|
packageSet = lib.findFirst (packages: hasVersion packages package version) null allPackages';
|
|
in
|
|
if packageSet == null then
|
|
throw ''
|
|
The version ${toString version} is missing in package ${package}.
|
|
The only available versions are ${
|
|
lib.concatStringsSep ", " (
|
|
lib.attrNames (lib.foldl (s: x: s // (x.${package} or { })) { } allPackages')
|
|
)
|
|
}.
|
|
''
|
|
else
|
|
packageSet.${package}.${toString version} or packageSet.${package}."${toString version}.0";
|
|
|
|
# Returns true if we should link the specified plugins.
|
|
shouldLink =
|
|
check: packages:
|
|
assert builtins.isList packages;
|
|
if check == true then
|
|
true
|
|
else if check == false then
|
|
false
|
|
else if check == "if-supported" then
|
|
let
|
|
hasSrc =
|
|
package: package.src != null && (builtins.isList package.src -> builtins.length package.src > 0);
|
|
in
|
|
packages != [ ] && lib.all hasSrc packages
|
|
else
|
|
throw "Invalid argument ${toString check}; use true, false, or if-supported";
|
|
|
|
# Function that automatically links all plugins for which multiple versions can coexist
|
|
linkPlugins =
|
|
{
|
|
name,
|
|
plugins,
|
|
check ? true,
|
|
}:
|
|
lib.optionalString (shouldLink check plugins) ''
|
|
mkdir -p ${name}
|
|
${lib.concatMapStrings (plugin: ''
|
|
ln -s ${plugin}/libexec/android-sdk/${name}/* ${name}
|
|
'') plugins}
|
|
'';
|
|
|
|
# Function that automatically links all NDK plugins.
|
|
linkNdkPlugins =
|
|
{
|
|
name,
|
|
plugins,
|
|
rootName ? name,
|
|
check ? true,
|
|
}:
|
|
lib.optionalString (shouldLink check plugins) ''
|
|
mkdir -p ${rootName}
|
|
${lib.concatMapStrings (plugin: ''
|
|
ln -s ${plugin}/libexec/android-sdk/${name} ${rootName}/${plugin.version}
|
|
'') plugins}
|
|
'';
|
|
|
|
# Function that automatically links the default NDK plugin.
|
|
linkNdkPlugin =
|
|
{
|
|
name,
|
|
plugin,
|
|
check,
|
|
}:
|
|
lib.optionalString (shouldLink check [ plugin ]) ''
|
|
ln -s ${plugin}/libexec/android-sdk/${name} ${name}
|
|
'';
|
|
|
|
# Function that automatically links a plugin for which only one version exists
|
|
linkPlugin =
|
|
{
|
|
name,
|
|
plugin,
|
|
check ? true,
|
|
}:
|
|
lib.optionalString (shouldLink check [ plugin ]) ''
|
|
ln -s ${plugin}/libexec/android-sdk/${name} ${name}
|
|
'';
|
|
|
|
linkSystemImages =
|
|
{ images, check }:
|
|
lib.optionalString (shouldLink check images) ''
|
|
mkdir -p system-images
|
|
${lib.concatMapStrings (system-image: ''
|
|
apiVersion=$(basename $(echo ${system-image}/libexec/android-sdk/system-images/*))
|
|
type=$(basename $(echo ${system-image}/libexec/android-sdk/system-images/*/*))
|
|
mkdir -p system-images/$apiVersion
|
|
ln -s ${system-image}/libexec/android-sdk/system-images/$apiVersion/$type system-images/$apiVersion/$type
|
|
'') images}
|
|
'';
|
|
|
|
# Links all plugins related to a requested platform
|
|
linkPlatformPlugins =
|
|
{
|
|
name,
|
|
plugins,
|
|
check,
|
|
}:
|
|
lib.optionalString (shouldLink check plugins) ''
|
|
mkdir -p ${name}
|
|
${lib.concatMapStrings (plugin: ''
|
|
ln -s ${plugin}/libexec/android-sdk/${name}/* ${name}
|
|
'') plugins}
|
|
''; # */
|
|
|
|
in
|
|
lib.recurseIntoAttrs rec {
|
|
deployAndroidPackages = callPackage ./deploy-androidpackages.nix {
|
|
inherit
|
|
stdenv
|
|
lib
|
|
mkLicenses
|
|
meta
|
|
os
|
|
arch
|
|
;
|
|
};
|
|
|
|
deployAndroidPackage = (
|
|
{
|
|
package,
|
|
buildInputs ? [ ],
|
|
patchInstructions ? "",
|
|
meta ? { },
|
|
...
|
|
}@args:
|
|
let
|
|
extraParams = removeAttrs args [
|
|
"package"
|
|
"os"
|
|
"arch"
|
|
"buildInputs"
|
|
"patchInstructions"
|
|
];
|
|
in
|
|
deployAndroidPackages (
|
|
{
|
|
inherit buildInputs;
|
|
packages = [ package ];
|
|
patchesInstructions = {
|
|
"${package.name}" = patchInstructions;
|
|
};
|
|
}
|
|
// extraParams
|
|
)
|
|
);
|
|
|
|
all = allPackages;
|
|
|
|
platform-tools = callPackage ./platform-tools.nix {
|
|
inherit
|
|
deployAndroidPackage
|
|
os
|
|
arch
|
|
meta
|
|
;
|
|
package = checkVersion allArchives.packages "platform-tools" (
|
|
parseVersion repo "platform-tools" platformToolsVersion
|
|
);
|
|
};
|
|
|
|
tools = callPackage ./tools.nix {
|
|
inherit
|
|
deployAndroidPackage
|
|
os
|
|
arch
|
|
meta
|
|
;
|
|
package = checkVersion allArchives.packages "tools" (parseVersion repo "tools" toolsVersion);
|
|
|
|
postInstall = ''
|
|
${linkPlugin {
|
|
name = "platform-tools";
|
|
plugin = platform-tools;
|
|
}}
|
|
${linkPlugin {
|
|
name = "emulator";
|
|
plugin = emulator;
|
|
check = includeEmulator;
|
|
}}
|
|
'';
|
|
};
|
|
|
|
build-tools = map (
|
|
version:
|
|
callPackage ./build-tools.nix {
|
|
inherit
|
|
deployAndroidPackage
|
|
os
|
|
arch
|
|
meta
|
|
;
|
|
package = checkVersion allArchives.packages "build-tools" version;
|
|
|
|
postInstall = ''
|
|
${linkPlugin {
|
|
name = "tools";
|
|
plugin = tools;
|
|
check = toolsVersion != null;
|
|
}}
|
|
'';
|
|
}
|
|
) (parseVersions repo "build-tools" buildToolsVersions);
|
|
|
|
emulator = callPackage ./emulator.nix {
|
|
inherit
|
|
deployAndroidPackage
|
|
os
|
|
arch
|
|
meta
|
|
;
|
|
package = checkVersion allArchives.packages "emulator" (
|
|
parseVersion repo "emulator" emulatorVersion
|
|
);
|
|
|
|
postInstall = ''
|
|
${linkSystemImages {
|
|
images = system-images;
|
|
check = includeSystemImages;
|
|
}}
|
|
'';
|
|
};
|
|
|
|
# This is a list of the chosen API levels, as integers.
|
|
platformVersions = platformVersions';
|
|
|
|
platforms = map (
|
|
version:
|
|
deployAndroidPackage {
|
|
package = checkVersion allArchives.packages "platforms" version;
|
|
}
|
|
) platformVersions';
|
|
|
|
# Google is not including sources for API 37+. If the user requests them, don't fail.
|
|
sources = lib.filter (source: source != null) (
|
|
map (
|
|
version:
|
|
let
|
|
package =
|
|
let
|
|
version' = builtins.tryEval (checkVersion allArchives.packages "sources" version);
|
|
in
|
|
if version'.success then version'.value else null;
|
|
in
|
|
if package == null then
|
|
null
|
|
else
|
|
deployAndroidPackage {
|
|
inherit package;
|
|
}
|
|
) platformVersions'
|
|
);
|
|
|
|
system-images = lib.flatten (
|
|
map (
|
|
apiVersion:
|
|
map (
|
|
type:
|
|
# Deploy all system images with the same systemImageType in one derivation to avoid the `null` problem below
|
|
# with avdmanager when trying to create an avd!
|
|
#
|
|
# ```
|
|
# $ yes "" | avdmanager create avd --force --name testAVD --package 'system-images;android-33;google_apis;x86_64'
|
|
# Error: Package path is not valid. Valid system image paths are:
|
|
# null
|
|
# ```
|
|
let
|
|
availablePackages =
|
|
map (abiVersion: allArchives.system-images.${toString apiVersion}.${type}.${abiVersion})
|
|
(
|
|
builtins.filter (
|
|
abiVersion: lib.hasAttrByPath [ (toString apiVersion) type abiVersion ] allArchives.system-images
|
|
) abiVersions
|
|
);
|
|
|
|
instructions = lib.listToAttrs (
|
|
map (package: {
|
|
name = package.name;
|
|
value = lib.optionalString (lib.hasPrefix "google_apis" type) ''
|
|
# Patch 'google_apis' system images so they're recognized by the sdk.
|
|
# Without this, `android list targets` shows 'Tag/ABIs : no ABIs' instead
|
|
# of 'Tag/ABIs : google_apis*/*' and the emulator fails with an ABI-related error.
|
|
sed -i '/^Addon.Vendor/d' source.properties
|
|
'';
|
|
}) availablePackages
|
|
);
|
|
in
|
|
lib.optionals (availablePackages != [ ]) (deployAndroidPackages {
|
|
packages = availablePackages;
|
|
patchesInstructions = instructions;
|
|
})
|
|
) systemImageTypes
|
|
) platformVersions'
|
|
);
|
|
|
|
cmake = map (
|
|
version:
|
|
callPackage ./cmake.nix {
|
|
inherit
|
|
deployAndroidPackage
|
|
os
|
|
arch
|
|
meta
|
|
;
|
|
package = checkVersion allArchives.packages "cmake" version;
|
|
}
|
|
) (parseVersions repo "cmake" cmakeVersions);
|
|
|
|
# All NDK bundles.
|
|
ndk-bundles =
|
|
let
|
|
# Creates a NDK bundle.
|
|
makeNdkBundle =
|
|
package:
|
|
callPackage ./ndk-bundle {
|
|
inherit
|
|
deployAndroidPackage
|
|
os
|
|
arch
|
|
platform-tools
|
|
meta
|
|
package
|
|
;
|
|
};
|
|
in
|
|
lib.flatten (
|
|
map (
|
|
version:
|
|
let
|
|
package = makeNdkBundle (
|
|
allArchives.packages.ndk-bundle.${version} or allArchives.packages.ndk.${version}
|
|
);
|
|
in
|
|
lib.optional (shouldLink includeNDK [ package ]) package
|
|
) (parseVersions repo "ndk" ndkVersions)
|
|
);
|
|
|
|
# The "default" NDK bundle.
|
|
ndk-bundle = if ndk-bundles == [ ] then null else lib.head ndk-bundles;
|
|
|
|
# Makes a Google API bundle from supported versions.
|
|
google-apis = map (
|
|
version:
|
|
deployAndroidPackage {
|
|
package = (checkVersion allArchives "addons" version).google_apis;
|
|
}
|
|
) (lib.filter (hasVersion allArchives "addons") platformVersions');
|
|
|
|
# Makes a Google TV addons bundle from supported versions.
|
|
google-tv-addons = map (
|
|
version:
|
|
deployAndroidPackage {
|
|
package = (checkVersion allArchives "addons" version).google_tv_addon;
|
|
}
|
|
) (lib.filter (hasVersion allArchives "addons") platformVersions');
|
|
|
|
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
|
|
# requested and throws.
|
|
androidsdk = callPackage ./cmdline-tools.nix {
|
|
inherit
|
|
deployAndroidPackage
|
|
os
|
|
arch
|
|
meta
|
|
;
|
|
|
|
package = cmdline-tools-package;
|
|
|
|
postInstall =
|
|
if !licenseAccepted then
|
|
throw ''
|
|
${builtins.concatStringsSep "\n\n" (mkLicenseTexts licenseNames)}
|
|
|
|
You must accept the following licenses:
|
|
${lib.concatMapStringsSep "\n" (str: " - ${str}") licenseNames}
|
|
|
|
a)
|
|
by setting nixpkgs config option 'android_sdk.accept_license = true;'.
|
|
b)
|
|
by an environment variable for a single invocation of the nix tools.
|
|
$ export NIXPKGS_ACCEPT_ANDROID_SDK_LICENSE=1
|
|
''
|
|
else
|
|
''
|
|
# Symlink all requested plugins
|
|
${linkPlugin {
|
|
name = "platform-tools";
|
|
plugin = platform-tools;
|
|
}}
|
|
${linkPlugin {
|
|
name = "tools";
|
|
plugin = tools;
|
|
check = toolsVersion != null;
|
|
}}
|
|
${linkPlugins {
|
|
name = "build-tools";
|
|
plugins = build-tools;
|
|
}}
|
|
${linkPlugin {
|
|
name = "emulator";
|
|
plugin = emulator;
|
|
check = includeEmulator;
|
|
}}
|
|
${linkPlugins {
|
|
name = "platforms";
|
|
plugins = platforms;
|
|
}}
|
|
${linkPlatformPlugins {
|
|
name = "sources";
|
|
plugins = sources;
|
|
check = includeSources;
|
|
}}
|
|
${linkPlugins {
|
|
name = "cmake";
|
|
plugins = cmake;
|
|
check = includeCmake;
|
|
}}
|
|
${linkNdkPlugins {
|
|
name = "ndk-bundle";
|
|
rootName = "ndk";
|
|
plugins = ndk-bundles;
|
|
check = includeNDK;
|
|
}}
|
|
${linkNdkPlugin {
|
|
name = "ndk-bundle";
|
|
plugin = ndk-bundle;
|
|
check = includeNDK;
|
|
}}
|
|
${linkSystemImages {
|
|
images = system-images;
|
|
check = includeSystemImages;
|
|
}}
|
|
${linkPlatformPlugins {
|
|
name = "add-ons";
|
|
plugins = google-apis;
|
|
check = useGoogleAPIs;
|
|
}}
|
|
${linkPlatformPlugins {
|
|
name = "add-ons";
|
|
plugins = google-tv-addons;
|
|
check = useGoogleTVAddOns;
|
|
}}
|
|
|
|
# Link extras
|
|
${lib.concatMapStrings (
|
|
identifier:
|
|
let
|
|
package = allArchives.extras.${identifier};
|
|
path = package.path;
|
|
extras = callPackage ./extras.nix {
|
|
inherit
|
|
deployAndroidPackage
|
|
package
|
|
os
|
|
arch
|
|
meta
|
|
;
|
|
};
|
|
in
|
|
''
|
|
targetDir=$(dirname ${path})
|
|
mkdir -p $targetDir
|
|
ln -s ${extras}/libexec/android-sdk/${path} $targetDir
|
|
''
|
|
) includeExtras}
|
|
|
|
# Expose common executables in bin/
|
|
mkdir -p $out/bin
|
|
|
|
for i in ${platform-tools}/bin/*; do
|
|
ln -s $i $out/bin
|
|
done
|
|
|
|
${lib.optionalString (shouldLink includeEmulator [ emulator ]) ''
|
|
for i in ${emulator}/bin/*; do
|
|
ln -s $i $out/bin
|
|
done
|
|
''}
|
|
|
|
find "$ANDROID_HOME/${cmdline-tools-package.path}/bin" -type f -executable | while read i; do
|
|
ln -s $i $out/bin
|
|
done
|
|
|
|
# Write licenses
|
|
mkdir -p licenses
|
|
${lib.concatMapStrings (
|
|
licenseName:
|
|
let
|
|
licenseHashes = builtins.concatStringsSep "\n" (mkLicenseHashes licenseName);
|
|
licenseHashFile = writeText "androidenv-${licenseName}" licenseHashes;
|
|
in
|
|
''
|
|
ln -s ${licenseHashFile} licenses/${licenseName}
|
|
''
|
|
) licenseNames}
|
|
'';
|
|
};
|
|
}
|