blob: 61fa9feaded7e98c531b620891443ba77f182e9b [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 '
1283 'Cuda compute capabilities you want to '
1284 '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 '
A. Unique TensorFlower1b212352018-07-19 13:48:50 -07001289 'build time and binary size. [Default is: %s]: ' %
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001290 default_cuda_compute_capabilities)
1291 tf_cuda_compute_capabilities = get_from_env_or_user_or_default(
1292 environ_cp, 'TF_CUDA_COMPUTE_CAPABILITIES',
1293 ask_cuda_compute_capabilities, default_cuda_compute_capabilities)
1294 # Check whether all capabilities from the input is valid
1295 all_valid = True
Maciejd0f5bc12018-04-30 22:30:58 -05001296 # Remove all whitespace characters before splitting the string
Michael Case51053502018-06-05 17:47:19 -07001297 # that users may insert by accident, as this will result in error
Maciejd0f5bc12018-04-30 22:30:58 -05001298 tf_cuda_compute_capabilities = ''.join(tf_cuda_compute_capabilities.split())
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001299 for compute_capability in tf_cuda_compute_capabilities.split(','):
Andrew Harp6e3e7d12017-08-21 12:10:44 -07001300 m = re.match('[0-9]+.[0-9]+', compute_capability)
1301 if not m:
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001302 print('Invalid compute capability: ' % compute_capability)
1303 all_valid = False
Andrew Harp6e3e7d12017-08-21 12:10:44 -07001304 else:
1305 ver = int(m.group(0).split('.')[0])
1306 if ver < 3:
1307 print('Only compute capabilities 3.0 or higher are supported.')
1308 all_valid = False
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001309
1310 if all_valid:
1311 break
1312
1313 # Reset and Retry
1314 environ_cp['TF_CUDA_COMPUTE_CAPABILITIES'] = ''
1315
1316 # Set TF_CUDA_COMPUTE_CAPABILITIES
1317 environ_cp['TF_CUDA_COMPUTE_CAPABILITIES'] = tf_cuda_compute_capabilities
1318 write_action_env_to_bazelrc('TF_CUDA_COMPUTE_CAPABILITIES',
1319 tf_cuda_compute_capabilities)
1320
1321
1322def set_other_cuda_vars(environ_cp):
1323 """Set other CUDA related variables."""
A. Unique TensorFlowerab391982018-07-11 04:52:49 -07001324 # If CUDA is enabled, always use GPU during build and test.
1325 if environ_cp.get('TF_CUDA_CLANG') == '1':
1326 write_to_bazelrc('build --config=cuda_clang')
1327 write_to_bazelrc('test --config=cuda_clang')
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001328 else:
A. Unique TensorFlowerab391982018-07-11 04:52:49 -07001329 write_to_bazelrc('build --config=cuda')
1330 write_to_bazelrc('test --config=cuda')
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001331
1332
1333def set_host_cxx_compiler(environ_cp):
1334 """Set HOST_CXX_COMPILER."""
Jonathan Hseu008910f2017-08-25 14:01:05 -07001335 default_cxx_host_compiler = which('g++') or ''
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001336
Austin Anderson6afface2017-12-05 11:59:17 -08001337 host_cxx_compiler = prompt_loop_or_load_from_env(
1338 environ_cp,
1339 var_name='HOST_CXX_COMPILER',
1340 var_default=default_cxx_host_compiler,
1341 ask_for_var=('Please specify which C++ compiler should be used as the '
1342 'host C++ compiler.'),
1343 check_success=os.path.exists,
1344 error_msg='Invalid C++ compiler path. %s cannot be found.',
1345 )
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001346
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001347 write_action_env_to_bazelrc('HOST_CXX_COMPILER', host_cxx_compiler)
1348
1349
1350def set_host_c_compiler(environ_cp):
1351 """Set HOST_C_COMPILER."""
Jonathan Hseu008910f2017-08-25 14:01:05 -07001352 default_c_host_compiler = which('gcc') or ''
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001353
Austin Anderson6afface2017-12-05 11:59:17 -08001354 host_c_compiler = prompt_loop_or_load_from_env(
1355 environ_cp,
1356 var_name='HOST_C_COMPILER',
1357 var_default=default_c_host_compiler,
Shanqing Cai71445712018-03-12 19:33:52 -07001358 ask_for_var=('Please specify which C compiler should be used as the host '
Austin Anderson6afface2017-12-05 11:59:17 -08001359 'C compiler.'),
1360 check_success=os.path.exists,
1361 error_msg='Invalid C compiler path. %s cannot be found.',
1362 )
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001363
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001364 write_action_env_to_bazelrc('HOST_C_COMPILER', host_c_compiler)
1365
1366
1367def set_computecpp_toolkit_path(environ_cp):
1368 """Set COMPUTECPP_TOOLKIT_PATH."""
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001369
Austin Anderson6afface2017-12-05 11:59:17 -08001370 def toolkit_exists(toolkit_path):
1371 """Check if a computecpp toolkit path is valid."""
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001372 if is_linux():
1373 sycl_rt_lib_path = 'lib/libComputeCpp.so'
1374 else:
1375 sycl_rt_lib_path = ''
1376
Gunhan Gulsoyffa90fc2018-09-26 01:38:55 -07001377 sycl_rt_lib_path_full = os.path.join(toolkit_path, sycl_rt_lib_path)
Austin Anderson6afface2017-12-05 11:59:17 -08001378 exists = os.path.exists(sycl_rt_lib_path_full)
1379 if not exists:
1380 print('Invalid SYCL %s library path. %s cannot be found' %
1381 (_TF_OPENCL_VERSION, sycl_rt_lib_path_full))
1382 return exists
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001383
Austin Anderson6afface2017-12-05 11:59:17 -08001384 computecpp_toolkit_path = prompt_loop_or_load_from_env(
1385 environ_cp,
1386 var_name='COMPUTECPP_TOOLKIT_PATH',
1387 var_default=_DEFAULT_COMPUTECPP_TOOLKIT_PATH,
1388 ask_for_var=(
1389 'Please specify the location where ComputeCpp for SYCL %s is '
1390 'installed.' % _TF_OPENCL_VERSION),
1391 check_success=toolkit_exists,
1392 error_msg='Invalid SYCL compiler path. %s cannot be found.',
1393 suppress_default_error=True)
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001394
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001395 write_action_env_to_bazelrc('COMPUTECPP_TOOLKIT_PATH',
1396 computecpp_toolkit_path)
1397
Michael Cased31531a2018-01-05 14:09:41 -08001398
Dandelion Man?90e42f32017-12-15 18:15:07 -08001399def set_trisycl_include_dir(environ_cp):
Michael Cased31531a2018-01-05 14:09:41 -08001400 """Set TRISYCL_INCLUDE_DIR."""
Frank Chenc4ef9272018-01-10 11:36:52 -08001401
Dandelion Man?90e42f32017-12-15 18:15:07 -08001402 ask_trisycl_include_dir = ('Please specify the location of the triSYCL '
1403 'include directory. (Use --config=sycl_trisycl '
1404 'when building with Bazel) '
Gunhan Gulsoyffa90fc2018-09-26 01:38:55 -07001405 '[Default is %s]: ') % (
1406 _DEFAULT_TRISYCL_INCLUDE_DIR)
Frank Chenc4ef9272018-01-10 11:36:52 -08001407
Dandelion Man?90e42f32017-12-15 18:15:07 -08001408 while True:
1409 trisycl_include_dir = get_from_env_or_user_or_default(
Michael Cased31531a2018-01-05 14:09:41 -08001410 environ_cp, 'TRISYCL_INCLUDE_DIR', ask_trisycl_include_dir,
1411 _DEFAULT_TRISYCL_INCLUDE_DIR)
Dandelion Man?90e42f32017-12-15 18:15:07 -08001412 if os.path.exists(trisycl_include_dir):
1413 break
1414
Gunhan Gulsoyffa90fc2018-09-26 01:38:55 -07001415 print('Invalid triSYCL include directory, %s cannot be found' %
1416 (trisycl_include_dir))
Dandelion Man?90e42f32017-12-15 18:15:07 -08001417
1418 # Set TRISYCL_INCLUDE_DIR
1419 environ_cp['TRISYCL_INCLUDE_DIR'] = trisycl_include_dir
Gunhan Gulsoyffa90fc2018-09-26 01:38:55 -07001420 write_action_env_to_bazelrc('TRISYCL_INCLUDE_DIR', trisycl_include_dir)
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001421
Yifei Fengb1d8c592017-11-22 13:42:21 -08001422
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001423def set_mpi_home(environ_cp):
1424 """Set MPI_HOME."""
Austin Anderson6afface2017-12-05 11:59:17 -08001425
Jonathan Hseu008910f2017-08-25 14:01:05 -07001426 default_mpi_home = which('mpirun') or which('mpiexec') or ''
1427 default_mpi_home = os.path.dirname(os.path.dirname(default_mpi_home))
1428
Austin Anderson6afface2017-12-05 11:59:17 -08001429 def valid_mpi_path(mpi_home):
Gunhan Gulsoyffa90fc2018-09-26 01:38:55 -07001430 exists = (
1431 os.path.exists(os.path.join(mpi_home, 'include')) and
TensorFlower Gardenerf7c861f2018-11-01 11:29:40 -07001432 (os.path.exists(os.path.join(mpi_home, 'lib')) or
1433 os.path.exists(os.path.join(mpi_home, 'lib64')) or
1434 os.path.exists(os.path.join(mpi_home, 'lib32'))))
Austin Anderson6afface2017-12-05 11:59:17 -08001435 if not exists:
TensorFlower Gardenerf7c861f2018-11-01 11:29:40 -07001436 print(
1437 'Invalid path to the MPI Toolkit. %s or %s or %s or %s cannot be found'
1438 % (os.path.join(mpi_home, 'include'),
Christian Gollba95d092018-10-04 17:06:23 +02001439 os.path.exists(os.path.join(mpi_home, 'lib')),
1440 os.path.exists(os.path.join(mpi_home, 'lib64')),
1441 os.path.exists(os.path.join(mpi_home, 'lib32'))))
Austin Anderson6afface2017-12-05 11:59:17 -08001442 return exists
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001443
Austin Anderson6afface2017-12-05 11:59:17 -08001444 _ = prompt_loop_or_load_from_env(
1445 environ_cp,
1446 var_name='MPI_HOME',
1447 var_default=default_mpi_home,
1448 ask_for_var='Please specify the MPI toolkit folder.',
1449 check_success=valid_mpi_path,
1450 error_msg='',
1451 suppress_default_error=True)
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001452
1453
1454def set_other_mpi_vars(environ_cp):
1455 """Set other MPI related variables."""
1456 # Link the MPI header files
1457 mpi_home = environ_cp.get('MPI_HOME')
1458 symlink_force('%s/include/mpi.h' % mpi_home, 'third_party/mpi/mpi.h')
1459
1460 # Determine if we use OpenMPI or MVAPICH, these require different header files
1461 # to be included here to make bazel dependency checker happy
1462 if os.path.exists(os.path.join(mpi_home, 'include/mpi_portable_platform.h')):
1463 symlink_force(
1464 os.path.join(mpi_home, 'include/mpi_portable_platform.h'),
1465 'third_party/mpi/mpi_portable_platform.h')
1466 # TODO(gunan): avoid editing files in configure
1467 sed_in_place('third_party/mpi/mpi.bzl', 'MPI_LIB_IS_OPENMPI=False',
1468 'MPI_LIB_IS_OPENMPI=True')
1469 else:
1470 # MVAPICH / MPICH
1471 symlink_force(
1472 os.path.join(mpi_home, 'include/mpio.h'), 'third_party/mpi/mpio.h')
1473 symlink_force(
1474 os.path.join(mpi_home, 'include/mpicxx.h'), 'third_party/mpi/mpicxx.h')
1475 # TODO(gunan): avoid editing files in configure
1476 sed_in_place('third_party/mpi/mpi.bzl', 'MPI_LIB_IS_OPENMPI=True',
1477 'MPI_LIB_IS_OPENMPI=False')
1478
1479 if os.path.exists(os.path.join(mpi_home, 'lib/libmpi.so')):
1480 symlink_force(
1481 os.path.join(mpi_home, 'lib/libmpi.so'), 'third_party/mpi/libmpi.so')
Christian Gollba95d092018-10-04 17:06:23 +02001482 elif os.path.exists(os.path.join(mpi_home, 'lib64/libmpi.so')):
1483 symlink_force(
1484 os.path.join(mpi_home, 'lib64/libmpi.so'), 'third_party/mpi/libmpi.so')
1485 elif os.path.exists(os.path.join(mpi_home, 'lib32/libmpi.so')):
1486 symlink_force(
1487 os.path.join(mpi_home, 'lib32/libmpi.so'), 'third_party/mpi/libmpi.so')
1488
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001489 else:
TensorFlower Gardenerf7c861f2018-11-01 11:29:40 -07001490 raise ValueError(
1491 'Cannot find the MPI library file in %s/lib or %s/lib64 or %s/lib32' %
Mihai Maruseac91ebeec2019-01-29 17:07:38 -08001492 (mpi_home, mpi_home, mpi_home))
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001493
1494
Yifei Feng5198cb82018-08-17 13:53:06 -07001495def set_system_libs_flag(environ_cp):
1496 syslibs = environ_cp.get('TF_SYSTEM_LIBS', '')
TensorFlower Gardener61a87202018-10-01 12:25:39 -07001497 if syslibs:
Jason Zaman5fc39bd2018-09-16 01:38:55 +08001498 if ',' in syslibs:
1499 syslibs = ','.join(sorted(syslibs.split(',')))
1500 else:
1501 syslibs = ','.join(sorted(syslibs.split()))
Yifei Feng5198cb82018-08-17 13:53:06 -07001502 write_action_env_to_bazelrc('TF_SYSTEM_LIBS', syslibs)
1503
Jason Zaman5fc39bd2018-09-16 01:38:55 +08001504 if 'PREFIX' in environ_cp:
1505 write_to_bazelrc('build --define=PREFIX=%s' % environ_cp['PREFIX'])
1506 if 'LIBDIR' in environ_cp:
1507 write_to_bazelrc('build --define=LIBDIR=%s' % environ_cp['LIBDIR'])
1508 if 'INCLUDEDIR' in environ_cp:
1509 write_to_bazelrc('build --define=INCLUDEDIR=%s' % environ_cp['INCLUDEDIR'])
1510
Yifei Feng5198cb82018-08-17 13:53:06 -07001511
A. Unique TensorFlower1b212352018-07-19 13:48:50 -07001512def set_windows_build_flags(environ_cp):
1513 """Set Windows specific build options."""
1514 # The non-monolithic build is not supported yet
1515 write_to_bazelrc('build --config monolithic')
1516 # Suppress warning messages
1517 write_to_bazelrc('build --copt=-w --host_copt=-w')
1518 # Output more verbose information when something goes wrong
1519 write_to_bazelrc('build --verbose_failures')
1520 # The host and target platforms are the same in Windows build. So we don't
1521 # have to distinct them. This avoids building the same targets twice.
1522 write_to_bazelrc('build --distinct_host_configuration=false')
A. Unique TensorFlower1b212352018-07-19 13:48:50 -07001523
1524 if get_var(
1525 environ_cp, 'TF_OVERRIDE_EIGEN_STRONG_INLINE', 'Eigen strong inline',
Gunhan Gulsoyffa90fc2018-09-26 01:38:55 -07001526 True, ('Would you like to override eigen strong inline for some C++ '
1527 'compilation to reduce the compilation time?'),
1528 'Eigen strong inline overridden.', 'Not overriding eigen strong inline, '
A. Unique TensorFlower1b212352018-07-19 13:48:50 -07001529 'some compilations could take more than 20 mins.'):
1530 # Due to a known MSVC compiler issue
1531 # https://github.com/tensorflow/tensorflow/issues/10521
1532 # Overriding eigen strong inline speeds up the compiling of
1533 # conv_grad_ops_3d.cc and conv_ops_3d.cc by 20 minutes,
1534 # but this also hurts the performance. Let users decide what they want.
1535 write_to_bazelrc('build --define=override_eigen_strong_inline=true')
Dandelion Man?90e42f32017-12-15 18:15:07 -08001536
A. Unique TensorFlower061c3592017-11-13 14:21:04 -08001537
Michael Cased31531a2018-01-05 14:09:41 -08001538def config_info_line(name, help_text):
1539 """Helper function to print formatted help text for Bazel config options."""
1540 print('\t--config=%-12s\t# %s' % (name, help_text))
1541
1542
A. Unique TensorFlower93e70732019-02-14 16:45:32 -08001543def configure_apple_bazel_rules():
1544 """Configures Bazel rules for building on Apple platforms.
1545
1546 Enables analyzing and building Apple Bazel rules on Apple platforms. This
1547 function will only be executed if `is_macos()` is true.
1548 """
1549 if not is_macos():
1550 return
1551 for filepath in APPLE_BAZEL_FILES:
1552 print(
1553 'Configuring %s file to analyze and build Bazel rules on Apple platforms.'
1554 % filepath)
1555 existing_filepath = os.path.join(_TF_WORKSPACE_ROOT, filepath + '.apple')
1556 renamed_filepath = os.path.join(_TF_WORKSPACE_ROOT, filepath)
1557 os.rename(existing_filepath, renamed_filepath)
1558
1559
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001560def main():
A. Unique TensorFlower7c5eb352018-10-01 07:15:23 -07001561 global _TF_WORKSPACE_ROOT
1562 global _TF_BAZELRC
1563
Shanqing Cai71445712018-03-12 19:33:52 -07001564 parser = argparse.ArgumentParser()
Gunhan Gulsoyffa90fc2018-09-26 01:38:55 -07001565 parser.add_argument(
1566 '--workspace',
1567 type=str,
A. Unique TensorFlower7c5eb352018-10-01 07:15:23 -07001568 default=os.path.abspath(os.path.dirname(__file__)),
Gunhan Gulsoyffa90fc2018-09-26 01:38:55 -07001569 help='The absolute path to your active Bazel workspace.')
Shanqing Cai71445712018-03-12 19:33:52 -07001570 args = parser.parse_args()
1571
A. Unique TensorFlower7c5eb352018-10-01 07:15:23 -07001572 _TF_WORKSPACE_ROOT = args.workspace
1573 _TF_BAZELRC = os.path.join(_TF_WORKSPACE_ROOT, _TF_BAZELRC_FILENAME)
1574
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001575 # Make a copy of os.environ to be clear when functions and getting and setting
1576 # environment variables.
1577 environ_cp = dict(os.environ)
1578
Gunhan Gulsoy91da8982019-02-04 13:31:05 -08001579 check_bazel_version('0.19.0', '0.22.0')
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001580
A. Unique TensorFlower7c5eb352018-10-01 07:15:23 -07001581 reset_tf_configure_bazelrc()
Yun Peng03e63a22018-11-07 11:18:53 +01001582
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001583 cleanup_makefile()
Gunhan Gulsoyed89a2b2017-09-19 18:36:26 -07001584 setup_python(environ_cp)
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001585
1586 if is_windows():
Yifei Fengb1d8c592017-11-22 13:42:21 -08001587 environ_cp['TF_NEED_OPENCL_SYCL'] = '0'
1588 environ_cp['TF_NEED_COMPUTECPP'] = '0'
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001589 environ_cp['TF_NEED_OPENCL'] = '0'
1590 environ_cp['TF_CUDA_CLANG'] = '0'
Guangda Lai76f69382018-01-25 23:59:19 -08001591 environ_cp['TF_NEED_TENSORRT'] = '0'
Ilya Biryukov9e651e42018-03-22 05:33:42 -07001592 # TODO(ibiryukov): Investigate using clang as a cpu or cuda compiler on
1593 # Windows.
1594 environ_cp['TF_DOWNLOAD_CLANG'] = '0'
A. Unique TensorFlower6e97fb32018-07-16 14:07:29 -07001595 environ_cp['TF_NEED_MPI'] = '0'
1596 environ_cp['TF_SET_ANDROID_WORKSPACE'] = '0'
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001597
1598 if is_macos():
Guangda Lai76f69382018-01-25 23:59:19 -08001599 environ_cp['TF_NEED_TENSORRT'] = '0'
A. Unique TensorFlower93e70732019-02-14 16:45:32 -08001600 else:
1601 environ_cp['TF_CONFIGURE_APPLE_BAZEL_RULES'] = '0'
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001602
Jon Triebenbach6896a742018-06-27 13:29:53 -05001603 # The numpy package on ppc64le uses OpenBLAS which has multi-threading
1604 # issues that lead to incorrect answers. Set OMP_NUM_THREADS=1 at
1605 # runtime to allow the Tensorflow testcases which compare numpy
1606 # results to Tensorflow results to succeed.
1607 if is_ppc64le():
Gunhan Gulsoyffa90fc2018-09-26 01:38:55 -07001608 write_action_env_to_bazelrc('OMP_NUM_THREADS', 1)
Jon Triebenbach6896a742018-06-27 13:29:53 -05001609
Grzegorz Pawelczakec82efd2018-10-09 15:03:46 +01001610 xla_enabled_by_default = is_linux()
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001611 set_build_var(environ_cp, 'TF_ENABLE_XLA', 'XLA JIT', 'with_xla_support',
Grzegorz Pawelczakec82efd2018-10-09 15:03:46 +01001612 xla_enabled_by_default, 'xla')
Gunhan Gulsoy3da0dff2018-09-26 11:55:50 -07001613
Yifei Fengb1d8c592017-11-22 13:42:21 -08001614 set_action_env_var(environ_cp, 'TF_NEED_OPENCL_SYCL', 'OpenCL SYCL', False)
1615 if environ_cp.get('TF_NEED_OPENCL_SYCL') == '1':
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001616 set_host_cxx_compiler(environ_cp)
1617 set_host_c_compiler(environ_cp)
Yifei Fengb1d8c592017-11-22 13:42:21 -08001618 set_action_env_var(environ_cp, 'TF_NEED_COMPUTECPP', 'ComputeCPP', True)
1619 if environ_cp.get('TF_NEED_COMPUTECPP') == '1':
1620 set_computecpp_toolkit_path(environ_cp)
1621 else:
1622 set_trisycl_include_dir(environ_cp)
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001623
Wen-Heng (Jack) Chung69d3b8f2018-06-22 23:09:43 -05001624 set_action_env_var(environ_cp, 'TF_NEED_ROCM', 'ROCm', False)
1625 if (environ_cp.get('TF_NEED_ROCM') == '1' and
TensorFlower Gardener62e60162018-09-27 10:22:55 -07001626 'LD_LIBRARY_PATH' in environ_cp and
1627 environ_cp.get('LD_LIBRARY_PATH') != '1'):
1628 write_action_env_to_bazelrc('LD_LIBRARY_PATH',
1629 environ_cp.get('LD_LIBRARY_PATH'))
Wen-Heng (Jack) Chung69d3b8f2018-06-22 23:09:43 -05001630
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001631 set_action_env_var(environ_cp, 'TF_NEED_CUDA', 'CUDA', False)
A. Unique TensorFlower24cbb2a2017-09-08 07:45:44 -07001632 if (environ_cp.get('TF_NEED_CUDA') == '1' and
1633 'TF_CUDA_CONFIG_REPO' not in environ_cp):
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001634 set_tf_cuda_version(environ_cp)
Yifei Fengb1d8c592017-11-22 13:42:21 -08001635 set_tf_cudnn_version(environ_cp)
Guangda Lai76f69382018-01-25 23:59:19 -08001636 if is_linux():
1637 set_tf_tensorrt_install_path(environ_cp)
Michael Case0073d132018-04-11 09:34:44 -07001638 set_tf_nccl_install_path(environ_cp)
1639
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001640 set_tf_cuda_compute_capabilities(environ_cp)
Ankur Taly0e6f39d2018-02-16 18:22:55 -08001641 if 'LD_LIBRARY_PATH' in environ_cp and environ_cp.get(
1642 'LD_LIBRARY_PATH') != '1':
1643 write_action_env_to_bazelrc('LD_LIBRARY_PATH',
1644 environ_cp.get('LD_LIBRARY_PATH'))
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001645
1646 set_tf_cuda_clang(environ_cp)
1647 if environ_cp.get('TF_CUDA_CLANG') == '1':
Ilya Biryukov9e651e42018-03-22 05:33:42 -07001648 # Ask whether we should download the clang toolchain.
1649 set_tf_download_clang(environ_cp)
A. Unique TensorFlowerfd29e952017-12-22 03:07:51 -08001650 if environ_cp.get('TF_DOWNLOAD_CLANG') != '1':
1651 # Set up which clang we should use as the cuda / host compiler.
1652 set_clang_cuda_compiler_path(environ_cp)
Ilya Biryukov1c3d02e2018-09-04 03:09:52 -07001653 else:
1654 # Use downloaded LLD for linking.
1655 write_to_bazelrc('build:cuda_clang --config=download_clang_use_lld')
1656 write_to_bazelrc('test:cuda_clang --config=download_clang_use_lld')
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001657 else:
1658 # Set up which gcc nvcc should use as the host compiler
1659 # No need to set this on Windows
1660 if not is_windows():
1661 set_gcc_host_compiler_path(environ_cp)
1662 set_other_cuda_vars(environ_cp)
Ilya Biryukov9e651e42018-03-22 05:33:42 -07001663 else:
1664 # CUDA not required. Ask whether we should download the clang toolchain and
1665 # use it for the CPU build.
1666 set_tf_download_clang(environ_cp)
1667 if environ_cp.get('TF_DOWNLOAD_CLANG') == '1':
1668 write_to_bazelrc('build --config=download_clang')
1669 write_to_bazelrc('test --config=download_clang')
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001670
Wen-Heng (Jack) Chung69d3b8f2018-06-22 23:09:43 -05001671 # SYCL / ROCm / CUDA are mutually exclusive.
1672 # At most 1 GPU platform can be configured.
1673 gpu_platform_count = 0
1674 if environ_cp.get('TF_NEED_OPENCL_SYCL') == '1':
1675 gpu_platform_count += 1
1676 if environ_cp.get('TF_NEED_ROCM') == '1':
1677 gpu_platform_count += 1
1678 if environ_cp.get('TF_NEED_CUDA') == '1':
1679 gpu_platform_count += 1
1680 if gpu_platform_count >= 2:
1681 raise UserInputError('SYCL / CUDA / ROCm are mututally exclusive. '
1682 'At most 1 GPU platform can be configured.')
1683
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001684 set_build_var(environ_cp, 'TF_NEED_MPI', 'MPI', 'with_mpi_support', False)
1685 if environ_cp.get('TF_NEED_MPI') == '1':
1686 set_mpi_home(environ_cp)
1687 set_other_mpi_vars(environ_cp)
1688
1689 set_cc_opt_flags(environ_cp)
Yifei Feng5198cb82018-08-17 13:53:06 -07001690 set_system_libs_flag(environ_cp)
A. Unique TensorFlower1b212352018-07-19 13:48:50 -07001691 if is_windows():
1692 set_windows_build_flags(environ_cp)
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001693
Anna Ra9a1d5a2018-09-14 12:44:31 -07001694 # Add a config option to build TensorFlow 2.0 API.
1695 write_to_bazelrc('build:v2 --define=tf_api_version=2')
1696
Gunhan Gulsoyffa90fc2018-09-26 01:38:55 -07001697 if get_var(environ_cp, 'TF_SET_ANDROID_WORKSPACE', 'android workspace', False,
1698 ('Would you like to interactively configure ./WORKSPACE for '
1699 'Android builds?'), 'Searching for NDK and SDK installations.',
1700 'Not configuring the WORKSPACE for Android builds.'):
Michael Case51053502018-06-05 17:47:19 -07001701 create_android_ndk_rule(environ_cp)
1702 create_android_sdk_rule(environ_cp)
Austin Anderson6afface2017-12-05 11:59:17 -08001703
A. Unique TensorFlower93e70732019-02-14 16:45:32 -08001704 if get_var(
1705 environ_cp, 'TF_CONFIGURE_APPLE_BAZEL_RULES',
1706 'Configure Bazel rules for Apple platforms', False,
1707 ('Would you like to configure Bazel rules for building on Apple platforms?'
1708 ), 'Configuring Bazel rules for Apple platforms.',
1709 'Not configuring Bazel rules for Apple platforms.'):
1710 configure_apple_bazel_rules()
1711
Gunhan Gulsoy34370982018-10-12 15:26:01 -07001712 print('Preconfigured Bazel build configs. You can use any of the below by '
1713 'adding "--config=<>" to your build command. See .bazelrc for more '
1714 'details.')
1715 config_info_line('mkl', 'Build with MKL support.')
1716 config_info_line('monolithic', 'Config for mostly static monolithic build.')
1717 config_info_line('gdr', 'Build with GDR support.')
1718 config_info_line('verbs', 'Build with libverbs support.')
1719 config_info_line('ngraph', 'Build with Intel nGraph support.')
TensorFlower Gardenerabb763b2019-02-06 16:23:03 -08001720 config_info_line(
1721 'dynamic_kernels',
1722 '(Experimental) Build kernels into separate shared objects.')
Gunhan Gulsoy34370982018-10-12 15:26:01 -07001723
1724 print('Preconfigured Bazel build configs to DISABLE default on features:')
1725 config_info_line('noaws', 'Disable AWS S3 filesystem support.')
1726 config_info_line('nogcp', 'Disable GCP support.')
1727 config_info_line('nohdfs', 'Disable HDFS support.')
Penporn Koanantakool489f1dc2019-01-10 22:07:22 -08001728 config_info_line('noignite', 'Disable Apache Ignite support.')
Gunhan Gulsoy34370982018-10-12 15:26:01 -07001729 config_info_line('nokafka', 'Disable Apache Kafka support.')
Gunhan Gulsoyeea81682018-11-26 16:51:23 -08001730 config_info_line('nonccl', 'Disable NVIDIA NCCL support.')
Austin Anderson6afface2017-12-05 11:59:17 -08001731
Gunhan Gulsoyffa90fc2018-09-26 01:38:55 -07001732
A. Unique TensorFlower73ea2872017-07-25 13:30:03 -07001733if __name__ == '__main__':
1734 main()