From bcfdf9a891900c3123203b6ee7e8c514462b75c6 Mon Sep 17 00:00:00 2001 From: Niyas Sait Date: Fri, 26 Nov 2021 02:01:35 -0800 Subject: [PATCH] Enable native support for Windows on arm64 Following changes are included - Fix AutoCpuConverter.java to identify win/arm64 CPU - Add win/arm64 JDK 17 - Add grpc patch to workaround build issues - Extend build_bazel_binaries.yml to cross-compile for win/arm64 - Fix msvc toolchain to look for tools in HostX86 directory as well Fixes: #14339 --- .bazelci/build_bazel_binaries.yml | 10 +++ WORKSPACE | 7 ++ src/BUILD | 10 ++- src/conditions/BUILD | 31 +++++++++ src/conditions/BUILD.tools | 2 +- .../lib/analysis/config/AutoCpuConverter.java | 2 + .../skyframe/ToolchainResolutionFunction.java | 2 +- third_party/def_parser/def_parser.cc | 1 + third_party/grpc/BUILD | 2 +- third_party/grpc/grpc_1.41.0.win_arm64.patch | 51 ++++++++++++++ tools/cpp/BUILD.windows.tpl | 66 +++++++++++++++++++ tools/cpp/cc_configure.bzl | 2 +- tools/cpp/lib_cc_configure.bzl | 7 +- tools/cpp/windows_cc_configure.bzl | 25 ++++--- tools/cpp/windows_cc_toolchain_config.bzl | 16 ++++- tools/def_parser/BUILD.tools | 2 +- 16 files changed, 217 insertions(+), 19 deletions(-) create mode 100644 third_party/grpc/grpc_1.41.0.win_arm64.patch diff --git a/.bazelci/build_bazel_binaries.yml b/.bazelci/build_bazel_binaries.yml index 5478050004e442..26c8b06d7935c9 100644 --- a/.bazelci/build_bazel_binaries.yml +++ b/.bazelci/build_bazel_binaries.yml @@ -44,3 +44,13 @@ platforms: build_targets: - "//src:bazel.exe" - "//src:bazel_nojdk.exe" + windows_arm64: + build_flags: + - "--copt=-w" + - "--host_copt=-w" + - "-c" + - "opt" + build_targets: + - "//src:bazel.exe" + - "//src:bazel_nojdk.exe" + - "--cpu=x64_arm64_windows" \ No newline at end of file diff --git a/WORKSPACE b/WORKSPACE index 2d995f095ed4f7..520cf3ee3d6430 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -447,6 +447,13 @@ http_file( urls = ["https://mirror.bazel.build/openjdk/azul-zulu11.37.17-ca-jdk11.0.6/zulu11.37.17-ca-jdk11.0.6-win_x64.zip"], ) +http_file( + name = "openjdk_win_arm64_vanilla", + downloaded_file_path = "zulu-win-arm64.zip", + sha256 = "811d7e7591bac4f081dfb00ba6bd15b6fc5969e1f89f0f327ef75147027c3877", + urls = ["https://cdn.azul.com/zulu/bin/zulu17.30.15-ca-jdk17.0.1-win_aarch64.zip"], +) + http_file( name = "openjdk_win_minimal", downloaded_file_path = "zulu-win-minimal.zip", diff --git a/src/BUILD b/src/BUILD index 936adcd513ed52..cbc363fd1cfec8 100644 --- a/src/BUILD +++ b/src/BUILD @@ -182,7 +182,10 @@ filegroup( "//src/conditions:darwin_arm64": [ "@openjdk_macos_aarch64//file", ], - "//src/conditions:windows": [ + "//src/conditions:windows_arm64": [ + "@openjdk_win_arm64_vanilla//file", # TODO(#14339): replace with openjdk_win_arm64 when packages are uploaded to bazel mirror server + ], + "//src/conditions:windows_x86_64": [ "@openjdk_win//file", ], "//src/conditions:linux_aarch64": [ @@ -204,7 +207,10 @@ filegroup( "//src/conditions:darwin_arm64": [ "@openjdk_macos_aarch64_minimal//file", ], - "//src/conditions:windows": [ + "//src/conditions:windows_arm64": [ + "@openjdk_win_arm64_vanilla//file", # TODO(#14339): replace with openjdk_win_arm64 when packages are uploaded to bazel mirror server + ], + "//src/conditions:windows_x86_64": [ "@openjdk_win_minimal//file", ], "//src/conditions:linux_aarch64": [ diff --git a/src/conditions/BUILD b/src/conditions/BUILD index 5f8f6a7767ffc4..35faefd06f8977 100644 --- a/src/conditions/BUILD +++ b/src/conditions/BUILD @@ -149,6 +149,37 @@ config_setting( visibility = ["//visibility:public"], ) +config_setting( + name = "windows_x86_64", + constraint_values = [ + "@platforms//os:windows", + "@platforms//cpu:x86_64", + ], + visibility = ["//visibility:public"], +) + +config_setting( + name = "windows_arm64_constraint", + constraint_values = [ + "@platforms//os:windows", + "@platforms//cpu:arm64", + ], +) + +config_setting( + name = "windows_arm64_flag", + values = {"cpu": "x64_arm64_windows"}, +) + +selects.config_setting_group( + name = "windows_arm64", + match_any = [ + ":windows_arm64_constraint", + ":windows_arm64_flag", + ], + visibility = ["//visibility:public"], +) + config_setting( name = "arm", constraint_values = ["@platforms//cpu:arm"], diff --git a/src/conditions/BUILD.tools b/src/conditions/BUILD.tools index ed90895b1a5750..06e836461d3a27 100644 --- a/src/conditions/BUILD.tools +++ b/src/conditions/BUILD.tools @@ -104,7 +104,7 @@ config_setting( # TODO: figure out how to base this selection on constraints config_setting( name = "host_windows", - values = {"host_cpu": "x64_windows"}, + values = {"host_cpu": "x64_arm64_windows"}, visibility = ["//visibility:public"], ) diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/AutoCpuConverter.java b/src/main/java/com/google/devtools/build/lib/analysis/config/AutoCpuConverter.java index 9f5fbca65fd003..69c40e381581a5 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/config/AutoCpuConverter.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/config/AutoCpuConverter.java @@ -50,6 +50,8 @@ public String convert(String input) throws OptionsParsingException { switch (CPU.getCurrent()) { case X86_64: return "x64_windows"; + case AARCH64: + return "x64_arm64_windows"; default: // We only support x64 Windows for now. return "unknown"; diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ToolchainResolutionFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/ToolchainResolutionFunction.java index ada82a6d20c37a..8412b8d731ff3a 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/ToolchainResolutionFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/ToolchainResolutionFunction.java @@ -80,7 +80,7 @@ public UnloadedToolchainContext compute(SkyKey skyKey, Environment env) Preconditions.checkNotNull(configuration.getFragment(PlatformConfiguration.class)); // Check if debug output should be generated. - boolean debug = + boolean debug = configuration.getOptions().get(PlatformOptions.class).toolchainResolutionDebug; // Load the configured target for the toolchain types to ensure that they are valid and diff --git a/third_party/def_parser/def_parser.cc b/third_party/def_parser/def_parser.cc index 2ed2db6cd1c5dd..08b383f462439d 100644 --- a/third_party/def_parser/def_parser.cc +++ b/third_party/def_parser/def_parser.cc @@ -378,6 +378,7 @@ bool DumpFile(const char* filename, std::set& symbols, /* Does it look like a COFF OBJ file??? */ else if (((dosHeader->e_magic == IMAGE_FILE_MACHINE_I386) || (dosHeader->e_magic == IMAGE_FILE_MACHINE_AMD64) || + (dosHeader->e_magic == IMAGE_FILE_MACHINE_ARM64) || (dosHeader->e_magic == IMAGE_FILE_MACHINE_ARMNT)) && (dosHeader->e_sp == 0)) { /* diff --git a/third_party/grpc/BUILD b/third_party/grpc/BUILD index 5b33e42ca210b5..4c333c5da623c0 100644 --- a/third_party/grpc/BUILD +++ b/third_party/grpc/BUILD @@ -18,7 +18,7 @@ load("//tools/distributions:distribution_rules.bzl", "distrib_java_import", "dis licenses(["notice"]) # Apache v2 -exports_files(["grpc_1.33.1.patch"]) +exports_files(["grpc_1.33.1.patch", "grpc_1.41.0.win_arm64.patch"]) package(default_visibility = ["//visibility:public"]) diff --git a/third_party/grpc/grpc_1.41.0.win_arm64.patch b/third_party/grpc/grpc_1.41.0.win_arm64.patch new file mode 100644 index 00000000000000..355c9dd4bd57e8 --- /dev/null +++ b/third_party/grpc/grpc_1.41.0.win_arm64.patch @@ -0,0 +1,51 @@ +From 6ce08c3da545358074eb66dc4202e0474fa5be1b Mon Sep 17 00:00:00 2001 +From: Niyas Sait +Date: Fri, 26 Nov 2021 02:43:37 -0800 +Subject: [PATCH] add workarounds to compile for win/arm64 + +--- + src/core/lib/transport/transport.cc | 8 ++++---- + third_party/cares/cares.BUILD | 2 +- + 2 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/src/core/lib/transport/transport.cc b/src/core/lib/transport/transport.cc +index 36060a6bd9..db847d53d2 100644 +--- a/src/core/lib/transport/transport.cc ++++ b/src/core/lib/transport/transport.cc +@@ -99,16 +99,16 @@ void grpc_stream_ref_init(grpc_stream_refcount* refcount, int /*initial_refs*/, + refcount, &refcount->slice_refcount); + } + +-static void move64(uint64_t* from, uint64_t* to) { ++static void move64bits(uint64_t* from, uint64_t* to) { + *to += *from; + *from = 0; + } + + void grpc_transport_move_one_way_stats(grpc_transport_one_way_stats* from, + grpc_transport_one_way_stats* to) { +- move64(&from->framing_bytes, &to->framing_bytes); +- move64(&from->data_bytes, &to->data_bytes); +- move64(&from->header_bytes, &to->header_bytes); ++ move64bits(&from->framing_bytes, &to->framing_bytes); ++ move64bits(&from->data_bytes, &to->data_bytes); ++ move64bits(&from->header_bytes, &to->header_bytes); + } + + void grpc_transport_move_stats(grpc_transport_stream_stats* from, +diff --git a/third_party/cares/cares.BUILD b/third_party/cares/cares.BUILD +index 7939021a25..430791aa8d 100644 +--- a/third_party/cares/cares.BUILD ++++ b/third_party/cares/cares.BUILD +@@ -22,7 +22,7 @@ config_setting( + + config_setting( + name = "windows", +- values = {"cpu": "x64_windows"}, ++ constraint_values = ["@platforms//os:windows"], + ) + + # Android is not officially supported through C++. +-- +2.33.0.windows.2 + diff --git a/tools/cpp/BUILD.windows.tpl b/tools/cpp/BUILD.windows.tpl index 7c00426da393d6..4609d20162f8c0 100644 --- a/tools/cpp/BUILD.windows.tpl +++ b/tools/cpp/BUILD.windows.tpl @@ -59,6 +59,7 @@ cc_toolchain_suite( "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|clang-cl": ":cc-compiler-x64_arm64_windows-clang-cl", "x64_arm64_windows": ":cc-compiler-x64_arm64_windows", "armeabi-v7a": ":cc-compiler-armeabi-v7a", }, @@ -488,6 +489,71 @@ toolchain( toolchain_type = "@bazel_tools//tools/cpp:toolchain_type", ) +cc_toolchain( + name = "cc-compiler-x64_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 = "x64_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_arm64_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}], + tool_paths = { + "ar": "%{clang_cl_lib_path}", + "ml": "%{clang_cl_ml_path}", + "cpp": "%{clang_cl_cl_path}", + "gcc": "%{clang_cl_cl_path}", + "gcov": "wrapper/bin/msvc_nop.bat", + "ld": "%{clang_cl_link_path}", + "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}", + fastbuild_mode_debug_flag = "", +) + +toolchain( + name = "cc-toolchain-x64_arm64_windows-clang-cl", + exec_compatible_with = [ + "@platforms//os:windows", + "@bazel_tools//tools/cpp:clang-cl", + ], + target_compatible_with = [ + "@platforms//os:windows", + ], + toolchain = ":cc-compiler-x64_arm64_windows-clang-cl", + toolchain_type = "@bazel_tools//tools/cpp:toolchain_type", +) + cc_toolchain( name = "cc-compiler-armeabi-v7a", toolchain_identifier = "stub_armeabi-v7a", diff --git a/tools/cpp/cc_configure.bzl b/tools/cpp/cc_configure.bzl index 8e5acc2ee319b6..ecc565ff8b74c1 100644 --- a/tools/cpp/cc_configure.bzl +++ b/tools/cpp/cc_configure.bzl @@ -116,7 +116,7 @@ def cc_autoconf_impl(repository_ctx, overriden_tools = dict()): # container so skipping until we have proper tests for these platforms. repository_ctx.symlink(paths["@bazel_tools//tools/cpp:bsd_cc_toolchain_config.bzl"], "cc_toolchain_config.bzl") repository_ctx.symlink(paths["@bazel_tools//tools/cpp:BUILD.static.bsd"], "BUILD") - elif cpu_value == "x64_windows": + elif cpu_value in ["x64_windows", "x64_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) diff --git a/tools/cpp/lib_cc_configure.bzl b/tools/cpp/lib_cc_configure.bzl index 1464d8ca6688e5..e48db4d19bc793 100644 --- a/tools/cpp/lib_cc_configure.bzl +++ b/tools/cpp/lib_cc_configure.bzl @@ -189,7 +189,12 @@ def get_cpu_value(repository_ctx): if os_name.find("openbsd") != -1: return "openbsd" if os_name.find("windows") != -1: - return "x64_windows" + arch = (get_env_var(repository_ctx, "PROCESSOR_ARCHITECTURE", None, False) or + get_env_var(repository_ctx, "PROCESSOR_ARCHITEW6432", None, False)) + if arch == "ARM64": + return "x64_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"]) diff --git a/tools/cpp/windows_cc_configure.bzl b/tools/cpp/windows_cc_configure.bzl index fa7b3399abd4a7..20ce5ac77481f9 100644 --- a/tools/cpp/windows_cc_configure.bzl +++ b/tools/cpp/windows_cc_configure.bzl @@ -320,6 +320,9 @@ def _get_vc_env_vars(repository_ctx, vc_path, msvc_vars_x64, target_arch): 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 on arm64 builds host toolchain runs in an emulated x86 environment + if not repository_ctx.path(tools_path).exists: + tools_path = tools_path.replace("HostX64", "HostX86") 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] @@ -445,6 +448,9 @@ def find_msvc_tool(repository_ctx, vc_path, tool, target_arch = "x64"): full_version = _get_vc_full_version(repository_ctx, vc_path) if full_version: tool_path = "%s\\Tools\\MSVC\\%s\\bin\\HostX64\\%s\\%s" % (vc_path, full_version, target_arch, tool) + # For native windows on arm64 builds host toolchain runs in an emulated x86 environment + if not repository_ctx.path(tool_path).exists: + tool_path = tool_path.replace("HostX64", "HostX86") else: # For VS 2015 and older version, the tools are under: # C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64 @@ -686,7 +692,7 @@ def _get_clang_cl_vars(repository_ctx, paths, msvc_vars): """Get the variables we need to populate the clang-cl toolchains.""" llvm_path = find_llvm_path(repository_ctx) error_script = None - if msvc_vars["%{msvc_cl_path_x64}"] == "vc_installation_error_x64.bat": + if msvc_vars["%{msvc_cl_path_arm64}"] == "vc_installation_error_x64.bat": error_script = "vc_installation_error_x64.bat" elif not llvm_path: repository_ctx.template( @@ -738,18 +744,18 @@ def _get_clang_cl_vars(repository_ctx, paths, msvc_vars): 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_x64}"] + (",\n \"%s\"" % clang_include_path) + clang_cl_include_directories = msvc_vars["%{msvc_cxx_builtin_include_directories_arm64}"] + (",\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_env_tmp}": msvc_vars["%{msvc_env_tmp_x64}"], - "%{clang_cl_env_path}": msvc_vars["%{msvc_env_path_x64}"], - "%{clang_cl_env_include}": msvc_vars["%{msvc_env_include_x64}"] + ";" + clang_include_path, - "%{clang_cl_env_lib}": msvc_vars["%{msvc_env_lib_x64}"] + ";" + clang_lib_path, + "%{clang_cl_env_tmp}": msvc_vars["%{msvc_env_tmp_arm64}"], + "%{clang_cl_env_path}": msvc_vars["%{msvc_env_path_arm64}"], + "%{clang_cl_env_include}": msvc_vars["%{msvc_env_include_arm64}"] + ";" + clang_include_path, + "%{clang_cl_env_lib}": msvc_vars["%{msvc_env_lib_arm64}"] + ";" + clang_lib_path, "%{clang_cl_cxx_builtin_include_directories}": clang_cl_include_directories, "%{clang_cl_cl_path}": clang_cl_path, "%{clang_cl_link_path}": lld_link_path, "%{clang_cl_lib_path}": llvm_lib_path, - "%{clang_cl_ml_path}": msvc_vars["%{msvc_ml_path_x64}"], + "%{clang_cl_ml_path}": clang_cl_path, # LLVM's lld-link.exe doesn't support /DEBUG:FASTLINK. "%{clang_cl_dbg_mode_debug_flag}": "/DEBUG", "%{clang_cl_fastbuild_mode_debug_flag}": "/DEBUG", @@ -783,11 +789,12 @@ def configure_windows_toolchain(repository_ctx): template_vars = dict() 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)) 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)) - template_vars.update(_get_msvc_vars(repository_ctx, paths, "arm64", 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)) repository_ctx.template( "BUILD", diff --git a/tools/cpp/windows_cc_toolchain_config.bzl b/tools/cpp/windows_cc_toolchain_config.bzl index 0c4cf58ad5376c..3999e0f1040e50 100644 --- a/tools/cpp/windows_cc_toolchain_config.bzl +++ b/tools/cpp/windows_cc_toolchain_config.bzl @@ -80,7 +80,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", "x64_arm64_windows"] and (ctx.attr.compiler == "msvc-cl" or ctx.attr.compiler == "clang-cl") def _impl(ctx): if _use_msvc_toolchain(ctx): @@ -461,7 +461,7 @@ def _impl(ctx): ], ), ], - implies = ["generate_pdb_file"], + implies = [], ) user_compile_flags_feature = feature( @@ -533,6 +533,17 @@ def _impl(ctx): requires = [feature_set(features = ["dbg"])], ) + target_system_feature = feature( + name = "target_system", + enabled = ctx.attr.compiler == "clang-cl" and ctx.attr.target_system_name != "local", + flag_sets = [ + flag_set( + actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], + flag_groups = [flag_group(flags = ["--target="+ctx.attr.target_system_name])], + ) + ] + ) + dbg_feature = feature( name = "dbg", flag_sets = [ @@ -1078,6 +1089,7 @@ def _impl(ctx): static_link_msvcrt_debug_feature, dynamic_link_msvcrt_debug_feature, dbg_feature, + target_system_feature, fastbuild_feature, opt_feature, frame_pointer_feature, diff --git a/tools/def_parser/BUILD.tools b/tools/def_parser/BUILD.tools index cf756859a501f7..1821a0056bf145 100644 --- a/tools/def_parser/BUILD.tools +++ b/tools/def_parser/BUILD.tools @@ -13,7 +13,7 @@ filegroup( srcs = select({ "//src/conditions:host_windows": ["def_parser_windows"], "//conditions:default": [ - "no_op.bat", + "def_parser_windows", ], }), )