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[](https://badge.fury.io/py/tensorflow) 18[](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