Merge branch 'main' into rules-based-toolchain-example

This commit is contained in:
Armando Montanez 2024-10-03 10:09:43 -07:00
commit 09cd8eb3d6
53 changed files with 3134 additions and 737 deletions

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
/bazel-*
/examples/rule_based_toolchain/bazel-*
MODULE.bazel.lock

View File

@ -8,8 +8,8 @@ bazel_dep(name = "bazel_skylib", version = "1.7.1")
bazel_dep(name = "platforms", version = "0.0.10")
bazel_dep(name = "stardoc", version = "0.7.0")
cc_configure = use_extension("@bazel_tools//tools/cpp:cc_configure.bzl", "cc_configure_extension")
use_repo(cc_configure, "local_config_cc_toolchains")
cc_configure = use_extension("//cc:extensions.bzl", "cc_configure_extension")
use_repo(cc_configure, "local_config_cc", "local_config_cc_toolchains")
register_toolchains("@local_config_cc_toolchains//:all")

View File

@ -102,4 +102,9 @@ bzl_library(
cc_toolchain_alias(name = "current_cc_toolchain")
cc_toolchain_alias(
name = "optional_current_cc_toolchain",
mandatory = False,
)
cc_libc_top_alias(name = "current_libc_top")

View File

@ -33,6 +33,13 @@ CPP_MODULE_CODEGEN_ACTION_NAME = "c++-module-codegen"
# Name of the C++ header parsing action.
CPP_HEADER_PARSING_ACTION_NAME = "c++-header-parsing"
# Name of the C++ deps scanning action.
CPP_MODULE_DEPS_SCANNING_ACTION_NAME = "c++-module-deps-scanning"
# Name of the C++ module compile action.
CPP20_MODULE_COMPILE_ACTION_NAME = "c++20-module-compile"
CPP20_MODULE_CODEGEN_ACTION_NAME = "c++20-module-codegen"
# Name of the C++ module compile action.
CPP_MODULE_COMPILE_ACTION_NAME = "c++-module-compile"
@ -42,6 +49,8 @@ ASSEMBLE_ACTION_NAME = "assemble"
# Name of the assembly preprocessing action.
PREPROCESS_ASSEMBLE_ACTION_NAME = "preprocess-assemble"
LLVM_COV = "llvm-cov"
# Name of the action producing ThinLto index.
LTO_INDEXING_ACTION_NAME = "lto-indexing"
@ -85,12 +94,15 @@ OBJC_EXECUTABLE_ACTION_NAME = "objc-executable"
# A string constant for the objc fully-link link action.
OBJC_FULLY_LINK_ACTION_NAME = "objc-fully-link"
# A string constant for the clif action.
# A string constant for the clif actions.
CLIF_MATCH_ACTION_NAME = "clif-match"
# A string constant for the obj copy actions.
OBJ_COPY_ACTION_NAME = "objcopy_embed_data"
# A string constant for the validation action for cc_static_library.
VALIDATE_STATIC_LIBRARY = "validate-static-library"
ACTION_NAMES = struct(
c_compile = C_COMPILE_ACTION_NAME,
cpp_compile = CPP_COMPILE_ACTION_NAME,
@ -98,9 +110,13 @@ ACTION_NAMES = struct(
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_deps_scanning = CPP_MODULE_DEPS_SCANNING_ACTION_NAME,
cpp20_module_compile = CPP20_MODULE_COMPILE_ACTION_NAME,
cpp20_module_codegen = CPP20_MODULE_CODEGEN_ACTION_NAME,
cpp_module_compile = CPP_MODULE_COMPILE_ACTION_NAME,
assemble = ASSEMBLE_ACTION_NAME,
preprocess_assemble = PREPROCESS_ASSEMBLE_ACTION_NAME,
llvm_cov = LLVM_COV,
lto_indexing = LTO_INDEXING_ACTION_NAME,
lto_backend = LTO_BACKEND_ACTION_NAME,
lto_index_for_executable = LTO_INDEX_FOR_EXECUTABLE_ACTION_NAME,
@ -117,6 +133,7 @@ ACTION_NAMES = struct(
objcpp_compile = OBJCPP_COMPILE_ACTION_NAME,
clif_match = CLIF_MATCH_ACTION_NAME,
objcopy_embed_data = OBJ_COPY_ACTION_NAME,
validate_static_library = VALIDATE_STATIC_LIBRARY,
)
# Names of actions that parse or compile C++ code.

View File

@ -29,9 +29,9 @@ Example:
name = "foo",
srcs = ["foo.cc"],
copts = select({
"@rules_cc//cc/compiler:gcc": [...],
"@rules_cc//cc/compiler:clang": [...],
"@rules_cc//cc/compiler:msvc-cl": [...],
"//cc/compiler:gcc": [...],
"//cc/compiler:clang": [...],
"//cc/compiler:msvc-cl": [...],
# Fallback case for an undetected compiler.
"//conditions:default": [...],
}),
@ -47,25 +47,25 @@ licenses(["notice"])
config_setting(
name = "clang",
flag_values = {"@bazel_tools//tools/cpp:compiler": "clang"},
flag_values = {"@rules_cc//cc/private/toolchain:compiler": "clang"},
)
config_setting(
name = "clang-cl",
flag_values = {"@bazel_tools//tools/cpp:compiler": "clang-cl"},
flag_values = {"@rules_cc//cc/private/toolchain:compiler": "clang-cl"},
)
config_setting(
name = "gcc",
flag_values = {"@bazel_tools//tools/cpp:compiler": "gcc"},
flag_values = {"@rules_cc//cc/private/toolchain:compiler": "gcc"},
)
config_setting(
name = "mingw-gcc",
flag_values = {"@bazel_tools//tools/cpp:compiler": "mingw-gcc"},
flag_values = {"@rules_cc//cc/private/toolchain:compiler": "mingw-gcc"},
)
config_setting(
name = "msvc-cl",
flag_values = {"@bazel_tools//tools/cpp:compiler": "msvc-cl"},
flag_values = {"@rules_cc//cc/private/toolchain:compiler": "msvc-cl"},
)

View File

@ -13,12 +13,11 @@
# limitations under the License.
"""Module extension for cc auto configuration."""
load("@bazel_tools//tools/osx:xcode_configure.bzl", "xcode_configure")
load("//cc/private/toolchain:cc_configure.bzl", "cc_autoconf", "cc_autoconf_toolchains")
def _cc_configure_impl(_):
def _cc_configure_extension_impl(ctx):
cc_autoconf_toolchains(name = "local_config_cc_toolchains")
cc_autoconf(name = "local_config_cc")
xcode_configure("@bazel_tools//tools/osx:xcode_locator.m")
return ctx.extension_metadata(reproducible = True)
cc_configure = module_extension(implementation = _cc_configure_impl)
cc_configure_extension = module_extension(implementation = _cc_configure_extension_impl)

View File

@ -13,10 +13,13 @@
# limitations under the License.
load("@rules_cc//cc:defs.bzl", "cc_library", "cc_toolchain", "cc_toolchain_suite")
load(":cc_toolchain_config.bzl", "cc_toolchain_config")
package(default_visibility = ["//visibility:public"])
load(":cc_toolchain_config.bzl", "cc_toolchain_config")
cc_library(
name = "link_extra_lib",
)
cc_library(
name = "malloc",
@ -30,8 +33,8 @@ filegroup(
cc_toolchain_suite(
name = "toolchain",
toolchains = {
"local": ":local",
"local|local": ":local",
"%{cpu}|local": ":local",
"%{cpu}": ":local",
},
)

View File

@ -12,12 +12,30 @@
# See the License for the specific language governing permissions and
# limitations under the License.
# This becomes the BUILD file for @local_config_cc// under FreeBSD.
# This becomes the BUILD file for @local_config_cc// under FreeBSD and OpenBSD.
load(":cc_toolchain_config.bzl", "cc_toolchain_config")
load("@rules_cc//cc:defs.bzl", "cc_library", "cc_toolchain", "cc_toolchain_suite")
package(default_visibility = ["//visibility:public"])
load("@rules_cc//cc:defs.bzl", "cc_library", "cc_toolchain", "cc_toolchain_suite")
load(":cc_toolchain_config.bzl", "cc_toolchain_config")
cc_library(name = "empty_lib")
# Label flag for extra libraries to be linked into every binary.
# TODO(bazel-team): Support passing flag multiple times to build a list.
label_flag(
name = "link_extra_libs",
build_setting_default = ":empty_lib",
)
# The final extra library to be linked into every binary target. This collects
# the above flag, but may also include more libraries depending on config.
cc_library(
name = "link_extra_lib",
deps = [
":link_extra_libs",
],
)
cc_library(
name = "malloc",
@ -32,10 +50,12 @@ filegroup(
cc_toolchain_suite(
name = "toolchain",
toolchains = {
"armeabi-v7a": ":cc-compiler-armeabi-v7a",
"armeabi-v7a|compiler": ":cc-compiler-armeabi-v7a",
"freebsd": ":cc-compiler-freebsd",
"freebsd|compiler": ":cc-compiler-freebsd",
"openbsd|compiler": ":cc-compiler-openbsd",
"armeabi-v7a": ":cc-compiler-armeabi-v7a",
"freebsd": ":cc-compiler-freebsd",
"openbsd": ":cc-compiler-openbsd",
},
)
@ -70,7 +90,41 @@ toolchain(
"@platforms//os:freebsd",
],
toolchain = ":cc-compiler-freebsd",
toolchain_type = "@rules_cc//cc:toolchain_type",
toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
)
cc_toolchain(
name = "cc-compiler-openbsd",
all_files = ":empty",
ar_files = ":empty",
as_files = ":empty",
compiler_files = ":empty",
dwp_files = ":empty",
linker_files = ":empty",
objcopy_files = ":empty",
strip_files = ":empty",
supports_param_files = 0,
toolchain_config = ":local_openbsd",
toolchain_identifier = "local_openbsd",
)
cc_toolchain_config(
name = "local_openbsd",
cpu = "openbsd",
)
toolchain(
name = "cc-toolchain-openbsd",
exec_compatible_with = [
"@platforms//cpu:x86_64",
"@platforms//os:openbsd",
],
target_compatible_with = [
"@platforms//cpu:x86_64",
"@platforms//os:openbsd",
],
toolchain = ":cc-compiler-openbsd",
toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
)
cc_toolchain(
@ -99,11 +153,11 @@ toolchain(
"@platforms//cpu:arm",
],
target_compatible_with = [
"@platforms//cpu:arm",
"@platforms//cpu:armv7",
"@platforms//os:android",
],
toolchain = ":cc-compiler-armeabi-v7a",
toolchain_type = "@rules_cc//cc:toolchain_type",
toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
)
filegroup(

View File

@ -5,16 +5,16 @@ toolchain(
exec_compatible_with = HOST_CONSTRAINTS,
target_compatible_with = HOST_CONSTRAINTS,
toolchain = "@local_config_cc//:cc-compiler-%{name}",
toolchain_type = "@rules_cc//cc:toolchain_type",
toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
)
toolchain(
name = "cc-toolchain-armeabi-v7a",
exec_compatible_with = HOST_CONSTRAINTS,
target_compatible_with = [
"@platforms//cpu:arm",
"@platforms//cpu:armv7",
"@platforms//os:android",
],
toolchain = "@local_config_cc//:cc-compiler-armeabi-v7a",
toolchain_type = "@rules_cc//cc:toolchain_type",
toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
)

View File

@ -12,16 +12,34 @@
# See the License for the specific language governing permissions and
# limitations under the License.
# This becomes the BUILD file for @local_config_cc// under non-FreeBSD unixes.
package(default_visibility = ["//visibility:public"])
# This becomes the BUILD file for @local_config_cc// under non-BSD unixes.
load(":cc_toolchain_config.bzl", "cc_toolchain_config")
load(":armeabi_cc_toolchain_config.bzl", "armeabi_cc_toolchain_config")
load("@rules_cc//cc:defs.bzl", "cc_toolchain", "cc_toolchain_suite")
package(default_visibility = ["//visibility:public"])
licenses(["notice"]) # Apache 2.0
cc_library(name = "empty_lib")
# Label flag for extra libraries to be linked into every binary.
# TODO(bazel-team): Support passing flag multiple times to build a list.
label_flag(
name = "link_extra_libs",
build_setting_default = ":empty_lib",
)
# The final extra library to be linked into every binary target. This collects
# the above flag, but may also include more libraries depending on config.
cc_library(
name = "link_extra_lib",
deps = [
":link_extra_libs",
],
)
cc_library(
name = "malloc",
)
@ -36,6 +54,15 @@ filegroup(
srcs = ["cc_wrapper.sh"],
)
filegroup(
name = "validate_static_library",
srcs = ["validate_static_library.sh"],
)
filegroup(
name = "deps_scanner_wrapper",
srcs = ["deps_scanner_wrapper.sh"],
)
filegroup(
name = "compiler_deps",
srcs = glob(["extra_tools/**"], allow_empty = True) + [%{cc_compiler_deps}],
@ -66,7 +93,9 @@ cc_toolchain(
linker_files = ":compiler_deps",
objcopy_files = ":empty",
strip_files = ":empty",
supports_param_files = %{supports_param_files},
supports_header_parsing = 1,
supports_param_files = 1,
module_map = %{modulemap},
)
cc_toolchain_config(
@ -84,6 +113,7 @@ cc_toolchain_config(
compile_flags = [%{compile_flags}],
opt_compile_flags = [%{opt_compile_flags}],
dbg_compile_flags = [%{dbg_compile_flags}],
conly_flags = [%{conly_flags}],
cxx_flags = [%{cxx_flags}],
link_flags = [%{link_flags}],
link_libs = [%{link_libs}],
@ -92,6 +122,7 @@ cc_toolchain_config(
coverage_compile_flags = [%{coverage_compile_flags}],
coverage_link_flags = [%{coverage_link_flags}],
supports_start_end_lib = %{supports_start_end_lib},
extra_flags_per_feature = %{extra_flags_per_feature},
)
# Android tooling requires a default toolchain for the armeabi-v7a cpu.

View File

@ -14,11 +14,30 @@
# This becomes the BUILD file for @local_config_cc// under Windows.
package(default_visibility = ["//visibility:public"])
load("@rules_cc//cc:defs.bzl", "cc_toolchain", "cc_toolchain_suite", "cc_library")
load(":windows_cc_toolchain_config.bzl", "cc_toolchain_config")
load(":armeabi_cc_toolchain_config.bzl", "armeabi_cc_toolchain_config")
package(default_visibility = ["//visibility:public"])
cc_library(name = "empty_lib")
# Label flag for extra libraries to be linked into every binary.
# TODO(bazel-team): Support passing flag multiple times to build a list.
label_flag(
name = "link_extra_libs",
build_setting_default = ":empty_lib",
)
# The final extra library to be linked into every binary target. This collects
# the above flag, but may also include more libraries depending on config.
cc_library(
name = "link_extra_lib",
deps = [
":link_extra_libs",
],
)
cc_library(
name = "malloc",
)
@ -40,7 +59,13 @@ filegroup(
filegroup(
name = "msvc_compiler_files",
srcs = [":builtin_include_directory_paths_msvc"]
srcs = [
":builtin_include_directory_paths_msvc",
"%{msvc_deps_scanner_wrapper_path_x86}",
"%{msvc_deps_scanner_wrapper_path_x64}",
"%{msvc_deps_scanner_wrapper_path_arm}",
"%{msvc_deps_scanner_wrapper_path_arm64}",
]
)
# Hardcoded toolchain, legacy behaviour.
@ -49,11 +74,23 @@ cc_toolchain_suite(
toolchains = {
"armeabi-v7a|compiler": ":cc-compiler-armeabi-v7a",
"x64_windows|msvc-cl": ":cc-compiler-x64_windows",
"x64_x86_windows|msvc-cl": ":cc-compiler-x64_x86_windows",
"x64_arm_windows|msvc-cl": ":cc-compiler-x64_arm_windows",
"x64_arm64_windows|msvc-cl": ":cc-compiler-arm64_windows",
"arm64_windows|msvc-cl": ":cc-compiler-arm64_windows",
"x64_windows|msys-gcc": ":cc-compiler-x64_windows_msys",
"x64_x86_windows|msys-gcc": ":cc-compiler-x64_x86_windows_msys",
"x64_windows|mingw-gcc": ":cc-compiler-x64_windows_mingw",
"x64_x86_windows|mingw-gcc": ":cc-compiler-x64_x86_windows_mingw",
"x64_windows|clang-cl": ":cc-compiler-x64_windows-clang-cl",
"x64_windows_msys": ":cc-compiler-x64_windows_msys",
"x64_windows": ":cc-compiler-x64_windows",
"x64_x86_windows": ":cc-compiler-x64_x86_windows",
"x64_arm_windows": ":cc-compiler-x64_arm_windows",
"x64_arm64_windows": ":cc-compiler-arm64_windows",
"arm64_windows": ":cc-compiler-arm64_windows",
"x64_arm64_windows|clang-cl": ":cc-compiler-arm64_windows-clang-cl",
"arm64_windows|clang-cl": ":cc-compiler-arm64_windows-clang-cl",
"armeabi-v7a": ":cc-compiler-armeabi-v7a",
},
)
@ -85,8 +122,6 @@ cc_toolchain_config(
cxx_builtin_include_directories = [%{cxx_builtin_include_directories}],
tool_paths = {%{tool_paths}},
tool_bin_path = "%{tool_bin_path}",
dbg_mode_debug_flag = "%{dbg_mode_debug_flag}",
fastbuild_mode_debug_flag = "%{fastbuild_mode_debug_flag}",
)
toolchain(
@ -101,7 +136,53 @@ toolchain(
"@platforms//os:windows",
],
toolchain = ":cc-compiler-x64_windows_msys",
toolchain_type = "@rules_cc//cc:toolchain_type",
toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
)
cc_toolchain(
name = "cc-compiler-x64_x86_windows_msys",
toolchain_identifier = "msys_x64_x86",
toolchain_config = ":msys_x64_x86",
all_files = ":empty",
ar_files = ":empty",
as_files = ":mingw_compiler_files",
compiler_files = ":mingw_compiler_files",
dwp_files = ":empty",
linker_files = ":empty",
objcopy_files = ":empty",
strip_files = ":empty",
supports_param_files = 1,
)
cc_toolchain_config(
name = "msys_x64_x86",
cpu = "x64_x86_windows",
compiler = "msys-gcc",
host_system_name = "local",
target_system_name = "local",
target_libc = "msys",
abi_version = "local",
abi_libc_version = "local",
cxx_builtin_include_directories = [%{cxx_builtin_include_directories}],
tool_paths = {%{tool_paths}},
tool_bin_path = "%{tool_bin_path}",
default_compile_flags = ["-m32"],
default_link_flags = ["-m32"],
)
toolchain(
name = "cc-toolchain-x64_x86_windows_msys",
exec_compatible_with = [
"@platforms//cpu:x86_64",
"@platforms//os:windows",
"@rules_cc//cc/private/toolchain:msys",
],
target_compatible_with = [
"@platforms//cpu:x86_32",
"@platforms//os:windows",
],
toolchain = ":cc-compiler-x64_x86_windows_msys",
toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
)
cc_toolchain(
@ -131,8 +212,6 @@ cc_toolchain_config(
tool_bin_path = "%{mingw_tool_bin_path}",
cxx_builtin_include_directories = [%{mingw_cxx_builtin_include_directories}],
tool_paths = {%{mingw_tool_paths}},
dbg_mode_debug_flag = "%{dbg_mode_debug_flag}",
fastbuild_mode_debug_flag = "%{fastbuild_mode_debug_flag}",
)
toolchain(
@ -147,7 +226,53 @@ toolchain(
"@platforms//os:windows",
],
toolchain = ":cc-compiler-x64_windows_mingw",
toolchain_type = "@rules_cc//cc:toolchain_type",
toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
)
cc_toolchain(
name = "cc-compiler-x64_x86_windows_mingw",
toolchain_identifier = "msys_x64_x86_mingw",
toolchain_config = ":msys_x64_x86_mingw",
all_files = ":empty",
ar_files = ":empty",
as_files = ":mingw_compiler_files",
compiler_files = ":mingw_compiler_files",
dwp_files = ":empty",
linker_files = ":empty",
objcopy_files = ":empty",
strip_files = ":empty",
supports_param_files = 0,
)
cc_toolchain_config(
name = "msys_x64_x86_mingw",
cpu = "x64_x86_windows",
compiler = "mingw-gcc",
host_system_name = "local",
target_system_name = "local",
target_libc = "mingw",
abi_version = "local",
abi_libc_version = "local",
tool_bin_path = "%{mingw_tool_bin_path}",
cxx_builtin_include_directories = [%{mingw_cxx_builtin_include_directories}],
tool_paths = {%{mingw_tool_paths}},
default_compile_flags = ["-m32"],
default_link_flags = ["-m32"],
)
toolchain(
name = "cc-toolchain-x64_x86_windows_mingw",
exec_compatible_with = [
"@platforms//cpu:x86_64",
"@platforms//os:windows",
"@rules_cc//cc/private/toolchain:mingw",
],
target_compatible_with = [
"@platforms//cpu:x86_32",
"@platforms//os:windows",
],
toolchain = ":cc-compiler-x64_x86_windows_mingw",
toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
)
cc_toolchain(
@ -175,30 +300,34 @@ cc_toolchain_config(
abi_version = "local",
abi_libc_version = "local",
toolchain_identifier = "msvc_x64",
msvc_env_tmp = "%{msvc_env_tmp}",
msvc_env_path = "%{msvc_env_path}",
msvc_env_include = "%{msvc_env_include}",
msvc_env_lib = "%{msvc_env_lib}",
msvc_cl_path = "%{msvc_cl_path}",
msvc_ml_path = "%{msvc_ml_path}",
msvc_link_path = "%{msvc_link_path}",
msvc_lib_path = "%{msvc_lib_path}",
cxx_builtin_include_directories = [%{msvc_cxx_builtin_include_directories}],
msvc_env_tmp = "%{msvc_env_tmp_x64}",
msvc_env_path = "%{msvc_env_path_x64}",
msvc_env_include = "%{msvc_env_include_x64}",
msvc_env_lib = "%{msvc_env_lib_x64}",
msvc_cl_path = "%{msvc_cl_path_x64}",
msvc_ml_path = "%{msvc_ml_path_x64}",
msvc_link_path = "%{msvc_link_path_x64}",
msvc_lib_path = "%{msvc_lib_path_x64}",
cxx_builtin_include_directories = [%{msvc_cxx_builtin_include_directories_x64}],
tool_paths = {
"ar": "%{msvc_lib_path}",
"ml": "%{msvc_ml_path}",
"cpp": "%{msvc_cl_path}",
"gcc": "%{msvc_cl_path}",
"ar": "%{msvc_lib_path_x64}",
"ml": "%{msvc_ml_path_x64}",
"cpp": "%{msvc_cl_path_x64}",
"gcc": "%{msvc_cl_path_x64}",
"gcov": "wrapper/bin/msvc_nop.bat",
"ld": "%{msvc_link_path}",
"ld": "%{msvc_link_path_x64}",
"nm": "wrapper/bin/msvc_nop.bat",
"objcopy": "wrapper/bin/msvc_nop.bat",
"objdump": "wrapper/bin/msvc_nop.bat",
"strip": "wrapper/bin/msvc_nop.bat",
"dumpbin": "%{msvc_dumpbin_path_x64}",
"cpp-module-deps-scanner": "%{msvc_deps_scanner_wrapper_path_x64}",
},
archiver_flags = ["/MACHINE:X64"],
default_link_flags = ["/MACHINE:X64"],
dbg_mode_debug_flag = "%{dbg_mode_debug_flag}",
fastbuild_mode_debug_flag = "%{fastbuild_mode_debug_flag}",
dbg_mode_debug_flag = "%{dbg_mode_debug_flag_x64}",
fastbuild_mode_debug_flag = "%{fastbuild_mode_debug_flag_x64}",
supports_parse_showincludes = %{msvc_parse_showincludes_x64},
)
toolchain(
@ -212,9 +341,216 @@ toolchain(
"@platforms//os:windows",
],
toolchain = ":cc-compiler-x64_windows",
toolchain_type = "@rules_cc//cc:toolchain_type",
toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
)
cc_toolchain(
name = "cc-compiler-x64_x86_windows",
toolchain_identifier = "msvc_x64_x86",
toolchain_config = ":msvc_x64_x86",
all_files = ":empty",
ar_files = ":empty",
as_files = ":msvc_compiler_files",
compiler_files = ":msvc_compiler_files",
dwp_files = ":empty",
linker_files = ":empty",
objcopy_files = ":empty",
strip_files = ":empty",
supports_param_files = 1,
)
cc_toolchain_config(
name = "msvc_x64_x86",
cpu = "x64_windows",
compiler = "msvc-cl",
host_system_name = "local",
target_system_name = "local",
target_libc = "msvcrt",
abi_version = "local",
abi_libc_version = "local",
toolchain_identifier = "msvc_x64_x86",
msvc_env_tmp = "%{msvc_env_tmp_x86}",
msvc_env_path = "%{msvc_env_path_x86}",
msvc_env_include = "%{msvc_env_include_x86}",
msvc_env_lib = "%{msvc_env_lib_x86}",
msvc_cl_path = "%{msvc_cl_path_x86}",
msvc_ml_path = "%{msvc_ml_path_x86}",
msvc_link_path = "%{msvc_link_path_x86}",
msvc_lib_path = "%{msvc_lib_path_x86}",
cxx_builtin_include_directories = [%{msvc_cxx_builtin_include_directories_x86}],
tool_paths = {
"ar": "%{msvc_lib_path_x86}",
"ml": "%{msvc_ml_path_x86}",
"cpp": "%{msvc_cl_path_x86}",
"gcc": "%{msvc_cl_path_x86}",
"gcov": "wrapper/bin/msvc_nop.bat",
"ld": "%{msvc_link_path_x86}",
"nm": "wrapper/bin/msvc_nop.bat",
"objcopy": "wrapper/bin/msvc_nop.bat",
"objdump": "wrapper/bin/msvc_nop.bat",
"strip": "wrapper/bin/msvc_nop.bat",
"dumpbin": "%{msvc_dumpbin_path_x86}",
"cpp-module-deps-scanner": "%{msvc_deps_scanner_wrapper_path_x86}",
},
archiver_flags = ["/MACHINE:X86"],
default_link_flags = ["/MACHINE:X86"],
dbg_mode_debug_flag = "%{dbg_mode_debug_flag_x86}",
fastbuild_mode_debug_flag = "%{fastbuild_mode_debug_flag_x86}",
supports_parse_showincludes = %{msvc_parse_showincludes_x86},
)
toolchain(
name = "cc-toolchain-x64_x86_windows",
exec_compatible_with = [
"@platforms//cpu:x86_64",
"@platforms//os:windows",
],
target_compatible_with = [
"@platforms//cpu:x86_32",
"@platforms//os:windows",
],
toolchain = ":cc-compiler-x64_x86_windows",
toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
)
cc_toolchain(
name = "cc-compiler-x64_arm_windows",
toolchain_identifier = "msvc_x64_arm",
toolchain_config = ":msvc_x64_arm",
all_files = ":empty",
ar_files = ":empty",
as_files = ":msvc_compiler_files",
compiler_files = ":msvc_compiler_files",
dwp_files = ":empty",
linker_files = ":empty",
objcopy_files = ":empty",
strip_files = ":empty",
supports_param_files = 1,
)
cc_toolchain_config(
name = "msvc_x64_arm",
cpu = "x64_windows",
compiler = "msvc-cl",
host_system_name = "local",
target_system_name = "local",
target_libc = "msvcrt",
abi_version = "local",
abi_libc_version = "local",
toolchain_identifier = "msvc_x64_arm",
msvc_env_tmp = "%{msvc_env_tmp_arm}",
msvc_env_path = "%{msvc_env_path_arm}",
msvc_env_include = "%{msvc_env_include_arm}",
msvc_env_lib = "%{msvc_env_lib_arm}",
msvc_cl_path = "%{msvc_cl_path_arm}",
msvc_ml_path = "%{msvc_ml_path_arm}",
msvc_link_path = "%{msvc_link_path_arm}",
msvc_lib_path = "%{msvc_lib_path_arm}",
cxx_builtin_include_directories = [%{msvc_cxx_builtin_include_directories_arm}],
tool_paths = {
"ar": "%{msvc_lib_path_arm}",
"ml": "%{msvc_ml_path_arm}",
"cpp": "%{msvc_cl_path_arm}",
"gcc": "%{msvc_cl_path_arm}",
"gcov": "wrapper/bin/msvc_nop.bat",
"ld": "%{msvc_link_path_arm}",
"nm": "wrapper/bin/msvc_nop.bat",
"objcopy": "wrapper/bin/msvc_nop.bat",
"objdump": "wrapper/bin/msvc_nop.bat",
"strip": "wrapper/bin/msvc_nop.bat",
"dumpbin": "%{msvc_dumpbin_path_arm}",
"cpp-module-deps-scanner": "%{msvc_deps_scanner_wrapper_path_arm}",
},
archiver_flags = ["/MACHINE:ARM"],
default_link_flags = ["/MACHINE:ARM"],
dbg_mode_debug_flag = "%{dbg_mode_debug_flag_arm}",
fastbuild_mode_debug_flag = "%{fastbuild_mode_debug_flag_arm}",
supports_parse_showincludes = %{msvc_parse_showincludes_arm},
)
toolchain(
name = "cc-toolchain-x64_arm_windows",
exec_compatible_with = [
"@platforms//cpu:x86_64",
"@platforms//os:windows",
],
target_compatible_with = [
"@platforms//cpu:arm",
"@platforms//os:windows",
],
toolchain = ":cc-compiler-x64_arm_windows",
toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
)
cc_toolchain(
name = "cc-compiler-arm64_windows",
toolchain_identifier = "msvc_arm64",
toolchain_config = ":msvc_arm64",
all_files = ":empty",
ar_files = ":empty",
as_files = ":msvc_compiler_files",
compiler_files = ":msvc_compiler_files",
dwp_files = ":empty",
linker_files = ":empty",
objcopy_files = ":empty",
strip_files = ":empty",
supports_param_files = 1,
)
cc_toolchain_config(
name = "msvc_arm64",
cpu = "x64_windows",
compiler = "msvc-cl",
host_system_name = "local",
target_system_name = "local",
target_libc = "msvcrt",
abi_version = "local",
abi_libc_version = "local",
toolchain_identifier = "msvc_arm64",
msvc_env_tmp = "%{msvc_env_tmp_arm64}",
msvc_env_path = "%{msvc_env_path_arm64}",
msvc_env_include = "%{msvc_env_include_arm64}",
msvc_env_lib = "%{msvc_env_lib_arm64}",
msvc_cl_path = "%{msvc_cl_path_arm64}",
msvc_ml_path = "%{msvc_ml_path_arm64}",
msvc_link_path = "%{msvc_link_path_arm64}",
msvc_lib_path = "%{msvc_lib_path_arm64}",
cxx_builtin_include_directories = [%{msvc_cxx_builtin_include_directories_arm64}],
tool_paths = {
"ar": "%{msvc_lib_path_arm64}",
"ml": "%{msvc_ml_path_arm64}",
"cpp": "%{msvc_cl_path_arm64}",
"gcc": "%{msvc_cl_path_arm64}",
"gcov": "wrapper/bin/msvc_nop.bat",
"ld": "%{msvc_link_path_arm64}",
"nm": "wrapper/bin/msvc_nop.bat",
"objcopy": "wrapper/bin/msvc_nop.bat",
"objdump": "wrapper/bin/msvc_nop.bat",
"strip": "wrapper/bin/msvc_nop.bat",
"dumpbin": "%{msvc_dumpbin_path_arm64}",
"cpp-module-deps-scanner": "%{msvc_deps_scanner_wrapper_path_arm64}",
},
archiver_flags = ["/MACHINE:ARM64"],
default_link_flags = ["/MACHINE:ARM64"],
dbg_mode_debug_flag = "%{dbg_mode_debug_flag_arm64}",
fastbuild_mode_debug_flag = "%{fastbuild_mode_debug_flag_arm64}",
supports_parse_showincludes = %{msvc_parse_showincludes_arm64},
)
toolchain(
name = "cc-toolchain-arm64_windows",
exec_compatible_with = [
"@platforms//os:windows",
],
target_compatible_with = [
"@platforms//cpu:arm64",
"@platforms//os:windows",
],
toolchain = ":cc-compiler-arm64_windows",
toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
)
cc_toolchain(
name = "cc-compiler-x64_windows-clang-cl",
toolchain_identifier = "clang_cl_x64",
@ -240,30 +576,32 @@ cc_toolchain_config(
abi_version = "local",
abi_libc_version = "local",
toolchain_identifier = "clang_cl_x64",
msvc_env_tmp = "%{clang_cl_env_tmp}",
msvc_env_path = "%{clang_cl_env_path}",
msvc_env_include = "%{clang_cl_env_include}",
msvc_env_lib = "%{clang_cl_env_lib}",
msvc_cl_path = "%{clang_cl_cl_path}",
msvc_ml_path = "%{clang_cl_ml_path}",
msvc_link_path = "%{clang_cl_link_path}",
msvc_lib_path = "%{clang_cl_lib_path}",
cxx_builtin_include_directories = [%{clang_cl_cxx_builtin_include_directories}],
msvc_env_tmp = "%{clang_cl_env_tmp_x64}",
msvc_env_path = "%{clang_cl_env_path_x64}",
msvc_env_include = "%{clang_cl_env_include_x64}",
msvc_env_lib = "%{clang_cl_env_lib_x64}",
msvc_cl_path = "%{clang_cl_cl_path_x64}",
msvc_ml_path = "%{clang_cl_ml_path_x64}",
msvc_link_path = "%{clang_cl_link_path_x64}",
msvc_lib_path = "%{clang_cl_lib_path_x64}",
cxx_builtin_include_directories = [%{clang_cl_cxx_builtin_include_directories_x64}],
tool_paths = {
"ar": "%{clang_cl_lib_path}",
"ml": "%{clang_cl_ml_path}",
"cpp": "%{clang_cl_cl_path}",
"gcc": "%{clang_cl_cl_path}",
"ar": "%{clang_cl_lib_path_x64}",
"ml": "%{clang_cl_ml_path_x64}",
"cpp": "%{clang_cl_cl_path_x64}",
"gcc": "%{clang_cl_cl_path_x64}",
"gcov": "wrapper/bin/msvc_nop.bat",
"ld": "%{clang_cl_link_path}",
"ld": "%{clang_cl_link_path_x64}",
"nm": "wrapper/bin/msvc_nop.bat",
"objcopy": "wrapper/bin/msvc_nop.bat",
"objdump": "wrapper/bin/msvc_nop.bat",
"strip": "wrapper/bin/msvc_nop.bat",
},
default_link_flags = ["/MACHINE:X64", "/DEFAULTLIB:clang_rt.builtins-x86_64.lib"],
dbg_mode_debug_flag = "%{clang_cl_dbg_mode_debug_flag}",
fastbuild_mode_debug_flag = "%{clang_cl_fastbuild_mode_debug_flag}",
archiver_flags = ["/MACHINE:X64"],
default_link_flags = ["/MACHINE:X64"],
dbg_mode_debug_flag = "%{clang_cl_dbg_mode_debug_flag_x64}",
fastbuild_mode_debug_flag = "%{clang_cl_fastbuild_mode_debug_flag_x64}",
supports_parse_showincludes = %{clang_cl_parse_showincludes_x64},
)
toolchain(
@ -278,7 +616,74 @@ toolchain(
"@platforms//os:windows",
],
toolchain = ":cc-compiler-x64_windows-clang-cl",
toolchain_type = "@rules_cc//cc:toolchain_type",
toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
)
cc_toolchain(
name = "cc-compiler-arm64_windows-clang-cl",
toolchain_identifier = "clang_cl_arm64",
toolchain_config = ":clang_cl_arm64",
all_files = ":empty",
ar_files = ":empty",
as_files = ":clangcl_compiler_files",
compiler_files = ":clangcl_compiler_files",
dwp_files = ":empty",
linker_files = ":empty",
objcopy_files = ":empty",
strip_files = ":empty",
supports_param_files = 1,
)
cc_toolchain_config(
name = "clang_cl_arm64",
cpu = "arm64_windows",
compiler = "clang-cl",
host_system_name = "local",
target_system_name = "aarch64-pc-windows-msvc",
target_libc = "msvcrt",
abi_version = "local",
abi_libc_version = "local",
toolchain_identifier = "clang_cl_arm64",
msvc_env_tmp = "%{clang_cl_env_tmp_arm64}",
msvc_env_path = "%{clang_cl_env_path_arm64}",
msvc_env_include = "%{clang_cl_env_include_arm64}",
msvc_env_lib = "%{clang_cl_env_lib_arm64}",
msvc_cl_path = "%{clang_cl_cl_path_arm64}",
msvc_ml_path = "%{clang_cl_ml_path_arm64}",
msvc_link_path = "%{clang_cl_link_path_arm64}",
msvc_lib_path = "%{clang_cl_lib_path_arm64}",
cxx_builtin_include_directories = [%{clang_cl_cxx_builtin_include_directories_arm64}],
tool_paths = {
"ar": "%{clang_cl_lib_path_arm64}",
"ml": "%{clang_cl_ml_path_arm64}",
"cpp": "%{clang_cl_cl_path_arm64}",
"gcc": "%{clang_cl_cl_path_arm64}",
"gcov": "wrapper/bin/msvc_nop.bat",
"ld": "%{clang_cl_link_path_arm64}",
"nm": "wrapper/bin/msvc_nop.bat",
"objcopy": "wrapper/bin/msvc_nop.bat",
"objdump": "wrapper/bin/msvc_nop.bat",
"strip": "wrapper/bin/msvc_nop.bat",
},
archiver_flags = ["/MACHINE:ARM64"],
default_link_flags = ["/MACHINE:ARM64"],
dbg_mode_debug_flag = "%{clang_cl_dbg_mode_debug_flag_arm64}",
fastbuild_mode_debug_flag = "%{clang_cl_fastbuild_mode_debug_flag_arm64}",
supports_parse_showincludes = %{clang_cl_parse_showincludes_arm64},
)
toolchain(
name = "cc-toolchain-arm64_windows-clang-cl",
exec_compatible_with = [
"@platforms//os:windows",
"@rules_cc//cc/private/toolchain:clang-cl",
],
target_compatible_with = [
"@platforms//cpu:arm64",
"@platforms//os:windows",
],
toolchain = ":cc-compiler-arm64_windows-clang-cl",
toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
)
cc_toolchain(
@ -303,14 +708,9 @@ toolchain(
exec_compatible_with = [
],
target_compatible_with = [
"@platforms//cpu:arm",
"@platforms//cpu:armv7",
"@platforms//os:android",
],
toolchain = ":cc-compiler-armeabi-v7a",
toolchain_type = "@rules_cc//cc:toolchain_type",
)
filegroup(
name = "link_dynamic_library",
srcs = ["link_dynamic_library.sh"],
toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
)

View File

@ -49,6 +49,7 @@ def _impl(ctx):
tool_path(name = "gcc", path = "/bin/false"),
tool_path(name = "gcov", path = "/bin/false"),
tool_path(name = "ld", path = "/bin/false"),
tool_path(name = "llvm-profdata", path = "/bin/false"),
tool_path(name = "nm", path = "/bin/false"),
tool_path(name = "objcopy", path = "/bin/false"),
tool_path(name = "objdump", path = "/bin/false"),

View File

@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
"""A Starlark cc_toolchain configuration rule for freebsd."""
"""A Starlark cc_toolchain configuration rule for FreeBSD and OpenBSD."""
load("@rules_cc//cc:action_names.bzl", "ACTION_NAMES")
load(
@ -24,7 +24,7 @@ load(
"tool",
"tool_path",
"with_feature_set",
)
) # buildifier: disable=deprecated-function
all_compile_actions = [
ACTION_NAMES.c_compile,
@ -56,13 +56,14 @@ all_link_actions = [
def _impl(ctx):
cpu = ctx.attr.cpu
is_bsd = cpu == "freebsd" or cpu == "openbsd"
compiler = "compiler"
toolchain_identifier = "local_freebsd" if cpu == "freebsd" else "stub_armeabi-v7a"
host_system_name = "local" if cpu == "freebsd" else "armeabi-v7a"
target_system_name = "local" if cpu == "freebsd" else "armeabi-v7a"
target_libc = "local" if cpu == "freebsd" else "armeabi-v7a"
abi_version = "local" if cpu == "freebsd" else "armeabi-v7a"
abi_libc_version = "local" if cpu == "freebsd" else "armeabi-v7a"
toolchain_identifier = "local_{}".format(cpu) if is_bsd else "stub_armeabi-v7a"
host_system_name = "local" if is_bsd else "armeabi-v7a"
target_system_name = "local" if is_bsd else "armeabi-v7a"
target_libc = "local" if is_bsd else "armeabi-v7a"
abi_version = "local" if is_bsd else "armeabi-v7a"
abi_libc_version = "local" if is_bsd else "armeabi-v7a"
objcopy_embed_data_action = action_config(
action_name = "objcopy_embed_data",
@ -70,7 +71,7 @@ def _impl(ctx):
tools = [tool(path = "/usr/bin/objcopy")],
)
action_configs = [objcopy_embed_data_action] if cpu == "freebsd" else []
action_configs = [objcopy_embed_data_action] if is_bsd else []
default_link_flags_feature = feature(
name = "default_link_flags",
@ -159,7 +160,7 @@ def _impl(ctx):
),
flag_set(
actions = all_cpp_compile_actions + [ACTION_NAMES.lto_backend],
flag_groups = [flag_group(flags = ["-std=c++0x"])],
flag_groups = [flag_group(flags = ["-std=c++17"])],
),
],
)
@ -224,7 +225,7 @@ def _impl(ctx):
],
)
if cpu == "freebsd":
if is_bsd:
features = [
default_compile_flags_feature,
default_link_flags_feature,
@ -240,12 +241,12 @@ def _impl(ctx):
else:
features = [supports_dynamic_linker_feature, supports_pic_feature]
if (cpu == "freebsd"):
if (is_bsd):
cxx_builtin_include_directories = ["/usr/lib/clang", "/usr/local/include", "/usr/include"]
else:
cxx_builtin_include_directories = []
if cpu == "freebsd":
if is_bsd:
tool_paths = [
tool_path(name = "ar", path = "/usr/bin/ar"),
tool_path(name = "compat-ld", path = "/usr/bin/ld"),

View File

@ -46,7 +46,6 @@ def cc_autoconf_toolchains_impl(repository_ctx):
cc_autoconf_toolchains = repository_rule(
environ = [
"BAZEL_USE_CPP_ONLY_TOOLCHAIN",
"BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN",
],
implementation = cc_autoconf_toolchains_impl,
@ -65,24 +64,26 @@ def cc_autoconf_impl(repository_ctx, overriden_tools = dict()):
cpu_value = get_cpu_value(repository_ctx)
if "BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN" in env and env["BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN"] == "1":
paths = resolve_labels(repository_ctx, [
"@rules_cc//cc/private/toolchain:BUILD.empty",
"@rules_cc//cc/private/toolchain:BUILD.empty.tpl",
"@rules_cc//cc/private/toolchain:empty_cc_toolchain_config.bzl",
])
repository_ctx.symlink(paths["@rules_cc//cc/private/toolchain:empty_cc_toolchain_config.bzl"], "cc_toolchain_config.bzl")
repository_ctx.symlink(paths["@rules_cc//cc/private/toolchain:BUILD.empty"], "BUILD")
elif cpu_value == "freebsd":
repository_ctx.template("BUILD", paths["@rules_cc//cc/private/toolchain:BUILD.empty.tpl"], {
"%{cpu}": get_cpu_value(repository_ctx),
})
elif cpu_value == "freebsd" or cpu_value == "openbsd":
paths = resolve_labels(repository_ctx, [
"@rules_cc//cc/private/toolchain:BUILD.static.freebsd",
"@rules_cc//cc/private/toolchain:freebsd_cc_toolchain_config.bzl",
"@rules_cc//cc/private/toolchain:BUILD.static.bsd",
"@rules_cc//cc/private/toolchain:bsd_cc_toolchain_config.bzl",
])
# This is defaulting to a static crosstool, we should eventually
# autoconfigure this platform too. Theorically, FreeBSD should be
# straightforward to add but we cannot run it in a docker container so
# skipping until we have proper tests for FreeBSD.
repository_ctx.symlink(paths["@rules_cc//cc/private/toolchain:freebsd_cc_toolchain_config.bzl"], "cc_toolchain_config.bzl")
repository_ctx.symlink(paths["@rules_cc//cc/private/toolchain:BUILD.static.freebsd"], "BUILD")
elif cpu_value == "x64_windows":
# This is defaulting to a static crosstool. We should eventually
# autoconfigure this platform too. Theoretically, FreeBSD and OpenBSD
# should be straightforward to add but we cannot run them in a Docker
# container so skipping until we have proper tests for these platforms.
repository_ctx.symlink(paths["@rules_cc//cc/private/toolchain:bsd_cc_toolchain_config.bzl"], "cc_toolchain_config.bzl")
repository_ctx.symlink(paths["@rules_cc//cc/private/toolchain:BUILD.static.bsd"], "BUILD")
elif cpu_value in ["x64_windows", "arm64_windows"]:
# TODO(ibiryukov): overriden_tools are only supported in configure_unix_toolchain.
# We might want to add that to Windows too(at least for msys toolchain).
configure_windows_toolchain(repository_ctx)
@ -111,16 +112,17 @@ cc_autoconf = repository_rule(
"ABI_VERSION",
"BAZEL_COMPILER",
"BAZEL_HOST_SYSTEM",
"BAZEL_CONLYOPTS",
"BAZEL_CXXOPTS",
"BAZEL_LINKOPTS",
"BAZEL_LINKLIBS",
"BAZEL_LLVM_COV",
"BAZEL_LLVM_PROFDATA",
"BAZEL_PYTHON",
"BAZEL_SH",
"BAZEL_TARGET_CPU",
"BAZEL_TARGET_LIBC",
"BAZEL_TARGET_SYSTEM",
"BAZEL_USE_CPP_ONLY_TOOLCHAIN",
"BAZEL_USE_XCODE_TOOLCHAIN",
"BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN",
"BAZEL_USE_LLVM_NATIVE_COVERAGE",
"BAZEL_LLVM",
@ -130,9 +132,12 @@ cc_autoconf = repository_rule(
"CC_CONFIGURE_DEBUG",
"CC_TOOLCHAIN_NAME",
"CPLUS_INCLUDE_PATH",
"DEVELOPER_DIR",
"GCOV",
"LIBTOOL",
"HOMEBREW_RUBY_PATH",
"SYSTEMROOT",
"USER",
] + MSVC_ENVVARS,
implementation = cc_autoconf_impl,
configure = True,

View File

@ -0,0 +1,11 @@
#!/usr/bin/env bash
#
# Ship the environment to the C++ action
#
set -eu
# Set-up the environment
%{env}
# Call the C++ compiler
%{deps_scanner} -format=p1689 -- %{cc} "$@" >"$DEPS_SCANNER_OUTPUT_FILE"

View File

@ -18,7 +18,7 @@ echo. 1>&2
echo The target you are compiling requires the Clang compiler. 1>&2
echo Bazel couldn't find a valid Clang installation on your machine. 1>&2
%{clang_error_message}
echo Please check your installation following https://docs.bazel.build/versions/main/windows.html#using 1>&2
echo Please check your installation following https://bazel.build/docs/windows#using 1>&2
echo. 1>&2
exit /b 1

View File

@ -0,0 +1,12 @@
#!/bin/bash
#
# Ship the environment to the C++ action
#
set -eu
# Set-up the environment
%{env}
# Call the C++ compiler
%{cc} -E -x c++ -fmodules-ts -fdeps-file=out.tmp -fdeps-format=p1689r5 "$@" >"$DEPS_SCANNER_OUTPUT_FILE"

View File

@ -0,0 +1,35 @@
#!/bin/bash
# Copyright 2020 The Bazel 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.
set -eu
echo 'module "crosstool" [system] {'
if [[ "$OSTYPE" == darwin* ]]; then
for dir in $@; do
find "$dir" -type f \( -name "*.h" -o -name "*.def" -o -path "*/c++/*" \) \
| LANG=C sort -u | while read -r header; do
echo " textual header \"${header}\""
done
done
else
for dir in $@; do
find -L "${dir}" -type f 2>/dev/null | LANG=C sort -u | while read -r header; do
echo " textual header \"${header}\""
done
done
fi
echo "}"

View File

@ -51,7 +51,7 @@ def split_escaped(string, delimiter):
Basic usage:
split_escaped("a:b:c", ":") -> [ "a", "b", "c" ]
Delimeter that is not supposed to be splitten on has to be %-escaped:
Delimiter that is not supposed to be splitten on has to be %-escaped:
split_escaped("a%:b", ":") -> [ "a:b" ]
Literal % can be represented by escaping it as %%:
@ -137,7 +137,8 @@ def get_env_var(repository_ctx, name, default = None, enable_warning = True):
if enable_warning:
auto_configure_warning("'%s' environment variable is not set, using '%s' as default" % (name, default))
return default
return auto_configure_fail("'%s' environment variable is not set" % name)
auto_configure_fail("'%s' environment variable is not set" % name)
return None
def which(repository_ctx, cmd, default = None):
"""A wrapper around repository_ctx.which() to provide a fallback value. Doesn't %-escape the value!
@ -176,7 +177,8 @@ def execute(
repository_ctx,
command,
environment = None,
expect_failure = False):
expect_failure = False,
expect_empty_output = False):
"""Execute a command, return stdout if succeed and throw an error if it fails. Doesn't %-escape the result!
Args:
@ -184,6 +186,7 @@ def execute(
command: command to execute.
environment: dictionary with environment variables to set for the command.
expect_failure: True if the command is expected to fail.
expect_empty_output: True if the command is expected to produce no output.
Returns:
stdout of the executed command.
"""
@ -208,10 +211,15 @@ def execute(
),
)
stripped_stdout = result.stdout.strip()
if not stripped_stdout:
auto_configure_fail(
"empty output from command %s, stderr: (%s)" % (command, result.stderr),
)
if expect_empty_output != (not stripped_stdout):
if expect_empty_output:
auto_configure_fail(
"non-empty output from command %s, stdout: (%s), stderr: (%s)" % (command, result.stdout, result.stderr),
)
else:
auto_configure_fail(
"empty output from command %s, stderr: (%s)" % (command, result.stderr),
)
return stripped_stdout
def get_cpu_value(repository_ctx):
@ -222,25 +230,34 @@ def get_cpu_value(repository_ctx):
Returns:
One of (darwin, freebsd, x64_windows, ppc, s390x, arm, aarch64, k8, piii)
"""
os_name = repository_ctx.os.name.lower()
os_name = repository_ctx.os.name
arch = repository_ctx.os.arch
if os_name.startswith("mac os"):
return "darwin"
# Check if we are on x86_64 or arm64 and return the corresponding cpu value.
return "darwin_" + ("arm64" if arch == "aarch64" else "x86_64")
if os_name.find("freebsd") != -1:
return "freebsd"
if os_name.find("openbsd") != -1:
return "openbsd"
if os_name.find("windows") != -1:
return "x64_windows"
if arch == "aarch64":
return "arm64_windows"
else:
return "x64_windows"
# Use uname to figure out whether we are on x86_32 or x86_64
result = repository_ctx.execute(["uname", "-m"])
if result.stdout.strip() in ["power", "ppc64le", "ppc", "ppc64"]:
if arch in ["power", "ppc64le", "ppc", "ppc64"]:
return "ppc"
if result.stdout.strip() in ["s390x"]:
if arch in ["s390x"]:
return "s390x"
if result.stdout.strip() in ["arm", "armv7l"]:
if arch in ["mips64"]:
return "mips64"
if arch in ["riscv64"]:
return "riscv64"
if arch in ["arm", "armv7l"]:
return "arm"
if result.stdout.strip() in ["aarch64"]:
if arch in ["aarch64"]:
return "aarch64"
return "k8" if result.stdout.strip() in ["amd64", "x86_64", "x64"] else "piii"
return "k8" if arch in ["amd64", "x86_64", "x64"] else "piii"
def is_cc_configure_debug(repository_ctx):
"""Returns True if CC_CONFIGURE_DEBUG is set to 1."""

View File

@ -18,8 +18,37 @@
#
set -eu
OUTPUT=
function parse_option() {
local -r opt="$1"
if [[ "${OUTPUT}" = "1" ]]; then
OUTPUT=$opt
elif [[ "$opt" = "-o" ]]; then
# output is coming
OUTPUT=1
fi
}
# let parse the option list
for i in "$@"; do
if [[ "$i" = @* && -r "${i:1}" ]]; then
while IFS= read -r opt
do
parse_option "$opt"
done < "${i:1}" || exit 1
else
parse_option "$i"
fi
done
# Set-up the environment
%{env}
# Call the C++ compiler
%{cc} "$@"
# Generate an empty file if header processing succeeded.
if [[ "${OUTPUT}" == *.h.processed ]]; then
echo -n > "${OUTPUT}"
fi

View File

@ -0,0 +1,16 @@
:: Copyright 2024 The Bazel 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.
@echo OFF
"%{cc}" /scanDependencies- /TP %* >%DEPS_SCANNER_OUTPUT_FILE%

View File

@ -27,9 +27,8 @@
#
set -eu
INSTALL_NAME_TOOL="/usr/bin/install_name_tool"
LIBS=
LIB_PATHS=
LIB_DIRS=
RPATHS=
OUTPUT=
@ -40,9 +39,13 @@ function parse_option() {
OUTPUT=$opt
elif [[ "$opt" =~ ^-l(.*)$ ]]; then
LIBS="${BASH_REMATCH[1]} $LIBS"
elif [[ "$opt" =~ ^(.*)\.so$ ]]; then
LIB_PATHS="${opt} $LIB_PATHS"
elif [[ "$opt" =~ ^(.*)\.dylib$ ]]; then
LIB_PATHS="${opt} $LIB_PATHS"
elif [[ "$opt" =~ ^-L(.*)$ ]]; then
LIB_DIRS="${BASH_REMATCH[1]} $LIB_DIRS"
elif [[ "$opt" =~ ^-Wl,-rpath,\@loader_path/(.*)$ ]]; then
elif [[ "$opt" =~ ^\@loader_path/(.*)$ ]]; then
RPATHS="${BASH_REMATCH[1]} ${RPATHS}"
elif [[ "$opt" = "-o" ]]; then
# output is coming
@ -52,7 +55,7 @@ function parse_option() {
# let parse the option list
for i in "$@"; do
if [[ "$i" = @* ]]; then
if [[ "$i" = @* && -r "${i:1}" ]]; then
while IFS= read -r opt
do
parse_option "$opt"
@ -68,6 +71,11 @@ done
# Call the C++ compiler
%{cc} "$@"
# Generate an empty file if header processing succeeded.
if [[ "${OUTPUT}" == *.h.processed ]]; then
echo -n > "${OUTPUT}"
fi
function get_library_path() {
for libdir in ${LIB_DIRS}; do
if [ -f ${libdir}/lib$1.so ]; then
@ -96,6 +104,11 @@ function get_otool_path() {
get_realpath $1 | sed 's|^.*/bazel-out/|bazel-out/|'
}
function call_install_name() {
/usr/bin/xcrun install_name_tool -change $(get_otool_path "$1") \
"@loader_path/$2/$3" "${OUTPUT}"
}
# Do replacements in the output
for rpath in ${RPATHS}; do
for lib in ${LIBS}; do
@ -110,10 +123,16 @@ for rpath in ${RPATHS}; do
if [[ -n "${libname-}" ]]; then
libpath=$(get_library_path ${lib})
if [ -n "${libpath}" ]; then
${INSTALL_NAME_TOOL} -change $(get_otool_path "${libpath}") \
"@loader_path/${rpath}/${libname}" "${OUTPUT}"
call_install_name "${libpath}" "${rpath}" "${libname}"
fi
fi
done
for libpath in ${LIB_PATHS}; do
if [ -f "$libpath" ]; then
libname=$(basename "$libpath")
if [ -f "$(dirname ${OUTPUT})/${rpath}/${libname}" ]; then
call_install_name "${libpath}" "${rpath}" "${libname}"
fi
fi
done
done

View File

@ -20,6 +20,7 @@ load(
"auto_configure_warning",
"auto_configure_warning_maybe",
"escape_string",
"execute",
"get_env_var",
"get_starlark_list",
"resolve_labels",
@ -34,16 +35,19 @@ def _uniq(iterable):
unique_elements = {element: None for element in iterable}
return unique_elements.keys()
def _generate_system_module_map(repository_ctx, dirs, script_path):
return execute(repository_ctx, [script_path] + dirs)
def _prepare_include_path(repo_ctx, path):
"""Resolve and sanitize include path before outputting it into the crosstool.
"""Resolve include path before outputting it into the crosstool.
Args:
repo_ctx: repository_ctx object.
path: an include path to be sanitized.
path: an include path to be resolved.
Returns:
Sanitized include path that can be written to the crosstoot. Resulting path
is absolute if it is outside the repository and relative otherwise.
Resolved include path. Resulting path is absolute if it is outside the
repository and relative otherwise.
"""
repo_root = str(repo_ctx.path("."))
@ -52,22 +56,24 @@ def _prepare_include_path(repo_ctx, path):
repo_root += "/"
path = str(repo_ctx.path(path))
if path.startswith(repo_root):
return escape_string(path[len(repo_root):])
return escape_string(path)
return path[len(repo_root):]
return path
def _find_tool(repository_ctx, tool, overriden_tools):
"""Find a tool for repository, taking overriden tools into account."""
if tool in overriden_tools:
return overriden_tools[tool]
def _find_tool(repository_ctx, tool, overridden_tools):
"""Find a tool for repository, taking overridden tools into account."""
if tool in overridden_tools:
return overridden_tools[tool]
return which(repository_ctx, tool, "/usr/bin/" + tool)
def _get_tool_paths(repository_ctx, overriden_tools):
def _get_tool_paths(repository_ctx, overridden_tools):
"""Compute the %-escaped path to the various tools"""
return dict({
k: escape_string(_find_tool(repository_ctx, k, overriden_tools))
k: escape_string(_find_tool(repository_ctx, k, overridden_tools))
for k in [
"ar",
"ld",
"llvm-cov",
"llvm-profdata",
"cpp",
"gcc",
"dwp",
@ -76,6 +82,7 @@ def _get_tool_paths(repository_ctx, overriden_tools):
"objcopy",
"objdump",
"strip",
"c++filt",
]
}.items())
@ -103,17 +110,8 @@ def _cxx_inc_convert(path):
path = path[:-_OSX_FRAMEWORK_SUFFIX_LEN].strip()
return path
def get_escaped_cxx_inc_directories(repository_ctx, cc, lang_flag, additional_flags = []):
"""Compute the list of default %-escaped C++ include directories.
Args:
repository_ctx: The repository context.
cc: path to the C compiler.
lang_flag: value for the language flag (c, c++).
additional_flags: additional flags to pass to cc.
Returns:
a list of escaped system include directories.
"""
def _get_cxx_include_directories(repository_ctx, print_resource_dir_supported, cc, lang_flag, additional_flags = []):
"""Compute the list of C++ include directories."""
result = repository_ctx.execute([cc, "-E", lang_flag, "-", "-v"] + additional_flags)
index1 = result.stderr.find(_INC_DIR_MARKER_BEGIN)
if index1 == -1:
@ -135,9 +133,9 @@ def get_escaped_cxx_inc_directories(repository_ctx, cc, lang_flag, additional_fl
for p in inc_dirs.split("\n")
]
if _is_compiler_option_supported(repository_ctx, cc, "-print-resource-dir"):
if print_resource_dir_supported:
resource_dir = repository_ctx.execute(
[cc, "-print-resource-dir"],
[cc, "-print-resource-dir"] + additional_flags,
).stdout.strip() + "/share"
inc_directories.append(_prepare_include_path(repository_ctx, resource_dir))
@ -155,10 +153,9 @@ def _is_compiler_option_supported(repository_ctx, cc, option):
])
return result.stderr.find(option) == -1
def _is_linker_option_supported(repository_ctx, cc, option, pattern):
def _is_linker_option_supported(repository_ctx, cc, force_linker_flags, option, pattern):
"""Checks that `option` is supported by the C linker. Doesn't %-escape the option."""
result = repository_ctx.execute([
cc,
result = repository_ctx.execute([cc] + force_linker_flags + [
option,
"-o",
"/dev/null",
@ -166,63 +163,50 @@ def _is_linker_option_supported(repository_ctx, cc, option, pattern):
])
return result.stderr.find(pattern) == -1
def _find_gold_linker_path(repository_ctx, cc):
"""Checks if `gold` is supported by the C compiler.
def _find_linker_path(repository_ctx, cc, linker, is_clang):
"""Checks if a given linker is supported by the C compiler.
Args:
repository_ctx: repository_ctx.
cc: path to the C compiler.
linker: linker to find
is_clang: whether the compiler is known to be clang
Returns:
String to put as value to -fuse-ld= flag, or None if gold couldn't be found.
String to put as value to -fuse-ld= flag, or None if linker couldn't be found.
"""
result = repository_ctx.execute([
cc,
str(repository_ctx.path("tools/cpp/empty.cc")),
"-o",
"/dev/null",
# Some macos clang versions don't fail when setting -fuse-ld=gold, adding
# Some macOS clang versions don't fail when setting -fuse-ld=gold, adding
# these lines to force it to. This also means that we will not detect
# gold when only a very old (year 2010 and older) is present.
"-Wl,--start-lib",
"-Wl,--end-lib",
"-fuse-ld=gold",
"-fuse-ld=" + linker,
"-v",
])
if result.return_code != 0:
return None
for line in result.stderr.splitlines():
if line.find("gold") == -1:
continue
for flag in line.split(" "):
if flag.find("gold") == -1:
continue
if flag.find("--enable-gold") > -1 or flag.find("--with-plugin-ld") > -1:
# skip build configuration options of gcc itself
# TODO(hlopko): Add redhat-like worker on the CI (#9392)
continue
if not is_clang:
return linker
# flag is '-fuse-ld=gold' for GCC or "/usr/lib/ld.gold" for Clang
# strip space, single quote, and double quotes
flag = flag.strip(" \"'")
# remove -fuse-ld= from GCC output so we have only the flag value part
flag = flag.replace("-fuse-ld=", "")
return flag
auto_configure_warning(
"CC with -fuse-ld=gold returned 0, but its -v output " +
"didn't contain 'gold', falling back to the default linker.",
)
return None
# Extract linker path from:
# /usr/bin/clang ...
# "/usr/bin/ld.lld" -pie -z ...
linker_command = result.stderr.splitlines()[-1]
return linker_command.strip().split(" ")[0].strip("\"'")
def _add_compiler_option_if_supported(repository_ctx, cc, option):
"""Returns `[option]` if supported, `[]` otherwise. Doesn't %-escape the option."""
return [option] if _is_compiler_option_supported(repository_ctx, cc, option) else []
def _add_linker_option_if_supported(repository_ctx, cc, option, pattern):
def _add_linker_option_if_supported(repository_ctx, cc, force_linker_flags, option, pattern):
"""Returns `[option]` if supported, `[]` otherwise. Doesn't %-escape the option."""
return [option] if _is_linker_option_supported(repository_ctx, cc, option, pattern) else []
return [option] if _is_linker_option_supported(repository_ctx, cc, force_linker_flags, option, pattern) else []
def _get_no_canonical_prefixes_opt(repository_ctx, cc):
# If the compiler sometimes rewrites paths in the .d files without symlinks
@ -280,11 +264,27 @@ def _coverage_flags(repository_ctx, darwin):
link_flags = '"--coverage"'
return compile_flags, link_flags
def _find_generic(repository_ctx, name, env_name, overriden_tools, warn = False, silent = False):
def _is_clang(repository_ctx, cc):
return "clang" in repository_ctx.execute([cc, "-v"]).stderr
def _is_gcc(repository_ctx, cc):
# GCC's version output uses the basename of argv[0] as the program name:
# https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=gcc/gcc.cc;h=158461167951c1b9540322fb19be6a89d6da07fc;hb=HEAD#l8728
cc_stdout = repository_ctx.execute([cc, "--version"]).stdout
return cc_stdout.startswith("gcc ") or cc_stdout.startswith("gcc-")
def _get_compiler_name(repository_ctx, cc):
if _is_clang(repository_ctx, cc):
return "clang"
if _is_gcc(repository_ctx, cc):
return "gcc"
return "compiler"
def _find_generic(repository_ctx, name, env_name, overridden_tools, warn = False, silent = False):
"""Find a generic C++ toolchain tool. Doesn't %-escape the result."""
if name in overriden_tools:
return overriden_tools[name]
if name in overridden_tools:
return overridden_tools[name]
result = name
env_value = repository_ctx.os.environ.get(env_name)
@ -295,7 +295,7 @@ def _find_generic(repository_ctx, name, env_name, overriden_tools, warn = False,
result = env_value
env_value_with_paren = " (%s)" % env_value
if result.startswith("/"):
# Absolute path, maybe we should make this suported by our which function.
# Absolute path, maybe we should make this supported by our which function.
return result
result = repository_ctx.which(result)
if result == None:
@ -308,23 +308,44 @@ def _find_generic(repository_ctx, name, env_name, overriden_tools, warn = False,
auto_configure_fail(msg)
return result
def find_cc(repository_ctx, overriden_tools):
return _find_generic(repository_ctx, "gcc", "CC", overriden_tools)
def configure_unix_toolchain(repository_ctx, cpu_value, overriden_tools):
"""Configure C++ toolchain on Unix platforms.
def find_cc(repository_ctx, overridden_tools):
"""Find the C compiler (gcc or clang) for the repository, considering overridden tools.
Args:
repository_ctx: The repository context.
cpu_value: current cpu name.
overriden_tools: overriden tools.
overridden_tools: A dictionary of overridden tools.
Returns:
The path to the C compiler.
"""
cc = _find_generic(repository_ctx, "gcc", "CC", overridden_tools)
if _is_clang(repository_ctx, cc):
# If clang is run through a symlink with -no-canonical-prefixes, it does
# not find its own include directory, which includes the headers for
# libc++. Resolving the potential symlink here prevents this.
result = repository_ctx.execute(["readlink", "-f", cc])
if result.return_code == 0:
return result.stdout.strip()
return cc
def configure_unix_toolchain(repository_ctx, cpu_value, overridden_tools):
"""Configure C++ toolchain on Unix platforms.
Args:
repository_ctx: The repository context.
cpu_value: The CPU value.
overridden_tools: A dictionary of overridden tools.
"""
paths = resolve_labels(repository_ctx, [
"@rules_cc//cc/private/toolchain:BUILD.tpl",
"@rules_cc//cc/private/toolchain:generate_system_module_map.sh",
"@rules_cc//cc/private/toolchain:armeabi_cc_toolchain_config.bzl",
"@rules_cc//cc/private/toolchain:unix_cc_toolchain_config.bzl",
"@rules_cc//cc/private/toolchain:linux_cc_wrapper.sh.tpl",
"@rules_cc//cc/private/toolchain:validate_static_library.sh.tpl",
"@rules_cc//cc/private/toolchain:osx_cc_wrapper.sh.tpl",
"@rules_cc//cc/private/toolchain:clang_deps_scanner_wrapper.sh.tpl",
"@rules_cc//cc/private/toolchain:gcc_deps_scanner_wrapper.sh.tpl",
])
repository_ctx.symlink(
@ -338,24 +359,56 @@ def configure_unix_toolchain(repository_ctx, cpu_value, overriden_tools):
)
repository_ctx.file("tools/cpp/empty.cc", "int main() {}")
darwin = cpu_value == "darwin"
darwin = cpu_value.startswith("darwin")
bsd = cpu_value == "freebsd" or cpu_value == "openbsd"
cc = _find_generic(repository_ctx, "gcc", "CC", overriden_tools)
overriden_tools = dict(overriden_tools)
overriden_tools["gcc"] = cc
overriden_tools["gcov"] = _find_generic(
cc = find_cc(repository_ctx, overridden_tools)
is_clang = _is_clang(repository_ctx, cc)
overridden_tools = dict(overridden_tools)
overridden_tools["gcc"] = cc
overridden_tools["gcov"] = _find_generic(
repository_ctx,
"gcov",
"GCOV",
overriden_tools,
overridden_tools,
warn = True,
silent = True,
)
overridden_tools["llvm-cov"] = _find_generic(
repository_ctx,
"llvm-cov",
"BAZEL_LLVM_COV",
overridden_tools,
warn = True,
silent = True,
)
overridden_tools["llvm-profdata"] = _find_generic(
repository_ctx,
"llvm-profdata",
"BAZEL_LLVM_PROFDATA",
overridden_tools,
warn = True,
silent = True,
)
overridden_tools["ar"] = _find_generic(
repository_ctx,
"ar",
"AR",
overridden_tools,
warn = True,
silent = True,
)
if darwin:
overriden_tools["gcc"] = "cc_wrapper.sh"
overriden_tools["ar"] = "/usr/bin/libtool"
overridden_tools["gcc"] = "cc_wrapper.sh"
overridden_tools["ar"] = _find_generic(repository_ctx, "libtool", "LIBTOOL", overridden_tools)
auto_configure_warning_maybe(repository_ctx, "CC used: " + str(cc))
tool_paths = _get_tool_paths(repository_ctx, overriden_tools)
tool_paths = _get_tool_paths(repository_ctx, overridden_tools)
tool_paths["cpp-module-deps-scanner"] = "deps_scanner_wrapper.sh"
# The parse_header tool needs to be a wrapper around the compiler as it has
# to touch the output file.
tool_paths["parse_headers"] = "cc_wrapper.sh"
cc_toolchain_identifier = escape_string(get_env_var(
repository_ctx,
"CC_TOOLCHAIN_NAME",
@ -363,6 +416,19 @@ def configure_unix_toolchain(repository_ctx, cpu_value, overriden_tools):
False,
))
if "nm" in tool_paths and "c++filt" in tool_paths:
repository_ctx.template(
"validate_static_library.sh",
paths["@rules_cc//cc/private/toolchain:validate_static_library.sh.tpl"],
{
"%{c++filt}": escape_string(str(repository_ctx.path(tool_paths["c++filt"]))),
# Certain weak symbols are otherwise listed with type T in the output of nm on macOS.
"%{nm_extra_args}": "--no-weak" if darwin else "",
"%{nm}": escape_string(str(repository_ctx.path(tool_paths["nm"]))),
},
)
tool_paths["validate_static_library"] = "validate_static_library.sh"
cc_wrapper_src = (
"@rules_cc//cc/private/toolchain:osx_cc_wrapper.sh.tpl" if darwin else "@rules_cc//cc/private/toolchain:linux_cc_wrapper.sh.tpl"
)
@ -374,16 +440,94 @@ def configure_unix_toolchain(repository_ctx, cpu_value, overriden_tools):
"%{env}": escape_string(get_env(repository_ctx)),
},
)
deps_scanner_wrapper_src = (
"@rules_cc//cc/private/toolchain:clang_deps_scanner_wrapper.sh.tpl" if is_clang else "@rules_cc//cc/private/toolchain:gcc_deps_scanner_wrapper.sh.tpl"
)
deps_scanner = "cpp-module-deps-scanner_not_found"
if is_clang:
cc_str = str(cc)
path_arr = cc_str.split("/")[:-1]
path_arr.append("clang-scan-deps")
deps_scanner = "/".join(path_arr)
repository_ctx.template(
"deps_scanner_wrapper.sh",
paths[deps_scanner_wrapper_src],
{
"%{cc}": escape_string(str(cc)),
"%{deps_scanner}": escape_string(deps_scanner),
"%{env}": escape_string(get_env(repository_ctx)),
},
)
conly_opts = split_escaped(get_env_var(
repository_ctx,
"BAZEL_CONLYOPTS",
"",
False,
), ":")
cxx_opts = split_escaped(get_env_var(
repository_ctx,
"BAZEL_CXXOPTS",
"-std=c++0x",
"-std=c++17",
False,
), ":")
bazel_linklibs = "-lstdc++:-lm"
gold_or_lld_linker_path = (
_find_linker_path(repository_ctx, cc, "lld", is_clang) or
_find_linker_path(repository_ctx, cc, "gold", is_clang)
)
cc_path = repository_ctx.path(cc)
if not str(cc_path).startswith(str(repository_ctx.path(".")) + "/"):
# cc is outside the repository, set -B
bin_search_flags = ["-B" + escape_string(str(cc_path.dirname))]
else:
# cc is inside the repository, don't set -B.
bin_search_flags = []
if not gold_or_lld_linker_path:
ld_path = repository_ctx.path(tool_paths["ld"])
if ld_path.dirname != cc_path.dirname:
bin_search_flags.append("-B" + str(ld_path.dirname))
force_linker_flags = []
if gold_or_lld_linker_path:
force_linker_flags.append("-fuse-ld=" + gold_or_lld_linker_path)
# TODO: It's unclear why these flags aren't added on macOS.
if bin_search_flags and not darwin:
force_linker_flags.extend(bin_search_flags)
use_libcpp = darwin or bsd
is_as_needed_supported = _is_linker_option_supported(
repository_ctx,
cc,
force_linker_flags,
"-Wl,-no-as-needed",
"-no-as-needed",
)
is_push_state_supported = _is_linker_option_supported(
repository_ctx,
cc,
force_linker_flags,
"-Wl,--push-state",
"--push-state",
)
if use_libcpp:
bazel_default_libs = ["-lc++", "-lm"]
else:
bazel_default_libs = ["-lstdc++", "-lm"]
if is_as_needed_supported and is_push_state_supported:
# Do not link against C++ standard libraries unless they are actually
# used.
# We assume that --push-state support implies --pop-state support.
bazel_linklibs_elements = [
arg
for lib in bazel_default_libs
for arg in ["-Wl,--push-state,-as-needed", lib, "-Wl,--pop-state"]
]
else:
bazel_linklibs_elements = bazel_default_libs
bazel_linklibs = ":".join(bazel_linklibs_elements)
bazel_linkopts = ""
link_opts = split_escaped(get_env_var(
repository_ctx,
"BAZEL_LINKOPTS",
@ -396,33 +540,73 @@ def configure_unix_toolchain(repository_ctx, cpu_value, overriden_tools):
bazel_linklibs,
False,
), ":")
gold_linker_path = _find_gold_linker_path(repository_ctx, cc)
cc_path = repository_ctx.path(cc)
if not str(cc_path).startswith(str(repository_ctx.path(".")) + "/"):
# cc is outside the repository, set -B
bin_search_flag = ["-B" + escape_string(str(cc_path.dirname))]
else:
# cc is inside the repository, don't set -B.
bin_search_flag = []
coverage_compile_flags, coverage_link_flags = _coverage_flags(repository_ctx, darwin)
print_resource_dir_supported = _is_compiler_option_supported(
repository_ctx,
cc,
"-print-resource-dir",
)
no_canonical_prefixes_opt = _get_no_canonical_prefixes_opt(repository_ctx, cc)
builtin_include_directories = _uniq(
get_escaped_cxx_inc_directories(repository_ctx, cc, "-xc") +
get_escaped_cxx_inc_directories(repository_ctx, cc, "-xc++", cxx_opts) +
get_escaped_cxx_inc_directories(
repository_ctx,
cc,
"-xc",
_get_no_canonical_prefixes_opt(repository_ctx, cc),
) +
get_escaped_cxx_inc_directories(
_get_cxx_include_directories(repository_ctx, print_resource_dir_supported, cc, "-xc", conly_opts) +
_get_cxx_include_directories(repository_ctx, print_resource_dir_supported, cc, "-xc++", cxx_opts) +
_get_cxx_include_directories(
repository_ctx,
print_resource_dir_supported,
cc,
"-xc++",
cxx_opts + _get_no_canonical_prefixes_opt(repository_ctx, cc),
),
cxx_opts + ["-stdlib=libc++"],
) +
_get_cxx_include_directories(
repository_ctx,
print_resource_dir_supported,
cc,
"-xc",
no_canonical_prefixes_opt,
) +
_get_cxx_include_directories(
repository_ctx,
print_resource_dir_supported,
cc,
"-xc++",
cxx_opts + no_canonical_prefixes_opt,
) +
_get_cxx_include_directories(
repository_ctx,
print_resource_dir_supported,
cc,
"-xc++",
cxx_opts + no_canonical_prefixes_opt + ["-stdlib=libc++"],
) +
# Always included in case the user has Xcode + the CLT installed, both
# paths can be used interchangeably
["/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk"],
)
generate_modulemap = is_clang
if generate_modulemap:
repository_ctx.file("module.modulemap", _generate_system_module_map(
repository_ctx,
builtin_include_directories,
paths["@rules_cc//cc/private/toolchain:generate_system_module_map.sh"],
))
extra_flags_per_feature = {}
if is_clang:
# Only supported by LLVM 14 and later, but required with C++20 and
# layering_check as C++ modules are the default.
# https://github.com/llvm/llvm-project/commit/0556138624edf48621dd49a463dbe12e7101f17d
result = repository_ctx.execute([
cc,
"-Xclang",
"-fno-cxx-modules",
"-o",
"/dev/null",
"-c",
str(repository_ctx.path("tools/cpp/empty.cc")),
])
if "-fno-cxx-modules" not in result.stderr:
extra_flags_per_feature["use_module_maps"] = ["-Xclang", "-fno-cxx-modules"]
write_builtin_include_directory_paths(repository_ctx, cc, builtin_include_directories)
repository_ctx.template(
"BUILD",
@ -440,23 +624,24 @@ def configure_unix_toolchain(repository_ctx, cpu_value, overriden_tools):
"local",
False,
)),
"%{cc_compiler_deps}": get_starlark_list([":builtin_include_directory_paths"] + (
[":cc_wrapper"] if darwin else []
"%{cc_compiler_deps}": get_starlark_list([
":builtin_include_directory_paths",
":cc_wrapper",
":deps_scanner_wrapper",
] + (
[":validate_static_library"] if "validate_static_library" in tool_paths else []
)),
"%{cc_toolchain_identifier}": cc_toolchain_identifier,
"%{compile_flags}": get_starlark_list(
[
# Security hardening requires optimization.
# We need to undef it as some distributions now have it enabled by default.
"-U_FORTIFY_SOURCE",
"-fstack-protector",
# All warnings are enabled. Maybe enable -Werror as well?
# All warnings are enabled.
"-Wall",
# Enable a few more warnings that aren't part of -Wall.
] + (
] + ((
_add_compiler_option_if_supported(repository_ctx, cc, "-Wthread-safety") +
_add_compiler_option_if_supported(repository_ctx, cc, "-Wself-assign")
) + (
)) + (
# Disable problematic warnings.
_add_compiler_option_if_supported(repository_ctx, cc, "-Wunused-but-set-parameter") +
# has false positives
@ -472,38 +657,34 @@ def configure_unix_toolchain(repository_ctx, cpu_value, overriden_tools):
"%{compiler}": escape_string(get_env_var(
repository_ctx,
"BAZEL_COMPILER",
"compiler",
_get_compiler_name(repository_ctx, cc),
False,
)),
"%{conly_flags}": get_starlark_list(conly_opts),
"%{coverage_compile_flags}": coverage_compile_flags,
"%{coverage_link_flags}": coverage_link_flags,
"%{cxx_builtin_include_directories}": get_starlark_list(builtin_include_directories),
"%{cxx_flags}": get_starlark_list(cxx_opts + _escaped_cplus_include_paths(repository_ctx)),
"%{dbg_compile_flags}": get_starlark_list(["-g"]),
"%{extra_flags_per_feature}": repr(extra_flags_per_feature),
"%{host_system_name}": escape_string(get_env_var(
repository_ctx,
"BAZEL_HOST_SYSTEM",
"local",
False,
)),
"%{link_flags}": get_starlark_list((
["-fuse-ld=" + gold_linker_path] if gold_linker_path else []
) + _add_linker_option_if_supported(
repository_ctx,
cc,
"-Wl,-no-as-needed",
"-no-as-needed",
"%{link_flags}": get_starlark_list(force_linker_flags + (
["-Wl,-no-as-needed"] if is_as_needed_supported else []
) + _add_linker_option_if_supported(
repository_ctx,
cc,
force_linker_flags,
"-Wl,-z,relro,-z,now",
"-z",
) + (
[
"-undefined",
"dynamic_lookup",
"-headerpad_max_install_names",
] if darwin else bin_search_flag + [
] if darwin else [
# Gold linker only? Can we enable this by default?
# "-Wl,--warn-execstack",
# "-Wl,--detect-odr-violations"
@ -515,6 +696,7 @@ def configure_unix_toolchain(repository_ctx, cpu_value, overriden_tools):
)
) + link_opts),
"%{link_libs}": get_starlark_list(link_libs),
"%{modulemap}": ("\":module.modulemap\"" if generate_modulemap else "None"),
"%{name}": cpu_value,
"%{opt_compile_flags}": get_starlark_list(
[
@ -543,15 +725,15 @@ def configure_unix_toolchain(repository_ctx, cpu_value, overriden_tools):
],
),
"%{opt_link_flags}": get_starlark_list(
[] if darwin else _add_linker_option_if_supported(
["-Wl,-dead_strip"] if darwin else _add_linker_option_if_supported(
repository_ctx,
cc,
force_linker_flags,
"-Wl,--gc-sections",
"-gc-sections",
),
),
"%{supports_param_files}": "0" if darwin else "1",
"%{supports_start_end_lib}": "True" if gold_linker_path else "False",
"%{supports_start_end_lib}": "True" if gold_or_lld_linker_path else "False",
"%{target_cpu}": escape_string(get_env_var(
repository_ctx,
"BAZEL_TARGET_CPU",
@ -571,7 +753,7 @@ def configure_unix_toolchain(repository_ctx, cpu_value, overriden_tools):
False,
)),
"%{tool_paths}": ",\n ".join(
['"%s": "%s"' % (k, v) for k, v in tool_paths.items()],
['"%s": "%s"' % (k, v) for k, v in tool_paths.items() if v != None],
),
"%{unfiltered_compile_flags}": get_starlark_list(
_get_no_canonical_prefixes_opt(repository_ctx, cc) + [

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,44 @@
#!/usr/bin/env bash
#
# Copyright 2023 The Bazel 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.
set -euo pipefail
# Find all duplicate symbols in the given static library:
# 1. Use nm to list all global symbols in the library in POSIX format:
# libstatic.a[my_object.o]: my_function T 1234 abcd
# 2. Use sed to transform the output to a format that can be sorted by symbol
# name and is readable by humans:
# my_object.o: T my_function
# By using the `t` and `d` commands, lines for symbols of type U (undefined)
# as well as V and W (weak) and their local lowercase variants are removed.
# 3. Use sort to sort the lines by symbol name.
# 4. Use uniq to only keep the lines corresponding to duplicate symbols.
# 5. Use c++filt to demangle the symbol names.
# c++filt is applied to the duplicated symbols instead of using the -C flag
# of nm because it is not in POSIX and demangled names may not be unique
# (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=35201).
DUPLICATE_SYMBOLS=$(
"%{nm}" -A -g -P %{nm_extra_args} "$1" |
sed -E -e 's/.*\[([^][]+)\]: (.+) ([A-TX-Z]) [a-f0-9]+ [a-f0-9]+/\1: \3 \2/g' -e t -e d |
LC_ALL=C sort -k 3 |
LC_ALL=C uniq -D -f 2 |
"%{c++filt}")
if [[ -n "$DUPLICATE_SYMBOLS" ]]; then
>&2 echo "Duplicate symbols found in $1:"
>&2 echo "$DUPLICATE_SYMBOLS"
exit 1
else
touch "$2"
fi

View File

@ -18,7 +18,7 @@ echo. 1>&2
echo The target you are compiling requires Visual C++ build tools. 1>&2
echo Bazel couldn't find a valid Visual C++ build tools installation on your machine. 1>&2
%{vc_error_message}
echo Please check your installation following https://docs.bazel.build/versions/main/windows.html#using 1>&2
echo Please check your installation following https://bazel.build/docs/windows#using 1>&2
echo. 1>&2
exit /b 1

View File

@ -25,12 +25,35 @@ load(
"write_builtin_include_directory_paths",
)
_targets_archs = {"arm": "amd64_arm", "arm64": "amd64_arm64", "x64": "amd64", "x86": "amd64_x86"}
_targets_lib_folder = {"arm": "arm", "arm64": "arm64", "x86": ""}
def _lookup_env_var(env, name, default = None):
"""Lookup environment variable case-insensitve.
If a matching (case-insensitive) entry is found in the env dict both
the key and the value are returned. The returned key might differ from
name in casing.
If a matching key was found its value is returned otherwise
the default is returned.
Return a (key, value) tuple"""
for key, value in env.items():
if name.lower() == key.lower():
return (key, value)
return (name, default)
def _get_env_var(repository_ctx, name, default = None):
"""Returns a value from an environment variable."""
return _lookup_env_var(repository_ctx.os.environ, name, default)[1]
def _get_path_env_var(repository_ctx, name):
"""Returns a path from an environment variable.
Removes quotes, replaces '/' with '\', and strips trailing '\'s."""
if name in repository_ctx.os.environ:
value = repository_ctx.os.environ[name]
value = _get_env_var(repository_ctx, name)
if value != None:
if value[0] == "\"":
if len(value) == 1 or value[-1] != "\"":
auto_configure_fail("'%s' environment variable has no trailing quote" % name)
@ -39,9 +62,7 @@ def _get_path_env_var(repository_ctx, name):
value = value.replace("/", "\\")
if value[-1] == "\\":
value = value.rstrip("\\")
return value
else:
return None
return value
def _get_temp_env(repository_ctx):
"""Returns the value of TMP, or TEMP, or if both undefined then C:\\Windows."""
@ -72,7 +93,7 @@ def _get_escaped_windows_msys_starlark_content(repository_ctx, use_mingw = False
tool_bin_path = tool_path_prefix + "/bin"
tool_path = {}
for tool in ["ar", "compat-ld", "cpp", "dwp", "gcc", "gcov", "ld", "nm", "objcopy", "objdump", "strip"]:
for tool in ["ar", "cpp", "dwp", "gcc", "gcov", "ld", "nm", "objcopy", "objdump", "strip"]:
if msys_root:
tool_path[tool] = tool_bin_path + "/" + tool
else:
@ -94,13 +115,19 @@ def _get_system_root(repository_ctx):
def _add_system_root(repository_ctx, env):
"""Running VCVARSALL.BAT and VCVARSQUERYREGISTRY.BAT need %SYSTEMROOT%\\\\system32 in PATH."""
if "PATH" not in env:
env["PATH"] = ""
env["PATH"] = env["PATH"] + ";" + _get_system_root(repository_ctx) + "\\system32"
env_key, env_value = _lookup_env_var(env, "PATH", default = "")
env[env_key] = env_value + ";" + _get_system_root(repository_ctx) + "\\system32"
return env
def _find_vc_path(repository_ctx):
"""Find Visual C++ build tools install path. Doesn't %-escape the result."""
def find_vc_path(repository_ctx):
"""Find Visual C++ build tools install path. Doesn't %-escape the result.
Args:
repository_ctx: The repository context.
Returns:
The path to the Visual C++ build tools installation.
"""
# 1. Check if BAZEL_VC or BAZEL_VS is already set by user.
bazel_vc = _get_path_env_var(repository_ctx, "BAZEL_VC")
@ -136,7 +163,27 @@ def _find_vc_path(repository_ctx):
" installed.",
)
# 2. Check if VS%VS_VERSION%COMNTOOLS is set, if true then try to find and use
# 2. Use vswhere to locate all Visual Studio installations
program_files_dir = _get_path_env_var(repository_ctx, "PROGRAMFILES(X86)")
if not program_files_dir:
program_files_dir = "C:\\Program Files (x86)"
auto_configure_warning_maybe(
repository_ctx,
"'PROGRAMFILES(X86)' environment variable is not set, using '%s' as default" % program_files_dir,
)
vswhere_binary = program_files_dir + "\\Microsoft Visual Studio\\Installer\\vswhere.exe"
if repository_ctx.path(vswhere_binary).exists:
result = repository_ctx.execute([vswhere_binary, "-requires", "Microsoft.VisualStudio.Component.VC.Tools.x86.x64", "-property", "installationPath", "-latest"])
auto_configure_warning_maybe(repository_ctx, "vswhere query result:\n\nSTDOUT(start)\n%s\nSTDOUT(end)\nSTDERR(start):\n%s\nSTDERR(end)\n" %
(result.stdout, result.stderr))
installation_path = result.stdout.strip()
if not result.stderr and installation_path:
vc_dir = installation_path + "\\VC"
auto_configure_warning_maybe(repository_ctx, "Visual C++ build tools found at %s" % vc_dir)
return vc_dir
# 3. Check if VS%VS_VERSION%COMNTOOLS is set, if true then try to find and use
# vcvarsqueryregistry.bat / VsDevCmd.bat to detect VC++.
auto_configure_warning_maybe(repository_ctx, "Looking for VS%VERSION%COMNTOOLS environment variables, " +
"eg. VS140COMNTOOLS")
@ -149,15 +196,16 @@ def _find_vc_path(repository_ctx):
("VS100COMNTOOLS", "vcvarsqueryregistry.bat"),
("VS90COMNTOOLS", "vcvarsqueryregistry.bat"),
]:
if vscommontools_env not in repository_ctx.os.environ:
path = _get_path_env_var(repository_ctx, vscommontools_env)
if path == None:
continue
script = _get_path_env_var(repository_ctx, vscommontools_env) + "\\" + script
script = path + "\\" + script
if not repository_ctx.path(script).exists:
continue
repository_ctx.file(
"get_vc_dir.bat",
"@echo off\n" +
"call \"" + script + "\"\n" +
"call \"" + script + "\" > NUL\n" +
"echo %VCINSTALLDIR%",
True,
)
@ -167,9 +215,8 @@ def _find_vc_path(repository_ctx):
auto_configure_warning_maybe(repository_ctx, "Visual C++ build tools found at %s" % vc_dir)
return vc_dir
# 3. User might have purged all environment variables. If so, look for Visual C++ in registry.
# 4. User might have purged all environment variables. If so, look for Visual C++ in registry.
# Works for Visual Studio 2017 and older. (Does not work for Visual Studio 2019 Preview.)
# TODO(laszlocsomor): check if "16.0" also has this registry key, after VS 2019 is released.
auto_configure_warning_maybe(repository_ctx, "Looking for Visual C++ through registry")
reg_binary = _get_system_root(repository_ctx) + "\\system32\\reg.exe"
vc_dir = None
@ -189,25 +236,13 @@ def _find_vc_path(repository_ctx):
auto_configure_warning_maybe(repository_ctx, "Visual C++ build tools found at %s" % vc_dir)
return vc_dir
# 4. Check default directories for VC installation
# 5. Check default directories for VC installation
auto_configure_warning_maybe(repository_ctx, "Looking for default Visual C++ installation directory")
program_files_dir = _get_path_env_var(repository_ctx, "PROGRAMFILES(X86)")
if not program_files_dir:
program_files_dir = "C:\\Program Files (x86)"
auto_configure_warning_maybe(
repository_ctx,
"'PROGRAMFILES(X86)' environment variable is not set, using '%s' as default" % program_files_dir,
)
for path in [
"Microsoft Visual Studio\\2019\\Preview\\VC",
"Microsoft Visual Studio\\2019\\BuildTools\\VC",
"Microsoft Visual Studio\\2019\\Community\\VC",
"Microsoft Visual Studio\\2019\\Professional\\VC",
"Microsoft Visual Studio\\2019\\Enterprise\\VC",
"Microsoft Visual Studio\\2017\\BuildTools\\VC",
"Microsoft Visual Studio\\2017\\Community\\VC",
"Microsoft Visual Studio\\2017\\Professional\\VC",
"Microsoft Visual Studio\\2017\\Enterprise\\VC",
"Microsoft Visual Studio\\%s\\%s\\VC" % (year, edition)
for year in (2022, 2019, 2017)
for edition in ("Preview", "BuildTools", "Community", "Professional", "Enterprise")
] + [
"Microsoft Visual Studio 14.0\\VC",
]:
path = program_files_dir + "\\" + path
@ -221,18 +256,22 @@ def _find_vc_path(repository_ctx):
auto_configure_warning_maybe(repository_ctx, "Visual C++ build tools found at %s" % vc_dir)
return vc_dir
def _is_vs_2017_or_2019(vc_path):
"""Check if the installed VS version is Visual Studio 2017."""
def _is_vs_2017_or_newer(repository_ctx, vc_path):
"""Check if the installed VS version is Visual Studio 2017 or newer."""
# In VS 2017 and 2019, the location of VC is like:
# C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\
# In VS 2015 or older version, it is like:
# C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\
return vc_path.find("2017") != -1 or vc_path.find("2019") != -1
# For VS 2017 and later, a `Tools` directory should exist under `BAZEL_VC`
return repository_ctx.path(vc_path).get_child("Tools").exists
def _is_msbuildtools(vc_path):
"""Check if the installed VC version is from MSBuildTools."""
# In MSBuildTools (usually container setup), the location of VC is like:
# C:\BuildTools\MSBuild\Microsoft\VC
return vc_path.find("BuildTools") != -1 and vc_path.find("MSBuild") != -1
def _find_vcvars_bat_script(repository_ctx, vc_path):
"""Find batch script to set up environment variables for VC. Doesn't %-escape the result."""
if _is_vs_2017_or_2019(vc_path):
if _is_vs_2017_or_newer(repository_ctx, vc_path):
vcvars_script = vc_path + "\\Auxiliary\\Build\\VCVARSALL.BAT"
else:
vcvars_script = vc_path + "\\VCVARSALL.BAT"
@ -250,17 +289,49 @@ def _is_support_vcvars_ver(vc_full_version):
def _is_support_winsdk_selection(repository_ctx, vc_path):
"""Windows SDK selection is supported with VC 2017 / 2019 or with full VS 2015 installation."""
if _is_vs_2017_or_2019(vc_path):
if _is_vs_2017_or_newer(repository_ctx, vc_path):
return True
# By checking the source code of VCVARSALL.BAT in VC 2015, we know that
# when devenv.exe or wdexpress.exe exists, VCVARSALL.BAT supports Windows SDK selection.
vc_common_ide = repository_ctx.path(vc_path).dirname.get_child("Common7").get_child("IDE")
vc_common_ide = repository_ctx.path(vc_path).dirname.get_child("Common7", "IDE")
for tool in ["devenv.exe", "wdexpress.exe"]:
if vc_common_ide.get_child(tool).exists:
return True
return False
def _get_vc_env_vars(repository_ctx, vc_path, msvc_vars_x64, target_arch):
"""Derive the environment variables set of a given target architecture from the environment variables of the x64 target.
This is done to avoid running VCVARSALL.BAT script for every target architecture.
Args:
repository_ctx: the repository_ctx object
vc_path: Visual C++ root directory
msvc_vars_x64: values of MSVC toolchain including the environment variables for x64 target architecture
target_arch: the target architecture to get its environment variables
Returns:
dictionary of envvars
"""
env = {}
if _is_vs_2017_or_newer(repository_ctx, vc_path):
lib = msvc_vars_x64["%{msvc_env_lib_x64}"]
full_version = _get_vc_full_version(repository_ctx, vc_path)
tools_path = "%s\\Tools\\MSVC\\%s\\bin\\HostX64\\%s" % (vc_path, full_version, target_arch)
# For native windows(10) on arm64 builds host toolchain runs in an emulated x86 environment
if not repository_ctx.path(tools_path).exists:
tools_path = "%s\\Tools\\MSVC\\%s\\bin\\HostX86\\%s" % (vc_path, full_version, target_arch)
else:
lib = msvc_vars_x64["%{msvc_env_lib_x64}"].replace("amd64", _targets_lib_folder[target_arch])
tools_path = vc_path + "\\bin\\" + _targets_archs[target_arch]
env["INCLUDE"] = msvc_vars_x64["%{msvc_env_include_x64}"]
env["LIB"] = lib.replace("x64", target_arch)
env["PATH"] = escape_string(tools_path.replace("\\", "\\\\")) + ";" + msvc_vars_x64["%{msvc_env_path_x64}"]
return env
def setup_vc_env_vars(repository_ctx, vc_path, envvars = [], allow_empty = False, escape = True):
"""Get environment variables set by VCVARSALL.BAT script. Doesn't %-escape the result!
@ -292,7 +363,7 @@ def setup_vc_env_vars(repository_ctx, vc_path, envvars = [], allow_empty = False
# Get VC version set by user. Only supports VC 2017 & 2019.
vcvars_ver = ""
if _is_vs_2017_or_2019(vc_path):
if _is_vs_2017_or_newer(repository_ctx, vc_path):
full_version = _get_vc_full_version(repository_ctx, vc_path)
# Because VCVARSALL.BAT is from the latest VC installed, so we check if the latest
@ -314,6 +385,7 @@ def setup_vc_env_vars(repository_ctx, vc_path, envvars = [], allow_empty = False
for env in envs:
key, value = env.split("=", 1)
env_map[key] = escape_string(value.replace("\\", "\\\\")) if escape else value
if not allow_empty:
_check_env_vars(env_map, cmd, expected = envvars)
return env_map
@ -347,48 +419,84 @@ def _get_latest_subversion(repository_ctx, vc_path):
version_list = sorted(version_list)
latest_version = version_list[-1][1]
auto_configure_warning_maybe(repository_ctx, "Found the following VC verisons:\n%s\n\nChoosing the latest version = %s" % ("\n".join(versions), latest_version))
auto_configure_warning_maybe(repository_ctx, "Found the following VC versions:\n%s\n\nChoosing the latest version = %s" % ("\n".join(versions), latest_version))
return latest_version
def _get_vc_full_version(repository_ctx, vc_path):
"""Return the value of BAZEL_VC_FULL_VERSION if defined, otherwise the latest version."""
if "BAZEL_VC_FULL_VERSION" in repository_ctx.os.environ:
return repository_ctx.os.environ["BAZEL_VC_FULL_VERSION"]
version = _get_env_var(repository_ctx, "BAZEL_VC_FULL_VERSION")
if version != None:
return version
return _get_latest_subversion(repository_ctx, vc_path)
def _get_winsdk_full_version(repository_ctx):
"""Return the value of BAZEL_WINSDK_FULL_VERSION if defined, otherwise an empty string."""
return repository_ctx.os.environ.get("BAZEL_WINSDK_FULL_VERSION", default = "")
return _get_env_var(repository_ctx, "BAZEL_WINSDK_FULL_VERSION", default = "")
def _find_msvc_tool(repository_ctx, vc_path, tool):
"""Find the exact path of a specific build tool in MSVC. Doesn't %-escape the result."""
def _find_msvc_tools(repository_ctx, vc_path, target_arch = "x64"):
"""Find the exact paths of the build tools in MSVC for the given target. Doesn't %-escape the result."""
build_tools_paths = {}
tools = _get_target_tools(target_arch)
for tool_name in tools:
build_tools_paths[tool_name] = find_msvc_tool(repository_ctx, vc_path, tools[tool_name], target_arch)
return build_tools_paths
def find_msvc_tool(repository_ctx, vc_path, tool, target_arch = "x64"):
"""Find the exact path of a specific build tool in MSVC. Doesn't %-escape the result.
Args:
repository_ctx: The repository context.
vc_path: Visual C++ root directory.
tool: The name of the tool to find.
target_arch: The target architecture (default is "x64").
Returns:
The exact path of the specified build tool in MSVC, or None if not found.
"""
tool_path = None
if _is_vs_2017_or_2019(vc_path):
if _is_vs_2017_or_newer(repository_ctx, vc_path) or _is_msbuildtools(vc_path):
full_version = _get_vc_full_version(repository_ctx, vc_path)
if full_version:
tool_path = "%s\\Tools\\MSVC\\%s\\bin\\HostX64\\x64\\%s" % (vc_path, full_version, tool)
tool_path = "%s\\Tools\\MSVC\\%s\\bin\\HostX64\\%s\\%s" % (vc_path, full_version, target_arch, tool)
# For native windows(10) on arm64 builds host toolchain runs in an emulated x86 environment
if not repository_ctx.path(tool_path).exists:
tool_path = "%s\\Tools\\MSVC\\%s\\bin\\HostX86\\%s\\%s" % (vc_path, full_version, target_arch, tool)
else:
# For VS 2015 and older version, the tools are under:
# C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64
tool_path = vc_path + "\\bin\\amd64\\" + tool
tool_path = vc_path + "\\bin\\" + _targets_archs[target_arch] + "\\" + tool
if not tool_path or not repository_ctx.path(tool_path).exists:
return None
return tool_path.replace("\\", "/")
def _find_missing_vc_tools(repository_ctx, vc_path):
"""Check if any required tool is missing under given VC path."""
def _find_missing_vc_tools(repository_ctx, vc_path, target_arch = "x64"):
"""Check if any required tool for the given target architecture is missing under given VC path."""
missing_tools = []
if not _find_vcvars_bat_script(repository_ctx, vc_path):
missing_tools.append("VCVARSALL.BAT")
for tool in ["cl.exe", "link.exe", "lib.exe", "ml64.exe"]:
if not _find_msvc_tool(repository_ctx, vc_path, tool):
missing_tools.append(tool)
tools = _get_target_tools(target_arch)
for tool_name in tools:
if not find_msvc_tool(repository_ctx, vc_path, tools[tool_name], target_arch):
missing_tools.append(tools[tool_name])
return missing_tools
def _get_target_tools(target):
"""Return a list of required tools names and their filenames for a certain target."""
tools = {
"arm": {"CL": "cl.exe", "DUMPBIN": "dumpbin.exe", "LIB": "lib.exe", "LINK": "link.exe"},
"arm64": {"CL": "cl.exe", "DUMPBIN": "dumpbin.exe", "LIB": "lib.exe", "LINK": "link.exe"},
"x64": {"CL": "cl.exe", "DUMPBIN": "dumpbin.exe", "LIB": "lib.exe", "LINK": "link.exe", "ML": "ml64.exe"},
"x86": {"CL": "cl.exe", "DUMPBIN": "dumpbin.exe", "LIB": "lib.exe", "LINK": "link.exe", "ML": "ml.exe"},
}
if tools.get(target) == None:
auto_configure_fail("Target architecture %s is not recognized" % target)
return tools.get(target)
def _is_support_debug_fastlink(repository_ctx, linker):
"""Run linker alone to see if it supports /DEBUG:FASTLINK."""
if _use_clang_cl(repository_ctx):
@ -397,8 +505,37 @@ def _is_support_debug_fastlink(repository_ctx, linker):
result = execute(repository_ctx, [linker], expect_failure = True)
return result.find("/DEBUG[:{FASTLINK|FULL|NONE}]") != -1
def _find_llvm_path(repository_ctx):
"""Find LLVM install path."""
def _is_support_parse_showincludes(repository_ctx, cl, env):
repository_ctx.file(
"main.cpp",
"#include \"bazel_showincludes.h\"\nint main(){}\n",
)
repository_ctx.file(
"bazel_showincludes.h",
"\n",
)
result = execute(
repository_ctx,
[cl, "/nologo", "/showIncludes", "/c", "main.cpp", "/out", "main.exe", "/Fo", "main.obj"],
# Attempt to force English language. This may fail if the language pack isn't installed.
environment = env | {"VSLANG": "1033"},
)
for file in ["main.cpp", "bazel_showincludes.h", "main.exe", "main.obj"]:
execute(repository_ctx, ["cmd", "/C", "del", file], expect_empty_output = True)
return any([
line.startswith("Note: including file:") and line.endswith("bazel_showincludes.h")
for line in result.split("\n")
])
def find_llvm_path(repository_ctx):
"""Find LLVM install path.
Args:
repository_ctx: The repository context.
Returns:
The path to the LLVM installation, or None if not found.
"""
# 1. Check if BAZEL_LLVM is already set by user.
bazel_llvm = _get_path_env_var(repository_ctx, "BAZEL_LLVM")
@ -443,8 +580,17 @@ def _find_llvm_path(repository_ctx):
auto_configure_warning_maybe(repository_ctx, "LLVM installation found at %s" % llvm_dir)
return llvm_dir
def _find_llvm_tool(repository_ctx, llvm_path, tool):
"""Find the exact path of a specific build tool in LLVM. Doesn't %-escape the result."""
def find_llvm_tool(repository_ctx, llvm_path, tool):
"""Find the exact path of a specific build tool in LLVM. Doesn't %-escape the result.
Args:
repository_ctx: The repository context.
llvm_path: The path to the LLVM installation.
tool: The name of the tool to find.
Returns:
The exact path of the specified build tool in LLVM, or None if not found.
"""
tool_path = llvm_path + "\\bin\\" + tool
if not repository_ctx.path(tool_path).exists:
@ -454,24 +600,37 @@ def _find_llvm_tool(repository_ctx, llvm_path, tool):
def _use_clang_cl(repository_ctx):
"""Returns True if USE_CLANG_CL is set to 1."""
return repository_ctx.os.environ.get("USE_CLANG_CL", default = "0") == "1"
return _get_env_var(repository_ctx, "USE_CLANG_CL", default = "0") == "1"
def _find_missing_llvm_tools(repository_ctx, llvm_path):
"""Check if any required tool is missing under given LLVM path."""
missing_tools = []
for tool in ["clang-cl.exe", "lld-link.exe", "llvm-lib.exe"]:
if not _find_llvm_tool(repository_ctx, llvm_path, tool):
if not find_llvm_tool(repository_ctx, llvm_path, tool):
missing_tools.append(tool)
return missing_tools
def _get_clang_version(repository_ctx, clang_cl):
result = repository_ctx.execute([clang_cl, "-v"])
if result.return_code != 0:
auto_configure_fail("Failed to get clang version by running \"%s -v\"" % clang_cl)
first_line = result.stderr.strip().splitlines()[0].strip()
# Stderr should look like "clang version X.X.X ..."
return result.stderr.splitlines()[0].split(" ")[2]
# The first line of stderr should look like "[vendor ]clang version X.X.X"
if result.return_code != 0 or first_line.find("clang version ") == -1:
auto_configure_fail("Failed to get clang version by running \"%s -v\"" % clang_cl)
return first_line.split(" ")[-1]
def _get_clang_dir(repository_ctx, llvm_path, clang_version):
"""Get the clang installation directory."""
# The clang_version string format is "X.X.X"
clang_dir = llvm_path + "\\lib\\clang\\" + clang_version
if repository_ctx.path(clang_dir).exists:
return clang_dir
# Clang 16 changed the install path to use just the major number.
clang_major_version = clang_version.split(".")[0]
return llvm_path + "\\lib\\clang\\" + clang_major_version
def _get_msys_mingw_vars(repository_ctx):
"""Get the variables we need to populate the msys/mingw toolchains."""
@ -488,29 +647,31 @@ def _get_msys_mingw_vars(repository_ctx):
}
return msys_mingw_vars
def _get_msvc_vars(repository_ctx, paths):
def _get_msvc_vars(repository_ctx, paths, target_arch = "x64", msvc_vars_x64 = None):
"""Get the variables we need to populate the MSVC toolchains."""
msvc_vars = dict()
vc_path = _find_vc_path(repository_ctx)
vc_path = find_vc_path(repository_ctx)
missing_tools = None
if not vc_path:
repository_ctx.template(
"vc_installation_error.bat",
"vc_installation_error_" + target_arch + ".bat",
paths["@rules_cc//cc/private/toolchain:vc_installation_error.bat.tpl"],
{"%{vc_error_message}": ""},
)
else:
missing_tools = _find_missing_vc_tools(repository_ctx, vc_path)
missing_tools = _find_missing_vc_tools(repository_ctx, vc_path, target_arch)
if missing_tools:
message = "\r\n".join([
"echo. 1>&2",
"echo Visual C++ build tools seems to be installed at %s 1>&2" % vc_path,
"echo But Bazel can't find the following tools: 1>&2",
"echo %s 1>&2" % ", ".join(missing_tools),
"echo for %s target architecture 1>&2" % target_arch,
"echo. 1>&2",
])
repository_ctx.template(
"vc_installation_error.bat",
"vc_installation_error_" + target_arch + ".bat",
paths["@rules_cc//cc/private/toolchain:vc_installation_error.bat.tpl"],
{"%{vc_error_message}": message},
)
@ -518,82 +679,92 @@ def _get_msvc_vars(repository_ctx, paths):
if not vc_path or missing_tools:
write_builtin_include_directory_paths(repository_ctx, "msvc", [], file_suffix = "_msvc")
msvc_vars = {
"%{dbg_mode_debug_flag}": "/DEBUG",
"%{fastbuild_mode_debug_flag}": "/DEBUG",
"%{msvc_cl_path}": "vc_installation_error.bat",
"%{msvc_cxx_builtin_include_directories}": "",
"%{msvc_env_include}": "msvc_not_found",
"%{msvc_env_lib}": "msvc_not_found",
"%{msvc_env_path}": "msvc_not_found",
"%{msvc_env_tmp}": "msvc_not_found",
"%{msvc_lib_path}": "vc_installation_error.bat",
"%{msvc_link_path}": "vc_installation_error.bat",
"%{msvc_ml_path}": "vc_installation_error.bat",
"%{msvc_env_tmp_" + target_arch + "}": "msvc_not_found",
"%{msvc_env_include_" + target_arch + "}": "msvc_not_found",
"%{msvc_cxx_builtin_include_directories_" + target_arch + "}": "",
"%{msvc_env_path_" + target_arch + "}": "msvc_not_found",
"%{msvc_env_lib_" + target_arch + "}": "msvc_not_found",
"%{msvc_cl_path_" + target_arch + "}": "vc_installation_error_" + target_arch + ".bat",
"%{msvc_ml_path_" + target_arch + "}": "vc_installation_error_" + target_arch + ".bat",
"%{msvc_link_path_" + target_arch + "}": "vc_installation_error_" + target_arch + ".bat",
"%{msvc_lib_path_" + target_arch + "}": "vc_installation_error_" + target_arch + ".bat",
"%{dbg_mode_debug_flag_" + target_arch + "}": "/DEBUG",
"%{fastbuild_mode_debug_flag_" + target_arch + "}": "/DEBUG",
"%{msvc_parse_showincludes_" + target_arch + "}": repr(False),
}
return msvc_vars
env = setup_vc_env_vars(repository_ctx, vc_path)
escaped_paths = escape_string(env["PATH"])
escaped_include_paths = escape_string(env["INCLUDE"])
escaped_lib_paths = escape_string(env["LIB"])
if msvc_vars_x64:
env = _get_vc_env_vars(repository_ctx, vc_path, msvc_vars_x64, target_arch)
else:
env = setup_vc_env_vars(repository_ctx, vc_path)
escaped_tmp_dir = escape_string(_get_temp_env(repository_ctx).replace("\\", "\\\\"))
escaped_include_paths = escape_string(env["INCLUDE"])
build_tools = {}
llvm_path = ""
if _use_clang_cl(repository_ctx):
llvm_path = _find_llvm_path(repository_ctx)
llvm_path = find_llvm_path(repository_ctx)
if not llvm_path:
auto_configure_fail("\nUSE_CLANG_CL is set to 1, but Bazel cannot find Clang installation on your system.\n" +
"Please install Clang via http://releases.llvm.org/download.html\n")
cl_path = _find_llvm_tool(repository_ctx, llvm_path, "clang-cl.exe")
link_path = _find_llvm_tool(repository_ctx, llvm_path, "lld-link.exe")
if not link_path:
link_path = _find_msvc_tool(repository_ctx, vc_path, "link.exe")
lib_path = _find_llvm_tool(repository_ctx, llvm_path, "llvm-lib.exe")
if not lib_path:
lib_path = _find_msvc_tool(repository_ctx, vc_path, "lib.exe")
build_tools["CL"] = find_llvm_tool(repository_ctx, llvm_path, "clang-cl.exe")
build_tools["ML"] = find_msvc_tool(repository_ctx, vc_path, "ml64.exe", "x64")
build_tools["LINK"] = find_llvm_tool(repository_ctx, llvm_path, "lld-link.exe")
if not build_tools["LINK"]:
build_tools["LINK"] = find_msvc_tool(repository_ctx, vc_path, "link.exe", "x64")
build_tools["LIB"] = find_llvm_tool(repository_ctx, llvm_path, "llvm-lib.exe")
if not build_tools["LIB"]:
build_tools["LIB"] = find_msvc_tool(repository_ctx, vc_path, "lib.exe", "x64")
else:
cl_path = _find_msvc_tool(repository_ctx, vc_path, "cl.exe")
link_path = _find_msvc_tool(repository_ctx, vc_path, "link.exe")
lib_path = _find_msvc_tool(repository_ctx, vc_path, "lib.exe")
build_tools = _find_msvc_tools(repository_ctx, vc_path, target_arch)
msvc_ml_path = _find_msvc_tool(repository_ctx, vc_path, "ml64.exe")
escaped_cxx_include_directories = []
for path in escaped_include_paths.split(";"):
if path:
escaped_cxx_include_directories.append("\"%s\"" % path)
if llvm_path:
clang_version = _get_clang_version(repository_ctx, cl_path)
clang_dir = llvm_path + "\\lib\\clang\\" + clang_version
clang_version = _get_clang_version(repository_ctx, build_tools["CL"])
clang_dir = _get_clang_dir(repository_ctx, llvm_path, clang_version)
clang_include_path = (clang_dir + "\\include").replace("\\", "\\\\")
escaped_cxx_include_directories.append("\"%s\"" % clang_include_path)
clang_lib_path = (clang_dir + "\\lib\\windows").replace("\\", "\\\\")
escaped_lib_paths = escaped_lib_paths + ";" + clang_lib_path
support_debug_fastlink = _is_support_debug_fastlink(repository_ctx, link_path)
env["LIB"] = escape_string(env["LIB"]) + ";" + clang_lib_path
support_debug_fastlink = _is_support_debug_fastlink(repository_ctx, build_tools["LINK"])
write_builtin_include_directory_paths(repository_ctx, "msvc", escaped_cxx_include_directories, file_suffix = "_msvc")
support_parse_showincludes = _is_support_parse_showincludes(repository_ctx, build_tools["CL"], env)
if not support_parse_showincludes:
auto_configure_warning("""
Header pruning has been disabled since Bazel failed to recognize the output of /showIncludes.
This can result in unnecessary recompilation.
Fix this by installing the English language pack for the Visual Studio installation at {} and run 'bazel sync --configure'.""".format(vc_path))
msvc_vars = {
"%{dbg_mode_debug_flag}": "/DEBUG:FULL" if support_debug_fastlink else "/DEBUG",
"%{fastbuild_mode_debug_flag}": "/DEBUG:FASTLINK" if support_debug_fastlink else "/DEBUG",
"%{msvc_cl_path}": cl_path,
"%{msvc_cxx_builtin_include_directories}": " " + ",\n ".join(escaped_cxx_include_directories),
"%{msvc_env_include}": escaped_include_paths,
"%{msvc_env_lib}": escaped_lib_paths,
"%{msvc_env_path}": escaped_paths,
"%{msvc_env_tmp}": escaped_tmp_dir,
"%{msvc_lib_path}": lib_path,
"%{msvc_link_path}": link_path,
"%{msvc_ml_path}": msvc_ml_path,
"%{msvc_env_tmp_" + target_arch + "}": escaped_tmp_dir,
"%{msvc_env_include_" + target_arch + "}": escaped_include_paths,
"%{msvc_cxx_builtin_include_directories_" + target_arch + "}": " " + ",\n ".join(escaped_cxx_include_directories),
"%{msvc_env_path_" + target_arch + "}": escape_string(env["PATH"]),
"%{msvc_env_lib_" + target_arch + "}": escape_string(env["LIB"]),
"%{msvc_cl_path_" + target_arch + "}": build_tools["CL"],
"%{msvc_ml_path_" + target_arch + "}": build_tools.get("ML", "msvc_arm_toolchain_does_not_support_ml"),
"%{msvc_link_path_" + target_arch + "}": build_tools["LINK"],
"%{msvc_lib_path_" + target_arch + "}": build_tools["LIB"],
"%{msvc_dumpbin_path_" + target_arch + "}": build_tools["DUMPBIN"],
"%{msvc_parse_showincludes_" + target_arch + "}": repr(support_parse_showincludes),
"%{dbg_mode_debug_flag_" + target_arch + "}": "/DEBUG:FULL" if support_debug_fastlink else "/DEBUG",
"%{fastbuild_mode_debug_flag_" + target_arch + "}": "/DEBUG:FASTLINK" if support_debug_fastlink else "/DEBUG",
}
return msvc_vars
def _get_clang_cl_vars(repository_ctx, paths, msvc_vars):
def _get_clang_cl_vars(repository_ctx, paths, msvc_vars, target_arch):
"""Get the variables we need to populate the clang-cl toolchains."""
llvm_path = _find_llvm_path(repository_ctx)
llvm_path = find_llvm_path(repository_ctx)
error_script = None
if msvc_vars["%{msvc_cl_path}"] == "vc_installation_error.bat":
error_script = "vc_installation_error.bat"
if msvc_vars["%{msvc_cl_path_" + target_arch + "}"] == "vc_installation_error_{}.bat".format(target_arch):
error_script = "vc_installation_error_{}.bat".format(target_arch)
elif not llvm_path:
repository_ctx.template(
"clang_installation_error.bat",
@ -621,52 +792,69 @@ def _get_clang_cl_vars(repository_ctx, paths, msvc_vars):
if error_script:
write_builtin_include_directory_paths(repository_ctx, "clang-cl", [], file_suffix = "_clangcl")
clang_cl_vars = {
"%{clang_cl_cl_path}": error_script,
"%{clang_cl_cxx_builtin_include_directories}": "",
"%{clang_cl_dbg_mode_debug_flag}": "/DEBUG",
"%{clang_cl_env_include}": "clang_cl_not_found",
"%{clang_cl_env_lib}": "clang_cl_not_found",
"%{clang_cl_env_path}": "clang_cl_not_found",
"%{clang_cl_env_tmp}": "clang_cl_not_found",
"%{clang_cl_fastbuild_mode_debug_flag}": "/DEBUG",
"%{clang_cl_lib_path}": error_script,
"%{clang_cl_link_path}": error_script,
"%{clang_cl_ml_path}": error_script,
"%{clang_cl_env_tmp_" + target_arch + "}": "clang_cl_not_found",
"%{clang_cl_env_path_" + target_arch + "}": "clang_cl_not_found",
"%{clang_cl_env_include_" + target_arch + "}": "clang_cl_not_found",
"%{clang_cl_env_lib_" + target_arch + "}": "clang_cl_not_found",
"%{clang_cl_cl_path_" + target_arch + "}": error_script,
"%{clang_cl_link_path_" + target_arch + "}": error_script,
"%{clang_cl_lib_path_" + target_arch + "}": error_script,
"%{clang_cl_ml_path_" + target_arch + "}": error_script,
"%{clang_cl_dbg_mode_debug_flag_" + target_arch + "}": "/DEBUG",
"%{clang_cl_fastbuild_mode_debug_flag_" + target_arch + "}": "/DEBUG",
"%{clang_cl_cxx_builtin_include_directories_" + target_arch + "}": "",
"%{clang_cl_parse_showincludes_" + target_arch + "}": repr(False),
}
return clang_cl_vars
clang_cl_path = _find_llvm_tool(repository_ctx, llvm_path, "clang-cl.exe")
lld_link_path = _find_llvm_tool(repository_ctx, llvm_path, "lld-link.exe")
llvm_lib_path = _find_llvm_tool(repository_ctx, llvm_path, "llvm-lib.exe")
clang_cl_path = find_llvm_tool(repository_ctx, llvm_path, "clang-cl.exe")
lld_link_path = find_llvm_tool(repository_ctx, llvm_path, "lld-link.exe")
llvm_lib_path = find_llvm_tool(repository_ctx, llvm_path, "llvm-lib.exe")
clang_version = _get_clang_version(repository_ctx, clang_cl_path)
clang_dir = llvm_path + "\\lib\\clang\\" + clang_version
clang_dir = _get_clang_dir(repository_ctx, llvm_path, clang_version)
clang_include_path = (clang_dir + "\\include").replace("\\", "\\\\")
clang_lib_path = (clang_dir + "\\lib\\windows").replace("\\", "\\\\")
clang_cl_include_directories = msvc_vars["%{msvc_cxx_builtin_include_directories}"] + (",\n \"%s\"" % clang_include_path)
clang_cl_include_directories = msvc_vars["%{msvc_cxx_builtin_include_directories_" + target_arch + "}"] + (",\n \"%s\"" % clang_include_path)
write_builtin_include_directory_paths(repository_ctx, "clang-cl", [clang_cl_include_directories], file_suffix = "_clangcl")
clang_cl_vars = {
"%{clang_cl_cl_path}": clang_cl_path,
"%{clang_cl_cxx_builtin_include_directories}": clang_cl_include_directories,
"%{clang_cl_env_tmp_" + target_arch + "}": msvc_vars["%{msvc_env_tmp_" + target_arch + "}"],
"%{clang_cl_env_path_" + target_arch + "}": msvc_vars["%{msvc_env_path_" + target_arch + "}"],
"%{clang_cl_env_include_" + target_arch + "}": msvc_vars["%{msvc_env_include_" + target_arch + "}"] + ";" + clang_include_path,
"%{clang_cl_env_lib_" + target_arch + "}": msvc_vars["%{msvc_env_lib_" + target_arch + "}"] + ";" + clang_lib_path,
"%{clang_cl_cxx_builtin_include_directories_" + target_arch + "}": clang_cl_include_directories,
"%{clang_cl_cl_path_" + target_arch + "}": clang_cl_path,
"%{clang_cl_link_path_" + target_arch + "}": lld_link_path,
"%{clang_cl_lib_path_" + target_arch + "}": llvm_lib_path,
# clang-cl does not support assembly files as input.
"%{clang_cl_ml_path_" + target_arch + "}": msvc_vars["%{msvc_ml_path_" + target_arch + "}"],
# LLVM's lld-link.exe doesn't support /DEBUG:FASTLINK.
"%{clang_cl_dbg_mode_debug_flag}": "/DEBUG",
"%{clang_cl_env_include}": msvc_vars["%{msvc_env_include}"] + ";" + clang_include_path,
"%{clang_cl_env_lib}": msvc_vars["%{msvc_env_lib}"] + ";" + clang_lib_path,
"%{clang_cl_env_path}": msvc_vars["%{msvc_env_path}"],
"%{clang_cl_env_tmp}": msvc_vars["%{msvc_env_tmp}"],
"%{clang_cl_fastbuild_mode_debug_flag}": "/DEBUG",
"%{clang_cl_lib_path}": llvm_lib_path,
"%{clang_cl_link_path}": lld_link_path,
"%{clang_cl_ml_path}": msvc_vars["%{msvc_ml_path}"],
"%{clang_cl_dbg_mode_debug_flag_" + target_arch + "}": "/DEBUG",
"%{clang_cl_fastbuild_mode_debug_flag_" + target_arch + "}": "/DEBUG",
# clang-cl always emits the English language version of the /showIncludes prefix.
"%{clang_cl_parse_showincludes_" + target_arch + "}": repr(True),
}
return clang_cl_vars
def _get_msvc_deps_scanner_vars(repository_ctx, paths, template_vars, target_arch = "x64"):
repository_ctx.template(
"msvc_deps_scanner_wrapper_" + target_arch + ".bat",
paths["@rules_cc//cc/private/toolchain:msvc_deps_scanner_wrapper.bat.tpl"],
{
"%{cc}": template_vars["%{msvc_cl_path_" + target_arch + "}"],
},
)
return {
"%{msvc_deps_scanner_wrapper_path_" + target_arch + "}": "msvc_deps_scanner_wrapper_" + target_arch + ".bat",
}
def configure_windows_toolchain(repository_ctx):
"""Configure C++ toolchain on Windows.
Args:
repository_ctx: The repository context.
repository_ctx: The repository context.
"""
paths = resolve_labels(repository_ctx, [
"@rules_cc//cc/private/toolchain:BUILD.windows.tpl",
@ -675,6 +863,7 @@ def configure_windows_toolchain(repository_ctx):
"@rules_cc//cc/private/toolchain:vc_installation_error.bat.tpl",
"@rules_cc//cc/private/toolchain:msys_gcc_installation_error.bat",
"@rules_cc//cc/private/toolchain:clang_installation_error.bat.tpl",
"@rules_cc//cc/private/toolchain:msvc_deps_scanner_wrapper.bat.tpl",
])
repository_ctx.symlink(
@ -691,11 +880,20 @@ def configure_windows_toolchain(repository_ctx):
)
template_vars = dict()
msvc_vars = _get_msvc_vars(repository_ctx, paths)
template_vars.update(msvc_vars)
template_vars.update(_get_clang_cl_vars(repository_ctx, paths, msvc_vars))
msvc_vars_x64 = _get_msvc_vars(repository_ctx, paths, "x64")
template_vars.update(msvc_vars_x64)
template_vars.update(_get_clang_cl_vars(repository_ctx, paths, msvc_vars_x64, "x64"))
template_vars.update(_get_msys_mingw_vars(repository_ctx))
template_vars.update(_get_msvc_vars(repository_ctx, paths, "x86", msvc_vars_x64))
template_vars.update(_get_msvc_vars(repository_ctx, paths, "arm", msvc_vars_x64))
msvc_vars_arm64 = _get_msvc_vars(repository_ctx, paths, "arm64", msvc_vars_x64)
template_vars.update(msvc_vars_arm64)
template_vars.update(_get_clang_cl_vars(repository_ctx, paths, msvc_vars_arm64, "arm64"))
template_vars.update(_get_msvc_deps_scanner_vars(repository_ctx, paths, template_vars, "x64"))
template_vars.update(_get_msvc_deps_scanner_vars(repository_ctx, paths, template_vars, "x86"))
template_vars.update(_get_msvc_deps_scanner_vars(repository_ctx, paths, template_vars, "arm"))
template_vars.update(_get_msvc_deps_scanner_vars(repository_ctx, paths, template_vars, "arm64"))
repository_ctx.template(
"BUILD",
paths["@rules_cc//cc/private/toolchain:BUILD.windows.tpl"],

View File

@ -22,9 +22,9 @@ load(
"env_entry",
"env_set",
"feature",
"feature_set",
"flag_group",
"flag_set",
"make_variable",
"tool",
"tool_path",
"variable_with_value",
@ -40,6 +40,9 @@ all_compile_actions = [
ACTION_NAMES.cpp_header_parsing,
ACTION_NAMES.cpp_module_compile,
ACTION_NAMES.cpp_module_codegen,
ACTION_NAMES.cpp_module_deps_scanning,
ACTION_NAMES.cpp20_module_compile,
ACTION_NAMES.cpp20_module_codegen,
ACTION_NAMES.clif_match,
ACTION_NAMES.lto_backend,
]
@ -50,6 +53,9 @@ all_cpp_compile_actions = [
ACTION_NAMES.cpp_header_parsing,
ACTION_NAMES.cpp_module_compile,
ACTION_NAMES.cpp_module_codegen,
ACTION_NAMES.cpp_module_deps_scanning,
ACTION_NAMES.cpp20_module_compile,
ACTION_NAMES.cpp20_module_codegen,
ACTION_NAMES.clif_match,
]
@ -60,6 +66,8 @@ preprocessor_compile_actions = [
ACTION_NAMES.preprocess_assemble,
ACTION_NAMES.cpp_header_parsing,
ACTION_NAMES.cpp_module_compile,
ACTION_NAMES.cpp_module_deps_scanning,
ACTION_NAMES.cpp20_module_compile,
ACTION_NAMES.clif_match,
]
@ -70,6 +78,7 @@ codegen_compile_actions = [
ACTION_NAMES.assemble,
ACTION_NAMES.preprocess_assemble,
ACTION_NAMES.cpp_module_codegen,
ACTION_NAMES.cpp20_module_codegen,
ACTION_NAMES.lto_backend,
]
@ -80,7 +89,7 @@ all_link_actions = [
]
def _use_msvc_toolchain(ctx):
return ctx.attr.cpu == "x64_windows" and (ctx.attr.compiler == "msvc-cl" or ctx.attr.compiler == "clang-cl")
return ctx.attr.cpu in ["x64_windows", "arm64_windows"] and (ctx.attr.compiler == "msvc-cl" or ctx.attr.compiler == "clang-cl")
def _impl(ctx):
if _use_msvc_toolchain(ctx):
@ -135,7 +144,6 @@ def _impl(ctx):
"output_execpath_flags",
"input_param_flags",
"user_link_flags",
"default_link_flags",
"linker_subsystem_flag",
"linker_param_file",
"msvc_env",
@ -184,13 +192,25 @@ def _impl(ctx):
c_compile_action = action_config(
action_name = ACTION_NAMES.c_compile,
implies = [
"compiler_input_flags",
"compiler_output_flags",
"nologo",
"msvc_env",
"user_compile_flags",
"sysroot",
],
tools = [tool(path = ctx.attr.msvc_cl_path)],
)
linkstamp_compile_action = action_config(
action_name = ACTION_NAMES.linkstamp_compile,
implies = [
"compiler_input_flags",
"compiler_output_flags",
"default_compile_flags",
"nologo",
"msvc_env",
"parse_showincludes",
"user_compile_flags",
"sysroot",
"unfiltered_compile_flags",
@ -203,13 +223,10 @@ def _impl(ctx):
implies = [
"compiler_input_flags",
"compiler_output_flags",
"default_compile_flags",
"nologo",
"msvc_env",
"parse_showincludes",
"user_compile_flags",
"sysroot",
"unfiltered_compile_flags",
],
tools = [tool(path = ctx.attr.msvc_cl_path)],
)
@ -222,7 +239,6 @@ def _impl(ctx):
"output_execpath_flags",
"input_param_flags",
"user_link_flags",
"default_link_flags",
"linker_subsystem_flag",
"linker_param_file",
"msvc_env",
@ -240,7 +256,6 @@ def _impl(ctx):
"output_execpath_flags",
"input_param_flags",
"user_link_flags",
"default_link_flags",
"linker_subsystem_flag",
"linker_param_file",
"msvc_env",
@ -251,15 +266,84 @@ def _impl(ctx):
tools = [tool(path = ctx.attr.msvc_link_path)],
)
deps_scanner = "cpp-module-deps-scanner_not_found"
if "cpp-module-deps-scanner" in ctx.attr.tool_paths:
deps_scanner = ctx.attr.tool_paths["cpp-module-deps-scanner"]
cpp_module_scan_deps = action_config(
action_name = ACTION_NAMES.cpp_module_deps_scanning,
tools = [
tool(
path = deps_scanner,
),
],
implies = [
"compiler_input_flags",
"compiler_output_flags",
"nologo",
"msvc_env",
"user_compile_flags",
"sysroot",
],
)
cpp20_module_compile = action_config(
action_name = ACTION_NAMES.cpp20_module_compile,
tools = [
tool(
path = ctx.attr.msvc_cl_path,
),
],
flag_sets = [
flag_set(
flag_groups = [
flag_group(
flags = [
"/TP",
"/interface",
],
),
],
),
],
implies = [
"compiler_input_flags",
"compiler_output_flags",
"nologo",
"msvc_env",
"user_compile_flags",
"sysroot",
],
)
cpp20_module_codegen = action_config(
action_name = ACTION_NAMES.cpp20_module_codegen,
tools = [
tool(
path = ctx.attr.msvc_cl_path,
),
],
implies = [
"compiler_input_flags",
"compiler_output_flags",
"nologo",
"msvc_env",
"user_compile_flags",
"sysroot",
],
)
action_configs = [
assemble_action,
preprocess_assemble_action,
c_compile_action,
linkstamp_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,
cpp_module_scan_deps,
cpp20_module_compile,
cpp20_module_codegen,
]
else:
action_configs = []
@ -317,10 +401,14 @@ def _impl(ctx):
ACTION_NAMES.assemble,
ACTION_NAMES.preprocess_assemble,
ACTION_NAMES.c_compile,
ACTION_NAMES.linkstamp_compile,
ACTION_NAMES.cpp_compile,
ACTION_NAMES.cpp_header_parsing,
ACTION_NAMES.cpp_module_compile,
ACTION_NAMES.cpp_module_codegen,
ACTION_NAMES.cpp_module_deps_scanning,
ACTION_NAMES.cpp20_module_compile,
ACTION_NAMES.cpp20_module_codegen,
ACTION_NAMES.cpp_link_executable,
ACTION_NAMES.cpp_link_dynamic_library,
ACTION_NAMES.cpp_link_nodeps_dynamic_library,
@ -338,15 +426,20 @@ def _impl(ctx):
unfiltered_compile_flags_feature = feature(
name = "unfiltered_compile_flags",
enabled = True,
flag_sets = [
flag_set(
actions = [
ACTION_NAMES.preprocess_assemble,
ACTION_NAMES.c_compile,
ACTION_NAMES.linkstamp_compile,
ACTION_NAMES.cpp_compile,
ACTION_NAMES.cpp_header_parsing,
ACTION_NAMES.cpp_module_compile,
ACTION_NAMES.cpp_module_codegen,
ACTION_NAMES.cpp_module_deps_scanning,
ACTION_NAMES.cpp20_module_compile,
ACTION_NAMES.cpp20_module_codegen,
],
flag_groups = [
flag_group(
@ -359,8 +452,14 @@ def _impl(ctx):
],
)
archive_param_file_feature = feature(
name = "archive_param_file",
enabled = True,
)
compiler_param_file_feature = feature(
name = "compiler_param_file",
enabled = True,
)
copy_dynamic_libraries_to_binary_feature = feature(
@ -471,10 +570,14 @@ def _impl(ctx):
actions = [
ACTION_NAMES.preprocess_assemble,
ACTION_NAMES.c_compile,
ACTION_NAMES.linkstamp_compile,
ACTION_NAMES.cpp_compile,
ACTION_NAMES.cpp_header_parsing,
ACTION_NAMES.cpp_module_compile,
ACTION_NAMES.cpp_module_codegen,
ACTION_NAMES.cpp_module_deps_scanning,
ACTION_NAMES.cpp20_module_compile,
ACTION_NAMES.cpp20_module_codegen,
],
flag_groups = [
flag_group(
@ -498,7 +601,12 @@ def _impl(ctx):
expand_if_available = "output_execpath",
),
flag_group(
flags = ["/MACHINE:X64"],
flags = ["%{user_archiver_flags}"],
iterate_over = "user_archiver_flags",
expand_if_available = "user_archiver_flags",
),
flag_group(
flags = ctx.attr.archiver_flags,
),
],
),
@ -516,21 +624,57 @@ def _impl(ctx):
],
)
static_link_msvcrt_feature = feature(name = "static_link_msvcrt")
dynamic_link_msvcrt_debug_feature = feature(
name = "dynamic_link_msvcrt_debug",
static_link_msvcrt_feature = feature(
name = "static_link_msvcrt",
flag_sets = [
flag_set(
actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile],
flag_groups = [flag_group(flags = ["/MT"])],
with_features = [with_feature_set(not_features = ["dbg"])],
),
flag_set(
actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile],
flag_groups = [flag_group(flags = ["/MTd"])],
with_features = [with_feature_set(features = ["dbg"])],
),
flag_set(
actions = all_link_actions,
flag_groups = [flag_group(flags = ["/DEFAULTLIB:libcmt.lib"])],
with_features = [with_feature_set(not_features = ["dbg"])],
),
flag_set(
actions = all_link_actions,
flag_groups = [flag_group(flags = ["/DEFAULTLIB:libcmtd.lib"])],
with_features = [with_feature_set(features = ["dbg"])],
),
],
)
dynamic_link_msvcrt_feature = feature(
name = "dynamic_link_msvcrt",
enabled = True,
flag_sets = [
flag_set(
actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile],
flag_groups = [flag_group(flags = ["/MD"])],
with_features = [with_feature_set(not_features = ["dbg", "static_link_msvcrt"])],
),
flag_set(
actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile],
flag_groups = [flag_group(flags = ["/MDd"])],
with_features = [with_feature_set(features = ["dbg"], not_features = ["static_link_msvcrt"])],
),
flag_set(
actions = all_link_actions,
flag_groups = [flag_group(flags = ["/DEFAULTLIB:msvcrt.lib"])],
with_features = [with_feature_set(not_features = ["dbg", "static_link_msvcrt"])],
),
flag_set(
actions = all_link_actions,
flag_groups = [flag_group(flags = ["/DEFAULTLIB:msvcrtd.lib"])],
with_features = [with_feature_set(features = ["dbg"], not_features = ["static_link_msvcrt"])],
),
],
requires = [feature_set(features = ["dbg"])],
)
dbg_feature = feature(
@ -598,6 +742,9 @@ def _impl(ctx):
ACTION_NAMES.cpp_header_parsing,
ACTION_NAMES.cpp_module_compile,
ACTION_NAMES.cpp_module_codegen,
ACTION_NAMES.cpp_module_deps_scanning,
ACTION_NAMES.cpp20_module_compile,
ACTION_NAMES.cpp20_module_codegen,
ACTION_NAMES.lto_backend,
ACTION_NAMES.clif_match,
],
@ -629,10 +776,14 @@ def _impl(ctx):
env_set(
actions = [
ACTION_NAMES.c_compile,
ACTION_NAMES.linkstamp_compile,
ACTION_NAMES.cpp_compile,
ACTION_NAMES.cpp_module_compile,
ACTION_NAMES.cpp_module_codegen,
ACTION_NAMES.cpp_header_parsing,
ACTION_NAMES.cpp_module_deps_scanning,
ACTION_NAMES.cpp20_module_compile,
ACTION_NAMES.cpp20_module_codegen,
ACTION_NAMES.assemble,
ACTION_NAMES.preprocess_assemble,
],
@ -650,9 +801,12 @@ def _impl(ctx):
ACTION_NAMES.assemble,
ACTION_NAMES.preprocess_assemble,
ACTION_NAMES.c_compile,
ACTION_NAMES.linkstamp_compile,
ACTION_NAMES.cpp_compile,
ACTION_NAMES.cpp_header_parsing,
ACTION_NAMES.cpp_module_compile,
ACTION_NAMES.cpp_module_deps_scanning,
ACTION_NAMES.cpp20_module_compile,
],
flag_groups = [
flag_group(
@ -668,6 +822,25 @@ def _impl(ctx):
name = "generate_pdb_file",
)
generate_linkmap_feature = feature(
name = "generate_linkmap",
flag_sets = [
flag_set(
actions = [
ACTION_NAMES.cpp_link_executable,
],
flag_groups = [
flag_group(
flags = [
"/MAP:%{output_execpath}.map",
],
expand_if_available = "output_execpath",
),
],
),
],
)
output_execpath_flags_feature = feature(
name = "output_execpath_flags",
flag_sets = [
@ -683,24 +856,6 @@ def _impl(ctx):
],
)
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"]),
],
)
disable_assertions_feature = feature(
name = "disable_assertions",
enabled = True,
@ -750,43 +905,50 @@ def _impl(ctx):
parse_showincludes_feature = feature(
name = "parse_showincludes",
enabled = ctx.attr.supports_parse_showincludes,
flag_sets = [
flag_set(
actions = [
ACTION_NAMES.preprocess_assemble,
ACTION_NAMES.c_compile,
ACTION_NAMES.linkstamp_compile,
ACTION_NAMES.cpp_compile,
ACTION_NAMES.cpp_module_compile,
ACTION_NAMES.cpp_header_parsing,
ACTION_NAMES.cpp_module_deps_scanning,
ACTION_NAMES.cpp20_module_compile,
],
flag_groups = [flag_group(flags = ["/showIncludes"])],
),
],
env_sets = [
env_set(
actions = [
ACTION_NAMES.preprocess_assemble,
ACTION_NAMES.c_compile,
ACTION_NAMES.linkstamp_compile,
ACTION_NAMES.cpp_compile,
ACTION_NAMES.cpp_module_compile,
ACTION_NAMES.cpp_header_parsing,
],
# Force English (and thus a consistent locale) output so that Bazel can parse
# the /showIncludes output without having to guess the encoding.
env_entries = [env_entry(key = "VSLANG", value = "1033")],
),
],
)
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"]),
],
# MSVC does not emit .d files.
no_dotd_file_feature = feature(
name = "no_dotd_file",
enabled = True,
)
treat_warnings_as_errors_feature = feature(
name = "treat_warnings_as_errors",
flag_sets = [
flag_set(
actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile],
actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile] + all_link_actions,
flag_groups = [flag_group(flags = ["/WX"])],
),
],
@ -805,6 +967,7 @@ def _impl(ctx):
ACTION_NAMES.assemble,
ACTION_NAMES.preprocess_assemble,
ACTION_NAMES.c_compile,
ACTION_NAMES.linkstamp_compile,
ACTION_NAMES.cpp_compile,
ACTION_NAMES.cpp_header_parsing,
ACTION_NAMES.cpp_module_compile,
@ -827,6 +990,34 @@ def _impl(ctx):
],
)
external_include_paths_feature = feature(
name = "external_include_paths",
flag_sets = [
flag_set(
actions = [
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_deps_scanning,
ACTION_NAMES.cpp20_module_compile,
ACTION_NAMES.clif_match,
ACTION_NAMES.objc_compile,
ACTION_NAMES.objcpp_compile,
],
flag_groups = [
flag_group(
flags = ["/external:I%{external_include_paths}"],
iterate_over = "external_include_paths",
expand_if_available = "external_include_paths",
),
],
),
],
)
linkstamps_feature = feature(
name = "linkstamps",
flag_sets = [
@ -859,21 +1050,6 @@ def _impl(ctx):
],
)
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"])],
)
frame_pointer_feature = feature(
name = "frame_pointer",
flag_sets = [
@ -906,10 +1082,14 @@ def _impl(ctx):
actions = [
ACTION_NAMES.preprocess_assemble,
ACTION_NAMES.c_compile,
ACTION_NAMES.linkstamp_compile,
ACTION_NAMES.cpp_compile,
ACTION_NAMES.cpp_header_parsing,
ACTION_NAMES.cpp_module_compile,
ACTION_NAMES.cpp_module_codegen,
ACTION_NAMES.cpp_module_deps_scanning,
ACTION_NAMES.cpp20_module_compile,
ACTION_NAMES.cpp20_module_codegen,
],
flag_groups = [
flag_group(
@ -951,10 +1131,14 @@ def _impl(ctx):
flag_set(
actions = [
ACTION_NAMES.c_compile,
ACTION_NAMES.linkstamp_compile,
ACTION_NAMES.cpp_compile,
ACTION_NAMES.cpp_module_compile,
ACTION_NAMES.cpp_module_codegen,
ACTION_NAMES.cpp_header_parsing,
ACTION_NAMES.cpp_module_deps_scanning,
ACTION_NAMES.cpp20_module_compile,
ACTION_NAMES.cpp20_module_codegen,
ACTION_NAMES.assemble,
ACTION_NAMES.preprocess_assemble,
ACTION_NAMES.cpp_link_executable,
@ -984,6 +1168,17 @@ def _impl(ctx):
],
)
remove_unreferenced_code_feature = feature(
name = "remove_unreferenced_code",
enabled = True,
flag_sets = [
flag_set(
actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile],
flag_groups = [flag_group(flags = ["/Zc:inline"])],
),
],
)
compiler_input_flags_feature = feature(
name = "compiler_input_flags",
flag_sets = [
@ -992,10 +1187,14 @@ def _impl(ctx):
ACTION_NAMES.assemble,
ACTION_NAMES.preprocess_assemble,
ACTION_NAMES.c_compile,
ACTION_NAMES.linkstamp_compile,
ACTION_NAMES.cpp_compile,
ACTION_NAMES.cpp_header_parsing,
ACTION_NAMES.cpp_module_compile,
ACTION_NAMES.cpp_module_codegen,
ACTION_NAMES.cpp_module_deps_scanning,
ACTION_NAMES.cpp20_module_compile,
ACTION_NAMES.cpp20_module_codegen,
],
flag_groups = [
flag_group(
@ -1028,10 +1227,14 @@ def _impl(ctx):
env_set(
actions = [
ACTION_NAMES.c_compile,
ACTION_NAMES.linkstamp_compile,
ACTION_NAMES.cpp_compile,
ACTION_NAMES.cpp_module_compile,
ACTION_NAMES.cpp_module_codegen,
ACTION_NAMES.cpp_header_parsing,
ACTION_NAMES.cpp_module_deps_scanning,
ACTION_NAMES.cpp20_module_compile,
ACTION_NAMES.cpp20_module_codegen,
ACTION_NAMES.assemble,
ACTION_NAMES.preprocess_assemble,
ACTION_NAMES.cpp_link_executable,
@ -1048,6 +1251,17 @@ def _impl(ctx):
],
implies = ["msvc_compile_env", "msvc_link_env"],
)
symbol_check_feature = feature(
name = "symbol_check",
flag_sets = [
flag_set(
actions = [ACTION_NAMES.cpp_link_static_library],
flag_groups = [flag_group(flags = ["/WX:4006"])],
),
],
)
features = [
no_legacy_features_feature,
nologo_feature,
@ -1060,9 +1274,12 @@ def _impl(ctx):
msvc_compile_env_feature,
msvc_link_env_feature,
include_paths_feature,
external_include_paths_feature,
preprocessor_defines_feature,
parse_showincludes_feature,
no_dotd_file_feature,
generate_pdb_file_feature,
generate_linkmap_feature,
shared_flag_feature,
linkstamps_feature,
output_execpath_flags_feature,
@ -1073,10 +1290,7 @@ def _impl(ctx):
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,
dynamic_link_msvcrt_feature,
dbg_feature,
fastbuild_feature,
opt_feature,
@ -1085,10 +1299,12 @@ def _impl(ctx):
determinism_feature,
treat_warnings_as_errors_feature,
smaller_binary_feature,
remove_unreferenced_code_feature,
ignore_noisy_warnings_feature,
user_compile_flags_feature,
sysroot_feature,
unfiltered_compile_flags_feature,
archive_param_file_feature,
compiler_param_file_feature,
compiler_output_flags_feature,
compiler_input_flags_feature,
@ -1097,6 +1313,7 @@ def _impl(ctx):
no_windows_export_all_symbols_feature,
supports_dynamic_linker_feature,
supports_interface_shared_libraries_feature,
symbol_check_feature,
]
else:
targets_windows_feature = feature(
@ -1114,10 +1331,14 @@ def _impl(ctx):
env_set(
actions = [
ACTION_NAMES.c_compile,
ACTION_NAMES.linkstamp_compile,
ACTION_NAMES.cpp_compile,
ACTION_NAMES.cpp_module_compile,
ACTION_NAMES.cpp_module_codegen,
ACTION_NAMES.cpp_header_parsing,
ACTION_NAMES.cpp_module_deps_scanning,
ACTION_NAMES.cpp20_module_compile,
ACTION_NAMES.cpp20_module_codegen,
ACTION_NAMES.assemble,
ACTION_NAMES.preprocess_assemble,
ACTION_NAMES.cpp_link_executable,
@ -1143,10 +1364,13 @@ def _impl(ctx):
ACTION_NAMES.cpp_header_parsing,
ACTION_NAMES.cpp_module_compile,
ACTION_NAMES.cpp_module_codegen,
ACTION_NAMES.cpp_module_deps_scanning,
ACTION_NAMES.cpp20_module_compile,
ACTION_NAMES.cpp20_module_codegen,
ACTION_NAMES.lto_backend,
ACTION_NAMES.clif_match,
],
flag_groups = [flag_group(flags = ["-std=gnu++0x"])],
flag_groups = [flag_group(flags = ["-std=gnu++14"] + ctx.attr.default_compile_flags)],
),
],
)
@ -1157,7 +1381,7 @@ def _impl(ctx):
flag_sets = [
flag_set(
actions = all_link_actions,
flag_groups = [flag_group(flags = ["-lstdc++"])],
flag_groups = [flag_group(flags = ["-lstdc++"] + ctx.attr.default_link_flags)],
),
],
)
@ -1167,7 +1391,42 @@ def _impl(ctx):
enabled = True,
)
dbg_feature = feature(
name = "dbg",
flag_sets = [
flag_set(
actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile],
flag_groups = [flag_group(flags = ["-g", "-Og"])],
),
],
)
opt_feature = feature(
name = "opt",
flag_sets = [
flag_set(
actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile],
flag_groups = [flag_group(flags = [
"-g0",
"-O3",
"-DNDEBUG",
"-ffunction-sections",
"-fdata-sections",
])],
),
flag_set(
actions = all_link_actions,
flag_groups = [flag_group(flags = ["-Wl,--gc-sections"])],
),
],
)
if ctx.attr.cpu == "x64_windows" and ctx.attr.compiler == "mingw-gcc":
archive_param_file_feature = feature(
name = "archive_param_file",
enabled = True,
)
compiler_param_file_feature = feature(
name = "compiler_param_file",
)
@ -1177,23 +1436,18 @@ def _impl(ctx):
copy_dynamic_libraries_to_binary_feature,
gcc_env_feature,
default_compile_flags_feature,
archive_param_file_feature,
compiler_param_file_feature,
default_link_flags_feature,
supports_dynamic_linker_feature,
dbg_feature,
opt_feature,
]
else:
supports_pic_feature = feature(
name = "supports_pic",
enabled = True,
)
supports_start_end_lib_feature = feature(
name = "supports_start_end_lib",
enabled = True,
)
dbg_feature = feature(name = "dbg")
opt_feature = feature(name = "opt")
sysroot_feature = feature(
name = "sysroot",
@ -1208,6 +1462,9 @@ def _impl(ctx):
ACTION_NAMES.cpp_header_parsing,
ACTION_NAMES.cpp_module_compile,
ACTION_NAMES.cpp_module_codegen,
ACTION_NAMES.cpp_module_deps_scanning,
ACTION_NAMES.cpp20_module_compile,
ACTION_NAMES.cpp20_module_codegen,
ACTION_NAMES.lto_backend,
ACTION_NAMES.clif_match,
ACTION_NAMES.cpp_link_executable,
@ -1243,6 +1500,20 @@ def _impl(ctx):
provides = ["profile"],
)
treat_warnings_as_errors_feature = feature(
name = "treat_warnings_as_errors",
flag_sets = [
flag_set(
actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile],
flag_groups = [flag_group(flags = ["-Werror"])],
),
flag_set(
actions = all_link_actions,
flag_groups = [flag_group(flags = ["-Wl,-fatal-warnings"])],
),
],
)
user_compile_flags_feature = feature(
name = "user_compile_flags",
enabled = True,
@ -1257,6 +1528,9 @@ def _impl(ctx):
ACTION_NAMES.cpp_header_parsing,
ACTION_NAMES.cpp_module_compile,
ACTION_NAMES.cpp_module_codegen,
ACTION_NAMES.cpp_module_deps_scanning,
ACTION_NAMES.cpp20_module_compile,
ACTION_NAMES.cpp20_module_codegen,
ACTION_NAMES.lto_backend,
ACTION_NAMES.clif_match,
],
@ -1276,7 +1550,6 @@ def _impl(ctx):
copy_dynamic_libraries_to_binary_feature,
gcc_env_feature,
supports_pic_feature,
supports_start_end_lib_feature,
default_compile_flags_feature,
default_link_flags_feature,
fdo_optimize_feature,
@ -1284,6 +1557,7 @@ def _impl(ctx):
dbg_feature,
opt_feature,
user_compile_flags_feature,
treat_warnings_as_errors_feature,
sysroot_feature,
]
@ -1292,9 +1566,61 @@ def _impl(ctx):
for name, path in ctx.attr.tool_paths.items()
]
make_variables = []
# dumpbin.exe is not available in MSYS toolchain
if "dumpbin" in ctx.attr.tool_paths:
make_variables.append(make_variable(name = "DUMPBIN", value = ctx.attr.tool_paths["dumpbin"]))
# Tell bazel we support C++ modules now
cpp_modules_feature = feature(
name = "cpp_modules",
# set default value to False
# to enable the feature
# use --features=cpp_modules
# or add cpp_modules to features attr
enabled = False,
)
cpp_module_modmap_file_feature = feature(
name = "cpp_module_modmap_file",
flag_sets = [
flag_set(
actions = [
ACTION_NAMES.cpp_compile,
ACTION_NAMES.cpp20_module_compile,
ACTION_NAMES.cpp20_module_codegen,
],
flag_groups = [
flag_group(
flags = ["@%{cpp_module_modmap_file}"],
expand_if_available = "cpp_module_modmap_file",
),
],
),
],
enabled = True,
)
cpp20_module_compile_flags_feature = feature(
name = "cpp20_module_compile_flags",
flag_sets = [
flag_set(
actions = [
ACTION_NAMES.cpp20_module_compile,
],
flag_groups = [
flag_group(
flags = ["/ifcOutput%{cpp_module_output_file}"],
expand_if_available = "cpp_module_output_file",
),
],
),
],
enabled = True,
)
return cc_common.create_cc_toolchain_config_info(
ctx = ctx,
features = features,
features = features + [cpp_modules_feature, cpp_module_modmap_file_feature, cpp20_module_compile_flags_feature],
action_configs = action_configs,
artifact_name_patterns = artifact_name_patterns,
cxx_builtin_include_directories = ctx.attr.cxx_builtin_include_directories,
@ -1307,6 +1633,7 @@ def _impl(ctx):
abi_version = ctx.attr.abi_version,
abi_libc_version = ctx.attr.abi_libc_version,
tool_paths = tool_paths,
make_variables = make_variables,
)
cc_toolchain_config = rule(
@ -1314,12 +1641,14 @@ cc_toolchain_config = rule(
attrs = {
"abi_libc_version": attr.string(),
"abi_version": attr.string(),
"archiver_flags": attr.string_list(default = []),
"compiler": attr.string(),
"cpu": attr.string(mandatory = True),
"cxx_builtin_include_directories": attr.string_list(),
"dbg_mode_debug_flag": attr.string(),
"dbg_mode_debug_flag": attr.string(default = ""),
"default_compile_flags": attr.string_list(default = []),
"default_link_flags": attr.string_list(default = []),
"fastbuild_mode_debug_flag": attr.string(),
"fastbuild_mode_debug_flag": attr.string(default = ""),
"host_system_name": attr.string(),
"msvc_cl_path": attr.string(default = "vc_installation_error.bat"),
"msvc_env_include": attr.string(default = "msvc_not_found"),
@ -1329,6 +1658,7 @@ cc_toolchain_config = rule(
"msvc_lib_path": attr.string(default = "vc_installation_error.bat"),
"msvc_link_path": attr.string(default = "vc_installation_error.bat"),
"msvc_ml_path": attr.string(default = "vc_installation_error.bat"),
"supports_parse_showincludes": attr.bool(),
"target_libc": attr.string(),
"target_system_name": attr.string(),
"tool_bin_path": attr.string(default = "not_found"),

View File

@ -53,6 +53,21 @@ cc_action_type(
action_name = ACTION_NAMES.cpp_header_parsing,
)
cc_action_type(
name = "cpp_module_deps_scanning",
action_name = ACTION_NAMES.cpp_module_deps_scanning,
)
cc_action_type(
name = "cpp20_module_compile",
action_name = ACTION_NAMES.cpp20_module_compile,
)
cc_action_type(
name = "cpp20_module_codegen",
action_name = ACTION_NAMES.cpp20_module_codegen,
)
cc_action_type(
name = "cpp_module_compile",
action_name = ACTION_NAMES.cpp_module_compile,
@ -68,6 +83,11 @@ cc_action_type(
action_name = ACTION_NAMES.preprocess_assemble,
)
cc_action_type(
name = "llvm_cov",
action_name = ACTION_NAMES.llvm_cov,
)
cc_action_type(
name = "lto_indexing",
action_name = ACTION_NAMES.lto_indexing,
@ -120,7 +140,12 @@ cc_action_type(
cc_action_type(
name = "objcopy_embed_data",
action_name = "objcopy_embed_data",
action_name = ACTION_NAMES.objcopy_embed_data,
)
cc_action_type(
name = "validate_static_library",
action_name = ACTION_NAMES.validate_static_library,
)
# ld_embed_data is only available within google.
@ -266,9 +291,13 @@ cc_action_type_set(
":cpp_module_codegen",
":cpp_header_analysis",
":cpp_header_parsing",
":cpp_module_deps_scanning",
":cpp20_module_compile",
":cpp20_module_codegen",
":cpp_module_compile",
":assemble",
":preprocess_assemble",
":llvm_cov",
":lto_indexing",
":lto_backend",
":lto_index_for_executable",
@ -287,5 +316,6 @@ cc_action_type_set(
":objcpp_compile",
":objcpp_executable",
":clif_match",
":validate_static_library",
],
)

View File

@ -0,0 +1,19 @@
load("//cc/toolchains:tool_capability.bzl", "cc_tool_capability")
package(default_visibility = ["//visibility:public"])
cc_tool_capability(
name = "supports_start_end_lib",
)
cc_tool_capability(
name = "supports_interface_shared_libraries",
)
cc_tool_capability(
name = "supports_dynamic_linker",
)
cc_tool_capability(
name = "supports_pic",
)

View File

@ -28,7 +28,7 @@ def _cc_flags_supplier_impl(ctx):
cc_flags_supplier = rule(
implementation = _cc_flags_supplier_impl,
attrs = {
"_cc_toolchain": attr.label(default = Label("@bazel_tools//tools/cpp:current_cc_toolchain")),
"_cc_toolchain": attr.label(default = Label("@rules_cc//cc:current_cc_toolchain")),
},
toolchains = use_cc_toolchain(),
fragments = ["cpp"],

View File

@ -156,6 +156,16 @@ ToolInfo = provider(
"runfiles": "(runfiles) The files required to run the tool",
"execution_requirements": "(Sequence[str]) A set of execution requirements of the tool",
"allowlist_include_directories": "(depset[DirectoryInfo]) Built-in include directories implied by this tool that should be allowlisted in Bazel's include checker",
"capabilities": "(Sequence[ToolCapabilityInfo]) Capabilities supported by the tool.",
},
)
ToolCapabilityInfo = provider(
doc = "A capability associated with a tool (eg. supports_pic).",
# @unsorted-dict-items
fields = {
"label": "(Label) The label defining this provider. Place in error messages to simplify debugging",
"feature": "(FeatureInfo) The feature this capability defines",
},
)

View File

@ -23,7 +23,7 @@ def _compiler_flag_impl(ctx):
compiler_flag = rule(
implementation = _compiler_flag_impl,
attrs = {
"_cc_toolchain": attr.label(default = Label("@bazel_tools//tools/cpp:current_cc_toolchain")),
"_cc_toolchain": attr.label(default = Label("@rules_cc//cc:current_cc_toolchain")),
},
toolchains = use_cc_toolchain(),
)

View File

@ -41,36 +41,12 @@ cc_external_feature(
overridable = True,
)
cc_external_feature(
name = "supports_start_end_lib",
feature_name = "supports_start_end_lib",
overridable = True,
)
cc_external_feature(
name = "supports_interface_shared_libraries",
feature_name = "supports_interface_shared_libraries",
overridable = True,
)
cc_external_feature(
name = "supports_dynamic_linker",
feature_name = "supports_dynamic_linker",
overridable = True,
)
cc_external_feature(
name = "static_link_cpp_runtimes",
feature_name = "static_link_cpp_runtimes",
overridable = True,
)
cc_external_feature(
name = "supports_pic",
feature_name = "supports_pic",
overridable = True,
)
cc_feature_set(
name = "all_non_legacy_builtin_features",
all_of = [
@ -80,11 +56,7 @@ cc_feature_set(
":static_linking_mode",
":dynamic_linking_mode",
":per_object_debug_info",
":supports_start_end_lib",
":supports_interface_shared_libraries",
":supports_dynamic_linker",
":static_link_cpp_runtimes",
":supports_pic",
],
visibility = ["//visibility:private"],
)

View File

@ -107,6 +107,7 @@ def collect_tools(ctx, targets, fail = fail):
runfiles = collect_data(ctx, [target]),
execution_requirements = tuple(),
allowlist_include_directories = depset(),
capabilities = tuple(),
))
else:
fail("Expected %s to be a cc_tool or a binary rule" % target.label)

View File

@ -22,12 +22,14 @@ load("//cc/toolchains:feature_set.bzl", _cc_feature_set = "cc_feature_set")
load("//cc/toolchains:mutually_exclusive_category.bzl", _cc_mutually_exclusive_category = "cc_mutually_exclusive_category")
load("//cc/toolchains:nested_args.bzl", _cc_nested_args = "cc_nested_args")
load("//cc/toolchains:tool.bzl", _cc_tool = "cc_tool")
load("//cc/toolchains:tool_capability.bzl", _cc_tool_capability = "cc_tool_capability")
load("//cc/toolchains:tool_map.bzl", _cc_tool_map = "cc_tool_map")
load("//cc/toolchains/impl:external_feature.bzl", _cc_external_feature = "cc_external_feature")
load("//cc/toolchains/impl:variables.bzl", _cc_variable = "cc_variable")
cc_tool_map = _cc_tool_map
cc_tool = _cc_tool
cc_tool_capability = _cc_tool_capability
cc_args = _cc_args
cc_nested_args = _cc_nested_args
cc_args_list = _cc_args_list
@ -46,6 +48,7 @@ cc_external_feature = _cc_external_feature
DOCUMENTED_TOOLCHAIN_RULES = [
"cc_tool_map",
"cc_tool",
"cc_tool_capability",
"cc_args",
"cc_nested_args",
"cc_args_list",

View File

@ -131,16 +131,30 @@ def convert_tool(tool):
with_features = [],
)
def convert_capability(capability):
return legacy_feature(
name = capability.name,
enabled = False,
)
def _convert_tool_map(tool_map):
return [
legacy_action_config(
action_configs = []
caps = {}
for action_type, tool in tool_map.configs.items():
action_configs.append(legacy_action_config(
action_name = action_type.name,
enabled = True,
tools = [convert_tool(tool_map.configs[action_type])],
implies = [],
)
for action_type in tool_map.configs.keys()
tools = [convert_tool(tool)],
implies = [cap.feature.name for cap in tool.capabilities],
))
for cap in tool.capabilities:
caps[cap] = None
cap_features = [
legacy_feature(name = cap.feature.name, enabled = False)
for cap in caps
]
return action_configs, cap_features
def convert_toolchain(toolchain):
"""Converts a rule-based toolchain into the legacy providers.
@ -155,6 +169,8 @@ def convert_toolchain(toolchain):
convert_feature(feature, enabled = feature in toolchain.enabled_features)
for feature in toolchain.features
]
action_configs, cap_features = _convert_tool_map(toolchain.tool_map)
features.extend(cap_features)
features.append(convert_feature(FeatureInfo(
# We reserve names starting with implied_by. This ensures we don't
# conflict with the name of a feature the user creates.
@ -167,7 +183,6 @@ def convert_toolchain(toolchain):
external = False,
allowlist_include_directories = depset(),
)))
action_configs = _convert_tool_map(toolchain.tool_map)
cxx_builtin_include_directories = [
d.path

View File

@ -54,9 +54,9 @@ def _feature_key(feature):
# This should be sufficiently unique.
return (feature.label, feature.name)
def _get_known_features(features, fail):
def _get_known_features(features, capability_features, fail):
feature_names = {}
for ft in features:
for ft in capability_features + features:
if ft.name in feature_names:
other = feature_names[ft.name]
if other.overrides != ft and ft.overrides != other:
@ -113,7 +113,10 @@ def _validate_feature(self, known_features, fail):
_validate_implies(self, known_features, fail = fail)
def _validate_toolchain(self, fail = fail):
known_features = _get_known_features(self.features, fail = fail)
capabilities = []
for tool in self.tool_map.configs.values():
capabilities.extend([cap.feature for cap in tool.capabilities])
known_features = _get_known_features(self.features, capabilities, fail = fail)
for feature in self.features:
_validate_feature(feature, known_features, fail = fail)

View File

@ -14,9 +14,10 @@
"""Implementation of cc_tool"""
load("@bazel_skylib//rules/directory:providers.bzl", "DirectoryInfo")
load("//cc/toolchains/impl:collect.bzl", "collect_data")
load("//cc/toolchains/impl:collect.bzl", "collect_data", "collect_provider")
load(
":cc_toolchain_info.bzl",
"ToolCapabilityInfo",
"ToolInfo",
)
@ -38,6 +39,7 @@ def _cc_tool_impl(ctx):
allowlist_include_directories = depset(
direct = [d[DirectoryInfo] for d in ctx.attr.allowlist_include_directories],
),
capabilities = tuple(collect_provider(ctx.attr.capabilities, ToolCapabilityInfo)),
)
link = ctx.actions.declare_file(ctx.label.name)
@ -94,6 +96,13 @@ and/or `-fno-canonical-system-headers` arguments.
This can help work around errors like:
`the source file 'main.c' includes the following non-builtin files with absolute paths
(if these are builtin files, make sure these paths are in your toolchain)`.
""",
),
"capabilities": attr.label_list(
providers = [ToolCapabilityInfo],
doc = """Declares that a tool is capable of doing something.
For example, `//cc/toolchains/capabilities:supports_pic`.
""",
),
},
@ -120,6 +129,7 @@ cc_tool(
# Suppose clang needs libc to run.
data = ["@llvm_toolchain//:lib/x86_64-linux-gnu/libc.so.6"]
tags = ["requires-network"],
capabilities = ["//cc/toolchains/capabilities:supports_pic"],
)
```
""",

View File

@ -0,0 +1,85 @@
# Copyright 2024 The Bazel 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.
"""Implementation of the cc_tool_capability rule."""
load(
":cc_toolchain_info.bzl",
"ArgsListInfo",
"FeatureConstraintInfo",
"FeatureInfo",
"ToolCapabilityInfo",
)
def _cc_tool_capability_impl(ctx):
ft = FeatureInfo(
name = ctx.attr.feature_name or ctx.label.name,
label = ctx.label,
enabled = False,
args = ArgsListInfo(
label = ctx.label,
args = (),
files = depset(),
by_action = (),
allowlist_include_directories = depset(),
),
implies = depset(),
requires_any_of = (),
mutually_exclusive = (),
# Mark it as external so that it doesn't complain if we say
# "requires" on a constraint that was never referenced elsewhere
# in the toolchain.
external = True,
overridable = True,
overrides = None,
allowlist_include_directories = depset(),
)
return [
ToolCapabilityInfo(label = ctx.label, feature = ft),
# Only give it a feature constraint info and not a feature info.
# This way you can't imply it - you can only require it.
FeatureConstraintInfo(label = ctx.label, all_of = depset([ft])),
]
cc_tool_capability = rule(
implementation = _cc_tool_capability_impl,
provides = [ToolCapabilityInfo, FeatureConstraintInfo],
doc = """A capability is an optional feature that a tool supports.
For example, not all compilers support PIC, so to handle this, we write:
```
cc_tool(
name = "clang",
src = "@host_tools/bin/clang",
capabilities = [
"//cc/toolchains/capabilities:supports_pic",
],
)
cc_args(
name = "pic",
requires = [
"//cc/toolchains/capabilities:supports_pic"
],
args = ["-fPIC"],
)
```
This ensures that `-fPIC` is added to the command-line only when we are using a
tool that supports PIC.
""",
attrs = {
"feature_name": attr.string(doc = "The name of the feature to generate for this capability"),
},
)

View File

@ -380,7 +380,7 @@ cc_feature(
## cc_tool
<pre>
cc_tool(<a href="#cc_tool-name">name</a>, <a href="#cc_tool-src">src</a>, <a href="#cc_tool-data">data</a>, <a href="#cc_tool-allowlist_include_directories">allowlist_include_directories</a>)
cc_tool(<a href="#cc_tool-name">name</a>, <a href="#cc_tool-src">src</a>, <a href="#cc_tool-data">data</a>, <a href="#cc_tool-allowlist_include_directories">allowlist_include_directories</a>, <a href="#cc_tool-capabilities">capabilities</a>)
</pre>
Declares a tool for use by toolchain actions.
@ -405,6 +405,7 @@ cc_tool(
# Suppose clang needs libc to run.
data = ["@llvm_toolchain//:lib/x86_64-linux-gnu/libc.so.6"]
tags = ["requires-network"],
capabilities = ["@rules_cc//cc/toolchains/capabilities:supports_pic"],
)
```
@ -417,6 +418,49 @@ cc_tool(
| <a id="cc_tool-src"></a>src | The underlying binary that this tool represents.<br><br>Usually just a single prebuilt (eg. @toolchain//:bin/clang), but may be any executable label. | <a href="https://bazel.build/concepts/labels">Label</a> | optional | `None` |
| <a id="cc_tool-data"></a>data | Additional files that are required for this tool to run.<br><br>Frequently, clang and gcc require additional files to execute as they often shell out to other binaries (e.g. `cc1`). | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
| <a id="cc_tool-allowlist_include_directories"></a>allowlist_include_directories | Include paths implied by using this tool.<br><br>Compilers may include a set of built-in headers that are implicitly available unless flags like `-nostdinc` are provided. Bazel checks that all included headers are properly provided by a dependency or allowlisted through this mechanism.<br><br>As a rule of thumb, only use this if Bazel is complaining about absolute paths in your toolchain and you've ensured that the toolchain is compiling with the `-no-canonical-prefixes` and/or `-fno-canonical-system-headers` arguments.<br><br>This can help work around errors like: `the source file 'main.c' includes the following non-builtin files with absolute paths (if these are builtin files, make sure these paths are in your toolchain)`. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
| <a id="cc_tool-capabilities"></a>capabilities | Declares that a tool is capable of doing something.<br><br>For example, `@rules_cc//cc/toolchains/capabilities:supports_pic`. | <a href="https://bazel.build/concepts/labels">List of labels</a> | optional | `[]` |
<a id="cc_tool_capability"></a>
## cc_tool_capability
<pre>
cc_tool_capability(<a href="#cc_tool_capability-name">name</a>, <a href="#cc_tool_capability-feature_name">feature_name</a>)
</pre>
A capability is an optional feature that a tool supports.
For example, not all compilers support PIC, so to handle this, we write:
```
cc_tool(
name = "clang",
src = "@host_tools/bin/clang",
capabilities = [
"@rules_cc//cc/toolchains/capabilities:supports_pic",
],
)
cc_args(
name = "pic",
requires = [
"@rules_cc//cc/toolchains/capabilities:supports_pic"
],
args = ["-fPIC"],
)
```
This ensures that `-fPIC` is added to the command-line only when we are using a
tool that supports PIC.
**ATTRIBUTES**
| Name | Description | Type | Mandatory | Default |
| :------------- | :------------- | :------------- | :------------- | :------------- |
| <a id="cc_tool_capability-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |
| <a id="cc_tool_capability-feature_name"></a>feature_name | The name of the feature to generate for this capability | String | optional | `""` |
<a id="cc_args"></a>

View File

@ -0,0 +1,29 @@
# Copyright 2024 The Bazel 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.
"""Exposing some helper functions for configure cc toolchains."""
load("//cc/private/toolchain:cc_configure.bzl", _MSVC_ENVVARS = "MSVC_ENVVARS")
load("//cc/private/toolchain:lib_cc_configure.bzl", _escape_string = "escape_string")
load("//cc/private/toolchain:windows_cc_configure.bzl", _find_vc_path = "find_vc_path", _setup_vc_env_vars = "setup_vc_env_vars")
MSVC_ENVVARS = _MSVC_ENVVARS
def find_vc_path(repository_ctx):
return _find_vc_path(repository_ctx)
def setup_vc_env_vars(repository_ctx):
return _setup_vc_env_vars(repository_ctx)
def escape_string(string):
return _escape_string(string)

View File

@ -12,7 +12,7 @@ https://docs.bazel.build/versions/main/tutorial/cc-toolchain-config.html for
advanced usage.
"""
load("@bazel_tools//tools/cpp:cc_toolchain_config_lib.bzl", "tool_path")
load("@rules_cc//cc:cc_toolchain_config_lib.bzl", "tool_path") # buildifier: disable=deprecated-function
def _impl(ctx):
tool_paths = [

View File

@ -14,8 +14,8 @@
"""Example showing how to create a rule that rules_cc can depend on."""
load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain", "use_cpp_toolchain")
load("@rules_cc//cc:action_names.bzl", "CPP_LINK_STATIC_LIBRARY_ACTION_NAME")
load("@rules_cc//cc:find_cc_toolchain.bzl", "find_cpp_toolchain", "use_cc_toolchain")
load("//examples/my_c_compile:my_c_compile.bzl", "MyCCompileInfo")
def _my_c_archive_impl(ctx):
@ -92,8 +92,8 @@ my_c_archive = rule(
attrs = {
"deps": attr.label_list(providers = [CcInfo]),
"object": attr.label(mandatory = True, providers = [MyCCompileInfo]),
"_cc_toolchain": attr.label(default = Label("@bazel_tools//tools/cpp:current_cc_toolchain")),
"_cc_toolchain": attr.label(default = Label("@rules_cc//cc:current_cc_toolchain")),
},
fragments = ["cpp"],
toolchains = use_cpp_toolchain(),
toolchains = use_cc_toolchain(),
)

View File

@ -14,8 +14,8 @@
"""Example showing how to create a rule that just compiles C sources."""
load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain", "use_cpp_toolchain")
load("@rules_cc//cc:action_names.bzl", "C_COMPILE_ACTION_NAME")
load("@rules_cc//cc:find_cc_toolchain.bzl", "find_cpp_toolchain", "use_cc_toolchain")
MyCCompileInfo = provider(doc = "", fields = ["object"])
@ -74,8 +74,8 @@ my_c_compile = rule(
implementation = _my_c_compile_impl,
attrs = {
"src": attr.label(mandatory = True, allow_single_file = True),
"_cc_toolchain": attr.label(default = Label("@bazel_tools//tools/cpp:current_cc_toolchain")),
"_cc_toolchain": attr.label(default = Label("@rules_cc//cc:current_cc_toolchain")),
},
toolchains = use_cpp_toolchain(),
toolchains = use_cc_toolchain(),
fragments = ["cpp"],
)

View File

@ -14,7 +14,7 @@
"""Example showing how to get CcToolchainInfo in a custom rule."""
load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain", "use_cpp_toolchain")
load("@rules_cc//cc:find_cc_toolchain.bzl", "find_cpp_toolchain", "use_cc_toolchain")
def _write_cc_toolchain_cpu_impl(ctx):
cc_toolchain = find_cpp_toolchain(ctx)
@ -26,7 +26,7 @@ def _write_cc_toolchain_cpu_impl(ctx):
write_cc_toolchain_cpu = rule(
implementation = _write_cc_toolchain_cpu_impl,
attrs = {
"_cc_toolchain": attr.label(default = Label("@bazel_tools//tools/cpp:current_cc_toolchain")),
"_cc_toolchain": attr.label(default = Label("@rules_cc//cc:current_cc_toolchain")),
},
toolchains = use_cpp_toolchain(),
toolchains = use_cc_toolchain(),
)

View File

@ -67,7 +67,7 @@ def generate_factory(type, name, attrs):
meta.add_failure("Wanted a %s but got" % name, value)
got_keys = sorted(structs.to_dict(value).keys())
subjects.collection(got_keys, meta = meta.derive(details = [
"Value was not a %s - it has a different set of fields" % name,
"Value %r was not a %s - it has a different set of fields" % (value, name),
])).contains_exactly(want_keys).in_order()
def type_factory(value, *, meta):

View File

@ -26,6 +26,7 @@ load(
"FeatureSetInfo",
"MutuallyExclusiveCategoryInfo",
"NestedArgsInfo",
"ToolCapabilityInfo",
"ToolConfigInfo",
"ToolInfo",
"ToolchainConfigInfo",
@ -178,6 +179,15 @@ _FeatureFactory = generate_factory(
),
)
# buildifier: disable=name-conventions
_ToolCapabilityFactory = generate_factory(
ToolCapabilityInfo,
"ToolCapabilityInfo",
dict(
name = _subjects.str,
),
)
# buildifier: disable=name-conventions
_ToolFactory = generate_factory(
ToolInfo,
@ -187,6 +197,7 @@ _ToolFactory = generate_factory(
runfiles = runfiles_subject,
execution_requirements = _subjects.collection,
allowlist_include_directories = _FakeDirectoryDepset,
capabilities = ProviderSequence(_ToolCapabilityFactory),
),
)

View File

@ -6,6 +6,7 @@ load(":tool_test.bzl", "TARGETS", "TESTS")
cc_tool(
name = "tool",
src = "//tests/rule_based_toolchain/testdata:bin_wrapper.sh",
capabilities = ["//cc/toolchains/capabilities:supports_pic"],
data = ["//tests/rule_based_toolchain/testdata:bin"],
tags = ["requires-network"],
)

View File

@ -47,6 +47,7 @@ cc_tool(
name = "c_compile_tool",
src = "//tests/rule_based_toolchain/testdata:bin_wrapper",
allowlist_include_directories = ["//tests/rule_based_toolchain/testdata:subdirectory_3"],
capabilities = ["//cc/toolchains/capabilities:supports_pic"],
)
cc_sysroot(

View File

@ -207,6 +207,10 @@ def _toolchain_collects_files_test(env, targets):
],
)],
),
legacy_feature(
name = "supports_pic",
enabled = False,
),
legacy_feature(
name = "implied_by_always_enabled",
enabled = True,
@ -252,6 +256,7 @@ def _toolchain_collects_files_test(env, targets):
action_name = "c_compile",
enabled = True,
tools = [legacy_tool(tool = exe)],
implies = ["supports_pic"],
),
legacy_action_config(
action_name = "cpp_compile",

View File

@ -27,7 +27,7 @@ type CToolchainIdentifier struct {
// Writes the load statement for the cc_toolchain_config_lib
func getCcToolchainConfigHeader() string {
return `load("@bazel_tools//tools/cpp:cc_toolchain_config_lib.bzl",
return `load("@rules_cc//cc:cc_toolchain_config_lib.bzl",
"action_config",
"artifact_name_pattern",
"env_entry",
@ -118,7 +118,7 @@ var actionNames = map[string]string{
}
func getLoadActionsStmt() string {
return "load(\"@bazel_tools//tools/build_defs/cc:action_names.bzl\", \"ACTION_NAMES\")\n\n"
return "load(\"@rules_cc//cc:action_names.bzl\", \"ACTION_NAMES\")\n\n"
}
// Returns a map {toolchain_identifier : CToolchainIdentifier}

View File

@ -1533,7 +1533,7 @@ func TestFeatureDeclaration(t *testing.T) {
func TestRule(t *testing.T) {
simpleToolchain := getSimpleCToolchain("simple")
expected := `load("@bazel_tools//tools/cpp:cc_toolchain_config_lib.bzl",
expected := `load("@rules_cc//cc:cc_toolchain_config_lib.bzl",
"action_config",
"artifact_name_pattern",
"env_entry",
@ -1548,7 +1548,7 @@ func TestRule(t *testing.T) {
"variable_with_value",
"with_feature_set",
)
load("@bazel_tools//tools/build_defs/cc:action_names.bzl", "ACTION_NAMES")
load("@rules_cc//cc:action_names.bzl", "ACTION_NAMES")
def _impl(ctx):
toolchain_identifier = "id-simple"