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