at master 5.5 kB view raw
1{ 2 stdenv, 3 lib, 4 unzip, 5 mkLicenses, 6 os, 7 arch, 8 meta, 9}: 10{ 11 packages, 12 nativeBuildInputs ? [ ], 13 buildInputs ? [ ], 14 patchesInstructions ? { }, 15 ... 16}@args: 17 18let 19 extraParams = removeAttrs args [ 20 "packages" 21 "os" 22 "buildInputs" 23 "nativeBuildInputs" 24 "patchesInstructions" 25 ]; 26 sortedPackages = builtins.sort (x: y: builtins.lessThan x.name y.name) packages; 27 28 mkXmlAttrs = 29 attrs: lib.concatStrings (lib.mapAttrsToList (name: value: " ${name}=\"${value}\"") attrs); 30 mkXmlValues = 31 attrs: 32 lib.concatStrings ( 33 lib.mapAttrsToList ( 34 name: value: 35 let 36 tag = builtins.head (builtins.match "([^:]+).*" name); 37 in 38 if builtins.typeOf value == "string" then "<${tag}>${value}</${tag}>" else mkXmlDoc name value 39 ) attrs 40 ); 41 mkXmlDoc = 42 name: doc: 43 let 44 tag = builtins.head (builtins.match "([^:]+).*" name); 45 hasXmlAttrs = builtins.hasAttr "element-attributes" doc; 46 xmlValues = removeAttrs doc [ "element-attributes" ]; 47 hasXmlValues = builtins.length (builtins.attrNames xmlValues) > 0; 48 in 49 if hasXmlAttrs && hasXmlValues then 50 "<${tag}${mkXmlAttrs doc.element-attributes}>${mkXmlValues xmlValues}</${tag}>" 51 else if hasXmlAttrs && !hasXmlValues then 52 "<${tag}${mkXmlAttrs doc.element-attributes}/>" 53 else if !hasXmlAttrs && hasXmlValues then 54 "<${tag}>${mkXmlValues xmlValues}</${tag}>" 55 else 56 "<${tag}/>"; 57 mkXmlPackage = package: '' 58 <?xml version="1.0" encoding="UTF-8" standalone="yes"?> 59 <ns2:repository 60 xmlns:ns2="http://schemas.android.com/repository/android/common/02" 61 xmlns:ns3="http://schemas.android.com/repository/android/common/01" 62 xmlns:ns4="http://schemas.android.com/repository/android/generic/01" 63 xmlns:ns5="http://schemas.android.com/repository/android/generic/02" 64 xmlns:ns6="http://schemas.android.com/sdk/android/repo/addon2/01" 65 xmlns:ns7="http://schemas.android.com/sdk/android/repo/addon2/02" 66 xmlns:ns8="http://schemas.android.com/sdk/android/repo/addon2/03" 67 xmlns:ns9="http://schemas.android.com/sdk/android/repo/repository2/01" 68 xmlns:ns10="http://schemas.android.com/sdk/android/repo/repository2/02" 69 xmlns:ns11="http://schemas.android.com/sdk/android/repo/repository2/03" 70 xmlns:ns12="http://schemas.android.com/sdk/android/repo/sys-img2/03" 71 xmlns:ns13="http://schemas.android.com/sdk/android/repo/sys-img2/02" 72 xmlns:ns14="http://schemas.android.com/sdk/android/repo/sys-img2/01" 73 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 74 <license id="${package.license}" type="text">${lib.concatStringsSep "---" (mkLicenses package.license)}</license> 75 <localPackage path="${builtins.replaceStrings [ "/" ] [ ";" ] package.path}" obsolete="${ 76 if (lib.hasAttrByPath [ "obsolete" ] package) then package.obsolete else "false" 77 }"> 78 ${mkXmlDoc "type-details" package.type-details} 79 ${mkXmlDoc "revision" package.revision-details} 80 ${lib.optionalString (lib.hasAttrByPath [ "dependencies" ] package) ( 81 mkXmlDoc "dependencies" package.dependencies 82 )} 83 <display-name>${package.displayName}</display-name> 84 <uses-license ref="${package.license}"/> 85 </localPackage> 86 </ns2:repository> 87 ''; 88in 89stdenv.mkDerivation ( 90 { 91 inherit buildInputs; 92 pname = "android-sdk-${lib.concatMapStringsSep "-" (package: package.name) sortedPackages}"; 93 version = lib.concatMapStringsSep "-" (package: package.revision) sortedPackages; 94 src = lib.flatten (map (package: package.archives) packages); 95 inherit os arch; 96 nativeBuildInputs = [ unzip ] ++ nativeBuildInputs; 97 preferLocalBuild = true; 98 99 unpackPhase = '' 100 runHook preUnpack 101 if [ -z "$src" ]; then 102 echo "$pname did not have any sources available for os=$os, arch=$arch." >&2 103 echo "Are packages available for this architecture?" >&2 104 exit 1 105 fi 106 buildDir=$PWD 107 i=0 108 for srcArchive in $src; do 109 extractedZip="extractedzip-$i" 110 i=$((i+1)) 111 cd "$buildDir" 112 mkdir "$extractedZip" 113 cd "$extractedZip" 114 unpackFile "$srcArchive" 115 done 116 runHook postUnpack 117 ''; 118 119 installPhase = '' 120 runHook preInstall 121 '' 122 + lib.concatStrings ( 123 lib.imap0 (i: package: '' 124 cd $buildDir/extractedzip-${toString i} 125 126 # Most Android Zip packages have a root folder, but some don't. We unpack 127 # the zip file in a folder and we try to discover whether it has a single root 128 # folder. If this is the case, we adjust the current working folder. 129 if [ "$(find . -mindepth 1 -maxdepth 1 -type d | wc -l)" -eq 1 ]; then 130 cd "$(find . -mindepth 1 -maxdepth 1 -type d)" 131 fi 132 extractedZip="$PWD" 133 134 packageBaseDir=$out/libexec/android-sdk/${package.path} 135 mkdir -p $packageBaseDir 136 cd $packageBaseDir 137 cp -a $extractedZip/* . 138 ${patchesInstructions.${package.name}} 139 140 if [ ! -f $packageBaseDir/package.xml ]; then 141 cat << EOF > $packageBaseDir/package.xml 142 ${mkXmlPackage package} 143 EOF 144 fi 145 '') packages 146 ) 147 + '' 148 runHook postInstall 149 ''; 150 151 # Some executables that have been patched with patchelf may not work any longer after they have been stripped. 152 dontStrip = true; 153 dontPatchELF = true; 154 dontAutoPatchelf = true; 155 156 inherit meta; 157 } 158 // extraParams 159)