diff --git a/configure.sh b/configure.sh index e85d577..2720c79 100755 --- a/configure.sh +++ b/configure.sh @@ -62,17 +62,32 @@ if is_windows; then echo "On windows, skipping toolchain flags.." else while [[ "$PIP_MANYLINUX2010" == "" ]]; do - read -p "Does the pip package have tag manylinux2010 (usually the case for nightly release after Aug 1, 2019, or official releases past 1.14.0)?"\ - " Y or enter for manylinux2010, N for manylinux1. [Y/n] " INPUT + read -p "Does the pip package have tag manylinux2010 (usually the case for nightly release after Aug 1, 2019, or official releases past 1.14.0)?. Y or enter for manylinux2010, N for manylinux1. [Y/n] " INPUT case $INPUT in - [Yy]* ) echo "Build against pip package with manylinux2010 tag. --crosstool_top=//third_party/toolchains/preconfig/ubuntu16.04/gcc7_manylinux2010-nvcc-cuda10.0:toolchain will be added to bazel command."; PIP_MANYLINUX2010=1;; - [Nn]* ) echo "Build against pip package with manylinux1."; PIP_MANYLINUX2010=0;; - "" ) echo "Build against pip package with manylinux2010 tag. --crosstool_top=//third_party/toolchains/preconfig/ubuntu16.04/gcc7_manylinux2010-nvcc-cuda10.0:toolchain will be added to bazel command."; PIP_MANYLINUX2010=1;; + [Yy]* ) PIP_MANYLINUX2010=1;; + [Nn]* ) PIP_MANYLINUX2010=0;; + "" ) PIP_MANYLINUX2010=1;; * ) echo "Invalid selection: " $INPUT;; esac done + + if [[ "$PIP_MANYLINUX2010" == "1" ]]; then + while [[ "$TF_CUDA_VERSION" == "" ]]; do + read -p "Are you building against TensorFlow 2.1(including RCs) or newer?[Y/n] " INPUT + case $INPUT in + [Yy]* ) echo "Build with the latest manylinux2010 compatible toolchains."; TF_CUDA_VERSION=10.1;; + [Nn]* ) echo "Build with prvious manylinux2010 compatible toolchains."; TF_CUDA_VERSION=10.0;; + "" ) echo "Build with the latest manylinux2010 compatible toolchains."; TF_CUDA_VERSION=10.1;; + * ) echo "Invalid selection: " $INPUT;; + esac + done + fi fi + + + + # CPU if [[ "$TF_NEED_CUDA" == "0" ]]; then @@ -123,7 +138,9 @@ if is_linux; then if [[ "$PIP_MANYLINUX2010" == "0" ]]; then write_to_bazelrc "build:cuda --crosstool_top=@local_config_cuda//crosstool:toolchain" fi - write_to_bazelrc "build:manylinux2010 --crosstool_top=//third_party/toolchains/preconfig/ubuntu16.04/gcc7_manylinux2010-nvcc-cuda10.0:toolchain" + write_to_bazelrc "build:manylinux2010cuda100 --crosstool_top=//third_party/toolchains/preconfig/ubuntu16.04/gcc7_manylinux2010-nvcc-cuda10.0:toolchain" + write_to_bazelrc "build:manylinux2010cuda101 --crosstool_top=//third_party/toolchains/preconfig/ubuntu16.04/gcc7_manylinux2010-nvcc-cuda10.1:toolchain" + fi write_to_bazelrc "build --spawn_strategy=standalone" write_to_bazelrc "build --strategy=Genrule=standalone" @@ -162,7 +179,7 @@ write_action_env_to_bazelrc "TF_NEED_CUDA" ${TF_NEED_CUDA} # TODO(yifeif): do not hardcode path if [[ "$TF_NEED_CUDA" == "1" ]]; then write_action_env_to_bazelrc "CUDNN_INSTALL_PATH" "/usr/lib/x86_64-linux-gnu" - write_action_env_to_bazelrc "TF_CUDA_VERSION" "10.0" + write_action_env_to_bazelrc "TF_CUDA_VERSION" ${TF_CUDA_VERSION} write_action_env_to_bazelrc "TF_CUDNN_VERSION" "7" write_action_env_to_bazelrc "CUDA_TOOLKIT_PATH" "/usr/local/cuda" write_to_bazelrc "build --config=cuda" @@ -171,6 +188,11 @@ fi if [[ "$PIP_MANYLINUX2010" == "1" ]]; then - write_to_bazelrc "build --config=manylinux2010" - write_to_bazelrc "test --config=manylinux2010" + if [[ "$TF_CUDA_VERSION" == "10.0" ]]; then + write_to_bazelrc "build --config=manylinux2010cuda100" + write_to_bazelrc "test --config=manylinux2010cuda100" + else + write_to_bazelrc "build --config=manylinux2010cuda101" + write_to_bazelrc "test --config=manylinux2010cuda101" + fi fi diff --git a/gpu/crosstool/BUILD.tpl b/gpu/crosstool/BUILD.tpl index 6fe5314..5a78654 100644 --- a/gpu/crosstool/BUILD.tpl +++ b/gpu/crosstool/BUILD.tpl @@ -1,3 +1,8 @@ +# This file is expanded from a template by cuda_configure.bzl +# Update cuda_configure.bzl#verify_build_defines when adding new variables. + +load(":cc_toolchain_config.bzl", "cc_toolchain_config") + licenses(["restricted"]) package(default_visibility = ["//visibility:public"]) @@ -24,6 +29,7 @@ cc_toolchain_suite( "x64_windows|msvc-cl": ":cc-compiler-windows", "x64_windows": ":cc-compiler-windows", "arm": ":cc-compiler-local", + "aarch64": ":cc-compiler-local", "k8": ":cc-compiler-local", "piii": ":cc-compiler-local", "ppc": ":cc-compiler-local", @@ -33,14 +39,13 @@ cc_toolchain_suite( cc_toolchain( name = "cc-compiler-local", - all_files = "%{linker_files}", - compiler_files = ":empty", - cpu = "local", + all_files = "%{compiler_deps}", + compiler_files = "%{compiler_deps}", + ar_files = "%{compiler_deps}", + as_files = "%{compiler_deps}", dwp_files = ":empty", - dynamic_runtime_libs = [":empty"], - linker_files = "%{linker_files}", + linker_files = "%{compiler_deps}", objcopy_files = ":empty", - static_runtime_libs = [":empty"], strip_files = ":empty", # To support linker flags that need to go to the start of command line # we need the toolchain to support parameter files. Parameter files are @@ -48,36 +53,77 @@ cc_toolchain( # regular options will be left of them. supports_param_files = 1, toolchain_identifier = "local_linux", + toolchain_config = ":cc-compiler-local-config", +) + +cc_toolchain_config( + name = "cc-compiler-local-config", + cpu = "local", + builtin_include_directories = [%{cxx_builtin_include_directories}], + extra_no_canonical_prefixes_flags = [%{extra_no_canonical_prefixes_flags}], + host_compiler_path = "%{host_compiler_path}", + host_compiler_prefix = "%{host_compiler_prefix}", + host_compiler_warnings = [%{host_compiler_warnings}], + host_unfiltered_compile_flags = [%{unfiltered_compile_flags}], + linker_bin_path = "%{linker_bin_path}", + builtin_sysroot = "%{builtin_sysroot}", + cuda_path = "%{cuda_toolkit_path}", ) cc_toolchain( name = "cc-compiler-darwin", - all_files = "%{linker_files}", - compiler_files = ":empty", - cpu = "darwin", + all_files = "%{compiler_deps}", + compiler_files = "%{compiler_deps}", + ar_files = "%{compiler_deps}", + as_files = "%{compiler_deps}", dwp_files = ":empty", - dynamic_runtime_libs = [":empty"], - linker_files = "%{linker_files}", + linker_files = "%{compiler_deps}", objcopy_files = ":empty", - static_runtime_libs = [":empty"], strip_files = ":empty", supports_param_files = 0, toolchain_identifier = "local_darwin", + toolchain_config = ":cc-compiler-local-darwin", +) + +cc_toolchain_config( + name = "cc-compiler-local-darwin", + cpu = "darwin", + builtin_include_directories = [%{cxx_builtin_include_directories}], + extra_no_canonical_prefixes_flags = [%{extra_no_canonical_prefixes_flags}], + host_compiler_path = "%{host_compiler_path}", + host_compiler_prefix = "%{host_compiler_prefix}", + host_compiler_warnings = [%{host_compiler_warnings}], + host_unfiltered_compile_flags = [%{unfiltered_compile_flags}], + linker_bin_path = "%{linker_bin_path}", ) cc_toolchain( name = "cc-compiler-windows", - all_files = "%{win_linker_files}", - compiler_files = ":empty", - cpu = "x64_windows", + all_files = "%{win_compiler_deps}", + compiler_files = "%{win_compiler_deps}", + ar_files = "%{win_compiler_deps}", + as_files = "%{win_compiler_deps}", dwp_files = ":empty", - dynamic_runtime_libs = [":empty"], - linker_files = "%{win_linker_files}", + linker_files = "%{win_compiler_deps}", objcopy_files = ":empty", - static_runtime_libs = [":empty"], strip_files = ":empty", supports_param_files = 1, toolchain_identifier = "local_windows", + toolchain_config = ":cc-compiler-windows-config", +) + +cc_toolchain_config( + name = "cc-compiler-windows-config", + cpu = "x64_windows", + builtin_include_directories = [%{cxx_builtin_include_directories}], + msvc_cl_path = "%{msvc_cl_path}", + msvc_env_include = "%{msvc_env_include}", + msvc_env_lib = "%{msvc_env_lib}", + msvc_env_path = "%{msvc_env_path}", + msvc_env_tmp = "%{msvc_env_tmp}", + msvc_lib_path = "%{msvc_lib_path}", + msvc_link_path = "%{msvc_link_path}", + msvc_ml_path = "%{msvc_ml_path}", ) filegroup( @@ -93,4 +139,4 @@ filegroup( filegroup( name = "windows_msvc_wrapper_files", srcs = glob(["windows/msvc_*"]), -) \ No newline at end of file +) diff --git a/gpu/crosstool/cc_toolchain_config.bzl.tpl b/gpu/crosstool/cc_toolchain_config.bzl.tpl new file mode 100644 index 0000000..3d4d41a --- /dev/null +++ b/gpu/crosstool/cc_toolchain_config.bzl.tpl @@ -0,0 +1,1516 @@ +"""cc_toolchain_config rule for configuring CUDA toolchains on Linux, Mac, and Windows.""" + +load( + "@bazel_tools//tools/cpp:cc_toolchain_config_lib.bzl", + "action_config", + "env_entry", + "env_set", + "feature", + "feature_set", + "flag_group", + "flag_set", + "tool", + "tool_path", + "variable_with_value", +) +load( + "@bazel_tools//tools/build_defs/cc:action_names.bzl", + "ASSEMBLE_ACTION_NAME", + "CC_FLAGS_MAKE_VARIABLE_ACTION_NAME", + "CLIF_MATCH_ACTION_NAME", + "CPP_COMPILE_ACTION_NAME", + "CPP_HEADER_PARSING_ACTION_NAME", + "CPP_LINK_DYNAMIC_LIBRARY_ACTION_NAME", + "CPP_LINK_EXECUTABLE_ACTION_NAME", + "CPP_LINK_NODEPS_DYNAMIC_LIBRARY_ACTION_NAME", + "CPP_LINK_STATIC_LIBRARY_ACTION_NAME", + "CPP_MODULE_CODEGEN_ACTION_NAME", + "CPP_MODULE_COMPILE_ACTION_NAME", + "C_COMPILE_ACTION_NAME", + "LINKSTAMP_COMPILE_ACTION_NAME", + "LTO_BACKEND_ACTION_NAME", + "LTO_INDEXING_ACTION_NAME", + "OBJCPP_COMPILE_ACTION_NAME", + "OBJCPP_EXECUTABLE_ACTION_NAME", + "OBJC_ARCHIVE_ACTION_NAME", + "OBJC_COMPILE_ACTION_NAME", + "OBJC_EXECUTABLE_ACTION_NAME", + "OBJC_FULLY_LINK_ACTION_NAME", + "PREPROCESS_ASSEMBLE_ACTION_NAME", + "STRIP_ACTION_NAME", +) + +ACTION_NAMES = struct( + c_compile = C_COMPILE_ACTION_NAME, + cpp_compile = CPP_COMPILE_ACTION_NAME, + linkstamp_compile = LINKSTAMP_COMPILE_ACTION_NAME, + cc_flags_make_variable = CC_FLAGS_MAKE_VARIABLE_ACTION_NAME, + cpp_module_codegen = CPP_MODULE_CODEGEN_ACTION_NAME, + cpp_header_parsing = CPP_HEADER_PARSING_ACTION_NAME, + cpp_module_compile = CPP_MODULE_COMPILE_ACTION_NAME, + assemble = ASSEMBLE_ACTION_NAME, + preprocess_assemble = PREPROCESS_ASSEMBLE_ACTION_NAME, + lto_indexing = LTO_INDEXING_ACTION_NAME, + lto_backend = LTO_BACKEND_ACTION_NAME, + cpp_link_executable = CPP_LINK_EXECUTABLE_ACTION_NAME, + cpp_link_dynamic_library = CPP_LINK_DYNAMIC_LIBRARY_ACTION_NAME, + cpp_link_nodeps_dynamic_library = CPP_LINK_NODEPS_DYNAMIC_LIBRARY_ACTION_NAME, + cpp_link_static_library = CPP_LINK_STATIC_LIBRARY_ACTION_NAME, + strip = STRIP_ACTION_NAME, + objc_archive = OBJC_ARCHIVE_ACTION_NAME, + objc_compile = OBJC_COMPILE_ACTION_NAME, + objc_executable = OBJC_EXECUTABLE_ACTION_NAME, + objc_fully_link = OBJC_FULLY_LINK_ACTION_NAME, + objcpp_compile = OBJCPP_COMPILE_ACTION_NAME, + objcpp_executable = OBJCPP_EXECUTABLE_ACTION_NAME, + clif_match = CLIF_MATCH_ACTION_NAME, + objcopy_embed_data = "objcopy_embed_data", + ld_embed_data = "ld_embed_data", +) + +def _impl(ctx): + if (ctx.attr.cpu == "darwin"): + toolchain_identifier = "local_darwin" + elif (ctx.attr.cpu == "local"): + toolchain_identifier = "local_linux" + elif (ctx.attr.cpu == "x64_windows"): + toolchain_identifier = "local_windows" + else: + fail("Unreachable") + + host_system_name = "local" + + target_system_name = "local" + + if (ctx.attr.cpu == "darwin"): + target_cpu = "darwin" + elif (ctx.attr.cpu == "local"): + target_cpu = "local" + elif (ctx.attr.cpu == "x64_windows"): + target_cpu = "x64_windows" + else: + fail("Unreachable") + + if (ctx.attr.cpu == "local"): + target_libc = "local" + elif (ctx.attr.cpu == "darwin"): + target_libc = "macosx" + elif (ctx.attr.cpu == "x64_windows"): + target_libc = "msvcrt" + else: + fail("Unreachable") + + if (ctx.attr.cpu == "darwin" or + ctx.attr.cpu == "local"): + compiler = "compiler" + elif (ctx.attr.cpu == "x64_windows"): + compiler = "msvc-cl" + else: + fail("Unreachable") + + abi_version = "local" + + abi_libc_version = "local" + + cc_target_os = None + + builtin_sysroot = ctx.attr.builtin_sysroot + + all_link_actions = [ + ACTION_NAMES.cpp_link_executable, + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ] + + cpp_link_dynamic_library_action = action_config( + action_name = ACTION_NAMES.cpp_link_dynamic_library, + implies = [ + "nologo", + "shared_flag", + "linkstamps", + "output_execpath_flags", + "input_param_flags", + "user_link_flags", + "linker_subsystem_flag", + "linker_param_file", + "msvc_env", + "no_stripping", + "has_configured_linker_path", + "def_file", + ], + tools = [tool(path = ctx.attr.msvc_link_path)], + ) + + cpp_link_nodeps_dynamic_library_action = action_config( + action_name = ACTION_NAMES.cpp_link_nodeps_dynamic_library, + implies = [ + "nologo", + "shared_flag", + "linkstamps", + "output_execpath_flags", + "input_param_flags", + "user_link_flags", + "linker_subsystem_flag", + "linker_param_file", + "msvc_env", + "no_stripping", + "has_configured_linker_path", + "def_file", + ], + tools = [tool(path = ctx.attr.msvc_link_path)], + ) + + cpp_link_static_library_action = action_config( + action_name = ACTION_NAMES.cpp_link_static_library, + implies = [ + "nologo", + "archiver_flags", + "input_param_flags", + "linker_param_file", + "msvc_env", + ], + tools = [tool(path = ctx.attr.msvc_lib_path)], + ) + + assemble_action = action_config( + action_name = ACTION_NAMES.assemble, + implies = [ + "compiler_input_flags", + "compiler_output_flags", + "nologo", + "msvc_env", + "sysroot", + ], + tools = [tool(path = ctx.attr.msvc_ml_path)], + ) + + preprocess_assemble_action = action_config( + action_name = ACTION_NAMES.preprocess_assemble, + implies = [ + "compiler_input_flags", + "compiler_output_flags", + "nologo", + "msvc_env", + "sysroot", + ], + tools = [tool(path = ctx.attr.msvc_ml_path)], + ) + + c_compile_action = action_config( + action_name = ACTION_NAMES.c_compile, + implies = [ + "compiler_input_flags", + "compiler_output_flags", + "nologo", + "msvc_env", + "parse_showincludes", + "user_compile_flags", + "sysroot", + "unfiltered_compile_flags", + ], + tools = [tool(path = ctx.attr.msvc_cl_path)], + ) + + cpp_compile_action = action_config( + action_name = ACTION_NAMES.cpp_compile, + implies = [ + "compiler_input_flags", + "compiler_output_flags", + "nologo", + "msvc_env", + "parse_showincludes", + "user_compile_flags", + "sysroot", + "unfiltered_compile_flags", + ], + tools = [tool(path = ctx.attr.msvc_cl_path)], + ) + + cpp_link_executable_action = action_config( + action_name = ACTION_NAMES.cpp_link_executable, + implies = [ + "nologo", + "linkstamps", + "output_execpath_flags", + "input_param_flags", + "user_link_flags", + "linker_subsystem_flag", + "linker_param_file", + "msvc_env", + "no_stripping", + ], + tools = [tool(path = ctx.attr.msvc_link_path)], + ) + + if (ctx.attr.cpu == "darwin" or + ctx.attr.cpu == "local"): + action_configs = [] + elif (ctx.attr.cpu == "x64_windows"): + action_configs = [ + assemble_action, + preprocess_assemble_action, + c_compile_action, + cpp_compile_action, + cpp_link_executable_action, + cpp_link_dynamic_library_action, + cpp_link_nodeps_dynamic_library_action, + cpp_link_static_library_action, + ] + else: + fail("Unreachable") + + no_windows_export_all_symbols_feature = feature(name = "no_windows_export_all_symbols") + + pic_feature = feature( + name = "pic", + enabled = True, + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [ + flag_group(flags = ["-fPIC"], expand_if_available = "pic"), + flag_group( + flags = ["-fPIE"], + expand_if_not_available = "pic", + ), + ], + ), + ], + ) + + preprocessor_defines_feature = feature( + name = "preprocessor_defines", + enabled = True, + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ], + flag_groups = [ + flag_group( + flags = ["/D%{preprocessor_defines}"], + iterate_over = "preprocessor_defines", + ), + ], + ), + ], + ) + + generate_pdb_file_feature = feature( + name = "generate_pdb_file", + requires = [ + feature_set(features = ["dbg"]), + feature_set(features = ["fastbuild"]), + ], + ) + + linkstamps_feature = feature( + name = "linkstamps", + flag_sets = [ + flag_set( + actions = all_link_actions, + flag_groups = [ + flag_group( + flags = ["%{linkstamp_paths}"], + iterate_over = "linkstamp_paths", + expand_if_available = "linkstamp_paths", + ), + ], + ), + ], + ) + + unfiltered_compile_flags_feature = feature( + name = "unfiltered_compile_flags", + flag_sets = ([ + flag_set( + actions = [ + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ], + flag_groups = [ + flag_group( + flags = ctx.attr.host_unfiltered_compile_flags, + ), + ], + ), + ] if ctx.attr.host_unfiltered_compile_flags else []), + ) + + determinism_feature = feature( + name = "determinism", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [ + flag_group( + flags = [ + "-Wno-builtin-macro-redefined", + "-D__DATE__=\"redacted\"", + "-D__TIMESTAMP__=\"redacted\"", + "-D__TIME__=\"redacted\"", + ], + ), + ], + ), + ], + ) + + nologo_feature = feature( + name = "nologo", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.cpp_link_executable, + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ACTION_NAMES.cpp_link_static_library, + ], + flag_groups = [flag_group(flags = ["/nologo"])], + ), + ], + ) + + supports_pic_feature = feature(name = "supports_pic", enabled = True) + + output_execpath_flags_feature = feature( + name = "output_execpath_flags", + flag_sets = [ + flag_set( + actions = all_link_actions, + flag_groups = [ + flag_group( + flags = ["/OUT:%{output_execpath}"], + expand_if_available = "output_execpath", + ), + ], + ), + ], + ) + + default_link_flags_feature = feature( + name = "default_link_flags", + enabled = True, + flag_sets = [ + flag_set( + actions = all_link_actions, + flag_groups = [flag_group(flags = ["/MACHINE:X64"])], + ), + ], + ) + + if (ctx.attr.cpu == "local"): + hardening_feature = feature( + name = "hardening", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [ + flag_group( + flags = [ + "-U_FORTIFY_SOURCE", + "-D_FORTIFY_SOURCE=1", + "-fstack-protector", + ], + ), + ], + ), + flag_set( + actions = [ + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ], + flag_groups = [flag_group(flags = ["-Wl,-z,relro,-z,now"])], + ), + flag_set( + actions = [ACTION_NAMES.cpp_link_executable], + flag_groups = [flag_group(flags = ["-pie", "-Wl,-z,relro,-z,now"])], + ), + ], + ) + elif (ctx.attr.cpu == "darwin"): + hardening_feature = feature( + name = "hardening", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [ + flag_group( + flags = [ + "-U_FORTIFY_SOURCE", + "-D_FORTIFY_SOURCE=1", + "-fstack-protector", + ], + ), + ], + ), + flag_set( + actions = [ACTION_NAMES.cpp_link_executable], + flag_groups = [flag_group(flags = ["-pie"])], + ), + ], + ) + else: + hardening_feature = None + + supports_dynamic_linker_feature = feature(name = "supports_dynamic_linker", enabled = True) + + targets_windows_feature = feature( + name = "targets_windows", + enabled = True, + implies = ["copy_dynamic_libraries_to_binary"], + ) + + msvc_env_feature = feature( + name = "msvc_env", + env_sets = [ + env_set( + actions = [ + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.cpp_link_executable, + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ACTION_NAMES.cpp_link_static_library, + ], + env_entries = [ + env_entry(key = "PATH", value = ctx.attr.msvc_env_path), + env_entry( + key = "INCLUDE", + value = ctx.attr.msvc_env_include, + ), + env_entry(key = "LIB", value = ctx.attr.msvc_env_lib), + env_entry(key = "TMP", value = ctx.attr.msvc_env_tmp), + env_entry(key = "TEMP", value = ctx.attr.msvc_env_tmp), + ], + ), + ], + ) + + linker_subsystem_flag_feature = feature( + name = "linker_subsystem_flag", + flag_sets = [ + flag_set( + actions = all_link_actions, + flag_groups = [flag_group(flags = ["/SUBSYSTEM:CONSOLE"])], + ), + ], + ) + + dynamic_link_msvcrt_no_debug_feature = feature( + name = "dynamic_link_msvcrt_no_debug", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [flag_group(flags = ["/MD"])], + ), + flag_set( + actions = all_link_actions, + flag_groups = [flag_group(flags = ["/DEFAULTLIB:msvcrt.lib"])], + ), + ], + requires = [ + feature_set(features = ["fastbuild"]), + feature_set(features = ["opt"]), + ], + ) + + warnings_feature = feature( + name = "warnings", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [ + flag_group( + flags = ["-Wall"] + ctx.attr.host_compiler_warnings, + ), + ], + ), + ], + ) + + dynamic_link_msvcrt_debug_feature = feature( + name = "dynamic_link_msvcrt_debug", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [flag_group(flags = ["/MDd"])], + ), + flag_set( + actions = all_link_actions, + flag_groups = [flag_group(flags = ["/DEFAULTLIB:msvcrtd.lib"])], + ), + ], + requires = [feature_set(features = ["dbg"])], + ) + + compiler_output_flags_feature = feature( + name = "compiler_output_flags", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.assemble], + flag_groups = [ + flag_group( + flag_groups = [ + flag_group( + flags = ["/Fo%{output_file}", "/Zi"], + expand_if_not_available = "output_preprocess_file", + ), + ], + expand_if_available = "output_file", + expand_if_not_available = "output_assembly_file", + ), + ], + ), + flag_set( + actions = [ + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ], + flag_groups = [ + flag_group( + flag_groups = [ + flag_group( + flags = ["/Fo%{output_file}"], + expand_if_not_available = "output_preprocess_file", + ), + ], + expand_if_available = "output_file", + expand_if_not_available = "output_assembly_file", + ), + flag_group( + flag_groups = [ + flag_group( + flags = ["/Fa%{output_file}"], + expand_if_available = "output_assembly_file", + ), + ], + expand_if_available = "output_file", + ), + flag_group( + flag_groups = [ + flag_group( + flags = ["/P", "/Fi%{output_file}"], + expand_if_available = "output_preprocess_file", + ), + ], + expand_if_available = "output_file", + ), + ], + ), + ], + ) + + default_compile_flags_feature = feature( + name = "default_compile_flags", + enabled = True, + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.linkstamp_compile, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.lto_backend, + ACTION_NAMES.clif_match, + ], + flag_groups = [ + flag_group( + flags = [ + "/DCOMPILER_MSVC", + "/DNOMINMAX", + "/D_WIN32_WINNT=0x0600", + "/D_CRT_SECURE_NO_DEPRECATE", + "/D_CRT_SECURE_NO_WARNINGS", + "/D_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS", + "/bigobj", + "/Zm500", + "/J", + "/Gy", + "/GF", + "/EHsc", + "/wd4351", + "/wd4291", + "/wd4250", + "/wd4996", + ], + ), + ], + ), + ], + ) + + static_link_msvcrt_debug_feature = feature( + name = "static_link_msvcrt_debug", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [flag_group(flags = ["/MTd"])], + ), + flag_set( + actions = all_link_actions, + flag_groups = [flag_group(flags = ["/DEFAULTLIB:libcmtd.lib"])], + ), + ], + requires = [feature_set(features = ["dbg"])], + ) + + static_link_msvcrt_feature = feature(name = "static_link_msvcrt") + + if (ctx.attr.cpu == "darwin" or + ctx.attr.cpu == "local"): + dbg_feature = feature( + name = "dbg", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [flag_group(flags = ["-g"])], + ), + ], + implies = ["common"], + ) + elif (ctx.attr.cpu == "x64_windows"): + dbg_feature = feature( + name = "dbg", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [flag_group(flags = ["/Od", "/Z7", "/DDEBUG"])], + ), + flag_set( + actions = all_link_actions, + flag_groups = [flag_group(flags = ["/DEBUG:FULL", "/INCREMENTAL:NO"])], + ), + ], + implies = ["generate_pdb_file"], + ) + else: + dbg_feature = None + + undefined_dynamic_feature = feature( + name = "undefined-dynamic", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ACTION_NAMES.cpp_link_executable, + ], + flag_groups = [flag_group(flags = ["-undefined", "dynamic_lookup"])], + ), + ], + ) + + parse_showincludes_feature = feature( + name = "parse_showincludes", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_header_parsing, + ], + flag_groups = [flag_group(flags = ["/showIncludes"])], + ), + ], + ) + + linker_param_file_feature = feature( + name = "linker_param_file", + flag_sets = [ + flag_set( + actions = all_link_actions + + [ACTION_NAMES.cpp_link_static_library], + flag_groups = [ + flag_group( + flags = ["@%{linker_param_file}"], + expand_if_available = "linker_param_file", + ), + ], + ), + ], + ) + + static_link_msvcrt_no_debug_feature = feature( + name = "static_link_msvcrt_no_debug", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [flag_group(flags = ["/MT"])], + ), + flag_set( + actions = all_link_actions, + flag_groups = [flag_group(flags = ["/DEFAULTLIB:libcmt.lib"])], + ), + ], + requires = [ + feature_set(features = ["fastbuild"]), + feature_set(features = ["opt"]), + ], + ) + + supports_interface_shared_libraries_feature = feature( + name = "supports_interface_shared_libraries", + enabled = True, + ) + + disable_assertions_feature = feature( + name = "disable-assertions", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [flag_group(flags = ["-DNDEBUG"])], + ), + ], + ) + + if (ctx.attr.cpu == "x64_windows"): + fastbuild_feature = feature( + name = "fastbuild", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [flag_group(flags = ["/Od", "/Z7", "/DDEBUG"])], + ), + flag_set( + actions = all_link_actions, + flag_groups = [ + flag_group(flags = ["/DEBUG:FASTLINK", "/INCREMENTAL:NO"]), + ], + ), + ], + implies = ["generate_pdb_file"], + ) + elif (ctx.attr.cpu == "darwin" or + ctx.attr.cpu == "local"): + fastbuild_feature = feature(name = "fastbuild", implies = ["common"]) + else: + fastbuild_feature = None + + user_compile_flags_feature = feature( + name = "user_compile_flags", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ], + flag_groups = [ + flag_group( + flags = ["%{user_compile_flags}"], + iterate_over = "user_compile_flags", + expand_if_available = "user_compile_flags", + ), + ], + ), + ], + ) + + compiler_input_flags_feature = feature( + name = "compiler_input_flags", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ], + flag_groups = [ + flag_group( + flags = ["/c", "%{source_file}"], + expand_if_available = "source_file", + ), + ], + ), + ], + ) + + no_legacy_features_feature = feature(name = "no_legacy_features") + + archiver_flags_feature = feature( + name = "archiver_flags", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.cpp_link_static_library], + flag_groups = [ + flag_group( + flags = ["/OUT:%{output_execpath}"], + expand_if_available = "output_execpath", + ), + ], + ), + ], + ) + + redirector_feature = feature( + name = "redirector", + enabled = True, + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ], + flag_groups = [ + flag_group( + flags = [ + "-B", + "external/local_config_cuda/crosstool/windows/msvc_wrapper_for_nvcc.py", + ], + ), + ], + ), + ], + ) + + linker_bin_path_feature = feature( + name = "linker-bin-path", + flag_sets = [ + flag_set( + actions = all_link_actions, + flag_groups = [flag_group(flags = ["-B" + ctx.attr.linker_bin_path])], + ), + ], + ) + + if (ctx.attr.cpu == "local"): + opt_feature = feature( + name = "opt", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [ + flag_group( + flags = ["-g0", "-O2", "-ffunction-sections", "-fdata-sections"], + ), + ], + ), + flag_set( + actions = [ + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ACTION_NAMES.cpp_link_executable, + ], + flag_groups = [flag_group(flags = ["-Wl,--gc-sections"])], + ), + ], + implies = ["common", "disable-assertions"], + ) + elif (ctx.attr.cpu == "darwin"): + opt_feature = feature( + name = "opt", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [ + flag_group( + flags = ["-g0", "-O2", "-ffunction-sections", "-fdata-sections"], + ), + ], + ), + ], + implies = ["common", "disable-assertions"], + ) + elif (ctx.attr.cpu == "x64_windows"): + opt_feature = feature( + name = "opt", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [flag_group(flags = ["/O2", "/DNDEBUG"])], + ), + ], + ) + else: + opt_feature = None + + include_paths_feature = feature( + name = "include_paths", + enabled = True, + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ], + flag_groups = [ + flag_group( + flags = ["/I%{quote_include_paths}"], + iterate_over = "quote_include_paths", + ), + flag_group( + flags = ["/I%{include_paths}"], + iterate_over = "include_paths", + ), + flag_group( + flags = ["/I%{system_include_paths}"], + iterate_over = "system_include_paths", + ), + ], + ), + ], + ) + + shared_flag_feature = feature( + name = "shared_flag", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ], + flag_groups = [flag_group(flags = ["/DLL"])], + ), + ], + ) + + windows_export_all_symbols_feature = feature(name = "windows_export_all_symbols") + + frame_pointer_feature = feature( + name = "frame-pointer", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [flag_group(flags = ["-fno-omit-frame-pointer"])], + ), + ], + ) + + build_id_feature = feature( + name = "build-id", + flag_sets = [ + flag_set( + actions = all_link_actions, + flag_groups = [ + flag_group( + flags = ["-Wl,--build-id=md5", "-Wl,--hash-style=gnu"], + ), + ], + ), + ], + ) + + sysroot_feature = feature( + name = "sysroot", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.cpp_link_executable, + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ], + flag_groups = [ + flag_group( + flags = ["--sysroot=%{sysroot}"], + iterate_over = "sysroot", + expand_if_available = "sysroot", + ), + ], + ), + ], + ) + + cuda_path_feature = feature( + name = "cuda_path", + enabled = True, + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.cpp_link_executable, + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ], + flag_groups = [ + flag_group( + flags = ["--cuda-path=" + ctx.attr.cuda_path], + ), + ], + ), + ], + ) + + def_file_feature = feature( + name = "def_file", + flag_sets = [ + flag_set( + actions = all_link_actions, + flag_groups = [ + flag_group( + flags = ["/DEF:%{def_file_path}", "/ignore:4070"], + expand_if_available = "def_file_path", + ), + ], + ), + ], + ) + + if (ctx.attr.cpu == "darwin"): + stdlib_feature = feature( + name = "stdlib", + flag_sets = [ + flag_set( + actions = all_link_actions, + flag_groups = [flag_group(flags = ["-lc++"])], + ), + ], + ) + elif (ctx.attr.cpu == "local"): + stdlib_feature = feature( + name = "stdlib", + flag_sets = [ + flag_set( + actions = all_link_actions, + flag_groups = [flag_group(flags = ["-lstdc++"])], + ), + ], + ) + else: + stdlib_feature = None + + no_stripping_feature = feature(name = "no_stripping") + + alwayslink_feature = feature( + name = "alwayslink", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ACTION_NAMES.cpp_link_executable, + ], + flag_groups = [flag_group(flags = ["-Wl,-no-as-needed"])], + ), + ], + ) + + input_param_flags_feature = feature( + name = "input_param_flags", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ], + flag_groups = [ + flag_group( + flags = ["/IMPLIB:%{interface_library_output_path}"], + expand_if_available = "interface_library_output_path", + ), + ], + ), + flag_set( + actions = all_link_actions + + [ACTION_NAMES.cpp_link_static_library], + flag_groups = [ + flag_group( + iterate_over = "libraries_to_link", + flag_groups = [ + flag_group( + iterate_over = "libraries_to_link.object_files", + flag_groups = [flag_group(flags = ["%{libraries_to_link.object_files}"])], + expand_if_equal = variable_with_value( + name = "libraries_to_link.type", + value = "object_file_group", + ), + ), + flag_group( + flag_groups = [flag_group(flags = ["%{libraries_to_link.name}"])], + expand_if_equal = variable_with_value( + name = "libraries_to_link.type", + value = "object_file", + ), + ), + flag_group( + flag_groups = [flag_group(flags = ["%{libraries_to_link.name}"])], + expand_if_equal = variable_with_value( + name = "libraries_to_link.type", + value = "interface_library", + ), + ), + flag_group( + flag_groups = [ + flag_group( + flags = ["%{libraries_to_link.name}"], + expand_if_false = "libraries_to_link.is_whole_archive", + ), + flag_group( + flags = ["/WHOLEARCHIVE:%{libraries_to_link.name}"], + expand_if_true = "libraries_to_link.is_whole_archive", + ), + ], + expand_if_equal = variable_with_value( + name = "libraries_to_link.type", + value = "static_library", + ), + ), + ], + expand_if_available = "libraries_to_link", + ), + ], + ), + ], + ) + + if (ctx.attr.cpu == "local"): + no_canonical_prefixes_feature = feature( + name = "no-canonical-prefixes", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_link_executable, + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ], + flag_groups = [ + flag_group( + flags = [ + "-no-canonical-prefixes", + ] + ctx.attr.extra_no_canonical_prefixes_flags, + ), + ], + ), + ], + ) + elif (ctx.attr.cpu == "darwin"): + no_canonical_prefixes_feature = feature( + name = "no-canonical-prefixes", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_link_executable, + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ], + flag_groups = [flag_group(flags = ["-no-canonical-prefixes"])], + ), + ], + ) + else: + no_canonical_prefixes_feature = None + + has_configured_linker_path_feature = feature(name = "has_configured_linker_path") + + copy_dynamic_libraries_to_binary_feature = feature(name = "copy_dynamic_libraries_to_binary") + + user_link_flags_feature = feature( + name = "user_link_flags", + flag_sets = [ + flag_set( + actions = all_link_actions, + flag_groups = [ + flag_group( + flags = ["%{user_link_flags}"], + iterate_over = "user_link_flags", + expand_if_available = "user_link_flags", + ), + ], + ), + ], + ) + + cpp11_feature = feature( + name = "c++11", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.cpp_compile], + flag_groups = [flag_group(flags = ["-std=c++11"])], + ), + ], + ) + + if (ctx.attr.cpu == "local"): + common_feature = feature( + name = "common", + implies = [ + "stdlib", + "c++11", + "determinism", + "alwayslink", + "hardening", + "warnings", + "frame-pointer", + "build-id", + "no-canonical-prefixes", + "linker-bin-path", + ], + ) + elif (ctx.attr.cpu == "darwin"): + common_feature = feature( + name = "common", + implies = [ + "stdlib", + "c++11", + "determinism", + "hardening", + "warnings", + "frame-pointer", + "no-canonical-prefixes", + "linker-bin-path", + "undefined-dynamic", + ], + ) + else: + common_feature = None + + if (ctx.attr.cpu == "local"): + features = [ + cpp11_feature, + stdlib_feature, + determinism_feature, + alwayslink_feature, + pic_feature, + hardening_feature, + warnings_feature, + frame_pointer_feature, + build_id_feature, + no_canonical_prefixes_feature, + disable_assertions_feature, + linker_bin_path_feature, + common_feature, + opt_feature, + fastbuild_feature, + dbg_feature, + supports_dynamic_linker_feature, + supports_pic_feature, + ] + if ctx.attr.cuda_path: + features += [cuda_path_feature] + elif (ctx.attr.cpu == "darwin"): + features = [ + cpp11_feature, + stdlib_feature, + determinism_feature, + pic_feature, + hardening_feature, + warnings_feature, + frame_pointer_feature, + no_canonical_prefixes_feature, + disable_assertions_feature, + linker_bin_path_feature, + undefined_dynamic_feature, + common_feature, + opt_feature, + fastbuild_feature, + dbg_feature, + supports_dynamic_linker_feature, + supports_pic_feature, + ] + elif (ctx.attr.cpu == "x64_windows"): + features = [ + no_legacy_features_feature, + redirector_feature, + nologo_feature, + has_configured_linker_path_feature, + no_stripping_feature, + targets_windows_feature, + copy_dynamic_libraries_to_binary_feature, + default_compile_flags_feature, + msvc_env_feature, + include_paths_feature, + preprocessor_defines_feature, + parse_showincludes_feature, + generate_pdb_file_feature, + shared_flag_feature, + linkstamps_feature, + output_execpath_flags_feature, + archiver_flags_feature, + input_param_flags_feature, + linker_subsystem_flag_feature, + user_link_flags_feature, + default_link_flags_feature, + linker_param_file_feature, + static_link_msvcrt_feature, + static_link_msvcrt_no_debug_feature, + dynamic_link_msvcrt_no_debug_feature, + static_link_msvcrt_debug_feature, + dynamic_link_msvcrt_debug_feature, + dbg_feature, + fastbuild_feature, + opt_feature, + user_compile_flags_feature, + sysroot_feature, + unfiltered_compile_flags_feature, + compiler_output_flags_feature, + compiler_input_flags_feature, + def_file_feature, + windows_export_all_symbols_feature, + no_windows_export_all_symbols_feature, + supports_dynamic_linker_feature, + supports_interface_shared_libraries_feature, + ] + else: + fail("Unreachable") + + cxx_builtin_include_directories = ctx.attr.builtin_include_directories + + if (ctx.attr.cpu == "x64_windows"): + tool_paths = [ + tool_path(name = "ar", path = ctx.attr.msvc_lib_path), + tool_path(name = "ml", path = ctx.attr.msvc_ml_path), + tool_path(name = "cpp", path = ctx.attr.msvc_cl_path), + tool_path(name = "gcc", path = ctx.attr.msvc_cl_path), + tool_path(name = "gcov", path = "wrapper/bin/msvc_nop.bat"), + tool_path(name = "ld", path = ctx.attr.msvc_link_path), + tool_path(name = "nm", path = "wrapper/bin/msvc_nop.bat"), + tool_path( + name = "objcopy", + path = "wrapper/bin/msvc_nop.bat", + ), + tool_path( + name = "objdump", + path = "wrapper/bin/msvc_nop.bat", + ), + tool_path( + name = "strip", + path = "wrapper/bin/msvc_nop.bat", + ), + ] + elif (ctx.attr.cpu == "local"): + tool_paths = [ + tool_path(name = "gcc", path = ctx.attr.host_compiler_path), + tool_path(name = "ar", path = ctx.attr.host_compiler_prefix + "/ar"), + tool_path(name = "compat-ld", path = ctx.attr.host_compiler_prefix + "/ld"), + tool_path(name = "cpp", path = ctx.attr.host_compiler_prefix + "/cpp"), + tool_path(name = "dwp", path = ctx.attr.host_compiler_prefix + "/dwp"), + tool_path(name = "gcov", path = ctx.attr.host_compiler_prefix + "/gcov"), + tool_path(name = "ld", path = ctx.attr.host_compiler_prefix + "/ld"), + tool_path(name = "nm", path = ctx.attr.host_compiler_prefix + "/nm"), + tool_path(name = "objcopy", path = ctx.attr.host_compiler_prefix + "/objcopy"), + tool_path(name = "objdump", path = ctx.attr.host_compiler_prefix + "/objdump"), + tool_path(name = "strip", path = ctx.attr.host_compiler_prefix + "/strip"), + ] + elif (ctx.attr.cpu == "darwin"): + tool_paths = [ + tool_path(name = "gcc", path = ctx.attr.host_compiler_path), + tool_path(name = "ar", path = ctx.attr.host_compiler_prefix + "/libtool"), + tool_path(name = "compat-ld", path = ctx.attr.host_compiler_prefix + "/ld"), + tool_path(name = "cpp", path = ctx.attr.host_compiler_prefix + "/cpp"), + tool_path(name = "dwp", path = ctx.attr.host_compiler_prefix + "/dwp"), + tool_path(name = "gcov", path = ctx.attr.host_compiler_prefix + "/gcov"), + tool_path(name = "ld", path = ctx.attr.host_compiler_prefix + "/ld"), + tool_path(name = "nm", path = ctx.attr.host_compiler_prefix + "/nm"), + tool_path(name = "objcopy", path = ctx.attr.host_compiler_prefix + "/objcopy"), + tool_path(name = "objdump", path = ctx.attr.host_compiler_prefix + "/objdump"), + tool_path(name = "strip", path = ctx.attr.host_compiler_prefix + "/strip"), + ] + else: + fail("Unreachable") + + out = ctx.actions.declare_file(ctx.label.name) + ctx.actions.write(out, "Fake executable") + return [ + cc_common.create_cc_toolchain_config_info( + ctx = ctx, + features = features, + action_configs = action_configs, + artifact_name_patterns = [], + cxx_builtin_include_directories = cxx_builtin_include_directories, + toolchain_identifier = toolchain_identifier, + host_system_name = host_system_name, + target_system_name = target_system_name, + target_cpu = target_cpu, + target_libc = target_libc, + compiler = compiler, + abi_version = abi_version, + abi_libc_version = abi_libc_version, + tool_paths = tool_paths, + make_variables = [], + builtin_sysroot = builtin_sysroot, + cc_target_os = cc_target_os, + ), + DefaultInfo( + executable = out, + ), + ] + +cc_toolchain_config = rule( + implementation = _impl, + attrs = { + "cpu": attr.string(mandatory = True, values = ["darwin", "local", "x64_windows"]), + "builtin_include_directories": attr.string_list(), + "extra_no_canonical_prefixes_flags": attr.string_list(), + "host_compiler_path": attr.string(), + "host_compiler_prefix": attr.string(), + "host_compiler_warnings": attr.string_list(), + "host_unfiltered_compile_flags": attr.string_list(), + "linker_bin_path": attr.string(), + "builtin_sysroot": attr.string(), + "cuda_path": attr.string(), + "msvc_cl_path": attr.string(default = "msvc_not_used"), + "msvc_env_include": attr.string(default = "msvc_not_used"), + "msvc_env_lib": attr.string(default = "msvc_not_used"), + "msvc_env_path": attr.string(default = "msvc_not_used"), + "msvc_env_tmp": attr.string(default = "msvc_not_used"), + "msvc_lib_path": attr.string(default = "msvc_not_used"), + "msvc_link_path": attr.string(default = "msvc_not_used"), + "msvc_ml_path": attr.string(default = "msvc_not_used"), + }, + provides = [CcToolchainConfigInfo], + executable = True, +) diff --git a/gpu/cuda/BUILD.tpl b/gpu/cuda/BUILD.tpl index dff8006..f28acff 100644 --- a/gpu/cuda/BUILD.tpl +++ b/gpu/cuda/BUILD.tpl @@ -1,4 +1,5 @@ load(":build_defs.bzl", "cuda_header_library") +#load("@bazel_skylib//:bzl_library.bzl", "bzl_library") licenses(["restricted"]) # MPL2, portions GPL v3, LGPL v3, BSD-like @@ -30,36 +31,29 @@ config_setting( config_setting( name = "darwin", values = {"cpu": "darwin"}, - visibility = ["//visibility:public"], ) config_setting( name = "freebsd", values = {"cpu": "freebsd"}, - visibility = ["//visibility:public"], ) cuda_header_library( name = "cuda_headers", hdrs = [ - %{cuda_headers} + "cuda/cuda_config.h", + ":cuda-include" ], include_prefix = "third_party/gpus", includes = [ - ".", + ".", # required to include cuda/cuda/cuda_config.h as cuda/config.h "cuda/include", - "cuda/include/crt", ], - visibility = ["//visibility:public"], ) cc_library( name = "cudart_static", srcs = ["cuda/lib/%{cudart_static_lib}"], - includes = [ - ".", - "cuda/include", - ], linkopts = select({ ":freebsd": [], "//conditions:default": ["-ldl"], @@ -67,104 +61,75 @@ cc_library( "-lpthread", %{cudart_static_linkopt} ], - visibility = ["//visibility:public"], ) cc_library( name = "cuda_driver", srcs = ["cuda/lib/%{cuda_driver_lib}"], - includes = [ - ".", - "cuda/include", - ], - visibility = ["//visibility:public"], ) cc_library( name = "cudart", srcs = ["cuda/lib/%{cudart_lib}"], data = ["cuda/lib/%{cudart_lib}"], - includes = [ - ".", - "cuda/include", - ], linkstatic = 1, - visibility = ["//visibility:public"], +) + +cuda_header_library( + name = "cublas_headers", + hdrs = [":cublas-include"], + include_prefix = "third_party/gpus/cuda/include", + strip_include_prefix = "cublas/include", + deps = [":cuda_headers"], + includes = ["cublas/include"], ) cc_library( name = "cublas", srcs = ["cuda/lib/%{cublas_lib}"], data = ["cuda/lib/%{cublas_lib}"], - includes = [ - ".", - "cuda/include", - ], linkstatic = 1, - visibility = ["//visibility:public"], ) cc_library( name = "cusolver", srcs = ["cuda/lib/%{cusolver_lib}"], data = ["cuda/lib/%{cusolver_lib}"], - includes = [ - ".", - "cuda/include", - ], linkopts = ["-lgomp"], linkstatic = 1, - visibility = ["//visibility:public"], ) cc_library( name = "cudnn", srcs = ["cuda/lib/%{cudnn_lib}"], data = ["cuda/lib/%{cudnn_lib}"], - includes = [ - ".", - "cuda/include", - ], linkstatic = 1, - visibility = ["//visibility:public"], ) cc_library( name = "cudnn_header", - includes = [ - ".", - "cuda/include", - ], - visibility = ["//visibility:public"], + hdrs = [":cudnn-include"], + include_prefix = "third_party/gpus/cudnn", + strip_include_prefix = "cudnn/include", + deps = [":cuda_headers"], ) cc_library( name = "cufft", srcs = ["cuda/lib/%{cufft_lib}"], data = ["cuda/lib/%{cufft_lib}"], - includes = [ - ".", - "cuda/include", - ], linkstatic = 1, - visibility = ["//visibility:public"], ) cc_library( name = "curand", srcs = ["cuda/lib/%{curand_lib}"], data = ["cuda/lib/%{curand_lib}"], - includes = [ - ".", - "cuda/include", - ], linkstatic = 1, - visibility = ["//visibility:public"], ) cc_library( name = "cuda", - visibility = ["//visibility:public"], deps = [ ":cublas", ":cuda_headers", @@ -175,33 +140,38 @@ cc_library( ], ) -cc_library( +cuda_header_library( name = "cupti_headers", - hdrs = [ - "cuda/cuda_config.h", - ":cuda-extras", - ], - includes = [ - ".", - "cuda/extras/CUPTI/include/", - ], - visibility = ["//visibility:public"], + hdrs = [":cuda-extras"], + include_prefix="third_party/gpus", + includes = ["cuda/extras/CUPTI/include/"], + deps = [":cuda_headers"], ) cc_library( name = "cupti_dsos", data = ["cuda/lib/%{cupti_lib}"], - includes = [ - ".", - "cuda/include", - ], - visibility = ["//visibility:public"], +) + +cc_library( + name = "cusparse", + srcs = ["cuda/lib/%{cusparse_lib}"], + data = ["cuda/lib/%{cusparse_lib}"], + linkopts = ["-lgomp"], + linkstatic = 1, ) cc_library( name = "libdevice_root", data = [":cuda-nvvm"], - visibility = ["//visibility:public"], ) +#bzl_library( +# name = "build_defs_bzl", +# srcs = ["build_defs.bzl"], +# deps = [ +# "@bazel_skylib//lib:selects", +# ], +#) + %{copy_rules} diff --git a/gpu/cuda/build_defs.bzl.tpl b/gpu/cuda/build_defs.bzl.tpl index a4f484f..43a7e13 100644 --- a/gpu/cuda/build_defs.bzl.tpl +++ b/gpu/cuda/build_defs.bzl.tpl @@ -8,7 +8,6 @@ def if_cuda(if_true, if_false = []): """ return select({ "@local_config_cuda//cuda:using_nvcc": if_true, - "@local_config_cuda//cuda:using_clang": if_true, "//conditions:default": if_false }) diff --git a/gpu/cuda_configure.bzl b/gpu/cuda_configure.bzl index 7fcca22..17fe1fd 100644 --- a/gpu/cuda_configure.bzl +++ b/gpu/cuda_configure.bzl @@ -1,25 +1,24 @@ -# -*- Python -*- """Repository rule for CUDA autoconfiguration. + `cuda_configure` depends on the following environment variables: + * `TF_NEED_CUDA`: Whether to enable building with CUDA. * `GCC_HOST_COMPILER_PATH`: The GCC host compiler path - * `TF_CUDA_CLANG`: Whether to use clang as a cuda compiler. - * `CLANG_CUDA_COMPILER_PATH`: The clang compiler path that will be used for - both host and device code compilation if TF_CUDA_CLANG is 1. - * `TF_DOWNLOAD_CLANG`: Whether to download a recent release of clang - compiler and use it to build tensorflow. When this option is set - CLANG_CUDA_COMPILER_PATH is ignored. - * `CUDA_TOOLKIT_PATH`: The path to the CUDA toolkit. Default is + * `TF_SYSROOT`: The sysroot to use when compiling. + * `TF_CUDA_PATHS`: The base paths to look for CUDA and cuDNN. Default is + `/usr/local/cuda,usr/`. + * `CUDA_TOOLKIT_PATH` (deprecated): The path to the CUDA toolkit. Default is `/usr/local/cuda`. * `TF_CUDA_VERSION`: The version of the CUDA toolkit. If this is blank, then use the system default. * `TF_CUDNN_VERSION`: The version of the cuDNN library. - * `CUDNN_INSTALL_PATH`: The path to the cuDNN library. Default is + * `CUDNN_INSTALL_PATH` (deprecated): The path to the cuDNN library. Default is `/usr/local/cuda`. * `TF_CUDA_COMPUTE_CAPABILITIES`: The CUDA compute capabilities. Default is `3.5,5.2`. * `PYTHON_BIN_PATH`: The python binary path """ + load( "@bazel_tools//tools/cpp:lib_cc_configure.bzl", "escape_string", @@ -33,92 +32,69 @@ load( ) _GCC_HOST_COMPILER_PATH = "GCC_HOST_COMPILER_PATH" -_CLANG_CUDA_COMPILER_PATH = "CLANG_CUDA_COMPILER_PATH" +_GCC_HOST_COMPILER_PREFIX = "GCC_HOST_COMPILER_PREFIX" +_TF_SYSROOT = "TF_SYSROOT" _CUDA_TOOLKIT_PATH = "CUDA_TOOLKIT_PATH" _TF_CUDA_VERSION = "TF_CUDA_VERSION" _TF_CUDNN_VERSION = "TF_CUDNN_VERSION" _CUDNN_INSTALL_PATH = "CUDNN_INSTALL_PATH" _TF_CUDA_COMPUTE_CAPABILITIES = "TF_CUDA_COMPUTE_CAPABILITIES" -_TF_DOWNLOAD_CLANG = "TF_DOWNLOAD_CLANG" +_TF_CUDA_CONFIG_REPO = "TF_CUDA_CONFIG_REPO" _PYTHON_BIN_PATH = "PYTHON_BIN_PATH" -_DEFAULT_CUDA_VERSION = "" -_DEFAULT_CUDNN_VERSION = "" -_DEFAULT_CUDA_TOOLKIT_PATH = "/usr/local/cuda" -_DEFAULT_CUDNN_INSTALL_PATH = "/usr/local/cuda" _DEFAULT_CUDA_COMPUTE_CAPABILITIES = ["3.5", "5.2"] -# Lookup paths for CUDA / cuDNN libraries, relative to the install directories. -# -# Paths will be tried out in the order listed below. The first successful path -# will be used. For example, when looking for the cudart libraries, the first -# attempt will be lib64/cudart inside the CUDA toolkit. -CUDA_LIB_PATHS = [ - "lib64/", - "lib64/stubs/", - "lib/powerpc64le-linux-gnu/", - "lib/x86_64-linux-gnu/", - "lib/x64/", - "lib/", - "", -] - -# Lookup paths for cupti.h, relative to the CUDA toolkit directory. -# -# On most systems, the cupti library is not installed in the same directory as -# the other CUDA libraries but rather in a special extras/CUPTI directory. -CUPTI_HEADER_PATHS = [ - "extras/CUPTI/include/", - "include/cuda/CUPTI/", - "include/", -] - -# Lookup paths for the cupti library, relative to the -# -# On most systems, the cupti library is not installed in the same directory as -# the other CUDA libraries but rather in a special extras/CUPTI directory. -CUPTI_LIB_PATHS = [ - "extras/CUPTI/lib64/", - "lib/powerpc64le-linux-gnu/", - "lib/x86_64-linux-gnu/", - "lib64/", - "extras/CUPTI/libx64/", - "extras/CUPTI/lib/", - "lib/", -] - -# Lookup paths for CUDA headers (cuda.h) relative to the CUDA toolkit directory. -CUDA_INCLUDE_PATHS = [ - "include/", - "include/cuda/", -] - -# Lookup paths for cudnn.h relative to the CUDNN install directory. -CUDNN_INCLUDE_PATHS = [ - "", - "include/", - "include/cuda/", -] - -# Lookup paths for NVVM libdevice relative to the CUDA directory toolkit. -# -# libdevice implements mathematical functions for GPU kernels, and is provided -# in NVVM bitcode (a subset of LLVM bitcode). -NVVM_LIBDEVICE_PATHS = [ - "nvvm/libdevice/", - "share/cuda/", - "lib/nvidia-cuda-toolkit/libdevice/", -] - -# Files used to detect the NVVM libdevice path. -NVVM_LIBDEVICE_FILES = [ - # CUDA 9.0 has a single file. - "libdevice.10.bc", - - # CUDA 8.0 has separate files for compute versions 2.0, 3.0, 3.5 and 5.0. - # Probing for one of them is sufficient. - "libdevice.compute_20.10.bc", -] +def to_list_of_strings(elements): + """Convert the list of ["a", "b", "c"] into '"a", "b", "c"'. + + This is to be used to put a list of strings into the bzl file templates + so it gets interpreted as list of strings in Starlark. + + Args: + elements: list of string elements + + Returns: + single string of elements wrapped in quotes separated by a comma.""" + quoted_strings = ["\"" + element + "\"" for element in elements] + return ", ".join(quoted_strings) + +def verify_build_defines(params): + """Verify all variables that crosstool/BUILD.tpl expects are substituted. + + Args: + params: dict of variables that will be passed to the BUILD.tpl template. + """ + missing = [] + for param in [ + "cxx_builtin_include_directories", + "extra_no_canonical_prefixes_flags", + "host_compiler_path", + "host_compiler_prefix", + "host_compiler_warnings", + "linker_bin_path", + "compiler_deps", + "msvc_cl_path", + "msvc_env_include", + "msvc_env_lib", + "msvc_env_path", + "msvc_env_tmp", + "msvc_lib_path", + "msvc_link_path", + "msvc_ml_path", + "unfiltered_compile_flags", + "win_compiler_deps", + ]: + if ("%{" + param + "}") not in params: + missing.append(param) + + if missing: + auto_configure_fail( + "BUILD.tpl template is missing these variables: " + + str(missing) + + ".\nWe only got: " + + str(params) + + ".", + ) def _get_python_bin(repository_ctx): """Gets the python bin path.""" @@ -139,7 +115,7 @@ def _get_python_bin(repository_ctx): ) def _get_nvcc_tmp_dir_for_windows(repository_ctx): - """Return the tmp directory for nvcc to generate intermediate source files.""" + """Return the Windows tmp directory for nvcc to generate intermediate source files.""" escaped_tmp_dir = escape_string( get_env_var(repository_ctx, "TMP", "C:\\Windows\\Temp").replace( "\\", @@ -148,6 +124,13 @@ def _get_nvcc_tmp_dir_for_windows(repository_ctx): ) return escaped_tmp_dir + "\\\\nvcc_inter_files_tmp_dir" +def _get_nvcc_tmp_dir_for_unix(repository_ctx): + """Return the UNIX tmp directory for nvcc to generate intermediate source files.""" + escaped_tmp_dir = escape_string( + get_env_var(repository_ctx, "TMPDIR", "/tmp"), + ) + return escaped_tmp_dir + "/nvcc_inter_files_tmp_dir" + def _get_msvc_compiler(repository_ctx): vc_path = find_vc_path(repository_ctx) return find_msvc_tool(repository_ctx, vc_path, "cl.exe").replace("\\", "/") @@ -155,20 +138,19 @@ def _get_msvc_compiler(repository_ctx): def _get_win_cuda_defines(repository_ctx): """Return CROSSTOOL defines for Windows""" - # If we are not on Windows, return empty vaules for Windows specific fields. + # If we are not on Windows, return fake vaules for Windows specific fields. # This ensures the CROSSTOOL file parser is happy. if not _is_windows(repository_ctx): - return dict({ - "%{msvc_env_tmp}": "", - "%{msvc_env_path}": "", - "%{msvc_env_include}": "", - "%{msvc_env_lib}": "", - "%{msvc_cl_path}": "", - "%{msvc_ml_path}": "", - "%{msvc_link_path}": "", - "%{msvc_lib_path}": "", - "%{cxx_builtin_include_directory}": "", - }) + return { + "%{msvc_env_tmp}": "msvc_not_used", + "%{msvc_env_path}": "msvc_not_used", + "%{msvc_env_include}": "msvc_not_used", + "%{msvc_env_lib}": "msvc_not_used", + "%{msvc_cl_path}": "msvc_not_used", + "%{msvc_ml_path}": "msvc_not_used", + "%{msvc_link_path}": "msvc_not_used", + "%{msvc_lib_path}": "msvc_not_used", + } vc_path = find_vc_path(repository_ctx) if not vc_path: @@ -204,16 +186,14 @@ def _get_win_cuda_defines(repository_ctx): ) # nvcc will generate some temporary source files under %{nvcc_tmp_dir} - # The generated files are guranteed to have unique name, so they can share the same tmp directory + # The generated files are guaranteed to have unique name, so they can share + # the same tmp directory escaped_cxx_include_directories = [ - "cxx_builtin_include_directory: \"%s\"" % _get_nvcc_tmp_dir_for_windows(repository_ctx), ] for path in escaped_include_paths.split(";"): if path: - escaped_cxx_include_directories.append( - "cxx_builtin_include_directory: \"%s\"" % path, - ) + escaped_cxx_include_directories.append(path) return { "%{msvc_env_tmp}": escaped_tmp_dir, @@ -224,9 +204,14 @@ def _get_win_cuda_defines(repository_ctx): "%{msvc_ml_path}": msvc_ml_path, "%{msvc_link_path}": msvc_link_path, "%{msvc_lib_path}": msvc_lib_path, - "%{cxx_builtin_include_directory}": "\n".join(escaped_cxx_include_directories), + "%{cxx_builtin_include_directories}": to_list_of_strings( + escaped_cxx_include_directories, + ), } +# TODO(dzc): Once these functions have been factored out of Bazel's +# cc_configure.bzl, load them from @bazel_tools instead. +# BEGIN cc_configure common functions. def find_cc(repository_ctx): """Find the C++ compiler.""" if _is_windows(repository_ctx): @@ -247,8 +232,7 @@ def find_cc(repository_ctx): if cc == None: fail(("Cannot find {}, either correct your path or set the {}" + " environment variable").format(target_cc_name, cc_path_envvar)) - return cc - + return str(cc) _INC_DIR_MARKER_BEGIN = "#include <...>" @@ -265,6 +249,7 @@ def _cxx_inc_convert(path): def _normalize_include_path(repository_ctx, path): """Normalizes include paths before writing them to the crosstool. + If path points inside the 'crosstool' folder of the repository, a relative path is returned. If path points outside the 'crosstool' folder, an absolute path is returned. @@ -277,13 +262,17 @@ def _normalize_include_path(repository_ctx, path): return path[len(crosstool_folder) + 1:] return path -def _get_cxx_inc_directories_impl(repository_ctx, cc, lang_is_cpp): +def _get_cxx_inc_directories_impl(repository_ctx, cc, lang_is_cpp, tf_sysroot): """Compute the list of default C or C++ include directories.""" if lang_is_cpp: lang = "c++" else: lang = "c" - result = repository_ctx.execute([cc, "-E", "-x" + lang, "-", "-v"]) + sysroot = [] + if tf_sysroot: + sysroot += ["--sysroot", tf_sysroot] + result = repository_ctx.execute([cc, "-E", "-x" + lang, "-", "-v"] + + sysroot) index1 = result.stderr.find(_INC_DIR_MARKER_BEGIN) if index1 == -1: return [] @@ -304,20 +293,29 @@ def _get_cxx_inc_directories_impl(repository_ctx, cc, lang_is_cpp): for p in inc_dirs.split("\n") ] -def get_cxx_inc_directories(repository_ctx, cc): +def get_cxx_inc_directories(repository_ctx, cc, tf_sysroot): """Compute the list of default C and C++ include directories.""" # For some reason `clang -xc` sometimes returns include paths that are # different from the ones from `clang -xc++`. (Symlink and a dir) # So we run the compiler with both `-xc` and `-xc++` and merge resulting lists - includes_cpp = _get_cxx_inc_directories_impl(repository_ctx, cc, True) - includes_c = _get_cxx_inc_directories_impl(repository_ctx, cc, False) + includes_cpp = _get_cxx_inc_directories_impl( + repository_ctx, + cc, + True, + tf_sysroot, + ) + includes_c = _get_cxx_inc_directories_impl( + repository_ctx, + cc, + False, + tf_sysroot, + ) - includes_cpp_set = depset(includes_cpp) return includes_cpp + [ inc for inc in includes_c - if inc not in includes_cpp_set + if inc not in includes_cpp ] def auto_configure_fail(msg): @@ -328,31 +326,15 @@ def auto_configure_fail(msg): # END cc_configure common functions (see TODO above). -def _host_compiler_includes(repository_ctx, cc): - """Generates the cxx_builtin_include_directory entries for gcc inc dirs. - Args: - repository_ctx: The repository context. - cc: The path to the gcc host compiler. - Returns: - A string containing the cxx_builtin_include_directory for each of the gcc - host compiler include directories, which can be added to the CROSSTOOL - file. - """ - inc_dirs = get_cxx_inc_directories(repository_ctx, cc) - inc_entries = [] - for inc_dir in inc_dirs: - inc_entries.append(" cxx_builtin_include_directory: \"%s\"" % inc_dir) - return "\n".join(inc_entries) - def _cuda_include_path(repository_ctx, cuda_config): - """Generates the cxx_builtin_include_directory entries for cuda inc dirs. + """Generates the Starlark string with cuda include directories. + Args: repository_ctx: The repository context. cc: The path to the gcc host compiler. + Returns: - A string containing the cxx_builtin_include_directory for each of the gcc - host compiler include directories, which can be added to the CROSSTOOL - file. + A list of the gcc host compiler include directories. """ nvcc_path = repository_ctx.path("%s/bin/nvcc%s" % ( cuda_config.cuda_toolkit_path, @@ -376,49 +358,23 @@ def _cuda_include_path(repository_ctx, cuda_config): ) inc_entries = [] if target_dir != "": - inc_entries.append(" cxx_builtin_include_directory: \"%s\"" % target_dir) - default_include = cuda_config.cuda_toolkit_path + "/include" - inc_entries.append( - " cxx_builtin_include_directory: \"%s\"" % default_include, - ) - return "\n".join(inc_entries) + inc_entries.append(target_dir) + inc_entries.append(cuda_config.cuda_toolkit_path + "/include") + return inc_entries def enable_cuda(repository_ctx): - if "TF_NEED_CUDA" in repository_ctx.os.environ: - enable_cuda = repository_ctx.os.environ["TF_NEED_CUDA"].strip() - return enable_cuda == "1" - return False - -def cuda_toolkit_path(repository_ctx): - """Finds the cuda toolkit directory. - Args: - repository_ctx: The repository context. - Returns: - A speculative real path of the cuda toolkit install directory. - """ - cuda_toolkit_path = _DEFAULT_CUDA_TOOLKIT_PATH - if _CUDA_TOOLKIT_PATH in repository_ctx.os.environ: - cuda_toolkit_path = repository_ctx.os.environ[_CUDA_TOOLKIT_PATH].strip() - if not repository_ctx.path(cuda_toolkit_path).exists: - auto_configure_fail("Cannot find cuda toolkit path.") - return str(repository_ctx.path(cuda_toolkit_path).realpath) - -def _cudnn_install_basedir(repository_ctx): - """Finds the cudnn install directory.""" - cudnn_install_path = _DEFAULT_CUDNN_INSTALL_PATH - if _CUDNN_INSTALL_PATH in repository_ctx.os.environ: - cudnn_install_path = repository_ctx.os.environ[_CUDNN_INSTALL_PATH].strip() - if not repository_ctx.path(cudnn_install_path).exists: - auto_configure_fail("Cannot find cudnn install path.") - return cudnn_install_path + """Returns whether to build with CUDA support.""" + return int(repository_ctx.os.environ.get("TF_NEED_CUDA", False)) def matches_version(environ_version, detected_version): """Checks whether the user-specified version matches the detected version. + This function performs a weak matching so that if the user specifies only the major or major and minor versions, the versions are still considered matching if the version parts match. To illustrate: + environ_version detected_version result ----------------------------------------- 5.1.3 5.1.3 True @@ -426,6 +382,7 @@ def matches_version(environ_version, detected_version): 5 5.1 True 5.1.3 5.1 False 5.2.3 5.1.3 False + Args: environ_version: The version specified by the user via environment variables. @@ -447,79 +404,20 @@ def matches_version(environ_version, detected_version): _NVCC_VERSION_PREFIX = "Cuda compilation tools, release " -def _cuda_version(repository_ctx, cuda_toolkit_path, cpu_value): - """Detects the version of CUDA installed on the system. - Args: - repository_ctx: The repository context. - cuda_toolkit_path: The CUDA install directory. - Returns: - String containing the version of CUDA. - """ - - # Run nvcc --version and find the line containing the CUDA version. - nvcc_path = repository_ctx.path("%s/bin/nvcc%s" % ( - cuda_toolkit_path, - ".exe" if cpu_value == "Windows" else "", - )) - if not nvcc_path.exists: - auto_configure_fail("Cannot find nvcc at %s" % str(nvcc_path)) - result = repository_ctx.execute([str(nvcc_path), "--version"]) - if result.stderr: - auto_configure_fail("Error running nvcc --version: %s" % result.stderr) - lines = result.stdout.splitlines() - version_line = lines[len(lines) - 1] - if version_line.find(_NVCC_VERSION_PREFIX) == -1: - auto_configure_fail( - "Could not parse CUDA version from nvcc --version. Got: %s" % - result.stdout, - ) - - # Parse the CUDA version from the line containing the CUDA version. - prefix_removed = version_line.replace(_NVCC_VERSION_PREFIX, "") - parts = prefix_removed.split(",") - if len(parts) != 2 or len(parts[0]) < 2: - auto_configure_fail( - "Could not parse CUDA version from nvcc --version. Got: %s" % - result.stdout, - ) - full_version = parts[1].strip() - if full_version.startswith("V"): - full_version = full_version[1:] - - # Check whether TF_CUDA_VERSION was set by the user and fail if it does not - # match the detected version. - environ_version = "" - if _TF_CUDA_VERSION in repository_ctx.os.environ: - environ_version = repository_ctx.os.environ[_TF_CUDA_VERSION].strip() - if environ_version and not matches_version(environ_version, full_version): - auto_configure_fail( - ("CUDA version detected from nvcc (%s) does not match " + - "TF_CUDA_VERSION (%s)") % (full_version, environ_version), - ) - - # We only use the version consisting of the major and minor version numbers. - version_parts = full_version.split(".") - if len(version_parts) < 2: - auto_configure_fail("CUDA version detected from nvcc (%s) is incomplete.") - if cpu_value == "Windows": - version = "64_%s%s" % (version_parts[0], version_parts[1]) - else: - version = "%s.%s" % (version_parts[0], version_parts[1]) - return version - _DEFINE_CUDNN_MAJOR = "#define CUDNN_MAJOR" -_DEFINE_CUDNN_MINOR = "#define CUDNN_MINOR" -_DEFINE_CUDNN_PATCHLEVEL = "#define CUDNN_PATCHLEVEL" def find_cuda_define(repository_ctx, header_dir, header_file, define): """Returns the value of a #define in a header file. + Greps through a header file and returns the value of the specified #define. If the #define is not found, then raise an error. + Args: repository_ctx: The repository context. header_dir: The directory containing the header file. header_file: The header file name. define: The #define to search for. + Returns: The value of the #define found in the header. """ @@ -576,58 +474,6 @@ def find_cuda_define(repository_ctx, header_dir, header_file, define): version = version[:version_end].strip() return version -def _cudnn_version(repository_ctx, cudnn_install_basedir, cpu_value): - """Detects the version of cuDNN installed on the system. - Args: - repository_ctx: The repository context. - cpu_value: The name of the host operating system. - cudnn_install_basedir: The cuDNN install directory. - Returns: - A string containing the version of cuDNN. - """ - cudnn_header_dir = _find_cudnn_header_dir( - repository_ctx, - cudnn_install_basedir, - ) - major_version = find_cuda_define( - repository_ctx, - cudnn_header_dir, - "cudnn.h", - _DEFINE_CUDNN_MAJOR, - ) - minor_version = find_cuda_define( - repository_ctx, - cudnn_header_dir, - "cudnn.h", - _DEFINE_CUDNN_MINOR, - ) - patch_version = find_cuda_define( - repository_ctx, - cudnn_header_dir, - "cudnn.h", - _DEFINE_CUDNN_PATCHLEVEL, - ) - full_version = "%s.%s.%s" % (major_version, minor_version, patch_version) - - # Check whether TF_CUDNN_VERSION was set by the user and fail if it does not - # match the detected version. - environ_version = "" - if _TF_CUDNN_VERSION in repository_ctx.os.environ: - environ_version = repository_ctx.os.environ[_TF_CUDNN_VERSION].strip() - if environ_version and not matches_version(environ_version, full_version): - cudnn_h_path = repository_ctx.path( - "%s/include/cudnn.h" % cudnn_install_basedir, - ) - auto_configure_fail(("cuDNN version detected from %s (%s) does not match " + - "TF_CUDNN_VERSION (%s)") % - (str(cudnn_h_path), full_version, environ_version)) - - # Only use the major version to match the SONAME of the library. - version = major_version - if cpu_value == "Windows": - version = "64_" + version - return version - def compute_capabilities(repository_ctx): """Returns a list of strings representing cuda compute capabilities.""" if _TF_CUDA_COMPUTE_CAPABILITIES not in repository_ctx.os.environ: @@ -645,8 +491,10 @@ def compute_capabilities(repository_ctx): def get_cpu_value(repository_ctx): """Returns the name of the host operating system. + Args: repository_ctx: The repository context. + Returns: A string containing the name of the host operating system. """ @@ -660,15 +508,17 @@ def get_cpu_value(repository_ctx): def _is_windows(repository_ctx): """Returns true if the host operating system is windows.""" - return get_cpu_value(repository_ctx) == "Windows" + return repository_ctx.os.name.lower().find("windows") >= 0 def lib_name(base_name, cpu_value, version = None, static = False): """Constructs the platform-specific name of a library. + Args: base_name: The name of the library, such as "cudart" cpu_value: The name of the host operating system. version: The version of the library. static: True the library is static or False if it is a shared object. + Returns: The platform-specific name of the library. """ @@ -689,8 +539,10 @@ def lib_name(base_name, cpu_value, version = None, static = False): def find_lib(repository_ctx, paths, check_soname = True): """ Finds a library among a list of potential paths. + Args: paths: List of paths to inspect. + Returns: Returns the first path in paths that exist. """ @@ -721,6 +573,7 @@ def _find_cuda_lib( version, static = False): """Finds the given CUDA or cuDNN library on the system. + Args: lib: The name of the library, such as "cudart" repository_ctx: The repository context. @@ -728,85 +581,49 @@ def _find_cuda_lib( basedir: The install directory of CUDA or cuDNN. version: The version of the library. static: True if static library, False if shared object. - Returns: - Returns the path to the library. - """ - file_name = lib_name(lib, cpu_value, version, static) - return find_lib(repository_ctx, [ - "%s/%s%s" % (basedir, path, file_name) - for path in CUDA_LIB_PATHS - ], check_soname = version and not static) - -def _find_cupti_header_dir(repository_ctx, cuda_config): - """Returns the path to the directory containing cupti.h - On most systems, the cupti library is not installed in the same directory as - the other CUDA libraries but rather in a special extras/CUPTI directory. - Args: - repository_ctx: The repository context. - cuda_config: The CUDA config as returned by _get_cuda_config - Returns: - The path of the directory containing the cupti header. - """ - cuda_toolkit_path = cuda_config.cuda_toolkit_path - for relative_path in CUPTI_HEADER_PATHS: - if repository_ctx.path( - "%s/%scupti.h" % (cuda_toolkit_path, relative_path), - ).exists: - return ("%s/%s" % (cuda_toolkit_path, relative_path))[:-1] - auto_configure_fail("Cannot find cupti.h under %s" % ", ".join( - [cuda_toolkit_path + "/" + s for s in CUPTI_HEADER_PATHS], - )) -def _find_cupti_lib(repository_ctx, cuda_config): - """Finds the cupti library on the system. - On most systems, the cupti library is not installed in the same directory as - the other CUDA libraries but rather in a special extras/CUPTI directory. - Args: - repository_ctx: The repository context. - cuda_config: The cuda configuration as returned by _get_cuda_config. Returns: Returns the path to the library. """ - file_name = lib_name( - "cupti", - cuda_config.cpu_value, - cuda_config.cuda_version, + file_name = lib_name(lib, cpu_value, version, static) + return find_lib( + repository_ctx, + ["%s/%s" % (basedir, file_name)], + check_soname = version and not static, ) - basedir = cuda_config.cuda_toolkit_path - return find_lib(repository_ctx, [ - "%s/%s%s" % (basedir, path, file_name) - for path in CUPTI_LIB_PATHS - ]) def _find_libs(repository_ctx, cuda_config): """Returns the CUDA and cuDNN libraries on the system. + Args: repository_ctx: The repository context. cuda_config: The CUDA config as returned by _get_cuda_config + Returns: Map of library names to structs of filename and path. """ cpu_value = cuda_config.cpu_value + stub_dir = "" if _is_windows(repository_ctx) else "/stubs" return { "cuda": _find_cuda_lib( "cuda", repository_ctx, cpu_value, - cuda_config.cuda_toolkit_path, + cuda_config.config["cuda_library_dir"] + stub_dir, None, ), "cudart": _find_cuda_lib( "cudart", repository_ctx, cpu_value, - cuda_config.cuda_toolkit_path, + cuda_config.config["cuda_library_dir"], cuda_config.cuda_version, ), "cudart_static": _find_cuda_lib( "cudart_static", repository_ctx, cpu_value, - cuda_config.cuda_toolkit_path, + cuda_config.config["cuda_library_dir"], cuda_config.cuda_version, static = True, ), @@ -814,103 +631,77 @@ def _find_libs(repository_ctx, cuda_config): "cublas", repository_ctx, cpu_value, - cuda_config.cuda_toolkit_path, - cuda_config.cuda_version, + cuda_config.config["cublas_library_dir"], + cuda_config.cuda_lib_version, ), "cusolver": _find_cuda_lib( "cusolver", repository_ctx, cpu_value, - cuda_config.cuda_toolkit_path, - cuda_config.cuda_version, + cuda_config.config["cuda_library_dir"], + cuda_config.cuda_lib_version, ), "curand": _find_cuda_lib( "curand", repository_ctx, cpu_value, - cuda_config.cuda_toolkit_path, - cuda_config.cuda_version, + cuda_config.config["cuda_library_dir"], + cuda_config.cuda_lib_version, ), "cufft": _find_cuda_lib( "cufft", repository_ctx, cpu_value, - cuda_config.cuda_toolkit_path, - cuda_config.cuda_version, + cuda_config.config["cuda_library_dir"], + cuda_config.cuda_lib_version, ), "cudnn": _find_cuda_lib( "cudnn", repository_ctx, cpu_value, - cuda_config.cudnn_install_basedir, + cuda_config.config["cudnn_library_dir"], cuda_config.cudnn_version, ), - "cupti": _find_cupti_lib(repository_ctx, cuda_config), + "cupti": _find_cuda_lib( + "cupti", + repository_ctx, + cpu_value, + cuda_config.config["cupti_library_dir"], + cuda_config.cuda_version, + ), + "cusparse": _find_cuda_lib( + "cusparse", + repository_ctx, + cpu_value, + cuda_config.config["cuda_library_dir"], + cuda_config.cuda_lib_version, + ), } -def _find_cuda_include_path(repository_ctx, cuda_config): - """Returns the path to the directory containing cuda.h - Args: - repository_ctx: The repository context. - cuda_config: The CUDA config as returned by _get_cuda_config - Returns: - The path of the directory containing the CUDA headers. - """ - cuda_toolkit_path = cuda_config.cuda_toolkit_path - for relative_path in CUDA_INCLUDE_PATHS: - if repository_ctx.path( - "%s/%scuda.h" % (cuda_toolkit_path, relative_path), - ).exists: - return ("%s/%s" % (cuda_toolkit_path, relative_path))[:-1] - auto_configure_fail("Cannot find cuda.h under %s" % cuda_toolkit_path) - -def _find_cudnn_header_dir(repository_ctx, cudnn_install_basedir): - """Returns the path to the directory containing cudnn.h - Args: - repository_ctx: The repository context. - cudnn_install_basedir: The cudnn install directory as returned by - _cudnn_install_basedir. - Returns: - The path of the directory containing the cudnn header. - """ - for relative_path in CUDA_INCLUDE_PATHS: - if repository_ctx.path( - "%s/%scudnn.h" % (cudnn_install_basedir, relative_path), - ).exists: - return ("%s/%s" % (cudnn_install_basedir, relative_path))[:-1] - if repository_ctx.path("/usr/include/cudnn.h").exists: - return "/usr/include" - auto_configure_fail("Cannot find cudnn.h under %s" % cudnn_install_basedir) - -def _find_nvvm_libdevice_dir(repository_ctx, cuda_config): - """Returns the path to the directory containing libdevice in bitcode format. - Args: - repository_ctx: The repository context. - cuda_config: The CUDA config as returned by _get_cuda_config - Returns: - The path of the directory containing the CUDA headers. - """ - cuda_toolkit_path = cuda_config.cuda_toolkit_path - for libdevice_file in NVVM_LIBDEVICE_FILES: - for relative_path in NVVM_LIBDEVICE_PATHS: - if repository_ctx.path("%s/%s%s" % ( - cuda_toolkit_path, - relative_path, - libdevice_file, - )).exists: - return ("%s/%s" % (cuda_toolkit_path, relative_path))[:-1] - auto_configure_fail( - "Cannot find libdevice*.bc files under %s" % cuda_toolkit_path, - ) - def _cudart_static_linkopt(cpu_value): """Returns additional platform-specific linkopts for cudart.""" return "" if cpu_value == "Darwin" else "\"-lrt\"," +# TODO(csigg): Only call once instead of from here, tensorrt_configure.bzl, +# and nccl_configure.bzl. +def find_cuda_config(repository_ctx, cuda_libraries): + """Returns CUDA config dictionary from running find_cuda_config.py""" + exec_result = repository_ctx.execute([ + _get_python_bin(repository_ctx), + repository_ctx.path(Label("//gpu:find_cuda_config.py")), + ] + cuda_libraries) + if exec_result.return_code: + auto_configure_fail("Failed to run find_cuda_config.py: %s" % exec_result.stderr) + + # Parse the dict from stdout. + return dict([tuple(x.split(": ")) for x in exec_result.stdout.splitlines()]) + def _get_cuda_config(repository_ctx): """Detects and returns information about the CUDA installation on the system. + Args: repository_ctx: The repository context. + Returns: A struct containing the following fields: cuda_toolkit_path: The CUDA toolkit installation directory. @@ -920,27 +711,36 @@ def _get_cuda_config(repository_ctx): compute_capabilities: A list of the system's CUDA compute capabilities. cpu_value: The name of the host operating system. """ + config = find_cuda_config(repository_ctx, ["cuda", "cudnn"]) cpu_value = get_cpu_value(repository_ctx) - toolkit_path = cuda_toolkit_path(repository_ctx) - cuda_version = _cuda_version(repository_ctx, toolkit_path, cpu_value) - cudnn_install_basedir = _cudnn_install_basedir(repository_ctx) - cudnn_version = _cudnn_version( - repository_ctx, - cudnn_install_basedir, - cpu_value, - ) + toolkit_path = config["cuda_toolkit_path"] + + is_windows = _is_windows(repository_ctx) + cuda_version = config["cuda_version"].split(".") + cuda_major = cuda_version[0] + cuda_minor = cuda_version[1] + + cuda_version = ("64_%s%s" if is_windows else "%s.%s") % (cuda_major, cuda_minor) + cudnn_version = ("64_%s" if is_windows else "%s") % config["cudnn_version"] + + # cuda_lib_version is for libraries like cuBLAS, cuFFT, cuSOLVER, etc. + # It changed from 'x.y' to just 'x' in CUDA 10.1. + if (int(cuda_major), int(cuda_minor)) >= (10, 1): + cuda_lib_version = ("64_%s" if is_windows else "%s") % cuda_major + else: + cuda_lib_version = cuda_version + return struct( cuda_toolkit_path = toolkit_path, - cudnn_install_basedir = cudnn_install_basedir, cuda_version = cuda_version, cudnn_version = cudnn_version, + cuda_lib_version = cuda_lib_version, compute_capabilities = compute_capabilities(repository_ctx), cpu_value = cpu_value, + config = config, ) def _tpl(repository_ctx, tpl, substitutions = {}, out = None): - if substitutions == None: - substitutions = {} if not out: out = tpl.replace(":", "/") repository_ctx.template( @@ -956,8 +756,28 @@ def _file(repository_ctx, label): {}, ) +_DUMMY_CROSSTOOL_BZL_FILE = """ +def error_gpu_disabled(): + fail("ERROR: Building with --config=cuda but TensorFlow is not configured " + + "to build with GPU support. Please re-run ./configure and enter 'Y' " + + "at the prompt to build with GPU support.") + + native.genrule( + name = "error_gen_crosstool", + outs = ["CROSSTOOL"], + cmd = "echo 'Should not be run.' && exit 1", + ) + + native.filegroup( + name = "crosstool", + srcs = [":CROSSTOOL"], + output_licenses = ["unencumbered"], + ) +""" + _DUMMY_CROSSTOOL_BUILD_FILE = """ load("//crosstool:error_gpu_disabled.bzl", "error_gpu_disabled") + error_gpu_disabled() """ @@ -991,8 +811,12 @@ def _create_dummy_repository(repository_ctx): "%{cufft_lib}": lib_name("cufft", cpu_value), "%{curand_lib}": lib_name("curand", cpu_value), "%{cupti_lib}": lib_name("cupti", cpu_value), - "%{copy_rules}": "", - "%{cuda_headers}": "", + "%{cusparse_lib}": lib_name("cusparse", cpu_value), + "%{copy_rules}": """ +filegroup(name="cuda-include") +filegroup(name="cublas-include") +filegroup(name="cudnn-include") +""", }, ) @@ -1013,7 +837,34 @@ def _create_dummy_repository(repository_ctx): repository_ctx.file("cuda/cuda/lib/%s" % lib_name("curand", cpu_value)) repository_ctx.file("cuda/cuda/lib/%s" % lib_name("cufft", cpu_value)) repository_ctx.file("cuda/cuda/lib/%s" % lib_name("cupti", cpu_value)) + repository_ctx.file("cuda/cuda/lib/%s" % lib_name("cusparse", cpu_value)) + + # Set up cuda_config.h, which is used by + # tensorflow/stream_executor/dso_loader.cc. + _tpl( + repository_ctx, + "cuda:cuda_config.h", + { + "%{cuda_version}": "", + "%{cuda_lib_version}": "", + "%{cudnn_version}": "", + "%{cuda_compute_capabilities}": ",".join([ + "CudaVersion(\"%s\")" % c + for c in _DEFAULT_CUDA_COMPUTE_CAPABILITIES + ]), + "%{cuda_toolkit_path}": "", + }, + "cuda/cuda/cuda_config.h", + ) + # If cuda_configure is not configured to build with GPU support, and the user + # attempts to build with --config=cuda, add a dummy build rule to intercept + # this and fail with an actionable error message. + repository_ctx.file( + "crosstool/error_gpu_disabled.bzl", + _DUMMY_CROSSTOOL_BZL_FILE, + ) + repository_ctx.file("crosstool/BUILD", _DUMMY_CROSSTOOL_BUILD_FILE) def _execute( repository_ctx, @@ -1022,6 +873,7 @@ def _execute( error_details = None, empty_stdout_fine = False): """Executes an arbitrary shell command. + Args: repository_ctx: the repository_ctx object cmdline: list of strings, the command to execute @@ -1055,7 +907,7 @@ def make_copy_files_rule(repository_ctx, name, srcs, outs): # Copy files. for src, out in zip(srcs, outs): - cmds.append('cp -f "%s" $(location %s)' % (src, out)) + cmds.append('cp -f "%s" "$(location %s)"' % (src, out)) outs = [(' "%s",' % out) for out in outs] return """genrule( name = "%s", @@ -1063,7 +915,7 @@ def make_copy_files_rule(repository_ctx, name, srcs, outs): %s ], cmd = \"""%s \""", -)""" % (name, "\n".join(outs), " && ".join(cmds)) +)""" % (name, "\n".join(outs), " && \\\n".join(cmds)) def make_copy_dir_rule(repository_ctx, name, src_dir, out_dir): """Returns a rule to recursively copy a directory.""" @@ -1085,6 +937,7 @@ def make_copy_dir_rule(repository_ctx, name, src_dir, out_dir): def _read_dir(repository_ctx, src_dir): """Returns a string with all files in a directory. + Finds all files inside a directory, traversing subfolders and following symlinks. The returned string contains the full path of all files separated by line breaks. @@ -1109,17 +962,33 @@ def _read_dir(repository_ctx, src_dir): result = find_result.stdout return sorted(result.splitlines()) +def _flag_enabled(repository_ctx, flag_name): + if flag_name in repository_ctx.os.environ: + value = repository_ctx.os.environ[flag_name].strip() + return value == "1" + return False + +def _tf_sysroot(repository_ctx): + if _TF_SYSROOT in repository_ctx.os.environ: + return repository_ctx.os.environ[_TF_SYSROOT] + return "" + +def _compute_cuda_extra_copts(repository_ctx, compute_capabilities): + capability_flags = [ + "--cuda-gpu-arch=sm_" + cap.replace(".", "") + for cap in compute_capabilities + ] + return str(capability_flags) + def _create_local_cuda_repository(repository_ctx): """Creates the repository containing files set up to build with CUDA.""" cuda_config = _get_cuda_config(repository_ctx) - cuda_include_path = _find_cuda_include_path(repository_ctx, cuda_config) - cudnn_header_dir = _find_cudnn_header_dir( - repository_ctx, - cuda_config.cudnn_install_basedir, - ) - cupti_header_dir = _find_cupti_header_dir(repository_ctx, cuda_config) - nvvm_libdevice_dir = _find_nvvm_libdevice_dir(repository_ctx, cuda_config) + cuda_include_path = cuda_config.config["cuda_include_dir"] + cublas_include_path = cuda_config.config["cublas_include_dir"] + cudnn_header_dir = cuda_config.config["cudnn_include_dir"] + cupti_header_dir = cuda_config.config["cupti_include_dir"] + nvvm_libdevice_dir = cuda_config.config["nvvm_library_dir"] # Create genrule to copy files from the installed CUDA toolkit into execroot. copy_rules = [ @@ -1143,6 +1012,21 @@ def _create_local_cuda_repository(repository_ctx): ), ] + copy_rules.append(make_copy_files_rule( + repository_ctx, + name = "cublas-include", + srcs = [ + cublas_include_path + "/cublas.h", + cublas_include_path + "/cublas_v2.h", + cublas_include_path + "/cublas_api.h", + ], + outs = [ + "cublas/include/cublas.h", + "cublas/include/cublas_v2.h", + "cublas/include/cublas_api.h", + ], + )) + cuda_libs = _find_libs(repository_ctx, cuda_config) cuda_lib_srcs = [] cuda_lib_outs = [] @@ -1156,24 +1040,30 @@ def _create_local_cuda_repository(repository_ctx): outs = cuda_lib_outs, )) - copy_rules.append(make_copy_dir_rule( + # copy files mentioned in third_party/nccl/build_defs.bzl.tpl + copy_rules.append(make_copy_files_rule( repository_ctx, name = "cuda-bin", - src_dir = cuda_config.cuda_toolkit_path + "/bin", - out_dir = "cuda/bin", + srcs = [ + cuda_config.cuda_toolkit_path + "/bin/" + "crt/link.stub", + cuda_config.cuda_toolkit_path + "/bin/" + "nvlink", + cuda_config.cuda_toolkit_path + "/bin/" + "fatbinary", + cuda_config.cuda_toolkit_path + "/bin/" + "bin2c", + ], + outs = [ + "cuda/bin/" + "crt/link.stub", + "cuda/bin/" + "nvlink", + "cuda/bin/" + "fatbinary", + "cuda/bin/" + "bin2c", + ], )) - # Copy cudnn.h if cuDNN was not installed to CUDA_TOOLKIT_PATH. - included_files = _read_dir(repository_ctx, cuda_include_path) - if not any([file.endswith("cudnn.h") for file in included_files]): - copy_rules.append(make_copy_files_rule( - repository_ctx, - name = "cudnn-include", - srcs = [cudnn_header_dir + "/cudnn.h"], - outs = ["cuda/include/cudnn.h"], - )) - else: - copy_rules.append("filegroup(name = 'cudnn-include')\n") + copy_rules.append(make_copy_files_rule( + repository_ctx, + name = "cudnn-include", + srcs = [cudnn_header_dir + "/cudnn.h"], + outs = ["cudnn/include/cudnn.h"], + )) # Set up BUILD file for cuda/ _tpl( @@ -1181,13 +1071,15 @@ def _create_local_cuda_repository(repository_ctx): "cuda:build_defs.bzl", { "%{cuda_is_configured}": "True", - "%{cuda_extra_copts}": "[]", + "%{cuda_extra_copts}": _compute_cuda_extra_copts( + repository_ctx, + cuda_config.compute_capabilities, + ), }, ) - _tpl( repository_ctx, - "cuda:BUILD", + "cuda:BUILD.windows" if _is_windows(repository_ctx) else "cuda:BUILD", { "%{cuda_driver_lib}": cuda_libs["cuda"].basename, "%{cudart_static_lib}": cuda_libs["cudart_static"].basename, @@ -1199,20 +1091,31 @@ def _create_local_cuda_repository(repository_ctx): "%{cufft_lib}": cuda_libs["cufft"].basename, "%{curand_lib}": cuda_libs["curand"].basename, "%{cupti_lib}": cuda_libs["cupti"].basename, + "%{cusparse_lib}": cuda_libs["cusparse"].basename, "%{copy_rules}": "\n".join(copy_rules), - "%{cuda_headers}": ( - '":cuda-include",\n' + ' ":cudnn-include",' - ), }, "cuda/BUILD", ) - + + tf_sysroot = _tf_sysroot(repository_ctx) + # Set up crosstool/ cc = find_cc(repository_ctx) - cc_fullpath = cc + cc_fullpath = "crosstool/" + cc - host_compiler_includes = _host_compiler_includes(repository_ctx, cc_fullpath) + host_compiler_includes = get_cxx_inc_directories( + repository_ctx, + cc_fullpath, + tf_sysroot, + ) cuda_defines = {} + cuda_defines["%{builtin_sysroot}"] = tf_sysroot + cuda_defines["%{cuda_toolkit_path}"] = "" + + host_compiler_prefix = "/usr/bin" + if _GCC_HOST_COMPILER_PREFIX in repository_ctx.os.environ: + host_compiler_prefix = repository_ctx.os.environ[_GCC_HOST_COMPILER_PREFIX].strip() + cuda_defines["%{host_compiler_prefix}"] = host_compiler_prefix # Bazel sets '-B/usr/bin' flag to workaround build errors on RHEL (see # https://github.com/bazelbuild/bazel/issues/760). @@ -1222,22 +1125,21 @@ def _create_local_cuda_repository(repository_ctx): # TODO: when bazel stops adding '-B/usr/bin' by default, remove this # flag from the CROSSTOOL completely (see # https://github.com/bazelbuild/bazel/issues/5634) - cuda_defines["%{linker_bin_path_flag}"] = 'flag: "-B/usr/bin"' + cuda_defines["%{linker_bin_path}"] = host_compiler_prefix - + cuda_defines["%{extra_no_canonical_prefixes_flags}"] = "" + cuda_defines["%{unfiltered_compile_flags}"] = "" cuda_defines["%{host_compiler_path}"] = "clang/bin/crosstool_wrapper_driver_is_not_gcc" cuda_defines["%{host_compiler_warnings}"] = "" # nvcc has the system include paths built in and will automatically # search them; we cannot work around that, so we add the relevant cuda # system paths to the allowed compiler specific include paths. - cuda_defines["%{host_compiler_includes}"] = ( - host_compiler_includes + "\n" + _cuda_include_path( + cuda_defines["%{cxx_builtin_include_directories}"] = to_list_of_strings( + host_compiler_includes + _cuda_include_path( repository_ctx, cuda_config, - ) + - "\n cxx_builtin_include_directory: \"%s\"" % cupti_header_dir + - "\n cxx_builtin_include_directory: \"%s\"" % cudnn_header_dir + ) + [cupti_header_dir, cudnn_header_dir], ) # For gcc, do not canonicalize system header paths; some versions of gcc @@ -1245,23 +1147,17 @@ def _create_local_cuda_repository(repository_ctx): # .d file - given that includes that are prefixed with "../" multiple # time quickly grow longer than the root of the tree, this can lead to # bazel's header check failing. - cuda_defines["%{extra_no_canonical_prefixes_flags}"] = ( - "flag: \"-fno-canonical-system-headers\"" - ) + cuda_defines["%{extra_no_canonical_prefixes_flags}"] = "\"-fno-canonical-system-headers\"" + nvcc_path = str( - repository_ctx.path("%s/bin/nvcc%s" % ( - cuda_config.cuda_toolkit_path, + repository_ctx.path("%s/nvcc%s" % ( + cuda_config.config["cuda_binary_dir"], ".exe" if _is_windows(repository_ctx) else "", )), ) - _tpl( - repository_ctx, - "crosstool:BUILD", - { - "%{linker_files}": ":crosstool_wrapper_driver_is_not_gcc", - "%{win_linker_files}": ":windows_msvc_wrapper_files", - }, - ) + cuda_defines["%{compiler_deps}"] = ":crosstool_wrapper_driver_is_not_gcc" + cuda_defines["%{win_compiler_deps}"] = ":windows_msvc_wrapper_files" + wrapper_defines = { "%{cpu_compiler}": str(cc), "%{cuda_version}": cuda_config.cuda_version, @@ -1283,17 +1179,77 @@ def _create_local_cuda_repository(repository_ctx): wrapper_defines, ) + cuda_defines.update(_get_win_cuda_defines(repository_ctx)) + + verify_build_defines(cuda_defines) + + # Only expand template variables in the BUILD file + _tpl(repository_ctx, "crosstool:BUILD", cuda_defines) + + # No templating of cc_toolchain_config - use attributes and templatize the + # BUILD file. + _file(repository_ctx, "crosstool:cc_toolchain_config.bzl") + + # Set up cuda_config.h, which is used by + # tensorflow/stream_executor/dso_loader.cc. + _tpl( + repository_ctx, + "cuda:cuda_config.h", + { + "%{cuda_version}": cuda_config.cuda_version, + "%{cuda_lib_version}": cuda_config.cuda_lib_version, + "%{cudnn_version}": cuda_config.cudnn_version, + "%{cuda_compute_capabilities}": ", ".join([ + "CudaVersion(\"%s\")" % c + for c in cuda_config.compute_capabilities + ]), + "%{cuda_toolkit_path}": cuda_config.cuda_toolkit_path, + }, + "cuda/cuda/cuda_config.h", + ) + +def _create_remote_cuda_repository(repository_ctx, remote_config_repo): + """Creates pointers to a remotely configured repo set up to build with CUDA.""" _tpl( repository_ctx, - "crosstool:CROSSTOOL", - cuda_defines.update(_get_win_cuda_defines(repository_ctx)), - out = "crosstool/CROSSTOOL", + "cuda:build_defs.bzl", + { + "%{cuda_is_configured}": "True", + "%{cuda_extra_copts}": _compute_cuda_extra_copts( + repository_ctx, + compute_capabilities(repository_ctx), + ), + }, + ) + repository_ctx.template( + "cuda/BUILD", + Label(remote_config_repo + "/cuda:BUILD"), + {}, + ) + repository_ctx.template( + "cuda/build_defs.bzl", + Label(remote_config_repo + "/cuda:build_defs.bzl"), + {}, + ) + repository_ctx.template( + "cuda/cuda/cuda_config.h", + Label(remote_config_repo + "/cuda:cuda/cuda_config.h"), + {}, ) def _cuda_autoconf_impl(repository_ctx): """Implementation of the cuda_autoconf repository rule.""" if not enable_cuda(repository_ctx): _create_dummy_repository(repository_ctx) + elif _TF_CUDA_CONFIG_REPO in repository_ctx.os.environ: + if (_TF_CUDA_VERSION not in repository_ctx.os.environ or + _TF_CUDNN_VERSION not in repository_ctx.os.environ): + auto_configure_fail("%s and %s must also be set if %s is specified" % + (_TF_CUDA_VERSION, _TF_CUDNN_VERSION, _TF_CUDA_CONFIG_REPO)) + _create_remote_cuda_repository( + repository_ctx, + repository_ctx.os.environ[_TF_CUDA_CONFIG_REPO], + ) else: _create_local_cuda_repository(repository_ctx) @@ -1301,25 +1257,30 @@ cuda_configure = repository_rule( implementation = _cuda_autoconf_impl, environ = [ _GCC_HOST_COMPILER_PATH, - _CLANG_CUDA_COMPILER_PATH, + _GCC_HOST_COMPILER_PREFIX, "TF_NEED_CUDA", - "TF_CUDA_CLANG", - _TF_DOWNLOAD_CLANG, _CUDA_TOOLKIT_PATH, _CUDNN_INSTALL_PATH, _TF_CUDA_VERSION, _TF_CUDNN_VERSION, _TF_CUDA_COMPUTE_CAPABILITIES, + _TF_CUDA_CONFIG_REPO, "NVVMIR_LIBRARY_DIR", _PYTHON_BIN_PATH, + "TMP", + "TMPDIR", + "TF_CUDA_PATHS", ], ) """Detects and configures the local CUDA toolchain. + Add the following to your WORKSPACE FILE: + ```python cuda_configure(name = "local_config_cuda") ``` + Args: name: A unique name for this workspace rule. """ diff --git a/gpu/find_cuda_config.py b/gpu/find_cuda_config.py new file mode 100644 index 0000000..39f2c21 --- /dev/null +++ b/gpu/find_cuda_config.py @@ -0,0 +1,500 @@ +# Copyright 2019 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Prints CUDA library and header directories and versions found on the system. + +The script searches for CUDA library and header files on the system, inspects +them to determine their version and prints the configuration to stdout. +The paths to inspect and the required versions are specified through environment +variables. If no valid configuration is found, the script prints to stderr and +returns an error code. + +The list of libraries to find is specified as arguments. Supported libraries are +CUDA (includes cuBLAS), cuDNN, NCCL, and TensorRT. + +The script takes a list of base directories specified by the TF_CUDA_PATHS +environment variable as comma-separated glob list. The script looks for headers +and library files in a hard-coded set of subdirectories from these base paths. +If TF_CUDA_PATHS is not specified, a OS specific default is used: + + Linux: /usr/local/cuda, /usr, and paths from 'ldconfig -p'. + Windows: CUDA_PATH environment variable, or + C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\* + +For backwards compatibility, some libraries also use alternative base +directories from other environment variables if they are specified. List of +library-specific environment variables: + + Library Version env variable Additional base directories + ---------------------------------------------------------------- + CUDA TF_CUDA_VERSION CUDA_TOOLKIT_PATH + cuBLAS TF_CUBLAS_VERSION CUDA_TOOLKIT_PATH + cuDNN TF_CUDNN_VERSION CUDNN_INSTALL_PATH + NCCL TF_NCCL_VERSION NCCL_INSTALL_PATH, NCCL_HDR_PATH + TensorRT TF_TENSORRT_VERSION TENSORRT_INSTALL_PATH + +Versions environment variables can be of the form 'x' or 'x.y' to request a +specific version, empty or unspecified to accept any version. + +The output of a found library is of the form: +tf__version: x.y.z +tf__header_dir: ... +tf__library_dir: ... +""" + +import io +import os +import glob +import platform +import re +import subprocess +import sys + +# pylint: disable=g-import-not-at-top +try: + from shutil import which +except ImportError: + from distutils.spawn import find_executable as which +# pylint: enable=g-import-not-at-top + + +class ConfigError(Exception): + pass + + +def _is_linux(): + return platform.system() == "Linux" + + +def _is_windows(): + return platform.system() == "Windows" + + +def _is_macos(): + return platform.system() == "Darwin" + + +def _matches_version(actual_version, required_version): + """Checks whether some version meets the requirements. + + All elements of the required_version need to be present in the + actual_version. + + required_version actual_version result + ----------------------------------------- + 1 1.1 True + 1.2 1 False + 1.2 1.3 False + 1 True + + Args: + required_version: The version specified by the user. + actual_version: The version detected from the CUDA installation. + Returns: Whether the actual version matches the required one. + """ + if actual_version is None: + return False + + # Strip spaces from the versions. + actual_version = actual_version.strip() + required_version = required_version.strip() + return actual_version.startswith(required_version) + + +def _at_least_version(actual_version, required_version): + actual = [int(v) for v in actual_version.split(".")] + required = [int(v) for v in required_version.split(".")] + return actual >= required + + +def _get_header_version(path, name): + """Returns preprocessor defines in C header file.""" + for line in io.open(path, "r", encoding="utf-8").readlines(): + match = re.match("#define %s +(\d+)" % name, line) + if match: + return match.group(1) + return "" + + +def _cartesian_product(first, second): + """Returns all path combinations of first and second.""" + return [os.path.join(f, s) for f in first for s in second] + + +def _get_ld_config_paths(): + """Returns all directories from 'ldconfig -p'.""" + if not _is_linux(): + return [] + ldconfig_path = which("ldconfig") or "/sbin/ldconfig" + output = subprocess.check_output([ldconfig_path, "-p"]) + pattern = re.compile(".* => (.*)") + result = set() + for line in output.splitlines(): + try: + match = pattern.match(line.decode("ascii")) + except UnicodeDecodeError: + match = False + if match: + result.add(os.path.dirname(match.group(1))) + return sorted(list(result)) + + +def _get_default_cuda_paths(cuda_version): + if not cuda_version: + cuda_version = "*" + elif not "." in cuda_version: + cuda_version = cuda_version + ".*" + + if _is_windows(): + return [ + os.environ.get( + "CUDA_PATH", + "C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v%s\\" % + cuda_version) + ] + return ["/usr/local/cuda-%s" % cuda_version, "/usr/local/cuda", "/usr", + "/usr/local/cudnn"] + _get_ld_config_paths() + + +def _header_paths(): + """Returns hard-coded set of relative paths to look for header files.""" + return [ + "", + "include", + "include/cuda", + "include/*-linux-gnu", + "extras/CUPTI/include", + "include/cuda/CUPTI", + ] + + +def _library_paths(): + """Returns hard-coded set of relative paths to look for library files.""" + return [ + "", + "lib64", + "lib", + "lib/*-linux-gnu", + "lib/x64", + "extras/CUPTI/*", + ] + + +def _not_found_error(base_paths, relative_paths, filepattern): + base_paths = "".join(["\n '%s'" % path for path in sorted(base_paths)]) + relative_paths = "".join(["\n '%s'" % path for path in relative_paths]) + return ConfigError( + "Could not find any %s in any subdirectory:%s\nof:%s\n" % + (filepattern, relative_paths, base_paths)) + + +def _find_file(base_paths, relative_paths, filepattern): + for path in _cartesian_product(base_paths, relative_paths): + for file in glob.glob(os.path.join(path, filepattern)): + return file + raise _not_found_error(base_paths, relative_paths, filepattern) + + +def _find_library(base_paths, library_name, required_version): + """Returns first valid path to the requested library.""" + if _is_windows(): + filepattern = library_name + ".lib" + elif _is_macos(): + filepattern = "%s*.dylib" % (".".join(["lib" + library_name] + + required_version.split(".")[:1])) + else: + filepattern = ".".join(["lib" + library_name, "so"] + + required_version.split(".")[:1]) + "*" + return _find_file(base_paths, _library_paths(), filepattern) + + +def _find_versioned_file(base_paths, relative_paths, filepattern, + required_version, get_version): + """Returns first valid path to a file that matches the requested version.""" + for path in _cartesian_product(base_paths, relative_paths): + for file in glob.glob(os.path.join(path, filepattern)): + actual_version = get_version(file) + if _matches_version(actual_version, required_version): + return file, actual_version + raise _not_found_error( + base_paths, relative_paths, + filepattern + " matching version '%s'" % required_version) + + +def _find_header(base_paths, header_name, required_version, get_version): + """Returns first valid path to a header that matches the requested version.""" + return _find_versioned_file(base_paths, _header_paths(), header_name, + required_version, get_version) + + +def _find_cuda_config(base_paths, required_version): + + def get_header_version(path): + version = int(_get_header_version(path, "CUDA_VERSION")) + if not version: + return None + return "%d.%d" % (version // 1000, version % 1000 // 10) + + cuda_header_path, header_version = _find_header(base_paths, "cuda.h", + required_version, + get_header_version) + cuda_version = header_version # x.y, see above. + + cuda_library_path = _find_library(base_paths, "cudart", cuda_version) + + def get_nvcc_version(path): + pattern = "Cuda compilation tools, release \d+\.\d+, V(\d+\.\d+\.\d+)" + for line in subprocess.check_output([path, "--version"]).splitlines(): + match = re.match(pattern, line.decode("ascii")) + if match: + return match.group(1) + return None + + nvcc_name = "nvcc.exe" if _is_windows() else "nvcc" + nvcc_path, nvcc_version = _find_versioned_file(base_paths, [ + "", + "bin", + ], nvcc_name, cuda_version, get_nvcc_version) + + nvvm_path = _find_file(base_paths, [ + "nvvm/libdevice", + "share/cuda", + "lib/nvidia-cuda-toolkit/libdevice", + ], "libdevice*.10.bc") + + cupti_header_path = _find_file(base_paths, _header_paths(), "cupti.h") + cupti_library_path = _find_library(base_paths, "cupti", required_version) + + cuda_binary_dir = os.path.dirname(nvcc_path) + nvvm_library_dir = os.path.dirname(nvvm_path) + + # XLA requires the toolkit path to find ptxas and libdevice. + # TODO(csigg): pass in both directories instead. + cuda_toolkit_paths = ( + os.path.normpath(os.path.join(cuda_binary_dir, "..")), + os.path.normpath(os.path.join(nvvm_library_dir, "../..")), + ) + if cuda_toolkit_paths[0] != cuda_toolkit_paths[1]: + raise ConfigError("Inconsistent CUDA toolkit path: %s vs %s" % + cuda_toolkit_paths) + + return { + "cuda_version": cuda_version, + "cuda_include_dir": os.path.dirname(cuda_header_path), + "cuda_library_dir": os.path.dirname(cuda_library_path), + "cuda_binary_dir": cuda_binary_dir, + "nvvm_library_dir": nvvm_library_dir, + "cupti_include_dir": os.path.dirname(cupti_header_path), + "cupti_library_dir": os.path.dirname(cupti_library_path), + "cuda_toolkit_path": cuda_toolkit_paths[0], + } + + +def _find_cublas_config(base_paths, required_version, cuda_version): + + if _at_least_version(cuda_version, "10.1"): + + def get_header_version(path): + version = ( + _get_header_version(path, name) + for name in ("CUBLAS_VER_MAJOR", "CUBLAS_VER_MINOR", + "CUBLAS_VER_PATCH")) + return ".".join(version) + + header_path, header_version = _find_header(base_paths, "cublas_api.h", + required_version, + get_header_version) + # cuBLAS uses the major version only. + cublas_version = header_version.split(".")[0] + + if not _matches_version(cuda_version, cublas_version): + raise ConfigError("cuBLAS version %s does not match CUDA version %s" % + (cublas_version, cuda_version)) + + else: + # There is no version info available before CUDA 10.1, just find the file. + header_path = _find_file(base_paths, _header_paths(), "cublas_api.h") + # cuBLAS version is the same as CUDA version (x.y). + cublas_version = required_version + + library_path = _find_library(base_paths, "cublas", cublas_version) + + return { + "cublas_include_dir": os.path.dirname(header_path), + "cublas_library_dir": os.path.dirname(library_path), + } + + +def _find_cudnn_config(base_paths, required_version): + + def get_header_version(path): + version = ( + _get_header_version(path, name) + for name in ("CUDNN_MAJOR", "CUDNN_MINOR", "CUDNN_PATCHLEVEL")) + return ".".join(version) + + header_path, header_version = _find_header(base_paths, "cudnn.h", + required_version, + get_header_version) + cudnn_version = header_version.split(".")[0] + + library_path = _find_library(base_paths, "cudnn", cudnn_version) + + return { + "cudnn_version": cudnn_version, + "cudnn_include_dir": os.path.dirname(header_path), + "cudnn_library_dir": os.path.dirname(library_path), + } + + +def _find_nccl_config(base_paths, required_version): + + def get_header_version(path): + version = ( + _get_header_version(path, name) + for name in ("NCCL_MAJOR", "NCCL_MINOR", "NCCL_PATCH")) + return ".".join(version) + + header_path, header_version = _find_header(base_paths, "nccl.h", + required_version, + get_header_version) + nccl_version = header_version.split(".")[0] + + library_path = _find_library(base_paths, "nccl", nccl_version) + + return { + "nccl_version": nccl_version, + "nccl_include_dir": os.path.dirname(header_path), + "nccl_library_dir": os.path.dirname(library_path), + } + + +def _find_tensorrt_config(base_paths, required_version): + + def get_header_version(path): + version = ( + _get_header_version(path, name) + for name in ("NV_TENSORRT_MAJOR", "NV_TENSORRT_MINOR", + "NV_TENSORRT_PATCH")) + # `version` is a generator object, so we convert it to a list before using + # it (muitiple times below). + version = list(version) + if not all(version): + return None # Versions not found, make _matches_version returns False. + return ".".join(version) + + try: + header_path, header_version = _find_header(base_paths, "NvInfer.h", + required_version, + get_header_version) + except ConfigError: + # TensorRT 6 moved the version information to NvInferVersion.h. + header_path, header_version = _find_header(base_paths, "NvInferVersion.h", + required_version, + get_header_version) + + tensorrt_version = header_version.split(".")[0] + library_path = _find_library(base_paths, "nvinfer", tensorrt_version) + + return { + "tensorrt_version": tensorrt_version, + "tensorrt_include_dir": os.path.dirname(header_path), + "tensorrt_library_dir": os.path.dirname(library_path), + } + + +def _list_from_env(env_name, default=[]): + """Returns comma-separated list from environment variable.""" + if env_name in os.environ: + return os.environ[env_name].split(",") + return default + + +def _get_legacy_path(env_name, default=[]): + """Returns a path specified by a legacy environment variable. + + CUDNN_INSTALL_PATH, NCCL_INSTALL_PATH, TENSORRT_INSTALL_PATH set to + '/usr/lib/x86_64-linux-gnu' would previously find both library and header + paths. Detect those and return '/usr', otherwise forward to _list_from_env(). + """ + if env_name in os.environ: + match = re.match("^(/[^/ ]*)+/lib/\w+-linux-gnu/?$", os.environ[env_name]) + if match: + return [match.group(1)] + return _list_from_env(env_name, default) + + +def _normalize_path(path): + """Returns normalized path, with forward slashes on Windows.""" + path = os.path.normpath(path) + if _is_windows(): + path = path.replace("\\", "/") + return path + + +def find_cuda_config(): + """Returns a dictionary of CUDA library and header file paths.""" + libraries = [argv.lower() for argv in sys.argv[1:]] + cuda_version = os.environ.get("TF_CUDA_VERSION", "") + base_paths = _list_from_env("TF_CUDA_PATHS", + _get_default_cuda_paths(cuda_version)) + base_paths = [path for path in base_paths if os.path.exists(path)] + + result = {} + if "cuda" in libraries: + cuda_paths = _list_from_env("CUDA_TOOLKIT_PATH", base_paths) + result.update(_find_cuda_config(cuda_paths, cuda_version)) + + cuda_version = result["cuda_version"] + cublas_paths = base_paths + if tuple(int(v) for v in cuda_version.split(".")) < (10, 1): + # Before CUDA 10.1, cuBLAS was in the same directory as the toolkit. + cublas_paths = cuda_paths + cublas_version = os.environ.get("TF_CUBLAS_VERSION", "") + result.update( + _find_cublas_config(cublas_paths, cublas_version, cuda_version)) + + if "cudnn" in libraries: + cudnn_paths = _get_legacy_path("CUDNN_INSTALL_PATH", base_paths) + cudnn_version = os.environ.get("TF_CUDNN_VERSION", "") + result.update(_find_cudnn_config(cudnn_paths, cudnn_version)) + + if "nccl" in libraries: + nccl_paths = _get_legacy_path("NCCL_INSTALL_PATH", base_paths) + nccl_version = os.environ.get("TF_NCCL_VERSION", "") + result.update(_find_nccl_config(nccl_paths, nccl_version)) + + if "tensorrt" in libraries: + tensorrt_paths = _get_legacy_path("TENSORRT_INSTALL_PATH", base_paths) + tensorrt_version = os.environ.get("TF_TENSORRT_VERSION", "") + result.update(_find_tensorrt_config(tensorrt_paths, tensorrt_version)) + + for k, v in result.items(): + if k.endswith("_dir") or k.endswith("_path"): + result[k] = _normalize_path(v) + + return result + + +def main(): + try: + for key, value in sorted(find_cuda_config().items()): + print("%s: %s" % (key, value)) + except ConfigError as e: + sys.stderr.write(str(e)) + sys.exit(1) + + +if __name__ == "__main__": + main() diff --git a/third_party/toolchains/preconfig/ubuntu16.04/gcc7_manylinux2010-nvcc-cuda10.1/BUILD b/third_party/toolchains/preconfig/ubuntu16.04/gcc7_manylinux2010-nvcc-cuda10.1/BUILD new file mode 100755 index 0000000..1537a03 --- /dev/null +++ b/third_party/toolchains/preconfig/ubuntu16.04/gcc7_manylinux2010-nvcc-cuda10.1/BUILD @@ -0,0 +1,175 @@ +# This file is expanded from a template by cuda_configure.bzl +# Update cuda_configure.bzl#verify_build_defines when adding new variables. + +load(":cc_toolchain_config.bzl", "cc_toolchain_config") + +licenses(["restricted"]) + +package(default_visibility = ["//visibility:public"]) + +toolchain( + name = "toolchain-linux-x86_64", + exec_compatible_with = [ + "@bazel_tools//platforms:linux", + "@bazel_tools//platforms:x86_64", + ], + target_compatible_with = [ + "@bazel_tools//platforms:linux", + "@bazel_tools//platforms:x86_64", + ], + toolchain = ":cc-compiler-local", + toolchain_type = "@bazel_tools//tools/cpp:toolchain_type", +) + +cc_toolchain_suite( + name = "toolchain", + toolchains = { + "local|compiler": ":cc-compiler-local", + "darwin|compiler": ":cc-compiler-darwin", + "x64_windows|msvc-cl": ":cc-compiler-windows", + "x64_windows": ":cc-compiler-windows", + "arm": ":cc-compiler-local", + "aarch64": ":cc-compiler-local", + "k8": ":cc-compiler-local", + "piii": ":cc-compiler-local", + "ppc": ":cc-compiler-local", + "darwin": ":cc-compiler-darwin", + }, +) + +cc_toolchain( + name = "cc-compiler-local", + all_files = ":crosstool_wrapper_driver_is_not_gcc", + ar_files = ":crosstool_wrapper_driver_is_not_gcc", + as_files = ":crosstool_wrapper_driver_is_not_gcc", + compiler_files = ":crosstool_wrapper_driver_is_not_gcc", + dwp_files = ":empty", + linker_files = ":crosstool_wrapper_driver_is_not_gcc", + objcopy_files = ":empty", + strip_files = ":empty", + # To support linker flags that need to go to the start of command line + # we need the toolchain to support parameter files. Parameter files are + # last on the command line and contain all shared libraries to link, so all + # regular options will be left of them. + supports_param_files = 1, + toolchain_config = ":cc-compiler-local-config", + toolchain_identifier = "local_linux", +) + +cc_toolchain_config( + name = "cc-compiler-local-config", + builtin_include_directories = [ + "/dt7/usr/include/c++/7", + "/dt7/usr/include/c++/7/x86_64-pc-linux-gnu", + "/dt7/usr/include/c++/7/backward", + "/dt7/usr/lib/gcc/x86_64-pc-linux-gnu/7/include", + "/dt7/usr/lib/gcc/x86_64-pc-linux-gnu/7/include-fixed", + "/dt7/usr/include", + "/usr/local/cuda-10.1/targets/x86_64-linux/include", + "/usr/local/cuda-10.1/include", + "/usr/local/cuda-10.1/extras/CUPTI/include", + "/usr/include", + ], + builtin_sysroot = "", + cpu = "local", + cuda_path = "", + extra_no_canonical_prefixes_flags = ["-fno-canonical-system-headers"], + host_compiler_path = "clang/bin/crosstool_wrapper_driver_is_not_gcc", + host_compiler_prefix = "/usr/bin", + host_compiler_warnings = [], + host_unfiltered_compile_flags = [], + linker_bin_path = "/usr/bin", +) + +cc_toolchain( + name = "cc-compiler-darwin", + all_files = ":crosstool_wrapper_driver_is_not_gcc", + ar_files = ":crosstool_wrapper_driver_is_not_gcc", + as_files = ":crosstool_wrapper_driver_is_not_gcc", + compiler_files = ":crosstool_wrapper_driver_is_not_gcc", + dwp_files = ":empty", + linker_files = ":crosstool_wrapper_driver_is_not_gcc", + objcopy_files = ":empty", + strip_files = ":empty", + supports_param_files = 0, + toolchain_config = ":cc-compiler-local-darwin", + toolchain_identifier = "local_darwin", +) + +cc_toolchain_config( + name = "cc-compiler-local-darwin", + builtin_include_directories = [ + "/dt7/usr/include/c++/7", + "/dt7/usr/include/c++/7/x86_64-pc-linux-gnu", + "/dt7/usr/include/c++/7/backward", + "/dt7/usr/lib/gcc/x86_64-pc-linux-gnu/7/include", + "/dt7/usr/lib/gcc/x86_64-pc-linux-gnu/7/include-fixed", + "/dt7/usr/include", + "/usr/local/cuda-10.1/targets/x86_64-linux/include", + "/usr/local/cuda-10.1/include", + "/usr/local/cuda-10.1/extras/CUPTI/include", + "/usr/include", + ], + cpu = "darwin", + extra_no_canonical_prefixes_flags = ["-fno-canonical-system-headers"], + host_compiler_path = "clang/bin/crosstool_wrapper_driver_is_not_gcc", + host_compiler_prefix = "/usr/bin", + host_compiler_warnings = [], + host_unfiltered_compile_flags = [], + linker_bin_path = "/usr/bin", +) + +cc_toolchain( + name = "cc-compiler-windows", + all_files = ":windows_msvc_wrapper_files", + ar_files = ":windows_msvc_wrapper_files", + as_files = ":windows_msvc_wrapper_files", + compiler_files = ":windows_msvc_wrapper_files", + dwp_files = ":empty", + linker_files = ":windows_msvc_wrapper_files", + objcopy_files = ":empty", + strip_files = ":empty", + supports_param_files = 1, + toolchain_config = ":cc-compiler-windows-config", + toolchain_identifier = "local_windows", +) + +cc_toolchain_config( + name = "cc-compiler-windows-config", + builtin_include_directories = [ + "/dt7/usr/include/c++/7", + "/dt7/usr/include/c++/7/x86_64-pc-linux-gnu", + "/dt7/usr/include/c++/7/backward", + "/dt7/usr/lib/gcc/x86_64-pc-linux-gnu/7/include", + "/dt7/usr/lib/gcc/x86_64-pc-linux-gnu/7/include-fixed", + "/dt7/usr/include", + "/usr/local/cuda-10.1/targets/x86_64-linux/include", + "/usr/local/cuda-10.1/include", + "/usr/local/cuda-10.1/extras/CUPTI/include", + "/usr/include", + ], + cpu = "x64_windows", + msvc_cl_path = "msvc_not_used", + msvc_env_include = "msvc_not_used", + msvc_env_lib = "msvc_not_used", + msvc_env_path = "msvc_not_used", + msvc_env_tmp = "msvc_not_used", + msvc_lib_path = "msvc_not_used", + msvc_link_path = "msvc_not_used", + msvc_ml_path = "msvc_not_used", +) + +filegroup( + name = "empty", + srcs = [], +) + +filegroup( + name = "crosstool_wrapper_driver_is_not_gcc", + srcs = ["clang/bin/crosstool_wrapper_driver_is_not_gcc"], +) + +filegroup( + name = "windows_msvc_wrapper_files", + srcs = glob(["windows/msvc_*"]), +) diff --git a/third_party/toolchains/preconfig/ubuntu16.04/gcc7_manylinux2010-nvcc-cuda10.1/cc_toolchain_config.bzl b/third_party/toolchains/preconfig/ubuntu16.04/gcc7_manylinux2010-nvcc-cuda10.1/cc_toolchain_config.bzl new file mode 100755 index 0000000..3d4d41a --- /dev/null +++ b/third_party/toolchains/preconfig/ubuntu16.04/gcc7_manylinux2010-nvcc-cuda10.1/cc_toolchain_config.bzl @@ -0,0 +1,1516 @@ +"""cc_toolchain_config rule for configuring CUDA toolchains on Linux, Mac, and Windows.""" + +load( + "@bazel_tools//tools/cpp:cc_toolchain_config_lib.bzl", + "action_config", + "env_entry", + "env_set", + "feature", + "feature_set", + "flag_group", + "flag_set", + "tool", + "tool_path", + "variable_with_value", +) +load( + "@bazel_tools//tools/build_defs/cc:action_names.bzl", + "ASSEMBLE_ACTION_NAME", + "CC_FLAGS_MAKE_VARIABLE_ACTION_NAME", + "CLIF_MATCH_ACTION_NAME", + "CPP_COMPILE_ACTION_NAME", + "CPP_HEADER_PARSING_ACTION_NAME", + "CPP_LINK_DYNAMIC_LIBRARY_ACTION_NAME", + "CPP_LINK_EXECUTABLE_ACTION_NAME", + "CPP_LINK_NODEPS_DYNAMIC_LIBRARY_ACTION_NAME", + "CPP_LINK_STATIC_LIBRARY_ACTION_NAME", + "CPP_MODULE_CODEGEN_ACTION_NAME", + "CPP_MODULE_COMPILE_ACTION_NAME", + "C_COMPILE_ACTION_NAME", + "LINKSTAMP_COMPILE_ACTION_NAME", + "LTO_BACKEND_ACTION_NAME", + "LTO_INDEXING_ACTION_NAME", + "OBJCPP_COMPILE_ACTION_NAME", + "OBJCPP_EXECUTABLE_ACTION_NAME", + "OBJC_ARCHIVE_ACTION_NAME", + "OBJC_COMPILE_ACTION_NAME", + "OBJC_EXECUTABLE_ACTION_NAME", + "OBJC_FULLY_LINK_ACTION_NAME", + "PREPROCESS_ASSEMBLE_ACTION_NAME", + "STRIP_ACTION_NAME", +) + +ACTION_NAMES = struct( + c_compile = C_COMPILE_ACTION_NAME, + cpp_compile = CPP_COMPILE_ACTION_NAME, + linkstamp_compile = LINKSTAMP_COMPILE_ACTION_NAME, + cc_flags_make_variable = CC_FLAGS_MAKE_VARIABLE_ACTION_NAME, + cpp_module_codegen = CPP_MODULE_CODEGEN_ACTION_NAME, + cpp_header_parsing = CPP_HEADER_PARSING_ACTION_NAME, + cpp_module_compile = CPP_MODULE_COMPILE_ACTION_NAME, + assemble = ASSEMBLE_ACTION_NAME, + preprocess_assemble = PREPROCESS_ASSEMBLE_ACTION_NAME, + lto_indexing = LTO_INDEXING_ACTION_NAME, + lto_backend = LTO_BACKEND_ACTION_NAME, + cpp_link_executable = CPP_LINK_EXECUTABLE_ACTION_NAME, + cpp_link_dynamic_library = CPP_LINK_DYNAMIC_LIBRARY_ACTION_NAME, + cpp_link_nodeps_dynamic_library = CPP_LINK_NODEPS_DYNAMIC_LIBRARY_ACTION_NAME, + cpp_link_static_library = CPP_LINK_STATIC_LIBRARY_ACTION_NAME, + strip = STRIP_ACTION_NAME, + objc_archive = OBJC_ARCHIVE_ACTION_NAME, + objc_compile = OBJC_COMPILE_ACTION_NAME, + objc_executable = OBJC_EXECUTABLE_ACTION_NAME, + objc_fully_link = OBJC_FULLY_LINK_ACTION_NAME, + objcpp_compile = OBJCPP_COMPILE_ACTION_NAME, + objcpp_executable = OBJCPP_EXECUTABLE_ACTION_NAME, + clif_match = CLIF_MATCH_ACTION_NAME, + objcopy_embed_data = "objcopy_embed_data", + ld_embed_data = "ld_embed_data", +) + +def _impl(ctx): + if (ctx.attr.cpu == "darwin"): + toolchain_identifier = "local_darwin" + elif (ctx.attr.cpu == "local"): + toolchain_identifier = "local_linux" + elif (ctx.attr.cpu == "x64_windows"): + toolchain_identifier = "local_windows" + else: + fail("Unreachable") + + host_system_name = "local" + + target_system_name = "local" + + if (ctx.attr.cpu == "darwin"): + target_cpu = "darwin" + elif (ctx.attr.cpu == "local"): + target_cpu = "local" + elif (ctx.attr.cpu == "x64_windows"): + target_cpu = "x64_windows" + else: + fail("Unreachable") + + if (ctx.attr.cpu == "local"): + target_libc = "local" + elif (ctx.attr.cpu == "darwin"): + target_libc = "macosx" + elif (ctx.attr.cpu == "x64_windows"): + target_libc = "msvcrt" + else: + fail("Unreachable") + + if (ctx.attr.cpu == "darwin" or + ctx.attr.cpu == "local"): + compiler = "compiler" + elif (ctx.attr.cpu == "x64_windows"): + compiler = "msvc-cl" + else: + fail("Unreachable") + + abi_version = "local" + + abi_libc_version = "local" + + cc_target_os = None + + builtin_sysroot = ctx.attr.builtin_sysroot + + all_link_actions = [ + ACTION_NAMES.cpp_link_executable, + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ] + + cpp_link_dynamic_library_action = action_config( + action_name = ACTION_NAMES.cpp_link_dynamic_library, + implies = [ + "nologo", + "shared_flag", + "linkstamps", + "output_execpath_flags", + "input_param_flags", + "user_link_flags", + "linker_subsystem_flag", + "linker_param_file", + "msvc_env", + "no_stripping", + "has_configured_linker_path", + "def_file", + ], + tools = [tool(path = ctx.attr.msvc_link_path)], + ) + + cpp_link_nodeps_dynamic_library_action = action_config( + action_name = ACTION_NAMES.cpp_link_nodeps_dynamic_library, + implies = [ + "nologo", + "shared_flag", + "linkstamps", + "output_execpath_flags", + "input_param_flags", + "user_link_flags", + "linker_subsystem_flag", + "linker_param_file", + "msvc_env", + "no_stripping", + "has_configured_linker_path", + "def_file", + ], + tools = [tool(path = ctx.attr.msvc_link_path)], + ) + + cpp_link_static_library_action = action_config( + action_name = ACTION_NAMES.cpp_link_static_library, + implies = [ + "nologo", + "archiver_flags", + "input_param_flags", + "linker_param_file", + "msvc_env", + ], + tools = [tool(path = ctx.attr.msvc_lib_path)], + ) + + assemble_action = action_config( + action_name = ACTION_NAMES.assemble, + implies = [ + "compiler_input_flags", + "compiler_output_flags", + "nologo", + "msvc_env", + "sysroot", + ], + tools = [tool(path = ctx.attr.msvc_ml_path)], + ) + + preprocess_assemble_action = action_config( + action_name = ACTION_NAMES.preprocess_assemble, + implies = [ + "compiler_input_flags", + "compiler_output_flags", + "nologo", + "msvc_env", + "sysroot", + ], + tools = [tool(path = ctx.attr.msvc_ml_path)], + ) + + c_compile_action = action_config( + action_name = ACTION_NAMES.c_compile, + implies = [ + "compiler_input_flags", + "compiler_output_flags", + "nologo", + "msvc_env", + "parse_showincludes", + "user_compile_flags", + "sysroot", + "unfiltered_compile_flags", + ], + tools = [tool(path = ctx.attr.msvc_cl_path)], + ) + + cpp_compile_action = action_config( + action_name = ACTION_NAMES.cpp_compile, + implies = [ + "compiler_input_flags", + "compiler_output_flags", + "nologo", + "msvc_env", + "parse_showincludes", + "user_compile_flags", + "sysroot", + "unfiltered_compile_flags", + ], + tools = [tool(path = ctx.attr.msvc_cl_path)], + ) + + cpp_link_executable_action = action_config( + action_name = ACTION_NAMES.cpp_link_executable, + implies = [ + "nologo", + "linkstamps", + "output_execpath_flags", + "input_param_flags", + "user_link_flags", + "linker_subsystem_flag", + "linker_param_file", + "msvc_env", + "no_stripping", + ], + tools = [tool(path = ctx.attr.msvc_link_path)], + ) + + if (ctx.attr.cpu == "darwin" or + ctx.attr.cpu == "local"): + action_configs = [] + elif (ctx.attr.cpu == "x64_windows"): + action_configs = [ + assemble_action, + preprocess_assemble_action, + c_compile_action, + cpp_compile_action, + cpp_link_executable_action, + cpp_link_dynamic_library_action, + cpp_link_nodeps_dynamic_library_action, + cpp_link_static_library_action, + ] + else: + fail("Unreachable") + + no_windows_export_all_symbols_feature = feature(name = "no_windows_export_all_symbols") + + pic_feature = feature( + name = "pic", + enabled = True, + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [ + flag_group(flags = ["-fPIC"], expand_if_available = "pic"), + flag_group( + flags = ["-fPIE"], + expand_if_not_available = "pic", + ), + ], + ), + ], + ) + + preprocessor_defines_feature = feature( + name = "preprocessor_defines", + enabled = True, + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ], + flag_groups = [ + flag_group( + flags = ["/D%{preprocessor_defines}"], + iterate_over = "preprocessor_defines", + ), + ], + ), + ], + ) + + generate_pdb_file_feature = feature( + name = "generate_pdb_file", + requires = [ + feature_set(features = ["dbg"]), + feature_set(features = ["fastbuild"]), + ], + ) + + linkstamps_feature = feature( + name = "linkstamps", + flag_sets = [ + flag_set( + actions = all_link_actions, + flag_groups = [ + flag_group( + flags = ["%{linkstamp_paths}"], + iterate_over = "linkstamp_paths", + expand_if_available = "linkstamp_paths", + ), + ], + ), + ], + ) + + unfiltered_compile_flags_feature = feature( + name = "unfiltered_compile_flags", + flag_sets = ([ + flag_set( + actions = [ + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ], + flag_groups = [ + flag_group( + flags = ctx.attr.host_unfiltered_compile_flags, + ), + ], + ), + ] if ctx.attr.host_unfiltered_compile_flags else []), + ) + + determinism_feature = feature( + name = "determinism", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [ + flag_group( + flags = [ + "-Wno-builtin-macro-redefined", + "-D__DATE__=\"redacted\"", + "-D__TIMESTAMP__=\"redacted\"", + "-D__TIME__=\"redacted\"", + ], + ), + ], + ), + ], + ) + + nologo_feature = feature( + name = "nologo", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.cpp_link_executable, + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ACTION_NAMES.cpp_link_static_library, + ], + flag_groups = [flag_group(flags = ["/nologo"])], + ), + ], + ) + + supports_pic_feature = feature(name = "supports_pic", enabled = True) + + output_execpath_flags_feature = feature( + name = "output_execpath_flags", + flag_sets = [ + flag_set( + actions = all_link_actions, + flag_groups = [ + flag_group( + flags = ["/OUT:%{output_execpath}"], + expand_if_available = "output_execpath", + ), + ], + ), + ], + ) + + default_link_flags_feature = feature( + name = "default_link_flags", + enabled = True, + flag_sets = [ + flag_set( + actions = all_link_actions, + flag_groups = [flag_group(flags = ["/MACHINE:X64"])], + ), + ], + ) + + if (ctx.attr.cpu == "local"): + hardening_feature = feature( + name = "hardening", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [ + flag_group( + flags = [ + "-U_FORTIFY_SOURCE", + "-D_FORTIFY_SOURCE=1", + "-fstack-protector", + ], + ), + ], + ), + flag_set( + actions = [ + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ], + flag_groups = [flag_group(flags = ["-Wl,-z,relro,-z,now"])], + ), + flag_set( + actions = [ACTION_NAMES.cpp_link_executable], + flag_groups = [flag_group(flags = ["-pie", "-Wl,-z,relro,-z,now"])], + ), + ], + ) + elif (ctx.attr.cpu == "darwin"): + hardening_feature = feature( + name = "hardening", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [ + flag_group( + flags = [ + "-U_FORTIFY_SOURCE", + "-D_FORTIFY_SOURCE=1", + "-fstack-protector", + ], + ), + ], + ), + flag_set( + actions = [ACTION_NAMES.cpp_link_executable], + flag_groups = [flag_group(flags = ["-pie"])], + ), + ], + ) + else: + hardening_feature = None + + supports_dynamic_linker_feature = feature(name = "supports_dynamic_linker", enabled = True) + + targets_windows_feature = feature( + name = "targets_windows", + enabled = True, + implies = ["copy_dynamic_libraries_to_binary"], + ) + + msvc_env_feature = feature( + name = "msvc_env", + env_sets = [ + env_set( + actions = [ + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.cpp_link_executable, + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ACTION_NAMES.cpp_link_static_library, + ], + env_entries = [ + env_entry(key = "PATH", value = ctx.attr.msvc_env_path), + env_entry( + key = "INCLUDE", + value = ctx.attr.msvc_env_include, + ), + env_entry(key = "LIB", value = ctx.attr.msvc_env_lib), + env_entry(key = "TMP", value = ctx.attr.msvc_env_tmp), + env_entry(key = "TEMP", value = ctx.attr.msvc_env_tmp), + ], + ), + ], + ) + + linker_subsystem_flag_feature = feature( + name = "linker_subsystem_flag", + flag_sets = [ + flag_set( + actions = all_link_actions, + flag_groups = [flag_group(flags = ["/SUBSYSTEM:CONSOLE"])], + ), + ], + ) + + dynamic_link_msvcrt_no_debug_feature = feature( + name = "dynamic_link_msvcrt_no_debug", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [flag_group(flags = ["/MD"])], + ), + flag_set( + actions = all_link_actions, + flag_groups = [flag_group(flags = ["/DEFAULTLIB:msvcrt.lib"])], + ), + ], + requires = [ + feature_set(features = ["fastbuild"]), + feature_set(features = ["opt"]), + ], + ) + + warnings_feature = feature( + name = "warnings", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [ + flag_group( + flags = ["-Wall"] + ctx.attr.host_compiler_warnings, + ), + ], + ), + ], + ) + + dynamic_link_msvcrt_debug_feature = feature( + name = "dynamic_link_msvcrt_debug", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [flag_group(flags = ["/MDd"])], + ), + flag_set( + actions = all_link_actions, + flag_groups = [flag_group(flags = ["/DEFAULTLIB:msvcrtd.lib"])], + ), + ], + requires = [feature_set(features = ["dbg"])], + ) + + compiler_output_flags_feature = feature( + name = "compiler_output_flags", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.assemble], + flag_groups = [ + flag_group( + flag_groups = [ + flag_group( + flags = ["/Fo%{output_file}", "/Zi"], + expand_if_not_available = "output_preprocess_file", + ), + ], + expand_if_available = "output_file", + expand_if_not_available = "output_assembly_file", + ), + ], + ), + flag_set( + actions = [ + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ], + flag_groups = [ + flag_group( + flag_groups = [ + flag_group( + flags = ["/Fo%{output_file}"], + expand_if_not_available = "output_preprocess_file", + ), + ], + expand_if_available = "output_file", + expand_if_not_available = "output_assembly_file", + ), + flag_group( + flag_groups = [ + flag_group( + flags = ["/Fa%{output_file}"], + expand_if_available = "output_assembly_file", + ), + ], + expand_if_available = "output_file", + ), + flag_group( + flag_groups = [ + flag_group( + flags = ["/P", "/Fi%{output_file}"], + expand_if_available = "output_preprocess_file", + ), + ], + expand_if_available = "output_file", + ), + ], + ), + ], + ) + + default_compile_flags_feature = feature( + name = "default_compile_flags", + enabled = True, + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.linkstamp_compile, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.lto_backend, + ACTION_NAMES.clif_match, + ], + flag_groups = [ + flag_group( + flags = [ + "/DCOMPILER_MSVC", + "/DNOMINMAX", + "/D_WIN32_WINNT=0x0600", + "/D_CRT_SECURE_NO_DEPRECATE", + "/D_CRT_SECURE_NO_WARNINGS", + "/D_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS", + "/bigobj", + "/Zm500", + "/J", + "/Gy", + "/GF", + "/EHsc", + "/wd4351", + "/wd4291", + "/wd4250", + "/wd4996", + ], + ), + ], + ), + ], + ) + + static_link_msvcrt_debug_feature = feature( + name = "static_link_msvcrt_debug", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [flag_group(flags = ["/MTd"])], + ), + flag_set( + actions = all_link_actions, + flag_groups = [flag_group(flags = ["/DEFAULTLIB:libcmtd.lib"])], + ), + ], + requires = [feature_set(features = ["dbg"])], + ) + + static_link_msvcrt_feature = feature(name = "static_link_msvcrt") + + if (ctx.attr.cpu == "darwin" or + ctx.attr.cpu == "local"): + dbg_feature = feature( + name = "dbg", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [flag_group(flags = ["-g"])], + ), + ], + implies = ["common"], + ) + elif (ctx.attr.cpu == "x64_windows"): + dbg_feature = feature( + name = "dbg", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [flag_group(flags = ["/Od", "/Z7", "/DDEBUG"])], + ), + flag_set( + actions = all_link_actions, + flag_groups = [flag_group(flags = ["/DEBUG:FULL", "/INCREMENTAL:NO"])], + ), + ], + implies = ["generate_pdb_file"], + ) + else: + dbg_feature = None + + undefined_dynamic_feature = feature( + name = "undefined-dynamic", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ACTION_NAMES.cpp_link_executable, + ], + flag_groups = [flag_group(flags = ["-undefined", "dynamic_lookup"])], + ), + ], + ) + + parse_showincludes_feature = feature( + name = "parse_showincludes", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_header_parsing, + ], + flag_groups = [flag_group(flags = ["/showIncludes"])], + ), + ], + ) + + linker_param_file_feature = feature( + name = "linker_param_file", + flag_sets = [ + flag_set( + actions = all_link_actions + + [ACTION_NAMES.cpp_link_static_library], + flag_groups = [ + flag_group( + flags = ["@%{linker_param_file}"], + expand_if_available = "linker_param_file", + ), + ], + ), + ], + ) + + static_link_msvcrt_no_debug_feature = feature( + name = "static_link_msvcrt_no_debug", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [flag_group(flags = ["/MT"])], + ), + flag_set( + actions = all_link_actions, + flag_groups = [flag_group(flags = ["/DEFAULTLIB:libcmt.lib"])], + ), + ], + requires = [ + feature_set(features = ["fastbuild"]), + feature_set(features = ["opt"]), + ], + ) + + supports_interface_shared_libraries_feature = feature( + name = "supports_interface_shared_libraries", + enabled = True, + ) + + disable_assertions_feature = feature( + name = "disable-assertions", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [flag_group(flags = ["-DNDEBUG"])], + ), + ], + ) + + if (ctx.attr.cpu == "x64_windows"): + fastbuild_feature = feature( + name = "fastbuild", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [flag_group(flags = ["/Od", "/Z7", "/DDEBUG"])], + ), + flag_set( + actions = all_link_actions, + flag_groups = [ + flag_group(flags = ["/DEBUG:FASTLINK", "/INCREMENTAL:NO"]), + ], + ), + ], + implies = ["generate_pdb_file"], + ) + elif (ctx.attr.cpu == "darwin" or + ctx.attr.cpu == "local"): + fastbuild_feature = feature(name = "fastbuild", implies = ["common"]) + else: + fastbuild_feature = None + + user_compile_flags_feature = feature( + name = "user_compile_flags", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ], + flag_groups = [ + flag_group( + flags = ["%{user_compile_flags}"], + iterate_over = "user_compile_flags", + expand_if_available = "user_compile_flags", + ), + ], + ), + ], + ) + + compiler_input_flags_feature = feature( + name = "compiler_input_flags", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ], + flag_groups = [ + flag_group( + flags = ["/c", "%{source_file}"], + expand_if_available = "source_file", + ), + ], + ), + ], + ) + + no_legacy_features_feature = feature(name = "no_legacy_features") + + archiver_flags_feature = feature( + name = "archiver_flags", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.cpp_link_static_library], + flag_groups = [ + flag_group( + flags = ["/OUT:%{output_execpath}"], + expand_if_available = "output_execpath", + ), + ], + ), + ], + ) + + redirector_feature = feature( + name = "redirector", + enabled = True, + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ], + flag_groups = [ + flag_group( + flags = [ + "-B", + "external/local_config_cuda/crosstool/windows/msvc_wrapper_for_nvcc.py", + ], + ), + ], + ), + ], + ) + + linker_bin_path_feature = feature( + name = "linker-bin-path", + flag_sets = [ + flag_set( + actions = all_link_actions, + flag_groups = [flag_group(flags = ["-B" + ctx.attr.linker_bin_path])], + ), + ], + ) + + if (ctx.attr.cpu == "local"): + opt_feature = feature( + name = "opt", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [ + flag_group( + flags = ["-g0", "-O2", "-ffunction-sections", "-fdata-sections"], + ), + ], + ), + flag_set( + actions = [ + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ACTION_NAMES.cpp_link_executable, + ], + flag_groups = [flag_group(flags = ["-Wl,--gc-sections"])], + ), + ], + implies = ["common", "disable-assertions"], + ) + elif (ctx.attr.cpu == "darwin"): + opt_feature = feature( + name = "opt", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [ + flag_group( + flags = ["-g0", "-O2", "-ffunction-sections", "-fdata-sections"], + ), + ], + ), + ], + implies = ["common", "disable-assertions"], + ) + elif (ctx.attr.cpu == "x64_windows"): + opt_feature = feature( + name = "opt", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [flag_group(flags = ["/O2", "/DNDEBUG"])], + ), + ], + ) + else: + opt_feature = None + + include_paths_feature = feature( + name = "include_paths", + enabled = True, + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ], + flag_groups = [ + flag_group( + flags = ["/I%{quote_include_paths}"], + iterate_over = "quote_include_paths", + ), + flag_group( + flags = ["/I%{include_paths}"], + iterate_over = "include_paths", + ), + flag_group( + flags = ["/I%{system_include_paths}"], + iterate_over = "system_include_paths", + ), + ], + ), + ], + ) + + shared_flag_feature = feature( + name = "shared_flag", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ], + flag_groups = [flag_group(flags = ["/DLL"])], + ), + ], + ) + + windows_export_all_symbols_feature = feature(name = "windows_export_all_symbols") + + frame_pointer_feature = feature( + name = "frame-pointer", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [flag_group(flags = ["-fno-omit-frame-pointer"])], + ), + ], + ) + + build_id_feature = feature( + name = "build-id", + flag_sets = [ + flag_set( + actions = all_link_actions, + flag_groups = [ + flag_group( + flags = ["-Wl,--build-id=md5", "-Wl,--hash-style=gnu"], + ), + ], + ), + ], + ) + + sysroot_feature = feature( + name = "sysroot", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.cpp_link_executable, + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ], + flag_groups = [ + flag_group( + flags = ["--sysroot=%{sysroot}"], + iterate_over = "sysroot", + expand_if_available = "sysroot", + ), + ], + ), + ], + ) + + cuda_path_feature = feature( + name = "cuda_path", + enabled = True, + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.assemble, + ACTION_NAMES.preprocess_assemble, + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing, + ACTION_NAMES.cpp_module_compile, + ACTION_NAMES.cpp_module_codegen, + ACTION_NAMES.cpp_link_executable, + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ], + flag_groups = [ + flag_group( + flags = ["--cuda-path=" + ctx.attr.cuda_path], + ), + ], + ), + ], + ) + + def_file_feature = feature( + name = "def_file", + flag_sets = [ + flag_set( + actions = all_link_actions, + flag_groups = [ + flag_group( + flags = ["/DEF:%{def_file_path}", "/ignore:4070"], + expand_if_available = "def_file_path", + ), + ], + ), + ], + ) + + if (ctx.attr.cpu == "darwin"): + stdlib_feature = feature( + name = "stdlib", + flag_sets = [ + flag_set( + actions = all_link_actions, + flag_groups = [flag_group(flags = ["-lc++"])], + ), + ], + ) + elif (ctx.attr.cpu == "local"): + stdlib_feature = feature( + name = "stdlib", + flag_sets = [ + flag_set( + actions = all_link_actions, + flag_groups = [flag_group(flags = ["-lstdc++"])], + ), + ], + ) + else: + stdlib_feature = None + + no_stripping_feature = feature(name = "no_stripping") + + alwayslink_feature = feature( + name = "alwayslink", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ACTION_NAMES.cpp_link_executable, + ], + flag_groups = [flag_group(flags = ["-Wl,-no-as-needed"])], + ), + ], + ) + + input_param_flags_feature = feature( + name = "input_param_flags", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ], + flag_groups = [ + flag_group( + flags = ["/IMPLIB:%{interface_library_output_path}"], + expand_if_available = "interface_library_output_path", + ), + ], + ), + flag_set( + actions = all_link_actions + + [ACTION_NAMES.cpp_link_static_library], + flag_groups = [ + flag_group( + iterate_over = "libraries_to_link", + flag_groups = [ + flag_group( + iterate_over = "libraries_to_link.object_files", + flag_groups = [flag_group(flags = ["%{libraries_to_link.object_files}"])], + expand_if_equal = variable_with_value( + name = "libraries_to_link.type", + value = "object_file_group", + ), + ), + flag_group( + flag_groups = [flag_group(flags = ["%{libraries_to_link.name}"])], + expand_if_equal = variable_with_value( + name = "libraries_to_link.type", + value = "object_file", + ), + ), + flag_group( + flag_groups = [flag_group(flags = ["%{libraries_to_link.name}"])], + expand_if_equal = variable_with_value( + name = "libraries_to_link.type", + value = "interface_library", + ), + ), + flag_group( + flag_groups = [ + flag_group( + flags = ["%{libraries_to_link.name}"], + expand_if_false = "libraries_to_link.is_whole_archive", + ), + flag_group( + flags = ["/WHOLEARCHIVE:%{libraries_to_link.name}"], + expand_if_true = "libraries_to_link.is_whole_archive", + ), + ], + expand_if_equal = variable_with_value( + name = "libraries_to_link.type", + value = "static_library", + ), + ), + ], + expand_if_available = "libraries_to_link", + ), + ], + ), + ], + ) + + if (ctx.attr.cpu == "local"): + no_canonical_prefixes_feature = feature( + name = "no-canonical-prefixes", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_link_executable, + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ], + flag_groups = [ + flag_group( + flags = [ + "-no-canonical-prefixes", + ] + ctx.attr.extra_no_canonical_prefixes_flags, + ), + ], + ), + ], + ) + elif (ctx.attr.cpu == "darwin"): + no_canonical_prefixes_feature = feature( + name = "no-canonical-prefixes", + flag_sets = [ + flag_set( + actions = [ + ACTION_NAMES.c_compile, + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_link_executable, + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ], + flag_groups = [flag_group(flags = ["-no-canonical-prefixes"])], + ), + ], + ) + else: + no_canonical_prefixes_feature = None + + has_configured_linker_path_feature = feature(name = "has_configured_linker_path") + + copy_dynamic_libraries_to_binary_feature = feature(name = "copy_dynamic_libraries_to_binary") + + user_link_flags_feature = feature( + name = "user_link_flags", + flag_sets = [ + flag_set( + actions = all_link_actions, + flag_groups = [ + flag_group( + flags = ["%{user_link_flags}"], + iterate_over = "user_link_flags", + expand_if_available = "user_link_flags", + ), + ], + ), + ], + ) + + cpp11_feature = feature( + name = "c++11", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.cpp_compile], + flag_groups = [flag_group(flags = ["-std=c++11"])], + ), + ], + ) + + if (ctx.attr.cpu == "local"): + common_feature = feature( + name = "common", + implies = [ + "stdlib", + "c++11", + "determinism", + "alwayslink", + "hardening", + "warnings", + "frame-pointer", + "build-id", + "no-canonical-prefixes", + "linker-bin-path", + ], + ) + elif (ctx.attr.cpu == "darwin"): + common_feature = feature( + name = "common", + implies = [ + "stdlib", + "c++11", + "determinism", + "hardening", + "warnings", + "frame-pointer", + "no-canonical-prefixes", + "linker-bin-path", + "undefined-dynamic", + ], + ) + else: + common_feature = None + + if (ctx.attr.cpu == "local"): + features = [ + cpp11_feature, + stdlib_feature, + determinism_feature, + alwayslink_feature, + pic_feature, + hardening_feature, + warnings_feature, + frame_pointer_feature, + build_id_feature, + no_canonical_prefixes_feature, + disable_assertions_feature, + linker_bin_path_feature, + common_feature, + opt_feature, + fastbuild_feature, + dbg_feature, + supports_dynamic_linker_feature, + supports_pic_feature, + ] + if ctx.attr.cuda_path: + features += [cuda_path_feature] + elif (ctx.attr.cpu == "darwin"): + features = [ + cpp11_feature, + stdlib_feature, + determinism_feature, + pic_feature, + hardening_feature, + warnings_feature, + frame_pointer_feature, + no_canonical_prefixes_feature, + disable_assertions_feature, + linker_bin_path_feature, + undefined_dynamic_feature, + common_feature, + opt_feature, + fastbuild_feature, + dbg_feature, + supports_dynamic_linker_feature, + supports_pic_feature, + ] + elif (ctx.attr.cpu == "x64_windows"): + features = [ + no_legacy_features_feature, + redirector_feature, + nologo_feature, + has_configured_linker_path_feature, + no_stripping_feature, + targets_windows_feature, + copy_dynamic_libraries_to_binary_feature, + default_compile_flags_feature, + msvc_env_feature, + include_paths_feature, + preprocessor_defines_feature, + parse_showincludes_feature, + generate_pdb_file_feature, + shared_flag_feature, + linkstamps_feature, + output_execpath_flags_feature, + archiver_flags_feature, + input_param_flags_feature, + linker_subsystem_flag_feature, + user_link_flags_feature, + default_link_flags_feature, + linker_param_file_feature, + static_link_msvcrt_feature, + static_link_msvcrt_no_debug_feature, + dynamic_link_msvcrt_no_debug_feature, + static_link_msvcrt_debug_feature, + dynamic_link_msvcrt_debug_feature, + dbg_feature, + fastbuild_feature, + opt_feature, + user_compile_flags_feature, + sysroot_feature, + unfiltered_compile_flags_feature, + compiler_output_flags_feature, + compiler_input_flags_feature, + def_file_feature, + windows_export_all_symbols_feature, + no_windows_export_all_symbols_feature, + supports_dynamic_linker_feature, + supports_interface_shared_libraries_feature, + ] + else: + fail("Unreachable") + + cxx_builtin_include_directories = ctx.attr.builtin_include_directories + + if (ctx.attr.cpu == "x64_windows"): + tool_paths = [ + tool_path(name = "ar", path = ctx.attr.msvc_lib_path), + tool_path(name = "ml", path = ctx.attr.msvc_ml_path), + tool_path(name = "cpp", path = ctx.attr.msvc_cl_path), + tool_path(name = "gcc", path = ctx.attr.msvc_cl_path), + tool_path(name = "gcov", path = "wrapper/bin/msvc_nop.bat"), + tool_path(name = "ld", path = ctx.attr.msvc_link_path), + tool_path(name = "nm", path = "wrapper/bin/msvc_nop.bat"), + tool_path( + name = "objcopy", + path = "wrapper/bin/msvc_nop.bat", + ), + tool_path( + name = "objdump", + path = "wrapper/bin/msvc_nop.bat", + ), + tool_path( + name = "strip", + path = "wrapper/bin/msvc_nop.bat", + ), + ] + elif (ctx.attr.cpu == "local"): + tool_paths = [ + tool_path(name = "gcc", path = ctx.attr.host_compiler_path), + tool_path(name = "ar", path = ctx.attr.host_compiler_prefix + "/ar"), + tool_path(name = "compat-ld", path = ctx.attr.host_compiler_prefix + "/ld"), + tool_path(name = "cpp", path = ctx.attr.host_compiler_prefix + "/cpp"), + tool_path(name = "dwp", path = ctx.attr.host_compiler_prefix + "/dwp"), + tool_path(name = "gcov", path = ctx.attr.host_compiler_prefix + "/gcov"), + tool_path(name = "ld", path = ctx.attr.host_compiler_prefix + "/ld"), + tool_path(name = "nm", path = ctx.attr.host_compiler_prefix + "/nm"), + tool_path(name = "objcopy", path = ctx.attr.host_compiler_prefix + "/objcopy"), + tool_path(name = "objdump", path = ctx.attr.host_compiler_prefix + "/objdump"), + tool_path(name = "strip", path = ctx.attr.host_compiler_prefix + "/strip"), + ] + elif (ctx.attr.cpu == "darwin"): + tool_paths = [ + tool_path(name = "gcc", path = ctx.attr.host_compiler_path), + tool_path(name = "ar", path = ctx.attr.host_compiler_prefix + "/libtool"), + tool_path(name = "compat-ld", path = ctx.attr.host_compiler_prefix + "/ld"), + tool_path(name = "cpp", path = ctx.attr.host_compiler_prefix + "/cpp"), + tool_path(name = "dwp", path = ctx.attr.host_compiler_prefix + "/dwp"), + tool_path(name = "gcov", path = ctx.attr.host_compiler_prefix + "/gcov"), + tool_path(name = "ld", path = ctx.attr.host_compiler_prefix + "/ld"), + tool_path(name = "nm", path = ctx.attr.host_compiler_prefix + "/nm"), + tool_path(name = "objcopy", path = ctx.attr.host_compiler_prefix + "/objcopy"), + tool_path(name = "objdump", path = ctx.attr.host_compiler_prefix + "/objdump"), + tool_path(name = "strip", path = ctx.attr.host_compiler_prefix + "/strip"), + ] + else: + fail("Unreachable") + + out = ctx.actions.declare_file(ctx.label.name) + ctx.actions.write(out, "Fake executable") + return [ + cc_common.create_cc_toolchain_config_info( + ctx = ctx, + features = features, + action_configs = action_configs, + artifact_name_patterns = [], + cxx_builtin_include_directories = cxx_builtin_include_directories, + toolchain_identifier = toolchain_identifier, + host_system_name = host_system_name, + target_system_name = target_system_name, + target_cpu = target_cpu, + target_libc = target_libc, + compiler = compiler, + abi_version = abi_version, + abi_libc_version = abi_libc_version, + tool_paths = tool_paths, + make_variables = [], + builtin_sysroot = builtin_sysroot, + cc_target_os = cc_target_os, + ), + DefaultInfo( + executable = out, + ), + ] + +cc_toolchain_config = rule( + implementation = _impl, + attrs = { + "cpu": attr.string(mandatory = True, values = ["darwin", "local", "x64_windows"]), + "builtin_include_directories": attr.string_list(), + "extra_no_canonical_prefixes_flags": attr.string_list(), + "host_compiler_path": attr.string(), + "host_compiler_prefix": attr.string(), + "host_compiler_warnings": attr.string_list(), + "host_unfiltered_compile_flags": attr.string_list(), + "linker_bin_path": attr.string(), + "builtin_sysroot": attr.string(), + "cuda_path": attr.string(), + "msvc_cl_path": attr.string(default = "msvc_not_used"), + "msvc_env_include": attr.string(default = "msvc_not_used"), + "msvc_env_lib": attr.string(default = "msvc_not_used"), + "msvc_env_path": attr.string(default = "msvc_not_used"), + "msvc_env_tmp": attr.string(default = "msvc_not_used"), + "msvc_lib_path": attr.string(default = "msvc_not_used"), + "msvc_link_path": attr.string(default = "msvc_not_used"), + "msvc_ml_path": attr.string(default = "msvc_not_used"), + }, + provides = [CcToolchainConfigInfo], + executable = True, +) diff --git a/third_party/toolchains/preconfig/ubuntu16.04/gcc7_manylinux2010-nvcc-cuda10.1/clang/bin/crosstool_wrapper_driver_is_not_gcc b/third_party/toolchains/preconfig/ubuntu16.04/gcc7_manylinux2010-nvcc-cuda10.1/clang/bin/crosstool_wrapper_driver_is_not_gcc new file mode 100755 index 0000000..44e745f --- /dev/null +++ b/third_party/toolchains/preconfig/ubuntu16.04/gcc7_manylinux2010-nvcc-cuda10.1/clang/bin/crosstool_wrapper_driver_is_not_gcc @@ -0,0 +1,272 @@ +#!/usr/bin/env python +# Copyright 2015 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== + +"""Crosstool wrapper for compiling CUDA programs. + +SYNOPSIS: + crosstool_wrapper_is_not_gcc [options passed in by cc_library() + or cc_binary() rule] + +DESCRIPTION: + This script is expected to be called by the cc_library() or cc_binary() bazel + rules. When the option "-x cuda" is present in the list of arguments passed + to this script, it invokes the nvcc CUDA compiler. Most arguments are passed + as is as a string to --compiler-options of nvcc. When "-x cuda" is not + present, this wrapper invokes hybrid_driver_is_not_gcc with the input + arguments as is. + +NOTES: + Changes to the contents of this file must be propagated from + //third_party/gpus/crosstool/crosstool_wrapper_is_not_gcc to + //third_party/gpus/crosstool/v*/*/clang/bin/crosstool_wrapper_is_not_gcc +""" + +from __future__ import print_function + +__author__ = 'keveman@google.com (Manjunath Kudlur)' + +from argparse import ArgumentParser +import os +import subprocess +import re +import sys +import pipes + +# Template values set by cuda_autoconf. +CPU_COMPILER = ('/dt7/usr/bin/gcc') +GCC_HOST_COMPILER_PATH = ('/dt7/usr/bin/gcc') + +NVCC_PATH = '/usr/local/cuda-10.1/bin/nvcc' +PREFIX_DIR = os.path.dirname(GCC_HOST_COMPILER_PATH) +NVCC_VERSION = '10.1' + +# Environment variable for supported TF CUDA Compute Capabilities +# eg. export TF_CUDA_COMPUTE_CAPABILITIES=3.5,3.7,5.2,6.0,6.1,7.0 +CUDA_COMPUTE_ENV_VAR = 'TF_CUDA_COMPUTE_CAPABILITIES' +DEFAULT_CUDA_COMPUTE_CAPABILITIES = '3.5,6.0' + +def Log(s): + print('gpus/crosstool: {0}'.format(s)) + + +def GetOptionValue(argv, option): + """Extract the list of values for option from the argv list. + + Args: + argv: A list of strings, possibly the argv passed to main(). + option: The option whose value to extract, without the leading '-'. + + Returns: + A list of values, either directly following the option, + (eg., -opt val1 val2) or values collected from multiple occurrences of + the option (eg., -opt val1 -opt val2). + """ + + parser = ArgumentParser() + parser.add_argument('-' + option, nargs='*', action='append') + args, _ = parser.parse_known_args(argv) + if not args or not vars(args)[option]: + return [] + else: + return sum(vars(args)[option], []) + + +def GetHostCompilerOptions(argv): + """Collect the -isystem, -iquote, and --sysroot option values from argv. + + Args: + argv: A list of strings, possibly the argv passed to main(). + + Returns: + The string that can be used as the --compiler-options to nvcc. + """ + + parser = ArgumentParser() + parser.add_argument('-isystem', nargs='*', action='append') + parser.add_argument('-iquote', nargs='*', action='append') + parser.add_argument('--sysroot', nargs=1) + parser.add_argument('-g', nargs='*', action='append') + parser.add_argument('-fno-canonical-system-headers', action='store_true') + parser.add_argument('-no-canonical-prefixes', action='store_true') + + args, _ = parser.parse_known_args(argv) + + opts = '' + + if args.isystem: + opts += ' -isystem ' + ' -isystem '.join(sum(args.isystem, [])) + if args.iquote: + opts += ' -iquote ' + ' -iquote '.join(sum(args.iquote, [])) + if args.g: + opts += ' -g' + ' -g'.join(sum(args.g, [])) + if args.fno_canonical_system_headers: + opts += ' -fno-canonical-system-headers' + if args.no_canonical_prefixes: + opts += ' -no-canonical-prefixes' + if args.sysroot: + opts += ' --sysroot ' + args.sysroot[0] + + return opts + +def _update_options(nvcc_options): + if NVCC_VERSION in ("7.0",): + return nvcc_options + + update_options = { "relaxed-constexpr" : "expt-relaxed-constexpr" } + return [ update_options[opt] if opt in update_options else opt + for opt in nvcc_options ] + +def GetNvccOptions(argv): + """Collect the -nvcc_options values from argv. + + Args: + argv: A list of strings, possibly the argv passed to main(). + + Returns: + The string that can be passed directly to nvcc. + """ + + parser = ArgumentParser() + parser.add_argument('-nvcc_options', nargs='*', action='append') + + args, _ = parser.parse_known_args(argv) + + if args.nvcc_options: + options = _update_options(sum(args.nvcc_options, [])) + return ' '.join(['--'+a for a in options]) + return '' + + +def InvokeNvcc(argv, log=False): + """Call nvcc with arguments assembled from argv. + + Args: + argv: A list of strings, possibly the argv passed to main(). + log: True if logging is requested. + + Returns: + The return value of calling os.system('nvcc ' + args) + """ + + host_compiler_options = GetHostCompilerOptions(argv) + nvcc_compiler_options = GetNvccOptions(argv) + opt_option = GetOptionValue(argv, 'O') + m_options = GetOptionValue(argv, 'm') + m_options = ''.join([' -m' + m for m in m_options if m in ['32', '64']]) + include_options = GetOptionValue(argv, 'I') + out_file = GetOptionValue(argv, 'o') + depfiles = GetOptionValue(argv, 'MF') + defines = GetOptionValue(argv, 'D') + defines = ''.join([' -D' + define for define in defines]) + undefines = GetOptionValue(argv, 'U') + undefines = ''.join([' -U' + define for define in undefines]) + std_options = GetOptionValue(argv, 'std') + # currently only c++11 is supported by Cuda 7.0 std argument + nvcc_allowed_std_options = ["c++11"] + std_options = ''.join([' -std=' + define + for define in std_options if define in nvcc_allowed_std_options]) + + # The list of source files get passed after the -c option. I don't know of + # any other reliable way to just get the list of source files to be compiled. + src_files = GetOptionValue(argv, 'c') + + # Pass -w through from host to nvcc, but don't do anything fancier with + # warnings-related flags, since they're not necessarily the same across + # compilers. + warning_options = ' -w' if '-w' in argv else '' + + if len(src_files) == 0: + return 1 + if len(out_file) != 1: + return 1 + + opt = (' -O2' if (len(opt_option) > 0 and int(opt_option[0]) > 0) + else ' -g -G') + + includes = (' -I ' + ' -I '.join(include_options) + if len(include_options) > 0 + else '') + + # Unfortunately, there are other options that have -c prefix too. + # So allowing only those look like C/C++ files. + src_files = [f for f in src_files if + re.search('\.cpp$|\.cc$|\.c$|\.cxx$|\.C$', f)] + srcs = ' '.join(src_files) + out = ' -o ' + out_file[0] + + supported_cuda_compute_capabilities = os.environ.get(CUDA_COMPUTE_ENV_VAR, DEFAULT_CUDA_COMPUTE_CAPABILITIES).split(',') + nvccopts = '-D_FORCE_INLINES ' + for capability in supported_cuda_compute_capabilities: + capability = capability.replace('.', '') + nvccopts += r'-gencode=arch=compute_%s,\"code=sm_%s,compute_%s\" ' % ( + capability, capability, capability) + nvccopts += ' ' + nvcc_compiler_options + nvccopts += undefines + nvccopts += defines + nvccopts += std_options + nvccopts += m_options + nvccopts += warning_options + + if depfiles: + # Generate the dependency file + depfile = depfiles[0] + cmd = (NVCC_PATH + ' ' + nvccopts + + ' --compiler-options "' + host_compiler_options + '"' + + ' --compiler-bindir=' + GCC_HOST_COMPILER_PATH + + ' -I .' + + ' -x cu ' + opt + includes + ' ' + srcs + ' -M -o ' + depfile) + if log: Log(cmd) + exit_status = os.system(cmd) + if exit_status != 0: + return exit_status + + cmd = (NVCC_PATH + ' ' + nvccopts + + ' --compiler-options "' + host_compiler_options + ' -fPIC"' + + ' --compiler-bindir=' + GCC_HOST_COMPILER_PATH + + ' -I .' + + ' -x cu ' + opt + includes + ' -c ' + srcs + out) + + # TODO(zhengxq): for some reason, 'gcc' needs this help to find 'as'. + # Need to investigate and fix. + cmd = 'PATH=' + PREFIX_DIR + ':$PATH ' + cmd + if log: Log(cmd) + return os.system(cmd) + + +def main(): + parser = ArgumentParser() + parser.add_argument('-x', nargs=1) + parser.add_argument('--cuda_log', action='store_true') + args, leftover = parser.parse_known_args(sys.argv[1:]) + + if args.x and args.x[0] == 'cuda': + if args.cuda_log: Log('-x cuda') + leftover = [pipes.quote(s) for s in leftover] + if args.cuda_log: Log('using nvcc') + return InvokeNvcc(leftover, log=args.cuda_log) + + # Strip our flags before passing through to the CPU compiler for files which + # are not -x cuda. We can't just pass 'leftover' because it also strips -x. + # We not only want to pass -x to the CPU compiler, but also keep it in its + # relative location in the argv list (the compiler is actually sensitive to + # this). + cpu_compiler_flags = [flag for flag in sys.argv[1:] + if not flag.startswith(('--cuda_log'))] + + return subprocess.call([CPU_COMPILER] + cpu_compiler_flags) + +if __name__ == '__main__': + sys.exit(main())