nixpkgs mirror (for testing) github.com/NixOS/nixpkgs
nix
at python-updates 201 lines 7.3 kB view raw
1{ 2 config, 3 lib, 4 stdenv, 5 makeWrapper, 6 runCommand, 7 wrapBintoolsWith, 8 wrapCCWith, 9 autoPatchelfHook, 10 llvmPackages, 11 buildAndroidndk, 12 androidndk, 13 targetAndroidndkPkgs, 14}: 15 16let 17 # Mapping from a platform to information needed to unpack NDK stuff for that 18 # platform. 19 # 20 # N.B. The Android NDK uses slightly different LLVM-style platform triples 21 # than we do. We don't just use theirs because ours are less ambiguous and 22 # some builds need that clarity. 23 # 24 ndkBuildInfoFun = 25 fallback: 26 { 27 x86_64-apple-darwin = { 28 double = "darwin-x86_64"; 29 }; 30 x86_64-unknown-linux-gnu = { 31 double = "linux-x86_64"; 32 }; 33 } 34 .${stdenv.buildPlatform.config} or fallback; 35 36 ndkTargetInfoFun = 37 fallback: 38 { 39 i686-unknown-linux-android = { 40 triple = "i686-linux-android"; 41 arch = "x86"; 42 }; 43 x86_64-unknown-linux-android = { 44 triple = "x86_64-linux-android"; 45 arch = "x86_64"; 46 }; 47 armv7a-unknown-linux-androideabi = { 48 arch = "arm"; 49 triple = "arm-linux-androideabi"; 50 }; 51 aarch64-unknown-linux-android = { 52 arch = "arm64"; 53 triple = "aarch64-linux-android"; 54 }; 55 } 56 .${stdenv.targetPlatform.config} or fallback; 57 58 buildInfo = ndkBuildInfoFun ( 59 throw "Android NDK doesn't support building on ${stdenv.buildPlatform.config}, as far as we know" 60 ); 61 targetInfo = ndkTargetInfoFun ( 62 throw "Android NDK doesn't support targetting ${stdenv.targetPlatform.config}, as far as we know" 63 ); 64 65 androidSdkVersion = 66 if 67 (stdenv.targetPlatform ? androidSdkVersion && stdenv.targetPlatform.androidSdkVersion != null) 68 then 69 stdenv.targetPlatform.androidSdkVersion 70 else 71 (throw "`androidSdkVersion` is not set during the importing of nixpkgs"); 72 suffixSalt = lib.replaceStrings [ "-" "." ] [ "_" "_" ] stdenv.targetPlatform.config; 73 74 # targetInfo.triple is what Google thinks the toolchain should be, this is a little 75 # different from what we use. We make it four parts to conform with the existing 76 # standard more properly. 77 targetPrefix = lib.optionalString (stdenv.targetPlatform != stdenv.hostPlatform) ( 78 stdenv.targetPlatform.config + "-" 79 ); 80in 81 82if !config.allowAliases && (ndkBuildInfoFun null == null || ndkTargetInfoFun null == null) then 83 # Don't throw without aliases to not break CI. 84 null 85else 86 lib.recurseIntoAttrs rec { 87 # Misc tools 88 binaries = stdenv.mkDerivation { 89 pname = "${targetPrefix}ndk-toolchain"; 90 inherit (androidndk) version; 91 nativeBuildInputs = [ 92 makeWrapper 93 autoPatchelfHook 94 ]; 95 propagatedBuildInputs = [ androidndk ]; 96 passthru = { 97 inherit targetPrefix; 98 isClang = true; # clang based cc, but bintools ld 99 inherit (llvmPackages.clang.cc) hardeningUnsupportedFlagsByTargetPlatform; 100 }; 101 dontUnpack = true; 102 dontBuild = true; 103 dontStrip = true; 104 dontConfigure = true; 105 dontPatch = true; 106 autoPatchelfIgnoreMissingDeps = true; 107 installPhase = '' 108 # https://developer.android.com/ndk/guides/other_build_systems 109 mkdir -p $out 110 cp -r ${androidndk}/libexec/android-sdk/ndk-bundle/toolchains/llvm/prebuilt/${buildInfo.double} $out/toolchain 111 find $out/toolchain -type d -exec chmod 777 {} \; 112 113 if [ ! -d $out/toolchain/sysroot/usr/lib/${targetInfo.triple}/${androidSdkVersion} ]; then 114 echo "NDK does not contain libraries for SDK version ${androidSdkVersion}"; 115 exit 1 116 fi 117 118 ln -vfs $out/toolchain/sysroot/usr/lib $out/lib 119 ln -s $out/toolchain/sysroot/usr/lib/${targetInfo.triple}/*.so $out/lib/ 120 ln -s $out/toolchain/sysroot/usr/lib/${targetInfo.triple}/*.a $out/lib/ 121 chmod +w $out/lib/* 122 ln -s $out/toolchain/sysroot/usr/lib/${targetInfo.triple}/${androidSdkVersion}/*.so $out/lib/ 123 ln -s $out/toolchain/sysroot/usr/lib/${targetInfo.triple}/${androidSdkVersion}/*.o $out/lib/ 124 125 echo "INPUT(-lc++_static)" > $out/lib/libc++.a 126 127 ln -s $out/toolchain/bin $out/bin 128 ln -s $out/toolchain/${targetInfo.triple}/bin/* $out/bin/ 129 for f in $out/bin/${targetInfo.triple}-*; do 130 ln -s $f ''${f/${targetInfo.triple}-/${targetPrefix}} 131 done 132 for f in $(find $out/toolchain -type d -name ${targetInfo.triple}); do 133 ln -s $f ''${f/${targetInfo.triple}/${targetPrefix}} 134 done 135 136 rm -f $out/bin/${targetPrefix}ld 137 ln -s $out/bin/lld $out/bin/${targetPrefix}ld 138 139 (cd $out/bin; 140 for tool in llvm-*; do 141 ln -sf $tool ${targetPrefix}$(echo $tool | sed 's/llvm-//') 142 ln -sf $tool $(echo $tool | sed 's/llvm-//') 143 done) 144 145 ln -sf $out/bin/yasm $out/bin/${targetPrefix}as 146 ln -sf $out/bin/yasm $out/bin/as 147 148 patchShebangs $out/bin 149 ''; 150 meta = { 151 description = "Android NDK toolchain, tuned for other platforms"; 152 license = with lib.licenses; [ unfree ]; 153 teams = [ lib.teams.android ]; 154 }; 155 }; 156 157 binutils = wrapBintoolsWith { 158 bintools = binaries; 159 libc = targetAndroidndkPkgs.libraries; 160 }; 161 162 clang = wrapCCWith { 163 cc = binaries // { 164 # for packages expecting libcompiler-rt, etc. to come from here (stdenv.cc.cc.lib) 165 lib = targetAndroidndkPkgs.libraries; 166 }; 167 bintools = binutils; 168 libc = targetAndroidndkPkgs.libraries; 169 extraBuildCommands = '' 170 echo "-D__ANDROID_API__=${stdenv.targetPlatform.androidSdkVersion}" >> $out/nix-support/cc-cflags 171 # Android needs executables linked with -pie since version 5.0 172 # Use -fPIC for compilation, and link with -pie if no -shared flag used in ldflags 173 echo "-target ${targetInfo.triple} -fPIC" >> $out/nix-support/cc-cflags 174 echo "-z,noexecstack -z,relro -z,now -z,muldefs" >> $out/nix-support/cc-ldflags 175 echo 'expandResponseParams "$@"' >> $out/nix-support/add-flags.sh 176 echo 'if [[ ! (" ''${params[@]} " =~ " -shared ") && ! (" ''${params[@]} " =~ " -no-pie ") ]]; then NIX_LDFLAGS_${suffixSalt}+=" -pie"; fi' >> $out/nix-support/add-flags.sh 177 echo "-Xclang -mnoexecstack" >> $out/nix-support/cc-cxxflags 178 if [ ${targetInfo.triple} == arm-linux-androideabi ]; then 179 # https://android.googlesource.com/platform/external/android-cmake/+/refs/heads/cmake-master-dev/android.toolchain.cmake 180 echo "--fix-cortex-a8" >> $out/nix-support/cc-ldflags 181 fi 182 ''; 183 }; 184 185 # Bionic lib C and other libraries. 186 # 187 # We use androidndk from the previous stage, else we waste time or get cycles 188 # cross-compiling packages to wrap incorrectly wrap binaries we don't include 189 # anyways. 190 libraries = runCommand "bionic-prebuilt" { } '' 191 lpath=${buildAndroidndk}/libexec/android-sdk/ndk-bundle/toolchains/llvm/prebuilt/${buildInfo.double}/sysroot/usr/lib/${targetInfo.triple}/${androidSdkVersion} 192 if [ ! -d $lpath ]; then 193 echo "NDK does not contain libraries for SDK version ${androidSdkVersion} <$lpath>" 194 exit 1 195 fi 196 mkdir -p $out/lib 197 cp $lpath/*.so $lpath/*.a $out/lib 198 chmod +w $out/lib/* 199 cp $lpath/* $out/lib 200 ''; 201 }