1{ stdenv 2, lib 3, fetchurl 4, buildPythonPackage 5, isPy3k, pythonOlder, pythonAtLeast, astor 6, gast 7, google-pasta 8, wrapt 9, numpy 10, six 11, termcolor 12, packaging 13, protobuf 14, absl-py 15, grpcio 16, mock 17, scipy 18, wheel 19, jax 20, opt-einsum 21, tensorflow-estimator-bin 22, tensorboard 23, config 24, cudaSupport ? config.cudaSupport 25, cudaPackages ? {} 26, zlib 27, python 28, keras-applications 29, keras-preprocessing 30, addOpenGLRunpath 31, astunparse 32, flatbuffers 33, h5py 34, typing-extensions 35}: 36 37# We keep this binary build for two reasons: 38# - the source build doesn't work on Darwin. 39# - the source build is currently brittle and not easy to maintain 40 41# unsupported combination 42assert ! (stdenv.isDarwin && cudaSupport); 43 44let 45 packages = import ./binary-hashes.nix; 46 inherit (cudaPackages) cudatoolkit cudnn; 47in buildPythonPackage { 48 pname = "tensorflow" + lib.optionalString cudaSupport "-gpu"; 49 inherit (packages) version; 50 format = "wheel"; 51 52 src = let 53 pyVerNoDot = lib.strings.stringAsChars (x: lib.optionalString (x != ".") x) python.pythonVersion; 54 platform = if stdenv.isDarwin then "mac" else "linux"; 55 unit = if cudaSupport then "gpu" else "cpu"; 56 key = "${platform}_py_${pyVerNoDot}_${unit}"; 57 in fetchurl (packages.${key} or {}); 58 59 propagatedBuildInputs = [ 60 astunparse 61 flatbuffers 62 typing-extensions 63 packaging 64 protobuf 65 numpy 66 scipy 67 jax 68 termcolor 69 grpcio 70 six 71 astor 72 absl-py 73 gast 74 opt-einsum 75 google-pasta 76 wrapt 77 tensorflow-estimator-bin 78 tensorboard 79 keras-applications 80 keras-preprocessing 81 h5py 82 ] ++ lib.optional (!isPy3k) mock; 83 84 nativeBuildInputs = [ wheel ] ++ lib.optionals cudaSupport [ addOpenGLRunpath ]; 85 86 preConfigure = '' 87 unset SOURCE_DATE_EPOCH 88 89 # Make sure that dist and the wheel file are writable. 90 chmod u+rwx -R ./dist 91 92 pushd dist 93 94 orig_name="$(echo ./*.whl)" 95 wheel unpack --dest unpacked ./*.whl 96 rm ./*.whl 97 ( 98 cd unpacked/tensorflow* 99 # Adjust dependency requirements: 100 # - Relax flatbuffers, gast, protobuf, tensorboard, and tensorflow-estimator version requirements that don't match what we have packaged 101 # - The purpose of python3Packages.libclang is not clear at the moment and we don't have it packaged yet 102 # - keras and tensorlow-io-gcs-filesystem will be considered as optional for now. 103 # - numpy was pinned to fix some internal tests: https://github.com/tensorflow/tensorflow/issues/60216 104 sed -i *.dist-info/METADATA \ 105 -e "/Requires-Dist: flatbuffers/d" \ 106 -e "/Requires-Dist: gast/d" \ 107 -e "/Requires-Dist: keras/d" \ 108 -e "/Requires-Dist: libclang/d" \ 109 -e "/Requires-Dist: protobuf/d" \ 110 -e "/Requires-Dist: tensorboard/d" \ 111 -e "/Requires-Dist: tensorflow-estimator/d" \ 112 -e "/Requires-Dist: tensorflow-io-gcs-filesystem/d" \ 113 -e "s/Requires-Dist: numpy (.*)/Requires-Dist: numpy/" 114 ) 115 wheel pack ./unpacked/tensorflow* 116 mv *.whl $orig_name # avoid changes to the _os_arch.whl suffix 117 118 popd 119 ''; 120 121 # Note that we need to run *after* the fixup phase because the 122 # libraries are loaded at runtime. If we run in preFixup then 123 # patchelf --shrink-rpath will remove the cuda libraries. 124 postFixup = 125 let 126 # rpaths we only need to add if CUDA is enabled. 127 cudapaths = lib.optionals cudaSupport [ 128 cudatoolkit.out 129 cudatoolkit.lib 130 cudnn 131 ]; 132 133 libpaths = [ 134 stdenv.cc.cc.lib 135 zlib 136 ]; 137 138 rpath = lib.makeLibraryPath (libpaths ++ cudapaths); 139 in 140 lib.optionalString stdenv.isLinux '' 141 # This is an array containing all the directories in the tensorflow2 142 # package that contain .so files. 143 # 144 # TODO: Create this list programmatically, and remove paths that aren't 145 # actually needed. 146 rrPathArr=( 147 "$out/${python.sitePackages}/tensorflow/" 148 "$out/${python.sitePackages}/tensorflow/core/kernels" 149 "$out/${python.sitePackages}/tensorflow/compiler/tf2tensorrt/" 150 "$out/${python.sitePackages}/tensorflow/compiler/tf2xla/ops/" 151 "$out/${python.sitePackages}/tensorflow/lite/experimental/microfrontend/python/ops/" 152 "$out/${python.sitePackages}/tensorflow/lite/python/analyzer_wrapper/" 153 "$out/${python.sitePackages}/tensorflow/lite/python/interpreter_wrapper/" 154 "$out/${python.sitePackages}/tensorflow/lite/python/metrics/" 155 "$out/${python.sitePackages}/tensorflow/lite/python/optimize/" 156 "$out/${python.sitePackages}/tensorflow/python/" 157 "$out/${python.sitePackages}/tensorflow/python/autograph/impl/testing" 158 "$out/${python.sitePackages}/tensorflow/python/client" 159 "$out/${python.sitePackages}/tensorflow/python/data/experimental/service" 160 "$out/${python.sitePackages}/tensorflow/python/framework" 161 "$out/${python.sitePackages}/tensorflow/python/grappler" 162 "$out/${python.sitePackages}/tensorflow/python/lib/core" 163 "$out/${python.sitePackages}/tensorflow/python/lib/io" 164 "$out/${python.sitePackages}/tensorflow/python/platform" 165 "$out/${python.sitePackages}/tensorflow/python/profiler/internal" 166 "$out/${python.sitePackages}/tensorflow/python/saved_model" 167 "$out/${python.sitePackages}/tensorflow/python/util" 168 "$out/${python.sitePackages}/tensorflow/tsl/python/lib/core" 169 "${rpath}" 170 ) 171 172 # The the bash array into a colon-separated list of RPATHs. 173 rrPath=$(IFS=$':'; echo "''${rrPathArr[*]}") 174 echo "about to run patchelf with the following rpath: $rrPath" 175 176 find $out -type f \( -name '*.so' -or -name '*.so.*' \) | while read lib; do 177 echo "about to patchelf $lib..." 178 chmod a+rx "$lib" 179 patchelf --set-rpath "$rrPath" "$lib" 180 ${lib.optionalString cudaSupport '' 181 addOpenGLRunpath "$lib" 182 ''} 183 done 184 ''; 185 186 # Upstream has a pip hack that results in bin/tensorboard being in both tensorflow 187 # and the propagated input tensorboard, which causes environment collisions. 188 # Another possibility would be to have tensorboard only in the buildInputs 189 # See https://github.com/NixOS/nixpkgs/pull/44381 for more information. 190 postInstall = '' 191 rm $out/bin/tensorboard 192 ''; 193 194 pythonImportsCheck = [ 195 "tensorflow" 196 "tensorflow.python" 197 "tensorflow.python.framework" 198 ]; 199 200 passthru = { 201 inherit cudaPackages; 202 }; 203 204 meta = with lib; { 205 description = "Computation using data flow graphs for scalable machine learning"; 206 homepage = "http://tensorflow.org"; 207 sourceProvenance = with sourceTypes; [ binaryNativeCode ]; 208 license = licenses.asl20; 209 maintainers = with maintainers; [ jyp abbradar ]; 210 platforms = [ "x86_64-linux" "x86_64-darwin" ]; 211 }; 212}