xref: /aosp_15_r20/external/tensorflow/tensorflow/tools/pip_package/setup.py (revision b6fb3261f9314811a0f4371741dbb8839866f948)
1# Copyright 2015 The TensorFlow Authors. All Rights Reserved.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#     http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License..
14# ==============================================================================
15"""TensorFlow is an open source machine learning framework for everyone.
16
17[![Python](https://img.shields.io/pypi/pyversions/tensorflow.svg?style=plastic)](https://badge.fury.io/py/tensorflow)
18[![PyPI](https://badge.fury.io/py/tensorflow.svg)](https://badge.fury.io/py/tensorflow)
19
20TensorFlow is an open source software library for high performance numerical
21computation. Its flexible architecture allows easy deployment of computation
22across a variety of platforms (CPUs, GPUs, TPUs), and from desktops to clusters
23of servers to mobile and edge devices.
24
25Originally developed by researchers and engineers from the Google Brain team
26within Google's AI organization, it comes with strong support for machine
27learning and deep learning and the flexible numerical computation core is used
28across many other scientific domains.
29"""
30
31import fnmatch
32import os
33import re
34import sys
35
36from setuptools import Command
37from setuptools import find_packages
38from setuptools import setup
39from setuptools.command.install import install as InstallCommandBase
40from setuptools.dist import Distribution
41
42
43# This version string is semver compatible, but incompatible with pip.
44# For pip, we will remove all '-' characters from this string, and use the
45# result for pip.
46# Also update tensorflow/tensorflow.bzl and
47# tensorflow/core/public/version.h
48_VERSION = '2.11.0'
49
50
51# We use the same setup.py for all tensorflow_* packages and for the nightly
52# equivalents (tf_nightly_*). The package is controlled from the argument line
53# when building the pip package.
54project_name = 'tensorflow'
55if '--project_name' in sys.argv:
56  project_name_idx = sys.argv.index('--project_name')
57  project_name = sys.argv[project_name_idx + 1]
58  sys.argv.remove('--project_name')
59  sys.argv.pop(project_name_idx)
60
61# Returns standard if a tensorflow-* package is being built, and nightly if a
62# tf_nightly-* package is being built.
63def standard_or_nightly(standard, nightly):
64  return nightly if 'tf_nightly' in project_name else standard
65
66# All versions of TF need these packages. We indicate the widest possible range
67# of package releases possible to be as up-to-date as possible as well as to
68# accomodate as many pre-installed packages as possible.
69# For packages that don't have yet a stable release, we pin using `~= 0.x` which
70# means we accept any `0.y` version (y >= x) but not the first major release. We
71# will need additional testing for that.
72# NOTE: This assumes that all packages follow SemVer. If a package follows a
73# different versioning scheme (e.g., PVP), we use different bound specifier and
74# comment the versioning scheme.
75REQUIRED_PACKAGES = [
76    'absl-py >= 1.0.0',
77    'astunparse >= 1.6.0',
78    'flatbuffers >= 2.0',
79    # TODO(b/213222745) gast versions above 0.4.0 break TF's tests
80    'gast >= 0.2.1, <= 0.4.0',
81    'google_pasta >= 0.1.1',
82    'h5py >= 2.9.0',
83    'keras_preprocessing >= 1.1.1',  # 1.1.0 needs tensorflow==1.7
84    'libclang >= 13.0.0',
85    'numpy >= 1.20',
86    'opt_einsum >= 2.3.2',
87    'packaging',
88    # TODO(b/182876485): Protobuf 3.20 results in linker errors on Windows
89    # Protobuf 4.0 is binary incompatible with what C++ TF uses.
90    # We need ~1 quarter to update properly.
91    # See also: https://github.com/tensorflow/tensorflow/issues/53234
92    # See also: https://github.com/protocolbuffers/protobuf/issues/9954
93    # See also: https://github.com/tensorflow/tensorflow/issues/56077
94    # This is a temporary patch for now, to patch previous TF releases.
95    'protobuf >= 3.9.2, < 3.20',
96    'setuptools',
97    'six >= 1.12.0',
98    'termcolor >= 1.1.0',
99    'typing_extensions >= 3.6.6',
100    'wrapt >= 1.11.0',
101    'tensorflow-io-gcs-filesystem >= 0.23.1',
102    # grpcio does not build correctly on big-endian machines due to lack of
103    # BoringSSL support.
104    # See https://github.com/tensorflow/tensorflow/issues/17882.
105    'grpcio >= 1.24.3, < 2.0' if sys.byteorder == 'little' else None,
106    # TensorFlow exposes the TF API for certain TF ecosystem packages like
107    # keras.  When TF depends on those packages, the package version needs to
108    # match the current TF version. For tf_nightly, we install the nightly
109    # variant of each package instead, which must be one version ahead of the
110    # current release version. These also usually have "alpha" or "dev" in their
111    # version name.
112    # These are all updated during the TF release process.
113    standard_or_nightly('tensorboard >= 2.10, < 2.11',
114                        'tb-nightly ~= 2.11.0.a'),
115    standard_or_nightly('tensorflow_estimator >= 2.10.0rc0, < 2.11',
116                        'tf-estimator-nightly ~= 2.11.0.dev'),
117    standard_or_nightly('keras >= 2.10.0rc0, < 2.11',
118                        'keras-nightly ~= 2.11.0.dev'),
119]
120REQUIRED_PACKAGES = [ p for p in REQUIRED_PACKAGES if p is not None ]
121
122DOCLINES = __doc__.split('\n')
123if project_name.endswith('-gpu'):
124  project_name_no_gpu = project_name[:-len('-gpu')]
125  _GPU_PACKAGE_NOTE = 'Note that %s package by default supports both CPU and '\
126      'GPU. %s has the same content and exists solely for backward '\
127      'compatibility. Please migrate to %s for GPU support.'\
128      % (project_name_no_gpu, project_name, project_name_no_gpu)
129  DOCLINES.append(_GPU_PACKAGE_NOTE)
130
131
132# pylint: disable=line-too-long
133CONSOLE_SCRIPTS = [
134    'toco_from_protos = tensorflow.lite.toco.python.toco_from_protos:main',
135    'tflite_convert = tensorflow.lite.python.tflite_convert:main',
136    'toco = tensorflow.lite.python.tflite_convert:main',
137    'saved_model_cli = tensorflow.python.tools.saved_model_cli:main',
138    'import_pb_to_tensorboard = tensorflow.python.tools.import_pb_to_tensorboard:main',
139    # We need to keep the TensorBoard command, even though the console script
140    # is now declared by the tensorboard pip package. If we remove the
141    # TensorBoard command, pip will inappropriately remove it during install,
142    # even though the command is not removed, just moved to a different wheel.
143    # We exclude it anyway if building tf_nightly.
144    standard_or_nightly('tensorboard = tensorboard.main:run_main', None),
145    'tf_upgrade_v2 = tensorflow.tools.compatibility.tf_upgrade_v2_main:main',
146    'estimator_ckpt_converter = '
147    'tensorflow_estimator.python.estimator.tools.checkpoint_converter:main',
148]
149CONSOLE_SCRIPTS = [ s for s in CONSOLE_SCRIPTS if s is not None ]
150# pylint: enable=line-too-long
151
152
153class BinaryDistribution(Distribution):
154
155  def has_ext_modules(self):
156    return True
157
158
159class InstallCommand(InstallCommandBase):
160  """Override the dir where the headers go."""
161
162  def finalize_options(self):
163    ret = InstallCommandBase.finalize_options(self)  # pylint: disable=assignment-from-no-return
164    self.install_headers = os.path.join(self.install_platlib, 'tensorflow',
165                                        'include')
166    self.install_lib = self.install_platlib
167    return ret
168
169
170class InstallHeaders(Command):
171  """Override how headers are copied.
172
173  The install_headers that comes with setuptools copies all files to
174  the same directory. But we need the files to be in a specific directory
175  hierarchy for -I <include_dir> to work correctly.
176  """
177  description = 'install C/C++ header files'
178
179  user_options = [
180      ('install-dir=', 'd', 'directory to install header files to'),
181      ('force', 'f', 'force installation (overwrite existing files)'),
182  ]
183
184  boolean_options = ['force']
185
186  def initialize_options(self):
187    self.install_dir = None
188    self.force = 0
189    self.outfiles = []
190
191  def finalize_options(self):
192    self.set_undefined_options('install', ('install_headers', 'install_dir'),
193                               ('force', 'force'))
194
195  def mkdir_and_copy_file(self, header):
196    install_dir = os.path.join(self.install_dir, os.path.dirname(header))
197    # Get rid of some extra intervening directories so we can have fewer
198    # directories for -I
199    install_dir = re.sub('/google/protobuf_archive/src', '', install_dir)
200
201    # Copy external code headers into tensorflow/include.
202    # A symlink would do, but the wheel file that gets created ignores
203    # symlink within the directory hierarchy.
204    # NOTE(keveman): Figure out how to customize bdist_wheel package so
205    # we can do the symlink.
206    external_header_locations = [
207        'tensorflow/include/external/eigen_archive/',
208        'tensorflow/include/external/com_google_absl/',
209    ]
210    for location in external_header_locations:
211      if location in install_dir:
212        extra_dir = install_dir.replace(location, '')
213        if not os.path.exists(extra_dir):
214          self.mkpath(extra_dir)
215        self.copy_file(header, extra_dir)
216
217    if not os.path.exists(install_dir):
218      self.mkpath(install_dir)
219    return self.copy_file(header, install_dir)
220
221  def run(self):
222    hdrs = self.distribution.headers
223    if not hdrs:
224      return
225
226    self.mkpath(self.install_dir)
227    for header in hdrs:
228      (out, _) = self.mkdir_and_copy_file(header)
229      self.outfiles.append(out)
230
231  def get_inputs(self):
232    return self.distribution.headers or []
233
234  def get_outputs(self):
235    return self.outfiles
236
237
238def find_files(pattern, root):
239  """Return all the files matching pattern below root dir."""
240  for dirpath, _, files in os.walk(root):
241    for filename in fnmatch.filter(files, pattern):
242      yield os.path.join(dirpath, filename)
243
244
245so_lib_paths = [
246    i for i in os.listdir('.')
247    if os.path.isdir(i) and fnmatch.fnmatch(i, '_solib_*')
248]
249
250matches = []
251for path in so_lib_paths:
252  matches.extend(['../' + x for x in find_files('*', path) if '.py' not in x])
253
254if os.name == 'nt':
255  EXTENSION_NAME = 'python/_pywrap_tensorflow_internal.pyd'
256else:
257  EXTENSION_NAME = 'python/_pywrap_tensorflow_internal.so'
258
259headers = (
260    list(find_files('*.proto', 'tensorflow/compiler')) +
261    list(find_files('*.proto', 'tensorflow/core')) +
262    list(find_files('*.proto', 'tensorflow/python')) +
263    list(find_files('*.proto', 'tensorflow/python/framework')) +
264    list(find_files('*.def', 'tensorflow/compiler')) +
265    list(find_files('*.h', 'tensorflow/c')) +
266    list(find_files('*.h', 'tensorflow/cc')) +
267    list(find_files('*.h', 'tensorflow/compiler')) +
268    list(find_files('*.h.inc', 'tensorflow/compiler')) +
269    list(find_files('*.h', 'tensorflow/core')) +
270    list(find_files('*.h', 'tensorflow/lite/kernels/shim')) +
271    list(find_files('*.h', 'tensorflow/python')) +
272    list(find_files('*.h', 'tensorflow/python/client')) +
273    list(find_files('*.h', 'tensorflow/python/framework')) +
274    list(find_files('*.h', 'tensorflow/stream_executor')) +
275    list(find_files('*.h', 'tensorflow/tsl')) +
276    list(find_files('*.h', 'google/com_google_protobuf/src')) +
277    list(find_files('*.inc', 'google/com_google_protobuf/src')) +
278    list(find_files('*', 'third_party/eigen3')) +
279    list(find_files('*.h', 'tensorflow/include/external/com_google_absl')) +
280    list(find_files('*.inc', 'tensorflow/include/external/com_google_absl')) +
281    list(find_files('*', 'tensorflow/include/external/eigen_archive')))
282
283setup(
284    name=project_name,
285    version=_VERSION.replace('-', ''),
286    description=DOCLINES[0],
287    long_description='\n'.join(DOCLINES[2:]),
288    long_description_content_type='text/markdown',
289    url='https://www.tensorflow.org/',
290    download_url='https://github.com/tensorflow/tensorflow/tags',
291    author='Google Inc.',
292    author_email='[email protected]',
293    # Contained modules and scripts.
294    packages=find_packages(),
295    entry_points={
296        'console_scripts': CONSOLE_SCRIPTS,
297    },
298    headers=headers,
299    install_requires=REQUIRED_PACKAGES,
300    # Add in any packaged data.
301    include_package_data=True,
302    package_data={
303        'tensorflow': [
304            EXTENSION_NAME,
305        ] + matches,
306    },
307    zip_safe=False,
308    distclass=BinaryDistribution,
309    cmdclass={
310        'install_headers': InstallHeaders,
311        'install': InstallCommand,
312    },
313    # Supported Python versions
314    python_requires='>=3.7',
315    # PyPI package information.
316    classifiers=sorted([
317        'Development Status :: 5 - Production/Stable',
318        # TODO(angerson) Add IFTTT when possible
319        'Environment :: GPU :: NVIDIA CUDA :: 11.2',
320        'Intended Audience :: Developers',
321        'Intended Audience :: Education',
322        'Intended Audience :: Science/Research',
323        'License :: OSI Approved :: Apache Software License',
324        'Programming Language :: Python :: 3',
325        'Programming Language :: Python :: 3.7',
326        'Programming Language :: Python :: 3.8',
327        'Programming Language :: Python :: 3.9',
328        'Programming Language :: Python :: 3.10',
329        'Programming Language :: Python :: 3 :: Only',
330        'Topic :: Scientific/Engineering',
331        'Topic :: Scientific/Engineering :: Mathematics',
332        'Topic :: Scientific/Engineering :: Artificial Intelligence',
333        'Topic :: Software Development',
334        'Topic :: Software Development :: Libraries',
335        'Topic :: Software Development :: Libraries :: Python Modules',
336    ]),
337    license='Apache 2.0',
338    keywords='tensorflow tensor machine learning',
339)
340