@@ -492,7 +492,8 @@ def set_tf_cuda_clang(environ_cp):
492492 question = question ,
493493 yes_reply = yes_reply ,
494494 no_reply = no_reply ,
495- bazel_config_name = 'cuda_clang' )
495+ bazel_config_name = 'cuda_clang' ,
496+ )
496497
497498
498499def set_tf_download_clang (environ_cp ):
@@ -751,17 +752,21 @@ def get_ndk_api_level(environ_cp, android_ndk_home_path):
751752
752753 def valid_api_level (api_level ):
753754 return os .path .exists (
754- os .path .join (android_ndk_home_path , 'platforms' ,
755- 'android-' + api_level ) )
755+ os .path .join (android_ndk_home_path , 'platforms' , 'android-' + api_level )
756+ )
756757
757758 android_ndk_api_level = prompt_loop_or_load_from_env (
758759 environ_cp ,
759760 var_name = 'ANDROID_NDK_API_LEVEL' ,
760761 var_default = '26' , # 26 is required to support AHardwareBuffer.
761- ask_for_var = ('Please specify the (min) Android NDK API level to use. '
762- '[Available levels: %s]' ) % api_levels ,
762+ ask_for_var = (
763+ 'Please specify the (min) Android NDK API level to use. '
764+ '[Available levels: %s]'
765+ )
766+ % api_levels ,
763767 check_success = valid_api_level ,
764- error_msg = 'Android-%s is not present in the NDK path.' )
768+ error_msg = 'Android-%s is not present in the NDK path.' ,
769+ )
765770
766771 return android_ndk_api_level
767772
@@ -789,6 +794,91 @@ def set_gcc_host_compiler_path(environ_cp):
789794 write_action_env_to_bazelrc ('GCC_HOST_COMPILER_PATH' , gcc_host_compiler_path )
790795
791796
797+ def choose_compiler (environ_cp ):
798+ question = 'Do you want to use Clang to build TensorFlow?'
799+ yes_reply = 'Clang will be used to compile TensorFlow.'
800+ no_reply = 'GCC will be used to compile TensorFlow.'
801+ var = int (
802+ get_var (
803+ environ_cp , 'TF_NEED_CLANG' , None , True , question , yes_reply , no_reply
804+ )
805+ )
806+ return var
807+
808+
809+ def set_clang_compiler_path (environ_cp ):
810+ """Set CLANG_COMPILER_PATH and environment variables.
811+
812+ Loop over user prompts for clang path until receiving a valid response.
813+ Default is used if no input is given. Set CLANG_COMPILER_PATH and write
814+ environment variables CC and BAZEL_COMPILER to .bazelrc.
815+
816+ Args:
817+ environ_cp: (Dict) copy of the os.environ.
818+
819+ Returns:
820+ string value for clang_compiler_path.
821+ """
822+ # Default path if clang-16 is installed by using apt-get install
823+ default_clang_path = '/usr/lib/llvm-16/bin/clang'
824+ if not os .path .exists (default_clang_path ):
825+ default_clang_path = which ('clang' ) or ''
826+
827+ clang_compiler_path = prompt_loop_or_load_from_env (
828+ environ_cp ,
829+ var_name = 'CLANG_COMPILER_PATH' ,
830+ var_default = default_clang_path ,
831+ ask_for_var = 'Please specify the path to clang executable.' ,
832+ check_success = os .path .exists ,
833+ resolve_symlinks = True ,
834+ error_msg = 'Invalid clang path. %s cannot be found.' ,
835+ )
836+
837+ write_action_env_to_bazelrc ('CLANG_COMPILER_PATH' , clang_compiler_path )
838+ write_to_bazelrc ('build --repo_env=CC=%s' % clang_compiler_path )
839+ write_to_bazelrc ('build --repo_env=BAZEL_COMPILER=%s' % clang_compiler_path )
840+
841+ return clang_compiler_path
842+
843+
844+ def retrieve_clang_version (clang_executable ):
845+ """Retrieve installed clang version.
846+
847+ Args:
848+ clang_executable: (String) path to clang executable
849+
850+ Returns:
851+ The clang version detected.
852+ """
853+ stderr = open (os .devnull , 'wb' )
854+ curr_version = run_shell ([clang_executable , '--version' ],
855+ allow_non_zero = True ,
856+ stderr = stderr )
857+
858+ curr_version_split = curr_version .lower ().split ('clang version ' )
859+ if len (curr_version_split ) > 1 :
860+ curr_version = curr_version_split [1 ].split ()[0 ]
861+
862+ curr_version_int = convert_version_to_int (curr_version )
863+ # Check if current clang version can be detected properly.
864+ if not curr_version_int :
865+ print ('WARNING: current clang installation is not a release version.\n ' )
866+ return None
867+
868+ print ('You have Clang %s installed.\n ' % curr_version )
869+ return curr_version
870+
871+
872+ # Disable clang extension that rejects type definitions within offsetof.
873+ # This was added in clang-16 by https://reviews.llvm.org/D133574.
874+ # Can be removed once upb is updated, since a type definition is used within
875+ # offset of in the current version of ubp. See
876+ # https://github.com/protocolbuffers/upb/blob/9effcbcb27f0a665f9f345030188c0b291e32482/upb/upb.c#L183.
877+ def disable_clang16_offsetof_extension (clang_version ):
878+ if int (clang_version .split ('.' )[0 ]) == 16 :
879+ write_to_bazelrc ('build --copt=-Wno-gnu-offsetof-extensions' )
880+
881+
792882def set_tf_cuda_paths (environ_cp ):
793883 """Set TF_CUDA_PATHS."""
794884 ask_cuda_paths = (
@@ -949,8 +1039,9 @@ def set_tf_cuda_compute_capabilities(environ_cp):
9491039
9501040 # Set TF_CUDA_COMPUTE_CAPABILITIES
9511041 environ_cp ['TF_CUDA_COMPUTE_CAPABILITIES' ] = tf_cuda_compute_capabilities
952- write_action_env_to_bazelrc ('TF_CUDA_COMPUTE_CAPABILITIES' ,
953- tf_cuda_compute_capabilities )
1042+ write_action_env_to_bazelrc (
1043+ 'TF_CUDA_COMPUTE_CAPABILITIES' , tf_cuda_compute_capabilities
1044+ )
9541045
9551046
9561047def set_other_cuda_vars (environ_cp ):
@@ -1308,9 +1399,13 @@ def main():
13081399 set_gcc_host_compiler_path (environ_cp )
13091400 set_other_cuda_vars (environ_cp )
13101401 else :
1311- # CUDA not required. Ask whether we should download the clang toolchain and
1312- # use it for the CPU build.
1313- set_tf_download_clang (environ_cp )
1402+ # CUDA not required. Ask whether we should use clang for the CPU build.
1403+ if is_linux ():
1404+ environ_cp ['TF_NEED_CLANG' ] = str (choose_compiler (environ_cp ))
1405+ if environ_cp .get ('TF_NEED_CLANG' ) == '1' :
1406+ clang_compiler_path = set_clang_compiler_path (environ_cp )
1407+ clang_version = retrieve_clang_version (clang_compiler_path )
1408+ disable_clang16_offsetof_extension (clang_version )
13141409
13151410 # ROCm / CUDA are mutually exclusive.
13161411 # At most 1 GPU platform can be configured.
0 commit comments