blob: e2a6fde99ed217f9ae10cc3a3ed25f57446ce17a [file] [log] [blame]
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001# Copyright 2017 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"""configure script to get build parameters from user."""
16
17from __future__ import absolute_import
18from __future__ import division
19from __future__ import print_function
20
Shanqing Cai71445712018-03-12 19:33:52 -070021import argparse
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -070022import errno
23import os
24import platform
25import re
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -070026import subprocess
27import sys
28
Andrew Sellec9885ea2017-11-06 09:37:03 -080029# pylint: disable=g-import-not-at-top
Jonathan Hseu008910f2017-08-25 14:01:05 -070030try:
31 from shutil import which
32except ImportError:
33 from distutils.spawn import find_executable as which
Andrew Sellec9885ea2017-11-06 09:37:03 -080034# pylint: enable=g-import-not-at-top
Jonathan Hseu008910f2017-08-25 14:01:05 -070035
Gunhan Gulsoyc59db932018-12-28 16:32:01 -080036_DEFAULT_CUDA_VERSION = '10.0'
Dandelion Man?90e42f32017-12-15 18:15:07 -080037_DEFAULT_CUDNN_VERSION = '7'
Smit Hinsufe7d1d92018-07-14 13:16:58 -070038_DEFAULT_CUDA_COMPUTE_CAPABILITIES = '3.5,7.0'
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -070039_DEFAULT_CUDA_PATH = '/usr/local/cuda'
40_DEFAULT_CUDA_PATH_LINUX = '/opt/cuda'
41_DEFAULT_CUDA_PATH_WIN = ('C:/Program Files/NVIDIA GPU Computing '
42 'Toolkit/CUDA/v%s' % _DEFAULT_CUDA_VERSION)
43_TF_OPENCL_VERSION = '1.2'
44_DEFAULT_COMPUTECPP_TOOLKIT_PATH = '/usr/local/computecpp'
Yifei Fengb1d8c592017-11-22 13:42:21 -080045_DEFAULT_TRISYCL_INCLUDE_DIR = '/usr/local/triSYCL/include'
A. Unique TensorFlower82820ef2018-11-12 13:22:13 -080046_SUPPORTED_ANDROID_NDK_VERSIONS = [10, 11, 12, 13, 14, 15, 16, 17, 18]
Austin Anderson6afface2017-12-05 11:59:17 -080047
48_DEFAULT_PROMPT_ASK_ATTEMPTS = 10
49
Shanqing Cai71445712018-03-12 19:33:52 -070050_TF_BAZELRC_FILENAME = '.tf_configure.bazelrc'
A. Unique TensorFlower7c5eb352018-10-01 07:15:23 -070051_TF_WORKSPACE_ROOT = ''
52_TF_BAZELRC = ''
Shanqing Cai71445712018-03-12 19:33:52 -070053
Jason Furmanek7c234152018-09-26 04:44:12 +000054NCCL_LIB_PATHS = [
TensorFlower Gardenerea5c5292018-10-01 17:28:26 -070055 'lib64/', 'lib/powerpc64le-linux-gnu/', 'lib/x86_64-linux-gnu/', ''
Jason Furmanek7c234152018-09-26 04:44:12 +000056]
Austin Anderson6afface2017-12-05 11:59:17 -080057
A. Unique TensorFlower93e70732019-02-14 16:45:32 -080058# List of files to be configured for using Bazel on Apple platforms.
59APPLE_BAZEL_FILES = [
60 'tensorflow/lite/experimental/objc/BUILD',
61 'tensorflow/lite/experimental/swift/BUILD'
62]
63
Gunhan Gulsoyffa90fc2018-09-26 01:38:55 -070064if platform.machine() == 'ppc64le':
65 _DEFAULT_TENSORRT_PATH_LINUX = '/usr/lib/powerpc64le-linux-gnu/'
66else:
67 _DEFAULT_TENSORRT_PATH_LINUX = '/usr/lib/%s-linux-gnu' % platform.machine()
68
Austin Anderson6afface2017-12-05 11:59:17 -080069
70class UserInputError(Exception):
71 pass
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -070072
73
74def is_windows():
75 return platform.system() == 'Windows'
76
77
78def is_linux():
79 return platform.system() == 'Linux'
80
81
82def is_macos():
83 return platform.system() == 'Darwin'
84
85
86def is_ppc64le():
87 return platform.machine() == 'ppc64le'
88
89
Jonathan Hseu008910f2017-08-25 14:01:05 -070090def is_cygwin():
91 return platform.system().startswith('CYGWIN_NT')
92
93
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -070094def get_input(question):
95 try:
96 try:
97 answer = raw_input(question)
98 except NameError:
99 answer = input(question) # pylint: disable=bad-builtin
100 except EOFError:
101 answer = ''
102 return answer
103
104
105def symlink_force(target, link_name):
106 """Force symlink, equivalent of 'ln -sf'.
107
108 Args:
109 target: items to link to.
110 link_name: name of the link.
111 """
112 try:
113 os.symlink(target, link_name)
114 except OSError as e:
115 if e.errno == errno.EEXIST:
116 os.remove(link_name)
117 os.symlink(target, link_name)
118 else:
119 raise e
120
121
122def sed_in_place(filename, old, new):
123 """Replace old string with new string in file.
124
125 Args:
126 filename: string for filename.
127 old: string to replace.
128 new: new string to replace to.
129 """
130 with open(filename, 'r') as f:
131 filedata = f.read()
132 newdata = filedata.replace(old, new)
133 with open(filename, 'w') as f:
134 f.write(newdata)
135
136
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700137def write_to_bazelrc(line):
138 with open(_TF_BAZELRC, 'a') as f:
139 f.write(line + '\n')
140
141
142def write_action_env_to_bazelrc(var_name, var):
143 write_to_bazelrc('build --action_env %s="%s"' % (var_name, str(var)))
144
145
Jonathan Hseu008910f2017-08-25 14:01:05 -0700146def run_shell(cmd, allow_non_zero=False):
147 if allow_non_zero:
148 try:
149 output = subprocess.check_output(cmd)
150 except subprocess.CalledProcessError as e:
151 output = e.output
152 else:
153 output = subprocess.check_output(cmd)
154 return output.decode('UTF-8').strip()
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700155
156
157def cygpath(path):
158 """Convert path from posix to windows."""
Martin Wicked57572e2017-09-02 19:21:45 -0700159 return os.path.abspath(path).replace('\\', '/')
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700160
161
Andrew Harp6e3e7d12017-08-21 12:10:44 -0700162def get_python_path(environ_cp, python_bin_path):
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700163 """Get the python site package paths."""
164 python_paths = []
165 if environ_cp.get('PYTHONPATH'):
166 python_paths = environ_cp.get('PYTHONPATH').split(':')
167 try:
Gunhan Gulsoyffa90fc2018-09-26 01:38:55 -0700168 library_paths = run_shell([
169 python_bin_path, '-c',
170 'import site; print("\\n".join(site.getsitepackages()))'
171 ]).split('\n')
Andrew Harp6e3e7d12017-08-21 12:10:44 -0700172 except subprocess.CalledProcessError:
Gunhan Gulsoyffa90fc2018-09-26 01:38:55 -0700173 library_paths = [
174 run_shell([
175 python_bin_path, '-c',
176 'from distutils.sysconfig import get_python_lib;'
177 'print(get_python_lib())'
178 ])
179 ]
Andrew Harp6e3e7d12017-08-21 12:10:44 -0700180
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700181 all_paths = set(python_paths + library_paths)
182
183 paths = []
184 for path in all_paths:
185 if os.path.isdir(path):
186 paths.append(path)
187 return paths
188
189
Andrew Harp6e3e7d12017-08-21 12:10:44 -0700190def get_python_major_version(python_bin_path):
191 """Get the python major version."""
Jonathan Hseu008910f2017-08-25 14:01:05 -0700192 return run_shell([python_bin_path, '-c', 'import sys; print(sys.version[0])'])
Andrew Harp6e3e7d12017-08-21 12:10:44 -0700193
194
Gunhan Gulsoyed89a2b2017-09-19 18:36:26 -0700195def setup_python(environ_cp):
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700196 """Setup python related env variables."""
197 # Get PYTHON_BIN_PATH, default is the current running python.
198 default_python_bin_path = sys.executable
199 ask_python_bin_path = ('Please specify the location of python. [Default is '
200 '%s]: ') % default_python_bin_path
201 while True:
202 python_bin_path = get_from_env_or_user_or_default(
203 environ_cp, 'PYTHON_BIN_PATH', ask_python_bin_path,
204 default_python_bin_path)
205 # Check if the path is valid
Gunhan Gulsoyffa90fc2018-09-26 01:38:55 -0700206 if os.path.isfile(python_bin_path) and os.access(python_bin_path, os.X_OK):
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700207 break
208 elif not os.path.exists(python_bin_path):
209 print('Invalid python path: %s cannot be found.' % python_bin_path)
210 else:
211 print('%s is not executable. Is it the python binary?' % python_bin_path)
212 environ_cp['PYTHON_BIN_PATH'] = ''
213
Andrew Harp6e3e7d12017-08-21 12:10:44 -0700214 # Convert python path to Windows style before checking lib and version
Martin Wicked57572e2017-09-02 19:21:45 -0700215 if is_windows() or is_cygwin():
Andrew Harp6e3e7d12017-08-21 12:10:44 -0700216 python_bin_path = cygpath(python_bin_path)
217
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700218 # Get PYTHON_LIB_PATH
219 python_lib_path = environ_cp.get('PYTHON_LIB_PATH')
220 if not python_lib_path:
Andrew Harp6e3e7d12017-08-21 12:10:44 -0700221 python_lib_paths = get_python_path(environ_cp, python_bin_path)
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700222 if environ_cp.get('USE_DEFAULT_PYTHON_LIB_PATH') == '1':
Vijay Vasudevana1fba7f2017-07-28 10:58:56 -0700223 python_lib_path = python_lib_paths[0]
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700224 else:
Jonathan Hseu008910f2017-08-25 14:01:05 -0700225 print('Found possible Python library paths:\n %s' %
226 '\n '.join(python_lib_paths))
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700227 default_python_lib_path = python_lib_paths[0]
228 python_lib_path = get_input(
Jonathan Hseu008910f2017-08-25 14:01:05 -0700229 'Please input the desired Python library path to use. '
230 'Default is [%s]\n' % python_lib_paths[0])
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700231 if not python_lib_path:
232 python_lib_path = default_python_lib_path
Vijay Vasudevana1fba7f2017-07-28 10:58:56 -0700233 environ_cp['PYTHON_LIB_PATH'] = python_lib_path
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700234
TensorFlower Gardener61a87202018-10-01 12:25:39 -0700235 _ = get_python_major_version(python_bin_path)
Andrew Harp6e3e7d12017-08-21 12:10:44 -0700236
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700237 # Convert python path to Windows style before writing into bazel.rc
Martin Wicked57572e2017-09-02 19:21:45 -0700238 if is_windows() or is_cygwin():
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700239 python_lib_path = cygpath(python_lib_path)
240
241 # Set-up env variables used by python_configure.bzl
242 write_action_env_to_bazelrc('PYTHON_BIN_PATH', python_bin_path)
243 write_action_env_to_bazelrc('PYTHON_LIB_PATH', python_lib_path)
Gunhan Gulsoyed89a2b2017-09-19 18:36:26 -0700244 write_to_bazelrc('build --python_path=\"%s"' % python_bin_path)
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700245 environ_cp['PYTHON_BIN_PATH'] = python_bin_path
246
William D. Ironsdcc76a52018-11-20 10:35:18 -0600247 # If choosen python_lib_path is from a path specified in the PYTHONPATH
248 # variable, need to tell bazel to include PYTHONPATH
249 if environ_cp.get('PYTHONPATH'):
250 python_paths = environ_cp.get('PYTHONPATH').split(':')
251 if python_lib_path in python_paths:
TensorFlower Gardener968cd182018-11-28 11:33:16 -0800252 write_action_env_to_bazelrc('PYTHONPATH', environ_cp.get('PYTHONPATH'))
William D. Ironsdcc76a52018-11-20 10:35:18 -0600253
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700254 # Write tools/python_bin_path.sh
Gunhan Gulsoyffa90fc2018-09-26 01:38:55 -0700255 with open(
256 os.path.join(_TF_WORKSPACE_ROOT, 'tools', 'python_bin_path.sh'),
257 'w') as f:
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700258 f.write('export PYTHON_BIN_PATH="%s"' % python_bin_path)
259
260
A. Unique TensorFlower7c5eb352018-10-01 07:15:23 -0700261def reset_tf_configure_bazelrc():
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700262 """Reset file that contains customized config settings."""
263 open(_TF_BAZELRC, 'w').close()
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700264
TensorFlower Gardenerabb763b2019-02-06 16:23:03 -0800265
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700266def cleanup_makefile():
267 """Delete any leftover BUILD files from the Makefile build.
268
269 These files could interfere with Bazel parsing.
270 """
Gunhan Gulsoyffa90fc2018-09-26 01:38:55 -0700271 makefile_download_dir = os.path.join(_TF_WORKSPACE_ROOT, 'tensorflow',
272 'contrib', 'makefile', 'downloads')
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700273 if os.path.isdir(makefile_download_dir):
274 for root, _, filenames in os.walk(makefile_download_dir):
275 for f in filenames:
276 if f.endswith('BUILD'):
277 os.remove(os.path.join(root, f))
278
279
280def get_var(environ_cp,
281 var_name,
282 query_item,
283 enabled_by_default,
284 question=None,
285 yes_reply=None,
286 no_reply=None):
287 """Get boolean input from user.
288
289 If var_name is not set in env, ask user to enable query_item or not. If the
290 response is empty, use the default.
291
292 Args:
293 environ_cp: copy of the os.environ.
294 var_name: string for name of environment variable, e.g. "TF_NEED_HDFS".
295 query_item: string for feature related to the variable, e.g. "Hadoop File
296 System".
297 enabled_by_default: boolean for default behavior.
298 question: optional string for how to ask for user input.
Michael Cased90054e2018-02-07 14:36:00 -0800299 yes_reply: optional string for reply when feature is enabled.
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700300 no_reply: optional string for reply when feature is disabled.
301
302 Returns:
303 boolean value of the variable.
Frank Chenc4ef9272018-01-10 11:36:52 -0800304
305 Raises:
306 UserInputError: if an environment variable is set, but it cannot be
307 interpreted as a boolean indicator, assume that the user has made a
308 scripting error, and will continue to provide invalid input.
309 Raise the error to avoid infinitely looping.
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700310 """
311 if not question:
312 question = 'Do you wish to build TensorFlow with %s support?' % query_item
313 if not yes_reply:
314 yes_reply = '%s support will be enabled for TensorFlow.' % query_item
315 if not no_reply:
316 no_reply = 'No %s' % yes_reply
317
318 yes_reply += '\n'
319 no_reply += '\n'
320
321 if enabled_by_default:
322 question += ' [Y/n]: '
323 else:
324 question += ' [y/N]: '
325
326 var = environ_cp.get(var_name)
Frank Chenc4ef9272018-01-10 11:36:52 -0800327 if var is not None:
328 var_content = var.strip().lower()
329 true_strings = ('1', 't', 'true', 'y', 'yes')
330 false_strings = ('0', 'f', 'false', 'n', 'no')
331 if var_content in true_strings:
332 var = True
333 elif var_content in false_strings:
334 var = False
335 else:
336 raise UserInputError(
337 'Environment variable %s must be set as a boolean indicator.\n'
338 'The following are accepted as TRUE : %s.\n'
339 'The following are accepted as FALSE: %s.\n'
Gunhan Gulsoyffa90fc2018-09-26 01:38:55 -0700340 'Current value is %s.' % (var_name, ', '.join(true_strings),
341 ', '.join(false_strings), var))
Frank Chenc4ef9272018-01-10 11:36:52 -0800342
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700343 while var is None:
344 user_input_origin = get_input(question)
345 user_input = user_input_origin.strip().lower()
346 if user_input == 'y':
347 print(yes_reply)
348 var = True
349 elif user_input == 'n':
350 print(no_reply)
351 var = False
352 elif not user_input:
353 if enabled_by_default:
354 print(yes_reply)
355 var = True
356 else:
357 print(no_reply)
358 var = False
359 else:
360 print('Invalid selection: %s' % user_input_origin)
361 return var
362
363
Gunhan Gulsoyffa90fc2018-09-26 01:38:55 -0700364def set_build_var(environ_cp,
365 var_name,
366 query_item,
367 option_name,
368 enabled_by_default,
369 bazel_config_name=None):
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700370 """Set if query_item will be enabled for the build.
371
372 Ask user if query_item will be enabled. Default is used if no input is given.
373 Set subprocess environment variable and write to .bazelrc if enabled.
374
375 Args:
376 environ_cp: copy of the os.environ.
377 var_name: string for name of environment variable, e.g. "TF_NEED_HDFS".
378 query_item: string for feature related to the variable, e.g. "Hadoop File
379 System".
380 option_name: string for option to define in .bazelrc.
381 enabled_by_default: boolean for default behavior.
Michael Case98850a52017-09-14 13:35:57 -0700382 bazel_config_name: Name for Bazel --config argument to enable build feature.
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700383 """
384
385 var = str(int(get_var(environ_cp, var_name, query_item, enabled_by_default)))
386 environ_cp[var_name] = var
387 if var == '1':
Yifei Fengec451f52018-10-05 12:53:50 -0700388 write_to_bazelrc(
389 'build:%s --define %s=true' % (bazel_config_name, option_name))
390 write_to_bazelrc('build --config=%s' % bazel_config_name)
Michael Case98850a52017-09-14 13:35:57 -0700391 elif bazel_config_name is not None:
392 # TODO(mikecase): Migrate all users of configure.py to use --config Bazel
393 # options and not to set build configs through environment variables.
Gunhan Gulsoyffa90fc2018-09-26 01:38:55 -0700394 write_to_bazelrc(
395 'build:%s --define %s=true' % (bazel_config_name, option_name))
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700396
397
398def set_action_env_var(environ_cp,
399 var_name,
400 query_item,
401 enabled_by_default,
402 question=None,
403 yes_reply=None,
404 no_reply=None):
405 """Set boolean action_env variable.
406
407 Ask user if query_item will be enabled. Default is used if no input is given.
408 Set environment variable and write to .bazelrc.
409
410 Args:
411 environ_cp: copy of the os.environ.
412 var_name: string for name of environment variable, e.g. "TF_NEED_HDFS".
413 query_item: string for feature related to the variable, e.g. "Hadoop File
414 System".
415 enabled_by_default: boolean for default behavior.
416 question: optional string for how to ask for user input.
Michael Cased90054e2018-02-07 14:36:00 -0800417 yes_reply: optional string for reply when feature is enabled.
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700418 no_reply: optional string for reply when feature is disabled.
419 """
420 var = int(
421 get_var(environ_cp, var_name, query_item, enabled_by_default, question,
422 yes_reply, no_reply))
423
424 write_action_env_to_bazelrc(var_name, var)
425 environ_cp[var_name] = str(var)
426
427
A. Unique TensorFlower6252d292017-08-04 00:52:34 -0700428def convert_version_to_int(version):
429 """Convert a version number to a integer that can be used to compare.
430
A. Unique TensorFlower28ce1d12017-08-15 12:08:29 -0700431 Version strings of the form X.YZ and X.Y.Z-xxxxx are supported. The
432 'xxxxx' part, for instance 'homebrew' on OS/X, is ignored.
433
A. Unique TensorFlower6252d292017-08-04 00:52:34 -0700434 Args:
A. Unique TensorFlower28ce1d12017-08-15 12:08:29 -0700435 version: a version to be converted
A. Unique TensorFlower6252d292017-08-04 00:52:34 -0700436
437 Returns:
438 An integer if converted successfully, otherwise return None.
439 """
A. Unique TensorFlower28ce1d12017-08-15 12:08:29 -0700440 version = version.split('-')[0]
A. Unique TensorFlower6252d292017-08-04 00:52:34 -0700441 version_segments = version.split('.')
442 for seg in version_segments:
443 if not seg.isdigit():
444 return None
445
446 version_str = ''.join(['%03d' % int(seg) for seg in version_segments])
447 return int(version_str)
448
449
Mihai Maruseace7a123f2018-11-30 13:33:25 -0800450def check_bazel_version(min_version, max_version):
451 """Check installed bazel version is between min_version and max_version.
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700452
453 Args:
454 min_version: string for minimum bazel version.
Mihai Maruseace7a123f2018-11-30 13:33:25 -0800455 max_version: string for maximum bazel version.
A. Unique TensorFlower6252d292017-08-04 00:52:34 -0700456
457 Returns:
458 The bazel version detected.
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700459 """
Jonathan Hseu008910f2017-08-25 14:01:05 -0700460 if which('bazel') is None:
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700461 print('Cannot find bazel. Please install bazel.')
462 sys.exit(0)
Gunhan Gulsoyffa90fc2018-09-26 01:38:55 -0700463 curr_version = run_shell(
464 ['bazel', '--batch', '--bazelrc=/dev/null', 'version'])
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700465
466 for line in curr_version.split('\n'):
467 if 'Build label: ' in line:
468 curr_version = line.split('Build label: ')[1]
469 break
470
A. Unique TensorFlower6252d292017-08-04 00:52:34 -0700471 min_version_int = convert_version_to_int(min_version)
472 curr_version_int = convert_version_to_int(curr_version)
Mihai Maruseace7a123f2018-11-30 13:33:25 -0800473 max_version_int = convert_version_to_int(max_version)
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700474
475 # Check if current bazel version can be detected properly.
A. Unique TensorFlower6252d292017-08-04 00:52:34 -0700476 if not curr_version_int:
477 print('WARNING: current bazel installation is not a release version.')
478 print('Make sure you are running at least bazel %s' % min_version)
479 return curr_version
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700480
Michael Cased94271a2017-08-22 17:26:52 -0700481 print('You have bazel %s installed.' % curr_version)
A. Unique TensorFlower28ce1d12017-08-15 12:08:29 -0700482
A. Unique TensorFlower6252d292017-08-04 00:52:34 -0700483 if curr_version_int < min_version_int:
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700484 print('Please upgrade your bazel installation to version %s or higher to '
485 'build TensorFlow!' % min_version)
Jason Zamanb41761c2018-10-14 11:28:53 +0800486 sys.exit(1)
TensorFlower Gardener78c246b2018-12-13 12:37:42 -0800487 if (curr_version_int > max_version_int and
488 'TF_IGNORE_MAX_BAZEL_VERSION' not in os.environ):
Mihai Maruseace7a123f2018-11-30 13:33:25 -0800489 print('Please downgrade your bazel installation to version %s or lower to '
Mihai Maruseace0963c42018-12-20 14:27:40 -0800490 'build TensorFlow! To downgrade: download the installer for the old '
491 'version (from https://github.com/bazelbuild/bazel/releases) then '
492 'run the installer.' % max_version)
Jason Zamanb41761c2018-10-14 11:28:53 +0800493 sys.exit(1)
A. Unique TensorFlower6252d292017-08-04 00:52:34 -0700494 return curr_version
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700495
496
497def set_cc_opt_flags(environ_cp):
498 """Set up architecture-dependent optimization flags.
499
500 Also append CC optimization flags to bazel.rc..
501
502 Args:
503 environ_cp: copy of the os.environ.
504 """
505 if is_ppc64le():
506 # gcc on ppc64le does not support -march, use mcpu instead
507 default_cc_opt_flags = '-mcpu=native'
A. Unique TensorFlower1bba94a2018-04-04 15:45:20 -0700508 elif is_windows():
509 default_cc_opt_flags = '/arch:AVX'
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700510 else:
Justin Lebar9ef04f52018-10-10 18:52:45 -0700511 default_cc_opt_flags = '-march=native -Wno-sign-compare'
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700512 question = ('Please specify optimization flags to use during compilation when'
513 ' bazel option "--config=opt" is specified [Default is %s]: '
514 ) % default_cc_opt_flags
515 cc_opt_flags = get_from_env_or_user_or_default(environ_cp, 'CC_OPT_FLAGS',
516 question, default_cc_opt_flags)
517 for opt in cc_opt_flags.split():
Michael Case00177422017-11-10 13:14:03 -0800518 write_to_bazelrc('build:opt --copt=%s' % opt)
519 # It should be safe on the same build host.
A. Unique TensorFlower1bba94a2018-04-04 15:45:20 -0700520 if not is_ppc64le() and not is_windows():
Shanqing Cai71445712018-03-12 19:33:52 -0700521 write_to_bazelrc('build:opt --host_copt=-march=native')
Michael Casebb3355d2017-11-09 08:46:31 -0800522 write_to_bazelrc('build:opt --define with_default_optimizations=true')
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700523
Gunhan Gulsoyffa90fc2018-09-26 01:38:55 -0700524
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700525def set_tf_cuda_clang(environ_cp):
526 """set TF_CUDA_CLANG action_env.
527
528 Args:
529 environ_cp: copy of the os.environ.
530 """
531 question = 'Do you want to use clang as CUDA compiler?'
532 yes_reply = 'Clang will be used as CUDA compiler.'
533 no_reply = 'nvcc will be used as CUDA compiler.'
534 set_action_env_var(
535 environ_cp,
536 'TF_CUDA_CLANG',
537 None,
538 False,
539 question=question,
540 yes_reply=yes_reply,
541 no_reply=no_reply)
542
543
A. Unique TensorFlowerfd29e952017-12-22 03:07:51 -0800544def set_tf_download_clang(environ_cp):
545 """Set TF_DOWNLOAD_CLANG action_env."""
Ilya Biryukov9e651e42018-03-22 05:33:42 -0700546 question = 'Do you wish to download a fresh release of clang? (Experimental)'
A. Unique TensorFlowerfd29e952017-12-22 03:07:51 -0800547 yes_reply = 'Clang will be downloaded and used to compile tensorflow.'
548 no_reply = 'Clang will not be downloaded.'
549 set_action_env_var(
550 environ_cp,
551 'TF_DOWNLOAD_CLANG',
552 None,
553 False,
554 question=question,
555 yes_reply=yes_reply,
556 no_reply=no_reply)
557
558
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700559def get_from_env_or_user_or_default(environ_cp, var_name, ask_for_var,
560 var_default):
561 """Get var_name either from env, or user or default.
562
563 If var_name has been set as environment variable, use the preset value, else
564 ask for user input. If no input is provided, the default is used.
565
566 Args:
567 environ_cp: copy of the os.environ.
568 var_name: string for name of environment variable, e.g. "TF_NEED_HDFS".
569 ask_for_var: string for how to ask for user input.
570 var_default: default value string.
571
572 Returns:
573 string value for var_name
574 """
575 var = environ_cp.get(var_name)
576 if not var:
577 var = get_input(ask_for_var)
Michael Cased94271a2017-08-22 17:26:52 -0700578 print('\n')
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700579 if not var:
580 var = var_default
581 return var
582
583
584def set_clang_cuda_compiler_path(environ_cp):
585 """Set CLANG_CUDA_COMPILER_PATH."""
Jonathan Hseu008910f2017-08-25 14:01:05 -0700586 default_clang_path = which('clang') or ''
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700587 ask_clang_path = ('Please specify which clang should be used as device and '
588 'host compiler. [Default is %s]: ') % default_clang_path
589
590 while True:
591 clang_cuda_compiler_path = get_from_env_or_user_or_default(
592 environ_cp, 'CLANG_CUDA_COMPILER_PATH', ask_clang_path,
593 default_clang_path)
594 if os.path.exists(clang_cuda_compiler_path):
595 break
596
597 # Reset and retry
598 print('Invalid clang path: %s cannot be found.' % clang_cuda_compiler_path)
599 environ_cp['CLANG_CUDA_COMPILER_PATH'] = ''
600
601 # Set CLANG_CUDA_COMPILER_PATH
602 environ_cp['CLANG_CUDA_COMPILER_PATH'] = clang_cuda_compiler_path
603 write_action_env_to_bazelrc('CLANG_CUDA_COMPILER_PATH',
604 clang_cuda_compiler_path)
605
606
Gunhan Gulsoyffa90fc2018-09-26 01:38:55 -0700607def prompt_loop_or_load_from_env(environ_cp,
608 var_name,
609 var_default,
610 ask_for_var,
611 check_success,
612 error_msg,
613 suppress_default_error=False,
614 n_ask_attempts=_DEFAULT_PROMPT_ASK_ATTEMPTS):
Austin Anderson6afface2017-12-05 11:59:17 -0800615 """Loop over user prompts for an ENV param until receiving a valid response.
616
617 For the env param var_name, read from the environment or verify user input
618 until receiving valid input. When done, set var_name in the environ_cp to its
619 new value.
620
621 Args:
622 environ_cp: (Dict) copy of the os.environ.
623 var_name: (String) string for name of environment variable, e.g. "TF_MYVAR".
624 var_default: (String) default value string.
625 ask_for_var: (String) string for how to ask for user input.
626 check_success: (Function) function that takes one argument and returns a
627 boolean. Should return True if the value provided is considered valid. May
628 contain a complex error message if error_msg does not provide enough
629 information. In that case, set suppress_default_error to True.
630 error_msg: (String) String with one and only one '%s'. Formatted with each
631 invalid response upon check_success(input) failure.
632 suppress_default_error: (Bool) Suppress the above error message in favor of
633 one from the check_success function.
634 n_ask_attempts: (Integer) Number of times to query for valid input before
635 raising an error and quitting.
636
637 Returns:
638 [String] The value of var_name after querying for input.
639
640 Raises:
641 UserInputError: if a query has been attempted n_ask_attempts times without
Frank Chenc4ef9272018-01-10 11:36:52 -0800642 success, assume that the user has made a scripting error, and will
643 continue to provide invalid input. Raise the error to avoid infinitely
644 looping.
Austin Anderson6afface2017-12-05 11:59:17 -0800645 """
646 default = environ_cp.get(var_name) or var_default
647 full_query = '%s [Default is %s]: ' % (
648 ask_for_var,
649 default,
650 )
651
652 for _ in range(n_ask_attempts):
Gunhan Gulsoyffa90fc2018-09-26 01:38:55 -0700653 val = get_from_env_or_user_or_default(environ_cp, var_name, full_query,
Austin Anderson6afface2017-12-05 11:59:17 -0800654 default)
655 if check_success(val):
656 break
657 if not suppress_default_error:
658 print(error_msg % val)
659 environ_cp[var_name] = ''
660 else:
Gunhan Gulsoyffa90fc2018-09-26 01:38:55 -0700661 raise UserInputError(
662 'Invalid %s setting was provided %d times in a row. '
663 'Assuming to be a scripting mistake.' % (var_name, n_ask_attempts))
Austin Anderson6afface2017-12-05 11:59:17 -0800664
665 environ_cp[var_name] = val
666 return val
667
668
669def create_android_ndk_rule(environ_cp):
670 """Set ANDROID_NDK_HOME and write Android NDK WORKSPACE rule."""
671 if is_windows() or is_cygwin():
Gunhan Gulsoyffa90fc2018-09-26 01:38:55 -0700672 default_ndk_path = cygpath(
673 '%s/Android/Sdk/ndk-bundle' % environ_cp['APPDATA'])
Austin Anderson6afface2017-12-05 11:59:17 -0800674 elif is_macos():
675 default_ndk_path = '%s/library/Android/Sdk/ndk-bundle' % environ_cp['HOME']
676 else:
677 default_ndk_path = '%s/Android/Sdk/ndk-bundle' % environ_cp['HOME']
678
679 def valid_ndk_path(path):
680 return (os.path.exists(path) and
681 os.path.exists(os.path.join(path, 'source.properties')))
682
683 android_ndk_home_path = prompt_loop_or_load_from_env(
684 environ_cp,
685 var_name='ANDROID_NDK_HOME',
686 var_default=default_ndk_path,
687 ask_for_var='Please specify the home path of the Android NDK to use.',
688 check_success=valid_ndk_path,
689 error_msg=('The path %s or its child file "source.properties" '
Gunhan Gulsoyffa90fc2018-09-26 01:38:55 -0700690 'does not exist.'))
Michael Case51053502018-06-05 17:47:19 -0700691 write_action_env_to_bazelrc('ANDROID_NDK_HOME', android_ndk_home_path)
692 write_action_env_to_bazelrc('ANDROID_NDK_API_LEVEL',
693 check_ndk_level(android_ndk_home_path))
Austin Anderson6afface2017-12-05 11:59:17 -0800694
695
696def create_android_sdk_rule(environ_cp):
697 """Set Android variables and write Android SDK WORKSPACE rule."""
698 if is_windows() or is_cygwin():
699 default_sdk_path = cygpath('%s/Android/Sdk' % environ_cp['APPDATA'])
700 elif is_macos():
Shashi Shekharc0ff0cc2018-07-17 09:00:24 -0700701 default_sdk_path = '%s/library/Android/Sdk' % environ_cp['HOME']
Austin Anderson6afface2017-12-05 11:59:17 -0800702 else:
703 default_sdk_path = '%s/Android/Sdk' % environ_cp['HOME']
704
705 def valid_sdk_path(path):
706 return (os.path.exists(path) and
707 os.path.exists(os.path.join(path, 'platforms')) and
708 os.path.exists(os.path.join(path, 'build-tools')))
709
710 android_sdk_home_path = prompt_loop_or_load_from_env(
711 environ_cp,
712 var_name='ANDROID_SDK_HOME',
713 var_default=default_sdk_path,
714 ask_for_var='Please specify the home path of the Android SDK to use.',
715 check_success=valid_sdk_path,
716 error_msg=('Either %s does not exist, or it does not contain the '
717 'subdirectories "platforms" and "build-tools".'))
718
719 platforms = os.path.join(android_sdk_home_path, 'platforms')
720 api_levels = sorted(os.listdir(platforms))
721 api_levels = [x.replace('android-', '') for x in api_levels]
722
723 def valid_api_level(api_level):
Gunhan Gulsoyffa90fc2018-09-26 01:38:55 -0700724 return os.path.exists(
725 os.path.join(android_sdk_home_path, 'platforms',
726 'android-' + api_level))
Austin Anderson6afface2017-12-05 11:59:17 -0800727
728 android_api_level = prompt_loop_or_load_from_env(
729 environ_cp,
730 var_name='ANDROID_API_LEVEL',
731 var_default=api_levels[-1],
732 ask_for_var=('Please specify the Android SDK API level to use. '
733 '[Available levels: %s]') % api_levels,
734 check_success=valid_api_level,
735 error_msg='Android-%s is not present in the SDK path.')
736
737 build_tools = os.path.join(android_sdk_home_path, 'build-tools')
738 versions = sorted(os.listdir(build_tools))
739
740 def valid_build_tools(version):
Gunhan Gulsoyffa90fc2018-09-26 01:38:55 -0700741 return os.path.exists(
742 os.path.join(android_sdk_home_path, 'build-tools', version))
Austin Anderson6afface2017-12-05 11:59:17 -0800743
744 android_build_tools_version = prompt_loop_or_load_from_env(
745 environ_cp,
746 var_name='ANDROID_BUILD_TOOLS_VERSION',
747 var_default=versions[-1],
748 ask_for_var=('Please specify an Android build tools version to use. '
749 '[Available versions: %s]') % versions,
750 check_success=valid_build_tools,
751 error_msg=('The selected SDK does not have build-tools version %s '
752 'available.'))
753
Michael Case51053502018-06-05 17:47:19 -0700754 write_action_env_to_bazelrc('ANDROID_BUILD_TOOLS_VERSION',
755 android_build_tools_version)
Gunhan Gulsoyffa90fc2018-09-26 01:38:55 -0700756 write_action_env_to_bazelrc('ANDROID_SDK_API_LEVEL', android_api_level)
757 write_action_env_to_bazelrc('ANDROID_SDK_HOME', android_sdk_home_path)
Austin Anderson6afface2017-12-05 11:59:17 -0800758
759
760def check_ndk_level(android_ndk_home_path):
761 """Check the revision number of an Android NDK path."""
762 properties_path = '%s/source.properties' % android_ndk_home_path
763 if is_windows() or is_cygwin():
764 properties_path = cygpath(properties_path)
765 with open(properties_path, 'r') as f:
766 filedata = f.read()
767
768 revision = re.search(r'Pkg.Revision = (\d+)', filedata)
769 if revision:
Michael Case51053502018-06-05 17:47:19 -0700770 ndk_api_level = revision.group(1)
771 else:
772 raise Exception('Unable to parse NDK revision.')
773 if int(ndk_api_level) not in _SUPPORTED_ANDROID_NDK_VERSIONS:
774 print('WARNING: The API level of the NDK in %s is %s, which is not '
775 'supported by Bazel (officially supported versions: %s). Please use '
776 'another version. Compiling Android targets may result in confusing '
777 'errors.\n' % (android_ndk_home_path, ndk_api_level,
778 _SUPPORTED_ANDROID_NDK_VERSIONS))
779 return ndk_api_level
Austin Anderson6afface2017-12-05 11:59:17 -0800780
781
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700782def set_gcc_host_compiler_path(environ_cp):
783 """Set GCC_HOST_COMPILER_PATH."""
Jonathan Hseu008910f2017-08-25 14:01:05 -0700784 default_gcc_host_compiler_path = which('gcc') or ''
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700785 cuda_bin_symlink = '%s/bin/gcc' % environ_cp.get('CUDA_TOOLKIT_PATH')
786
787 if os.path.islink(cuda_bin_symlink):
788 # os.readlink is only available in linux
Jonathan Hseu008910f2017-08-25 14:01:05 -0700789 default_gcc_host_compiler_path = os.path.realpath(cuda_bin_symlink)
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700790
Austin Anderson6afface2017-12-05 11:59:17 -0800791 gcc_host_compiler_path = prompt_loop_or_load_from_env(
792 environ_cp,
793 var_name='GCC_HOST_COMPILER_PATH',
794 var_default=default_gcc_host_compiler_path,
TensorFlower Gardenerabb763b2019-02-06 16:23:03 -0800795 ask_for_var='Please specify which gcc should be used by nvcc as the host compiler.',
Austin Anderson6afface2017-12-05 11:59:17 -0800796 check_success=os.path.exists,
797 error_msg='Invalid gcc path. %s cannot be found.',
798 )
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700799
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700800 write_action_env_to_bazelrc('GCC_HOST_COMPILER_PATH', gcc_host_compiler_path)
801
802
Ankur Taly0e6f39d2018-02-16 18:22:55 -0800803def reformat_version_sequence(version_str, sequence_count):
804 """Reformat the version string to have the given number of sequences.
805
806 For example:
807 Given (7, 2) -> 7.0
808 (7.0.1, 2) -> 7.0
809 (5, 1) -> 5
810 (5.0.3.2, 1) -> 5
811
812 Args:
813 version_str: String, the version string.
814 sequence_count: int, an integer.
Gunhan Gulsoyffa90fc2018-09-26 01:38:55 -0700815
Ankur Taly0e6f39d2018-02-16 18:22:55 -0800816 Returns:
817 string, reformatted version string.
818 """
819 v = version_str.split('.')
820 if len(v) < sequence_count:
821 v = v + (['0'] * (sequence_count - len(v)))
822
823 return '.'.join(v[:sequence_count])
824
825
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700826def set_tf_cuda_version(environ_cp):
827 """Set CUDA_TOOLKIT_PATH and TF_CUDA_VERSION."""
828 ask_cuda_version = (
A. Unique TensorFlowerb15500b2018-05-08 12:04:38 -0700829 'Please specify the CUDA SDK version you want to use. '
830 '[Leave empty to default to CUDA %s]: ') % _DEFAULT_CUDA_VERSION
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700831
Austin Andersonf9a88f82017-12-13 11:49:40 -0800832 for _ in range(_DEFAULT_PROMPT_ASK_ATTEMPTS):
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700833 # Configure the Cuda SDK version to use.
834 tf_cuda_version = get_from_env_or_user_or_default(
835 environ_cp, 'TF_CUDA_VERSION', ask_cuda_version, _DEFAULT_CUDA_VERSION)
Ankur Taly0e6f39d2018-02-16 18:22:55 -0800836 tf_cuda_version = reformat_version_sequence(str(tf_cuda_version), 2)
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700837
838 # Find out where the CUDA toolkit is installed
839 default_cuda_path = _DEFAULT_CUDA_PATH
Martin Wicked57572e2017-09-02 19:21:45 -0700840 if is_windows() or is_cygwin():
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700841 default_cuda_path = cygpath(
842 environ_cp.get('CUDA_PATH', _DEFAULT_CUDA_PATH_WIN))
843 elif is_linux():
844 # If the default doesn't exist, try an alternative default.
845 if (not os.path.exists(default_cuda_path)
846 ) and os.path.exists(_DEFAULT_CUDA_PATH_LINUX):
847 default_cuda_path = _DEFAULT_CUDA_PATH_LINUX
848 ask_cuda_path = ('Please specify the location where CUDA %s toolkit is'
849 ' installed. Refer to README.md for more details. '
850 '[Default is %s]: ') % (tf_cuda_version, default_cuda_path)
851 cuda_toolkit_path = get_from_env_or_user_or_default(
852 environ_cp, 'CUDA_TOOLKIT_PATH', ask_cuda_path, default_cuda_path)
A. Unique TensorFlower02f17fe2018-07-07 06:59:19 -0700853 if is_windows() or is_cygwin():
854 cuda_toolkit_path = cygpath(cuda_toolkit_path)
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700855
856 if is_windows():
Niall Moranb7d97e82018-08-09 00:29:49 +0100857 cuda_rt_lib_paths = ['lib/x64/cudart.lib']
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700858 elif is_linux():
Gunhan Gulsoyffa90fc2018-09-26 01:38:55 -0700859 cuda_rt_lib_paths = [
860 '%s/libcudart.so.%s' % (x, tf_cuda_version) for x in [
861 'lib64',
862 'lib/powerpc64le-linux-gnu',
863 'lib/x86_64-linux-gnu',
864 ]
865 ]
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700866 elif is_macos():
Niall Moranb7d97e82018-08-09 00:29:49 +0100867 cuda_rt_lib_paths = ['lib/libcudart.%s.dylib' % tf_cuda_version]
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700868
Gunhan Gulsoyffa90fc2018-09-26 01:38:55 -0700869 cuda_toolkit_paths_full = [
870 os.path.join(cuda_toolkit_path, x) for x in cuda_rt_lib_paths
871 ]
Sergei Lebedev95d7bbb2018-11-21 10:40:10 -0800872 if any(os.path.exists(x) for x in cuda_toolkit_paths_full):
Yifei Feng5198cb82018-08-17 13:53:06 -0700873 break
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700874
875 # Reset and retry
876 print('Invalid path to CUDA %s toolkit. %s cannot be found' %
hellcom9a13fc32018-09-12 10:58:24 +0300877 (tf_cuda_version, cuda_toolkit_paths_full))
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700878 environ_cp['TF_CUDA_VERSION'] = ''
879 environ_cp['CUDA_TOOLKIT_PATH'] = ''
880
Austin Andersonf9a88f82017-12-13 11:49:40 -0800881 else:
882 raise UserInputError('Invalid TF_CUDA_SETTING setting was provided %d '
883 'times in a row. Assuming to be a scripting mistake.' %
884 _DEFAULT_PROMPT_ASK_ATTEMPTS)
885
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700886 # Set CUDA_TOOLKIT_PATH and TF_CUDA_VERSION
887 environ_cp['CUDA_TOOLKIT_PATH'] = cuda_toolkit_path
888 write_action_env_to_bazelrc('CUDA_TOOLKIT_PATH', cuda_toolkit_path)
889 environ_cp['TF_CUDA_VERSION'] = tf_cuda_version
890 write_action_env_to_bazelrc('TF_CUDA_VERSION', tf_cuda_version)
891
892
Yifei Fengb1d8c592017-11-22 13:42:21 -0800893def set_tf_cudnn_version(environ_cp):
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700894 """Set CUDNN_INSTALL_PATH and TF_CUDNN_VERSION."""
895 ask_cudnn_version = (
Jonathan Hseu008910f2017-08-25 14:01:05 -0700896 'Please specify the cuDNN version you want to use. '
A. Unique TensorFlower44acd832018-10-01 13:42:40 -0700897 '[Leave empty to default to cuDNN %s]: ') % _DEFAULT_CUDNN_VERSION
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700898
Austin Andersonf9a88f82017-12-13 11:49:40 -0800899 for _ in range(_DEFAULT_PROMPT_ASK_ATTEMPTS):
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700900 tf_cudnn_version = get_from_env_or_user_or_default(
901 environ_cp, 'TF_CUDNN_VERSION', ask_cudnn_version,
902 _DEFAULT_CUDNN_VERSION)
Ankur Taly0e6f39d2018-02-16 18:22:55 -0800903 tf_cudnn_version = reformat_version_sequence(str(tf_cudnn_version), 1)
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700904
905 default_cudnn_path = environ_cp.get('CUDA_TOOLKIT_PATH')
906 ask_cudnn_path = (r'Please specify the location where cuDNN %s library is '
907 'installed. Refer to README.md for more details. [Default'
A. Unique TensorFlower1b212352018-07-19 13:48:50 -0700908 ' is %s]: ') % (tf_cudnn_version, default_cudnn_path)
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700909 cudnn_install_path = get_from_env_or_user_or_default(
910 environ_cp, 'CUDNN_INSTALL_PATH', ask_cudnn_path, default_cudnn_path)
911
912 # Result returned from "read" will be used unexpanded. That make "~"
913 # unusable. Going through one more level of expansion to handle that.
914 cudnn_install_path = os.path.realpath(
915 os.path.expanduser(cudnn_install_path))
Martin Wicked57572e2017-09-02 19:21:45 -0700916 if is_windows() or is_cygwin():
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700917 cudnn_install_path = cygpath(cudnn_install_path)
918
919 if is_windows():
920 cuda_dnn_lib_path = 'lib/x64/cudnn.lib'
921 cuda_dnn_lib_alt_path = 'lib/x64/cudnn.lib'
922 elif is_linux():
923 cuda_dnn_lib_path = 'lib64/libcudnn.so.%s' % tf_cudnn_version
924 cuda_dnn_lib_alt_path = 'libcudnn.so.%s' % tf_cudnn_version
925 elif is_macos():
926 cuda_dnn_lib_path = 'lib/libcudnn.%s.dylib' % tf_cudnn_version
927 cuda_dnn_lib_alt_path = 'libcudnn.%s.dylib' % tf_cudnn_version
928
929 cuda_dnn_lib_path_full = os.path.join(cudnn_install_path, cuda_dnn_lib_path)
930 cuda_dnn_lib_alt_path_full = os.path.join(cudnn_install_path,
931 cuda_dnn_lib_alt_path)
932 if os.path.exists(cuda_dnn_lib_path_full) or os.path.exists(
933 cuda_dnn_lib_alt_path_full):
934 break
935
936 # Try another alternative for Linux
937 if is_linux():
Jonathan Hseu008910f2017-08-25 14:01:05 -0700938 ldconfig_bin = which('ldconfig') or '/sbin/ldconfig'
939 cudnn_path_from_ldconfig = run_shell([ldconfig_bin, '-p'])
940 cudnn_path_from_ldconfig = re.search('.*libcudnn.so .* => (.*)',
A. Unique TensorFlowere7223582017-09-06 17:57:04 -0700941 cudnn_path_from_ldconfig)
942 if cudnn_path_from_ldconfig:
943 cudnn_path_from_ldconfig = cudnn_path_from_ldconfig.group(1)
Gunhan Gulsoyffa90fc2018-09-26 01:38:55 -0700944 if os.path.exists(
945 '%s.%s' % (cudnn_path_from_ldconfig, tf_cudnn_version)):
A. Unique TensorFlowere7223582017-09-06 17:57:04 -0700946 cudnn_install_path = os.path.dirname(cudnn_path_from_ldconfig)
947 break
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700948
949 # Reset and Retry
950 print(
951 'Invalid path to cuDNN %s toolkit. None of the following files can be '
952 'found:' % tf_cudnn_version)
953 print(cuda_dnn_lib_path_full)
954 print(cuda_dnn_lib_alt_path_full)
955 if is_linux():
956 print('%s.%s' % (cudnn_path_from_ldconfig, tf_cudnn_version))
957
958 environ_cp['TF_CUDNN_VERSION'] = ''
Austin Andersonf9a88f82017-12-13 11:49:40 -0800959 else:
960 raise UserInputError('Invalid TF_CUDNN setting was provided %d '
961 'times in a row. Assuming to be a scripting mistake.' %
962 _DEFAULT_PROMPT_ASK_ATTEMPTS)
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -0700963
964 # Set CUDNN_INSTALL_PATH and TF_CUDNN_VERSION
965 environ_cp['CUDNN_INSTALL_PATH'] = cudnn_install_path
966 write_action_env_to_bazelrc('CUDNN_INSTALL_PATH', cudnn_install_path)
967 environ_cp['TF_CUDNN_VERSION'] = tf_cudnn_version
968 write_action_env_to_bazelrc('TF_CUDNN_VERSION', tf_cudnn_version)
969
970
Mingxing Tan1e7b0e42018-06-28 19:13:20 -0700971def is_cuda_compatible(lib, cuda_ver, cudnn_ver):
972 """Check compatibility between given library and cudnn/cudart libraries."""
973 ldd_bin = which('ldd') or '/usr/bin/ldd'
974 ldd_out = run_shell([ldd_bin, lib], True)
975 ldd_out = ldd_out.split(os.linesep)
976 cudnn_pattern = re.compile('.*libcudnn.so\\.?(.*) =>.*$')
977 cuda_pattern = re.compile('.*libcudart.so\\.?(.*) =>.*$')
978 cudnn = None
979 cudart = None
980 cudnn_ok = True # assume no cudnn dependency by default
981 cuda_ok = True # assume no cuda dependency by default
982 for line in ldd_out:
983 if 'libcudnn.so' in line:
984 cudnn = cudnn_pattern.search(line)
985 cudnn_ok = False
986 elif 'libcudart.so' in line:
987 cudart = cuda_pattern.search(line)
988 cuda_ok = False
989 if cudnn and len(cudnn.group(1)):
990 cudnn = convert_version_to_int(cudnn.group(1))
991 if cudart and len(cudart.group(1)):
992 cudart = convert_version_to_int(cudart.group(1))
993 if cudnn is not None:
994 cudnn_ok = (cudnn == cudnn_ver)
995 if cudart is not None:
996 cuda_ok = (cudart == cuda_ver)
997 return cudnn_ok and cuda_ok
998
999
Guangda Lai76f69382018-01-25 23:59:19 -08001000def set_tf_tensorrt_install_path(environ_cp):
1001 """Set TENSORRT_INSTALL_PATH and TF_TENSORRT_VERSION.
1002
1003 Adapted from code contributed by Sami Kama (https://github.com/samikama).
1004
1005 Args:
1006 environ_cp: copy of the os.environ.
1007
1008 Raises:
1009 ValueError: if this method was called under non-Linux platform.
1010 UserInputError: if user has provided invalid input multiple times.
1011 """
1012 if not is_linux():
1013 raise ValueError('Currently TensorRT is only supported on Linux platform.')
1014
1015 # Ask user whether to add TensorRT support.
Mingxing Tan1e7b0e42018-06-28 19:13:20 -07001016 if str(int(get_var(environ_cp, 'TF_NEED_TENSORRT', 'TensorRT',
1017 False))) != '1':
Guangda Lai76f69382018-01-25 23:59:19 -08001018 return
1019
1020 for _ in range(_DEFAULT_PROMPT_ASK_ATTEMPTS):
1021 ask_tensorrt_path = (r'Please specify the location where TensorRT is '
1022 'installed. [Default is %s]:') % (
1023 _DEFAULT_TENSORRT_PATH_LINUX)
1024 trt_install_path = get_from_env_or_user_or_default(
1025 environ_cp, 'TENSORRT_INSTALL_PATH', ask_tensorrt_path,
1026 _DEFAULT_TENSORRT_PATH_LINUX)
1027
1028 # Result returned from "read" will be used unexpanded. That make "~"
1029 # unusable. Going through one more level of expansion to handle that.
Mingxing Tan1e7b0e42018-06-28 19:13:20 -07001030 trt_install_path = os.path.realpath(os.path.expanduser(trt_install_path))
Guangda Lai76f69382018-01-25 23:59:19 -08001031
1032 def find_libs(search_path):
1033 """Search for libnvinfer.so in "search_path"."""
1034 fl = set()
1035 if os.path.exists(search_path) and os.path.isdir(search_path):
Mingxing Tan1e7b0e42018-06-28 19:13:20 -07001036 fl.update([
1037 os.path.realpath(os.path.join(search_path, x))
1038 for x in os.listdir(search_path)
1039 if 'libnvinfer.so' in x
1040 ])
Guangda Lai76f69382018-01-25 23:59:19 -08001041 return fl
1042
1043 possible_files = find_libs(trt_install_path)
1044 possible_files.update(find_libs(os.path.join(trt_install_path, 'lib')))
1045 possible_files.update(find_libs(os.path.join(trt_install_path, 'lib64')))
Guangda Lai76f69382018-01-25 23:59:19 -08001046 cuda_ver = convert_version_to_int(environ_cp['TF_CUDA_VERSION'])
1047 cudnn_ver = convert_version_to_int(environ_cp['TF_CUDNN_VERSION'])
1048 nvinfer_pattern = re.compile('.*libnvinfer.so.?(.*)$')
1049 highest_ver = [0, None, None]
1050
1051 for lib_file in possible_files:
Mingxing Tan1e7b0e42018-06-28 19:13:20 -07001052 if is_cuda_compatible(lib_file, cuda_ver, cudnn_ver):
Jacques Pienaar2d0531d2018-03-21 12:07:51 -07001053 matches = nvinfer_pattern.search(lib_file)
TensorFlower Gardener61a87202018-10-01 12:25:39 -07001054 if not matches.groups():
Jacques Pienaar2d0531d2018-03-21 12:07:51 -07001055 continue
1056 ver_str = matches.group(1)
Guangda Lai76f69382018-01-25 23:59:19 -08001057 ver = convert_version_to_int(ver_str) if len(ver_str) else 0
1058 if ver > highest_ver[0]:
1059 highest_ver = [ver, ver_str, lib_file]
1060 if highest_ver[1] is not None:
1061 trt_install_path = os.path.dirname(highest_ver[2])
1062 tf_tensorrt_version = highest_ver[1]
1063 break
1064
1065 # Try another alternative from ldconfig.
1066 ldconfig_bin = which('ldconfig') or '/sbin/ldconfig'
1067 ldconfig_output = run_shell([ldconfig_bin, '-p'])
Mingxing Tan1e7b0e42018-06-28 19:13:20 -07001068 search_result = re.search('.*libnvinfer.so\\.?([0-9.]*).* => (.*)',
1069 ldconfig_output)
Guangda Lai76f69382018-01-25 23:59:19 -08001070 if search_result:
1071 libnvinfer_path_from_ldconfig = search_result.group(2)
1072 if os.path.exists(libnvinfer_path_from_ldconfig):
Mingxing Tan1e7b0e42018-06-28 19:13:20 -07001073 if is_cuda_compatible(libnvinfer_path_from_ldconfig, cuda_ver,
1074 cudnn_ver):
Guangda Lai76f69382018-01-25 23:59:19 -08001075 trt_install_path = os.path.dirname(libnvinfer_path_from_ldconfig)
1076 tf_tensorrt_version = search_result.group(1)
1077 break
1078
1079 # Reset and Retry
Yifei Fengdce9a492018-02-22 14:24:57 -08001080 if possible_files:
1081 print('TensorRT libraries found in one the following directories',
1082 'are not compatible with selected cuda and cudnn installations')
1083 print(trt_install_path)
1084 print(os.path.join(trt_install_path, 'lib'))
1085 print(os.path.join(trt_install_path, 'lib64'))
1086 if search_result:
1087 print(libnvinfer_path_from_ldconfig)
1088 else:
1089 print(
1090 'Invalid path to TensorRT. None of the following files can be found:')
1091 print(trt_install_path)
1092 print(os.path.join(trt_install_path, 'lib'))
1093 print(os.path.join(trt_install_path, 'lib64'))
1094 if search_result:
1095 print(libnvinfer_path_from_ldconfig)
Guangda Lai76f69382018-01-25 23:59:19 -08001096
1097 else:
1098 raise UserInputError('Invalid TF_TENSORRT setting was provided %d '
1099 'times in a row. Assuming to be a scripting mistake.' %
1100 _DEFAULT_PROMPT_ASK_ATTEMPTS)
1101
1102 # Set TENSORRT_INSTALL_PATH and TF_TENSORRT_VERSION
1103 environ_cp['TENSORRT_INSTALL_PATH'] = trt_install_path
1104 write_action_env_to_bazelrc('TENSORRT_INSTALL_PATH', trt_install_path)
1105 environ_cp['TF_TENSORRT_VERSION'] = tf_tensorrt_version
1106 write_action_env_to_bazelrc('TF_TENSORRT_VERSION', tf_tensorrt_version)
1107
1108
A. Unique TensorFlower1fda7642018-04-05 03:09:27 -07001109def set_tf_nccl_install_path(environ_cp):
Jason Furmanek7c234152018-09-26 04:44:12 +00001110 """Set NCCL_INSTALL_PATH, NCCL_HDR_PATH and TF_NCCL_VERSION.
A. Unique TensorFlower1fda7642018-04-05 03:09:27 -07001111
1112 Args:
1113 environ_cp: copy of the os.environ.
1114
1115 Raises:
1116 ValueError: if this method was called under non-Linux platform.
1117 UserInputError: if user has provided invalid input multiple times.
1118 """
1119 if not is_linux():
1120 raise ValueError('Currently NCCL is only supported on Linux platforms.')
1121
1122 ask_nccl_version = (
A. Unique TensorFlower53faa312018-10-05 08:46:54 -07001123 'Please specify the locally installed NCCL version you want to use. '
1124 '[Default is to use https://github.com/nvidia/nccl]: ')
A. Unique TensorFlower1fda7642018-04-05 03:09:27 -07001125
1126 for _ in range(_DEFAULT_PROMPT_ASK_ATTEMPTS):
1127 tf_nccl_version = get_from_env_or_user_or_default(
A. Unique TensorFlower53faa312018-10-05 08:46:54 -07001128 environ_cp, 'TF_NCCL_VERSION', ask_nccl_version, '')
A. Unique TensorFlower1fda7642018-04-05 03:09:27 -07001129
A. Unique TensorFlower53faa312018-10-05 08:46:54 -07001130 if not tf_nccl_version:
1131 break # No need to get install path, building the open source code.
1132
1133 tf_nccl_version = reformat_version_sequence(str(tf_nccl_version), 1)
A. Unique TensorFlower1fda7642018-04-05 03:09:27 -07001134
Jason Furmanek7c234152018-09-26 04:44:12 +00001135 # Look with ldconfig first if we can find the library in paths
A. Unique TensorFlower1fda7642018-04-05 03:09:27 -07001136 # like /usr/lib/x86_64-linux-gnu and the header file in the corresponding
1137 # include directory. This is where the NCCL .deb packages install them.
A. Unique TensorFlower1fda7642018-04-05 03:09:27 -07001138
Jason Furmanek7c234152018-09-26 04:44:12 +00001139 # First check to see if NCCL is in the ldconfig.
1140 # If its found, use that location.
1141 if is_linux():
1142 ldconfig_bin = which('ldconfig') or '/sbin/ldconfig'
1143 nccl2_path_from_ldconfig = run_shell([ldconfig_bin, '-p'])
1144 nccl2_path_from_ldconfig = re.search('.*libnccl.so .* => (.*)',
1145 nccl2_path_from_ldconfig)
1146 if nccl2_path_from_ldconfig:
1147 nccl2_path_from_ldconfig = nccl2_path_from_ldconfig.group(1)
1148 if os.path.exists('%s.%s' % (nccl2_path_from_ldconfig, tf_nccl_version)):
1149 nccl_install_path = os.path.dirname(nccl2_path_from_ldconfig)
1150 print('NCCL libraries found in ' + nccl2_path_from_ldconfig)
A. Unique TensorFlower1fda7642018-04-05 03:09:27 -07001151
Jason Furmanek7c234152018-09-26 04:44:12 +00001152 # Check if this is the main system lib location
1153 if re.search('.*linux-gnu', nccl_install_path):
TensorFlower Gardenerea5c5292018-10-01 17:28:26 -07001154 trunc_nccl_install_path = '/usr'
1155 print('This looks like a system path.')
Jason Furmanek7c234152018-09-26 04:44:12 +00001156 else:
TensorFlower Gardenerea5c5292018-10-01 17:28:26 -07001157 trunc_nccl_install_path = nccl_install_path + '/..'
A. Unique TensorFlower1fda7642018-04-05 03:09:27 -07001158
Jason Furmanek7c234152018-09-26 04:44:12 +00001159 # Look for header
TensorFlower Gardenerea5c5292018-10-01 17:28:26 -07001160 nccl_hdr_path = trunc_nccl_install_path + '/include'
1161 print('Assuming NCCL header path is ' + nccl_hdr_path)
1162 if os.path.exists(nccl_hdr_path + '/nccl.h'):
Jason Furmanek7c234152018-09-26 04:44:12 +00001163 # Set NCCL_INSTALL_PATH
1164 environ_cp['NCCL_INSTALL_PATH'] = nccl_install_path
1165 write_action_env_to_bazelrc('NCCL_INSTALL_PATH', nccl_install_path)
A. Unique TensorFlower1fda7642018-04-05 03:09:27 -07001166
Jason Furmanek7c234152018-09-26 04:44:12 +00001167 # Set NCCL_HDR_PATH
1168 environ_cp['NCCL_HDR_PATH'] = nccl_hdr_path
1169 write_action_env_to_bazelrc('NCCL_HDR_PATH', nccl_hdr_path)
1170 break
1171 else:
TensorFlower Gardenerea5c5292018-10-01 17:28:26 -07001172 print(
1173 'The header for NCCL2 cannot be found. Please install the libnccl-dev package.'
1174 )
Jason Furmanek7c234152018-09-26 04:44:12 +00001175 else:
TensorFlower Gardenerea5c5292018-10-01 17:28:26 -07001176 print('NCCL2 is listed by ldconfig but the library is not found. '
1177 'Your ldconfig is out of date. Please run sudo ldconfig.')
Jason Furmanek7c234152018-09-26 04:44:12 +00001178 else:
1179 # NCCL is not found in ldconfig. Ask the user for the location.
1180 default_nccl_path = environ_cp.get('CUDA_TOOLKIT_PATH')
TensorFlower Gardenerea5c5292018-10-01 17:28:26 -07001181 ask_nccl_path = (
1182 r'Please specify the location where NCCL %s library is '
1183 'installed. Refer to README.md for more details. [Default '
1184 'is %s]:') % (tf_nccl_version, default_nccl_path)
Jason Furmanek7c234152018-09-26 04:44:12 +00001185 nccl_install_path = get_from_env_or_user_or_default(
TensorFlower Gardenerea5c5292018-10-01 17:28:26 -07001186 environ_cp, 'NCCL_INSTALL_PATH', ask_nccl_path, default_nccl_path)
A. Unique TensorFlower1fda7642018-04-05 03:09:27 -07001187
Jason Furmanek7c234152018-09-26 04:44:12 +00001188 # Result returned from "read" will be used unexpanded. That make "~"
1189 # unusable. Going through one more level of expansion to handle that.
TensorFlower Gardenerea5c5292018-10-01 17:28:26 -07001190 nccl_install_path = os.path.realpath(
1191 os.path.expanduser(nccl_install_path))
Jason Furmanek7c234152018-09-26 04:44:12 +00001192 if is_windows() or is_cygwin():
1193 nccl_install_path = cygpath(nccl_install_path)
A. Unique TensorFlower1fda7642018-04-05 03:09:27 -07001194
Guangda Lai62ebf622018-10-23 07:44:13 -07001195 nccl_lib_path = ''
Jason Furmanek7c234152018-09-26 04:44:12 +00001196 if is_windows():
1197 nccl_lib_path = 'lib/x64/nccl.lib'
1198 elif is_linux():
1199 nccl_lib_filename = 'libnccl.so.%s' % tf_nccl_version
1200 nccl_lpath = '%s/lib/%s' % (nccl_install_path, nccl_lib_filename)
1201 if not os.path.exists(nccl_lpath):
1202 for relative_path in NCCL_LIB_PATHS:
TensorFlower Gardenerea5c5292018-10-01 17:28:26 -07001203 path = '%s/%s%s' % (nccl_install_path, relative_path,
1204 nccl_lib_filename)
Jason Furmanek7c234152018-09-26 04:44:12 +00001205 if os.path.exists(path):
TensorFlower Gardenerea5c5292018-10-01 17:28:26 -07001206 print('NCCL found at ' + path)
Jason Furmanek7c234152018-09-26 04:44:12 +00001207 nccl_lib_path = path
1208 break
1209 else:
1210 nccl_lib_path = nccl_lpath
1211 elif is_macos():
1212 nccl_lib_path = 'lib/libnccl.%s.dylib' % tf_nccl_version
A. Unique TensorFlower1fda7642018-04-05 03:09:27 -07001213
Jason Furmanek7c234152018-09-26 04:44:12 +00001214 nccl_lib_path = os.path.join(nccl_install_path, nccl_lib_path)
TensorFlower Gardenerea5c5292018-10-01 17:28:26 -07001215 nccl_hdr_path = os.path.join(
1216 os.path.dirname(nccl_lib_path), '../include/nccl.h')
1217 print('Assuming NCCL header path is ' + nccl_hdr_path)
Jason Furmanek7c234152018-09-26 04:44:12 +00001218 if os.path.exists(nccl_lib_path) and os.path.exists(nccl_hdr_path):
1219 # Set NCCL_INSTALL_PATH
1220 environ_cp['NCCL_INSTALL_PATH'] = os.path.dirname(nccl_lib_path)
TensorFlower Gardenerea5c5292018-10-01 17:28:26 -07001221 write_action_env_to_bazelrc('NCCL_INSTALL_PATH',
1222 os.path.dirname(nccl_lib_path))
A. Unique TensorFlower1fda7642018-04-05 03:09:27 -07001223
Jason Furmanek7c234152018-09-26 04:44:12 +00001224 # Set NCCL_HDR_PATH
1225 environ_cp['NCCL_HDR_PATH'] = os.path.dirname(nccl_hdr_path)
TensorFlower Gardenerea5c5292018-10-01 17:28:26 -07001226 write_action_env_to_bazelrc('NCCL_HDR_PATH',
1227 os.path.dirname(nccl_hdr_path))
Jason Furmanek7c234152018-09-26 04:44:12 +00001228 break
1229
1230 # Reset and Retry
TensorFlower Gardenerea5c5292018-10-01 17:28:26 -07001231 print(
1232 'Invalid path to NCCL %s toolkit, %s or %s not found. Please use the '
A. Unique TensorFlower1fda7642018-04-05 03:09:27 -07001233 'O/S agnostic package of NCCL 2' % (tf_nccl_version, nccl_lib_path,
1234 nccl_hdr_path))
1235
Jason Furmanek7c234152018-09-26 04:44:12 +00001236 environ_cp['TF_NCCL_VERSION'] = ''
A. Unique TensorFlower1fda7642018-04-05 03:09:27 -07001237 else:
1238 raise UserInputError('Invalid TF_NCCL setting was provided %d '
1239 'times in a row. Assuming to be a scripting mistake.' %
1240 _DEFAULT_PROMPT_ASK_ATTEMPTS)
1241
1242 # Set TF_NCCL_VERSION
1243 environ_cp['TF_NCCL_VERSION'] = tf_nccl_version
1244 write_action_env_to_bazelrc('TF_NCCL_VERSION', tf_nccl_version)
1245
TensorFlower Gardenerabb763b2019-02-06 16:23:03 -08001246
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001247def get_native_cuda_compute_capabilities(environ_cp):
1248 """Get native cuda compute capabilities.
1249
1250 Args:
1251 environ_cp: copy of the os.environ.
Gunhan Gulsoyffa90fc2018-09-26 01:38:55 -07001252
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001253 Returns:
1254 string of native cuda compute capabilities, separated by comma.
1255 """
1256 device_query_bin = os.path.join(
1257 environ_cp.get('CUDA_TOOLKIT_PATH'), 'extras/demo_suite/deviceQuery')
Jonathan Hseu008910f2017-08-25 14:01:05 -07001258 if os.path.isfile(device_query_bin) and os.access(device_query_bin, os.X_OK):
1259 try:
1260 output = run_shell(device_query_bin).split('\n')
1261 pattern = re.compile('[0-9]*\\.[0-9]*')
1262 output = [pattern.search(x) for x in output if 'Capability' in x]
1263 output = ','.join(x.group() for x in output if x is not None)
1264 except subprocess.CalledProcessError:
1265 output = ''
1266 else:
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001267 output = ''
1268 return output
1269
1270
1271def set_tf_cuda_compute_capabilities(environ_cp):
1272 """Set TF_CUDA_COMPUTE_CAPABILITIES."""
1273 while True:
1274 native_cuda_compute_capabilities = get_native_cuda_compute_capabilities(
1275 environ_cp)
1276 if not native_cuda_compute_capabilities:
1277 default_cuda_compute_capabilities = _DEFAULT_CUDA_COMPUTE_CAPABILITIES
1278 else:
1279 default_cuda_compute_capabilities = native_cuda_compute_capabilities
1280
1281 ask_cuda_compute_capabilities = (
1282 'Please specify a list of comma-separated '
P Sudeepam52093562019-02-17 17:34:01 +05301283 'CUDA compute capabilities you want to '
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001284 'build with.\nYou can find the compute '
1285 'capability of your device at: '
1286 'https://developer.nvidia.com/cuda-gpus.\nPlease'
1287 ' note that each additional compute '
1288 'capability significantly increases your '
P Sudeepam52093562019-02-17 17:34:01 +05301289 'build time and binary size, and that '
1290 'TensorFlow only supports compute '
1291 'capabilities >= 3.5' [Default is: %s]: ' %
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001292 default_cuda_compute_capabilities)
1293 tf_cuda_compute_capabilities = get_from_env_or_user_or_default(
1294 environ_cp, 'TF_CUDA_COMPUTE_CAPABILITIES',
1295 ask_cuda_compute_capabilities, default_cuda_compute_capabilities)
1296 # Check whether all capabilities from the input is valid
1297 all_valid = True
Maciejd0f5bc12018-04-30 22:30:58 -05001298 # Remove all whitespace characters before splitting the string
Michael Case51053502018-06-05 17:47:19 -07001299 # that users may insert by accident, as this will result in error
Maciejd0f5bc12018-04-30 22:30:58 -05001300 tf_cuda_compute_capabilities = ''.join(tf_cuda_compute_capabilities.split())
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001301 for compute_capability in tf_cuda_compute_capabilities.split(','):
Andrew Harp6e3e7d12017-08-21 12:10:44 -07001302 m = re.match('[0-9]+.[0-9]+', compute_capability)
1303 if not m:
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001304 print('Invalid compute capability: ' % compute_capability)
1305 all_valid = False
Andrew Harp6e3e7d12017-08-21 12:10:44 -07001306 else:
P Sudeepam52093562019-02-17 17:34:01 +05301307 ver = float(m.group(0))
1308 if ver < 3.5:
1309 print('ERROR: TensorFlow only supports CUDA compute capabilities 3.5 '
1310 'or higher. Please re-specify the list of compute capabilities,'
1311 ' excluding all those versions that are less than 3.5')
Andrew Harp6e3e7d12017-08-21 12:10:44 -07001312 all_valid = False
P Sudeepam52093562019-02-17 17:34:01 +05301313
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001314 if all_valid:
1315 break
1316
1317 # Reset and Retry
1318 environ_cp['TF_CUDA_COMPUTE_CAPABILITIES'] = ''
1319
1320 # Set TF_CUDA_COMPUTE_CAPABILITIES
1321 environ_cp['TF_CUDA_COMPUTE_CAPABILITIES'] = tf_cuda_compute_capabilities
1322 write_action_env_to_bazelrc('TF_CUDA_COMPUTE_CAPABILITIES',
1323 tf_cuda_compute_capabilities)
1324
1325
1326def set_other_cuda_vars(environ_cp):
1327 """Set other CUDA related variables."""
A. Unique TensorFlowerab391982018-07-11 04:52:49 -07001328 # If CUDA is enabled, always use GPU during build and test.
1329 if environ_cp.get('TF_CUDA_CLANG') == '1':
1330 write_to_bazelrc('build --config=cuda_clang')
1331 write_to_bazelrc('test --config=cuda_clang')
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001332 else:
A. Unique TensorFlowerab391982018-07-11 04:52:49 -07001333 write_to_bazelrc('build --config=cuda')
1334 write_to_bazelrc('test --config=cuda')
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001335
1336
1337def set_host_cxx_compiler(environ_cp):
1338 """Set HOST_CXX_COMPILER."""
Jonathan Hseu008910f2017-08-25 14:01:05 -07001339 default_cxx_host_compiler = which('g++') or ''
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001340
Austin Anderson6afface2017-12-05 11:59:17 -08001341 host_cxx_compiler = prompt_loop_or_load_from_env(
1342 environ_cp,
1343 var_name='HOST_CXX_COMPILER',
1344 var_default=default_cxx_host_compiler,
1345 ask_for_var=('Please specify which C++ compiler should be used as the '
1346 'host C++ compiler.'),
1347 check_success=os.path.exists,
1348 error_msg='Invalid C++ compiler path. %s cannot be found.',
1349 )
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001350
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001351 write_action_env_to_bazelrc('HOST_CXX_COMPILER', host_cxx_compiler)
1352
1353
1354def set_host_c_compiler(environ_cp):
1355 """Set HOST_C_COMPILER."""
Jonathan Hseu008910f2017-08-25 14:01:05 -07001356 default_c_host_compiler = which('gcc') or ''
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001357
Austin Anderson6afface2017-12-05 11:59:17 -08001358 host_c_compiler = prompt_loop_or_load_from_env(
1359 environ_cp,
1360 var_name='HOST_C_COMPILER',
1361 var_default=default_c_host_compiler,
Shanqing Cai71445712018-03-12 19:33:52 -07001362 ask_for_var=('Please specify which C compiler should be used as the host '
Austin Anderson6afface2017-12-05 11:59:17 -08001363 'C compiler.'),
1364 check_success=os.path.exists,
1365 error_msg='Invalid C compiler path. %s cannot be found.',
1366 )
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001367
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001368 write_action_env_to_bazelrc('HOST_C_COMPILER', host_c_compiler)
1369
1370
1371def set_computecpp_toolkit_path(environ_cp):
1372 """Set COMPUTECPP_TOOLKIT_PATH."""
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001373
Austin Anderson6afface2017-12-05 11:59:17 -08001374 def toolkit_exists(toolkit_path):
1375 """Check if a computecpp toolkit path is valid."""
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001376 if is_linux():
1377 sycl_rt_lib_path = 'lib/libComputeCpp.so'
1378 else:
1379 sycl_rt_lib_path = ''
1380
Gunhan Gulsoyffa90fc2018-09-26 01:38:55 -07001381 sycl_rt_lib_path_full = os.path.join(toolkit_path, sycl_rt_lib_path)
Austin Anderson6afface2017-12-05 11:59:17 -08001382 exists = os.path.exists(sycl_rt_lib_path_full)
1383 if not exists:
1384 print('Invalid SYCL %s library path. %s cannot be found' %
1385 (_TF_OPENCL_VERSION, sycl_rt_lib_path_full))
1386 return exists
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001387
Austin Anderson6afface2017-12-05 11:59:17 -08001388 computecpp_toolkit_path = prompt_loop_or_load_from_env(
1389 environ_cp,
1390 var_name='COMPUTECPP_TOOLKIT_PATH',
1391 var_default=_DEFAULT_COMPUTECPP_TOOLKIT_PATH,
1392 ask_for_var=(
1393 'Please specify the location where ComputeCpp for SYCL %s is '
1394 'installed.' % _TF_OPENCL_VERSION),
1395 check_success=toolkit_exists,
1396 error_msg='Invalid SYCL compiler path. %s cannot be found.',
1397 suppress_default_error=True)
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001398
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001399 write_action_env_to_bazelrc('COMPUTECPP_TOOLKIT_PATH',
1400 computecpp_toolkit_path)
1401
Michael Cased31531a2018-01-05 14:09:41 -08001402
Dandelion Man?90e42f32017-12-15 18:15:07 -08001403def set_trisycl_include_dir(environ_cp):
Michael Cased31531a2018-01-05 14:09:41 -08001404 """Set TRISYCL_INCLUDE_DIR."""
Frank Chenc4ef9272018-01-10 11:36:52 -08001405
Dandelion Man?90e42f32017-12-15 18:15:07 -08001406 ask_trisycl_include_dir = ('Please specify the location of the triSYCL '
1407 'include directory. (Use --config=sycl_trisycl '
1408 'when building with Bazel) '
Gunhan Gulsoyffa90fc2018-09-26 01:38:55 -07001409 '[Default is %s]: ') % (
1410 _DEFAULT_TRISYCL_INCLUDE_DIR)
Frank Chenc4ef9272018-01-10 11:36:52 -08001411
Dandelion Man?90e42f32017-12-15 18:15:07 -08001412 while True:
1413 trisycl_include_dir = get_from_env_or_user_or_default(
Michael Cased31531a2018-01-05 14:09:41 -08001414 environ_cp, 'TRISYCL_INCLUDE_DIR', ask_trisycl_include_dir,
1415 _DEFAULT_TRISYCL_INCLUDE_DIR)
Dandelion Man?90e42f32017-12-15 18:15:07 -08001416 if os.path.exists(trisycl_include_dir):
1417 break
1418
Gunhan Gulsoyffa90fc2018-09-26 01:38:55 -07001419 print('Invalid triSYCL include directory, %s cannot be found' %
1420 (trisycl_include_dir))
Dandelion Man?90e42f32017-12-15 18:15:07 -08001421
1422 # Set TRISYCL_INCLUDE_DIR
1423 environ_cp['TRISYCL_INCLUDE_DIR'] = trisycl_include_dir
Gunhan Gulsoyffa90fc2018-09-26 01:38:55 -07001424 write_action_env_to_bazelrc('TRISYCL_INCLUDE_DIR', trisycl_include_dir)
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001425
Yifei Fengb1d8c592017-11-22 13:42:21 -08001426
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001427def set_mpi_home(environ_cp):
1428 """Set MPI_HOME."""
Austin Anderson6afface2017-12-05 11:59:17 -08001429
Jonathan Hseu008910f2017-08-25 14:01:05 -07001430 default_mpi_home = which('mpirun') or which('mpiexec') or ''
1431 default_mpi_home = os.path.dirname(os.path.dirname(default_mpi_home))
1432
Austin Anderson6afface2017-12-05 11:59:17 -08001433 def valid_mpi_path(mpi_home):
Gunhan Gulsoyffa90fc2018-09-26 01:38:55 -07001434 exists = (
1435 os.path.exists(os.path.join(mpi_home, 'include')) and
TensorFlower Gardenerf7c861f2018-11-01 11:29:40 -07001436 (os.path.exists(os.path.join(mpi_home, 'lib')) or
1437 os.path.exists(os.path.join(mpi_home, 'lib64')) or
1438 os.path.exists(os.path.join(mpi_home, 'lib32'))))
Austin Anderson6afface2017-12-05 11:59:17 -08001439 if not exists:
TensorFlower Gardenerf7c861f2018-11-01 11:29:40 -07001440 print(
1441 'Invalid path to the MPI Toolkit. %s or %s or %s or %s cannot be found'
1442 % (os.path.join(mpi_home, 'include'),
Christian Gollba95d092018-10-04 17:06:23 +02001443 os.path.exists(os.path.join(mpi_home, 'lib')),
1444 os.path.exists(os.path.join(mpi_home, 'lib64')),
1445 os.path.exists(os.path.join(mpi_home, 'lib32'))))
Austin Anderson6afface2017-12-05 11:59:17 -08001446 return exists
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001447
Austin Anderson6afface2017-12-05 11:59:17 -08001448 _ = prompt_loop_or_load_from_env(
1449 environ_cp,
1450 var_name='MPI_HOME',
1451 var_default=default_mpi_home,
1452 ask_for_var='Please specify the MPI toolkit folder.',
1453 check_success=valid_mpi_path,
1454 error_msg='',
1455 suppress_default_error=True)
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001456
1457
1458def set_other_mpi_vars(environ_cp):
1459 """Set other MPI related variables."""
1460 # Link the MPI header files
1461 mpi_home = environ_cp.get('MPI_HOME')
1462 symlink_force('%s/include/mpi.h' % mpi_home, 'third_party/mpi/mpi.h')
1463
1464 # Determine if we use OpenMPI or MVAPICH, these require different header files
1465 # to be included here to make bazel dependency checker happy
1466 if os.path.exists(os.path.join(mpi_home, 'include/mpi_portable_platform.h')):
1467 symlink_force(
1468 os.path.join(mpi_home, 'include/mpi_portable_platform.h'),
1469 'third_party/mpi/mpi_portable_platform.h')
1470 # TODO(gunan): avoid editing files in configure
1471 sed_in_place('third_party/mpi/mpi.bzl', 'MPI_LIB_IS_OPENMPI=False',
1472 'MPI_LIB_IS_OPENMPI=True')
1473 else:
1474 # MVAPICH / MPICH
1475 symlink_force(
1476 os.path.join(mpi_home, 'include/mpio.h'), 'third_party/mpi/mpio.h')
1477 symlink_force(
1478 os.path.join(mpi_home, 'include/mpicxx.h'), 'third_party/mpi/mpicxx.h')
1479 # TODO(gunan): avoid editing files in configure
1480 sed_in_place('third_party/mpi/mpi.bzl', 'MPI_LIB_IS_OPENMPI=True',
1481 'MPI_LIB_IS_OPENMPI=False')
1482
1483 if os.path.exists(os.path.join(mpi_home, 'lib/libmpi.so')):
1484 symlink_force(
1485 os.path.join(mpi_home, 'lib/libmpi.so'), 'third_party/mpi/libmpi.so')
Christian Gollba95d092018-10-04 17:06:23 +02001486 elif os.path.exists(os.path.join(mpi_home, 'lib64/libmpi.so')):
1487 symlink_force(
1488 os.path.join(mpi_home, 'lib64/libmpi.so'), 'third_party/mpi/libmpi.so')
1489 elif os.path.exists(os.path.join(mpi_home, 'lib32/libmpi.so')):
1490 symlink_force(
1491 os.path.join(mpi_home, 'lib32/libmpi.so'), 'third_party/mpi/libmpi.so')
1492
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001493 else:
TensorFlower Gardenerf7c861f2018-11-01 11:29:40 -07001494 raise ValueError(
1495 'Cannot find the MPI library file in %s/lib or %s/lib64 or %s/lib32' %
Mihai Maruseac91ebeec2019-01-29 17:07:38 -08001496 (mpi_home, mpi_home, mpi_home))
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001497
1498
Yifei Feng5198cb82018-08-17 13:53:06 -07001499def set_system_libs_flag(environ_cp):
1500 syslibs = environ_cp.get('TF_SYSTEM_LIBS', '')
TensorFlower Gardener61a87202018-10-01 12:25:39 -07001501 if syslibs:
Jason Zaman5fc39bd2018-09-16 01:38:55 +08001502 if ',' in syslibs:
1503 syslibs = ','.join(sorted(syslibs.split(',')))
1504 else:
1505 syslibs = ','.join(sorted(syslibs.split()))
Yifei Feng5198cb82018-08-17 13:53:06 -07001506 write_action_env_to_bazelrc('TF_SYSTEM_LIBS', syslibs)
1507
Jason Zaman5fc39bd2018-09-16 01:38:55 +08001508 if 'PREFIX' in environ_cp:
1509 write_to_bazelrc('build --define=PREFIX=%s' % environ_cp['PREFIX'])
1510 if 'LIBDIR' in environ_cp:
1511 write_to_bazelrc('build --define=LIBDIR=%s' % environ_cp['LIBDIR'])
1512 if 'INCLUDEDIR' in environ_cp:
1513 write_to_bazelrc('build --define=INCLUDEDIR=%s' % environ_cp['INCLUDEDIR'])
1514
Yifei Feng5198cb82018-08-17 13:53:06 -07001515
A. Unique TensorFlower1b212352018-07-19 13:48:50 -07001516def set_windows_build_flags(environ_cp):
1517 """Set Windows specific build options."""
1518 # The non-monolithic build is not supported yet
1519 write_to_bazelrc('build --config monolithic')
1520 # Suppress warning messages
1521 write_to_bazelrc('build --copt=-w --host_copt=-w')
1522 # Output more verbose information when something goes wrong
1523 write_to_bazelrc('build --verbose_failures')
1524 # The host and target platforms are the same in Windows build. So we don't
1525 # have to distinct them. This avoids building the same targets twice.
1526 write_to_bazelrc('build --distinct_host_configuration=false')
A. Unique TensorFlower1b212352018-07-19 13:48:50 -07001527
1528 if get_var(
1529 environ_cp, 'TF_OVERRIDE_EIGEN_STRONG_INLINE', 'Eigen strong inline',
Gunhan Gulsoyffa90fc2018-09-26 01:38:55 -07001530 True, ('Would you like to override eigen strong inline for some C++ '
1531 'compilation to reduce the compilation time?'),
1532 'Eigen strong inline overridden.', 'Not overriding eigen strong inline, '
A. Unique TensorFlower1b212352018-07-19 13:48:50 -07001533 'some compilations could take more than 20 mins.'):
1534 # Due to a known MSVC compiler issue
1535 # https://github.com/tensorflow/tensorflow/issues/10521
1536 # Overriding eigen strong inline speeds up the compiling of
1537 # conv_grad_ops_3d.cc and conv_ops_3d.cc by 20 minutes,
1538 # but this also hurts the performance. Let users decide what they want.
1539 write_to_bazelrc('build --define=override_eigen_strong_inline=true')
Dandelion Man?90e42f32017-12-15 18:15:07 -08001540
A. Unique TensorFlower061c3592017-11-13 14:21:04 -08001541
Michael Cased31531a2018-01-05 14:09:41 -08001542def config_info_line(name, help_text):
1543 """Helper function to print formatted help text for Bazel config options."""
1544 print('\t--config=%-12s\t# %s' % (name, help_text))
1545
1546
A. Unique TensorFlower93e70732019-02-14 16:45:32 -08001547def configure_apple_bazel_rules():
1548 """Configures Bazel rules for building on Apple platforms.
1549
1550 Enables analyzing and building Apple Bazel rules on Apple platforms. This
1551 function will only be executed if `is_macos()` is true.
1552 """
1553 if not is_macos():
1554 return
1555 for filepath in APPLE_BAZEL_FILES:
1556 print(
1557 'Configuring %s file to analyze and build Bazel rules on Apple platforms.'
1558 % filepath)
1559 existing_filepath = os.path.join(_TF_WORKSPACE_ROOT, filepath + '.apple')
1560 renamed_filepath = os.path.join(_TF_WORKSPACE_ROOT, filepath)
1561 os.rename(existing_filepath, renamed_filepath)
1562
1563
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001564def main():
A. Unique TensorFlower7c5eb352018-10-01 07:15:23 -07001565 global _TF_WORKSPACE_ROOT
1566 global _TF_BAZELRC
1567
Shanqing Cai71445712018-03-12 19:33:52 -07001568 parser = argparse.ArgumentParser()
Gunhan Gulsoyffa90fc2018-09-26 01:38:55 -07001569 parser.add_argument(
1570 '--workspace',
1571 type=str,
A. Unique TensorFlower7c5eb352018-10-01 07:15:23 -07001572 default=os.path.abspath(os.path.dirname(__file__)),
Gunhan Gulsoyffa90fc2018-09-26 01:38:55 -07001573 help='The absolute path to your active Bazel workspace.')
Shanqing Cai71445712018-03-12 19:33:52 -07001574 args = parser.parse_args()
1575
A. Unique TensorFlower7c5eb352018-10-01 07:15:23 -07001576 _TF_WORKSPACE_ROOT = args.workspace
1577 _TF_BAZELRC = os.path.join(_TF_WORKSPACE_ROOT, _TF_BAZELRC_FILENAME)
1578
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001579 # Make a copy of os.environ to be clear when functions and getting and setting
1580 # environment variables.
1581 environ_cp = dict(os.environ)
1582
Gunhan Gulsoy91da8982019-02-04 13:31:05 -08001583 check_bazel_version('0.19.0', '0.22.0')
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001584
A. Unique TensorFlower7c5eb352018-10-01 07:15:23 -07001585 reset_tf_configure_bazelrc()
Yun Peng03e63a22018-11-07 11:18:53 +01001586
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001587 cleanup_makefile()
Gunhan Gulsoyed89a2b2017-09-19 18:36:26 -07001588 setup_python(environ_cp)
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001589
1590 if is_windows():
Yifei Fengb1d8c592017-11-22 13:42:21 -08001591 environ_cp['TF_NEED_OPENCL_SYCL'] = '0'
1592 environ_cp['TF_NEED_COMPUTECPP'] = '0'
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001593 environ_cp['TF_NEED_OPENCL'] = '0'
1594 environ_cp['TF_CUDA_CLANG'] = '0'
Guangda Lai76f69382018-01-25 23:59:19 -08001595 environ_cp['TF_NEED_TENSORRT'] = '0'
Ilya Biryukov9e651e42018-03-22 05:33:42 -07001596 # TODO(ibiryukov): Investigate using clang as a cpu or cuda compiler on
1597 # Windows.
1598 environ_cp['TF_DOWNLOAD_CLANG'] = '0'
A. Unique TensorFlower6e97fb32018-07-16 14:07:29 -07001599 environ_cp['TF_NEED_MPI'] = '0'
1600 environ_cp['TF_SET_ANDROID_WORKSPACE'] = '0'
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001601
1602 if is_macos():
Guangda Lai76f69382018-01-25 23:59:19 -08001603 environ_cp['TF_NEED_TENSORRT'] = '0'
A. Unique TensorFlower93e70732019-02-14 16:45:32 -08001604 else:
1605 environ_cp['TF_CONFIGURE_APPLE_BAZEL_RULES'] = '0'
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001606
Jon Triebenbach6896a742018-06-27 13:29:53 -05001607 # The numpy package on ppc64le uses OpenBLAS which has multi-threading
1608 # issues that lead to incorrect answers. Set OMP_NUM_THREADS=1 at
1609 # runtime to allow the Tensorflow testcases which compare numpy
1610 # results to Tensorflow results to succeed.
1611 if is_ppc64le():
Gunhan Gulsoyffa90fc2018-09-26 01:38:55 -07001612 write_action_env_to_bazelrc('OMP_NUM_THREADS', 1)
Jon Triebenbach6896a742018-06-27 13:29:53 -05001613
Grzegorz Pawelczakec82efd2018-10-09 15:03:46 +01001614 xla_enabled_by_default = is_linux()
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001615 set_build_var(environ_cp, 'TF_ENABLE_XLA', 'XLA JIT', 'with_xla_support',
Grzegorz Pawelczakec82efd2018-10-09 15:03:46 +01001616 xla_enabled_by_default, 'xla')
Gunhan Gulsoy3da0dff2018-09-26 11:55:50 -07001617
Yifei Fengb1d8c592017-11-22 13:42:21 -08001618 set_action_env_var(environ_cp, 'TF_NEED_OPENCL_SYCL', 'OpenCL SYCL', False)
1619 if environ_cp.get('TF_NEED_OPENCL_SYCL') == '1':
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001620 set_host_cxx_compiler(environ_cp)
1621 set_host_c_compiler(environ_cp)
Yifei Fengb1d8c592017-11-22 13:42:21 -08001622 set_action_env_var(environ_cp, 'TF_NEED_COMPUTECPP', 'ComputeCPP', True)
1623 if environ_cp.get('TF_NEED_COMPUTECPP') == '1':
1624 set_computecpp_toolkit_path(environ_cp)
1625 else:
1626 set_trisycl_include_dir(environ_cp)
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001627
Wen-Heng (Jack) Chung69d3b8f2018-06-22 23:09:43 -05001628 set_action_env_var(environ_cp, 'TF_NEED_ROCM', 'ROCm', False)
1629 if (environ_cp.get('TF_NEED_ROCM') == '1' and
TensorFlower Gardener62e60162018-09-27 10:22:55 -07001630 'LD_LIBRARY_PATH' in environ_cp and
1631 environ_cp.get('LD_LIBRARY_PATH') != '1'):
1632 write_action_env_to_bazelrc('LD_LIBRARY_PATH',
1633 environ_cp.get('LD_LIBRARY_PATH'))
Wen-Heng (Jack) Chung69d3b8f2018-06-22 23:09:43 -05001634
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001635 set_action_env_var(environ_cp, 'TF_NEED_CUDA', 'CUDA', False)
A. Unique TensorFlower24cbb2a2017-09-08 07:45:44 -07001636 if (environ_cp.get('TF_NEED_CUDA') == '1' and
1637 'TF_CUDA_CONFIG_REPO' not in environ_cp):
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001638 set_tf_cuda_version(environ_cp)
Yifei Fengb1d8c592017-11-22 13:42:21 -08001639 set_tf_cudnn_version(environ_cp)
Guangda Lai76f69382018-01-25 23:59:19 -08001640 if is_linux():
1641 set_tf_tensorrt_install_path(environ_cp)
Michael Case0073d132018-04-11 09:34:44 -07001642 set_tf_nccl_install_path(environ_cp)
1643
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001644 set_tf_cuda_compute_capabilities(environ_cp)
Ankur Taly0e6f39d2018-02-16 18:22:55 -08001645 if 'LD_LIBRARY_PATH' in environ_cp and environ_cp.get(
1646 'LD_LIBRARY_PATH') != '1':
1647 write_action_env_to_bazelrc('LD_LIBRARY_PATH',
1648 environ_cp.get('LD_LIBRARY_PATH'))
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001649
1650 set_tf_cuda_clang(environ_cp)
1651 if environ_cp.get('TF_CUDA_CLANG') == '1':
Ilya Biryukov9e651e42018-03-22 05:33:42 -07001652 # Ask whether we should download the clang toolchain.
1653 set_tf_download_clang(environ_cp)
A. Unique TensorFlowerfd29e952017-12-22 03:07:51 -08001654 if environ_cp.get('TF_DOWNLOAD_CLANG') != '1':
1655 # Set up which clang we should use as the cuda / host compiler.
1656 set_clang_cuda_compiler_path(environ_cp)
Ilya Biryukov1c3d02e2018-09-04 03:09:52 -07001657 else:
1658 # Use downloaded LLD for linking.
1659 write_to_bazelrc('build:cuda_clang --config=download_clang_use_lld')
1660 write_to_bazelrc('test:cuda_clang --config=download_clang_use_lld')
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001661 else:
1662 # Set up which gcc nvcc should use as the host compiler
1663 # No need to set this on Windows
1664 if not is_windows():
1665 set_gcc_host_compiler_path(environ_cp)
1666 set_other_cuda_vars(environ_cp)
Ilya Biryukov9e651e42018-03-22 05:33:42 -07001667 else:
1668 # CUDA not required. Ask whether we should download the clang toolchain and
1669 # use it for the CPU build.
1670 set_tf_download_clang(environ_cp)
1671 if environ_cp.get('TF_DOWNLOAD_CLANG') == '1':
1672 write_to_bazelrc('build --config=download_clang')
1673 write_to_bazelrc('test --config=download_clang')
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001674
Wen-Heng (Jack) Chung69d3b8f2018-06-22 23:09:43 -05001675 # SYCL / ROCm / CUDA are mutually exclusive.
1676 # At most 1 GPU platform can be configured.
1677 gpu_platform_count = 0
1678 if environ_cp.get('TF_NEED_OPENCL_SYCL') == '1':
1679 gpu_platform_count += 1
1680 if environ_cp.get('TF_NEED_ROCM') == '1':
1681 gpu_platform_count += 1
1682 if environ_cp.get('TF_NEED_CUDA') == '1':
1683 gpu_platform_count += 1
1684 if gpu_platform_count >= 2:
1685 raise UserInputError('SYCL / CUDA / ROCm are mututally exclusive. '
1686 'At most 1 GPU platform can be configured.')
1687
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001688 set_build_var(environ_cp, 'TF_NEED_MPI', 'MPI', 'with_mpi_support', False)
1689 if environ_cp.get('TF_NEED_MPI') == '1':
1690 set_mpi_home(environ_cp)
1691 set_other_mpi_vars(environ_cp)
1692
1693 set_cc_opt_flags(environ_cp)
Yifei Feng5198cb82018-08-17 13:53:06 -07001694 set_system_libs_flag(environ_cp)
A. Unique TensorFlower1b212352018-07-19 13:48:50 -07001695 if is_windows():
1696 set_windows_build_flags(environ_cp)
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001697
Anna Ra9a1d5a2018-09-14 12:44:31 -07001698 # Add a config option to build TensorFlow 2.0 API.
1699 write_to_bazelrc('build:v2 --define=tf_api_version=2')
1700
Gunhan Gulsoyffa90fc2018-09-26 01:38:55 -07001701 if get_var(environ_cp, 'TF_SET_ANDROID_WORKSPACE', 'android workspace', False,
1702 ('Would you like to interactively configure ./WORKSPACE for '
1703 'Android builds?'), 'Searching for NDK and SDK installations.',
1704 'Not configuring the WORKSPACE for Android builds.'):
Michael Case51053502018-06-05 17:47:19 -07001705 create_android_ndk_rule(environ_cp)
1706 create_android_sdk_rule(environ_cp)
Austin Anderson6afface2017-12-05 11:59:17 -08001707
A. Unique TensorFlower93e70732019-02-14 16:45:32 -08001708 if get_var(
1709 environ_cp, 'TF_CONFIGURE_APPLE_BAZEL_RULES',
1710 'Configure Bazel rules for Apple platforms', False,
1711 ('Would you like to configure Bazel rules for building on Apple platforms?'
1712 ), 'Configuring Bazel rules for Apple platforms.',
1713 'Not configuring Bazel rules for Apple platforms.'):
1714 configure_apple_bazel_rules()
1715
Gunhan Gulsoy34370982018-10-12 15:26:01 -07001716 print('Preconfigured Bazel build configs. You can use any of the below by '
1717 'adding "--config=<>" to your build command. See .bazelrc for more '
1718 'details.')
1719 config_info_line('mkl', 'Build with MKL support.')
1720 config_info_line('monolithic', 'Config for mostly static monolithic build.')
1721 config_info_line('gdr', 'Build with GDR support.')
1722 config_info_line('verbs', 'Build with libverbs support.')
1723 config_info_line('ngraph', 'Build with Intel nGraph support.')
TensorFlower Gardenerabb763b2019-02-06 16:23:03 -08001724 config_info_line(
1725 'dynamic_kernels',
1726 '(Experimental) Build kernels into separate shared objects.')
Gunhan Gulsoy34370982018-10-12 15:26:01 -07001727
1728 print('Preconfigured Bazel build configs to DISABLE default on features:')
1729 config_info_line('noaws', 'Disable AWS S3 filesystem support.')
1730 config_info_line('nogcp', 'Disable GCP support.')
1731 config_info_line('nohdfs', 'Disable HDFS support.')
Penporn Koanantakool489f1dc2019-01-10 22:07:22 -08001732 config_info_line('noignite', 'Disable Apache Ignite support.')
Gunhan Gulsoy34370982018-10-12 15:26:01 -07001733 config_info_line('nokafka', 'Disable Apache Kafka support.')
Gunhan Gulsoyeea81682018-11-26 16:51:23 -08001734 config_info_line('nonccl', 'Disable NVIDIA NCCL support.')
Austin Anderson6afface2017-12-05 11:59:17 -08001735
Gunhan Gulsoyffa90fc2018-09-26 01:38:55 -07001736
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001737if __name__ == '__main__':
1738 main()