Something went wrong. Try again.
What happens if I push all of nixpkgs
Something went wrong. Try again.
22 kB · 773 lines
Nix
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774{ 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;
# 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, 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 let 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 (parseVersion repo "platforms" minPlatformVersion); latestPlatformVersionInt = lib.max minPlatformVersionInt (coerceInt repo.latest.platforms); firstPlatformVersionInt = lib.max minPlatformVersionInt ( latestPlatformVersionInt - (lib.max 1 numLatestPlatformVersions) + 1 ); in lib.range firstPlatformVersionInt latestPlatformVersionInt, includeSources ? false, includeSystemImages ? false, systemImageTypes ? [ "google_apis" "google_apis_playstore" ], 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' = map coerceInt (parseVersions repo "platforms" platformVersions);
# Determine the Android os identifier from Nix's system identifier os = { x86_64-linux = "linux"; x86_64-darwin = "macosx"; 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"; x86_64-darwin = "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 { inherit (archive) url sha1; preferLocalBuild = true; passthru = { info = packageInfo; }; }).overrideAttrs (prev: { # fetchurl won't generate the correct filename if we specify pname and version, # and we still want the version attribute to show up in search, so specify these in an override pname = packageInfo.name; version = packageInfo.revision; }) ) 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 ( builtins.map ( licenseName: builtins.map (licenseText: "--- ${licenseName} ---\n${licenseText}") (mkLicenses licenseName) ) licenseNames );
# Converts a license name to a list of license hashes. mkLicenseHashes = licenseName: builtins.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;
# Displays a nice error message that includes the available options if a version doesn't exist. checkVersion = packages: package: version: if hasVersion packages package version then packages.${package}.${toString version} else throw '' The version ${toString version} is missing in package ${package}. The only available versions are ${ builtins.concatStringsSep ", " (builtins.attrNames packages.${package}) }. '';
# 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} ''; # */
inlib.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; }} ''; };
platformVersions = platformVersions';
platforms = map ( version: deployAndroidPackage { package = checkVersion allArchives.packages "platforms" version; } ) platformVersions';
sources = map ( version: deployAndroidPackage { package = checkVersion allArchives.packages "sources" version; } ) 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 = builtins.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_SDK_ROOT/${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} ''; };}