Windows: Windows SDK version can be specified through BAZEL_WINSDK_FULL_VERSION Fixes https://github.com/bazelbuild/bazel/issues/8721 Closes #8747. PiperOrigin-RevId: 255958288
diff --git a/site/docs/windows.md b/site/docs/windows.md index 262cc56..3043b7b 100644 --- a/site/docs/windows.md +++ b/site/docs/windows.md
@@ -184,7 +184,19 @@ SDK](https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk). The Windows SDK contains header files and libraries you need when building - Windows applications, including Bazel itself. + Windows applications, including Bazel itself. By default, the latest Windows SDK installed will + be used. You also can specify Windows SDK version by setting `BAZEL_WINSDK_FULL_VERSION`. You + can use a full Windows 10 SDK number such as 10.0.10240.0, or specify 8.1 to use the Windows 8.1 + SDK (only one version of Windows 8.1 SDK is available). Please make sure you have the specified + Windows SDK installed. + + **Requirement**: This is supported with VC 2017 and 2019. The standalone VC 2015 Build Tools doesn't + support selecting Windows SDK, you'll need the full Visual Studio 2015 installation, otherwise + `BAZEL_WINSDK_FULL_VERSION` will be ignored. + + ``` + set BAZEL_WINSDK_FULL_VERSION=10.0.10240.0 + ``` If everything is set up, you can build a C++ target now!
diff --git a/tools/cpp/cc_configure.bzl b/tools/cpp/cc_configure.bzl index 66dce02..b2e2080 100644 --- a/tools/cpp/cc_configure.bzl +++ b/tools/cpp/cc_configure.bzl
@@ -139,6 +139,7 @@ "BAZEL_VC", "BAZEL_VC_FULL_VERSION", "BAZEL_VS", + "BAZEL_WINSDK_FULL_VERSION", "BAZEL_LLVM", "USE_CLANG_CL", "CC",
diff --git a/tools/cpp/windows_cc_configure.bzl b/tools/cpp/windows_cc_configure.bzl index dcdf3d6..5a52486 100644 --- a/tools/cpp/windows_cc_configure.bzl +++ b/tools/cpp/windows_cc_configure.bzl
@@ -229,32 +229,58 @@ # C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\ return vc_path.find("2017") != -1 or vc_path.find("2019") != -1 -def _find_vcvarsall_bat_script(repository_ctx, vc_path): - """Find vcvarsall.bat script. Doesn't %-escape the result.""" +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): - vcvarsall = vc_path + "\\Auxiliary\\Build\\VCVARSALL.BAT" + vcvars_script = vc_path + "\\Auxiliary\\Build\\VCVARSALL.BAT" else: - vcvarsall = vc_path + "\\VCVARSALL.BAT" + vcvars_script = vc_path + "\\VCVARSALL.BAT" - if not repository_ctx.path(vcvarsall).exists: + if not repository_ctx.path(vcvars_script).exists: return None - return vcvarsall + return vcvars_script + +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): + 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") + for tool in ["devenv.exe", "wdexpress.exe"]: + if vc_common_ide.get_child(tool).exists: + return True + return False def setup_vc_env_vars(repository_ctx, vc_path): - """Get environment variables set by VCVARSALL.BAT. Doesn't %-escape the result!""" - vcvarsall = _find_vcvarsall_bat_script(repository_ctx, vc_path) - if not vcvarsall: - return None + """Get environment variables set by VCVARSALL.BAT script. Doesn't %-escape the result!""" + vcvars_script = _find_vcvars_bat_script(repository_ctx, vc_path) + if not vcvars_script: + auto_configure_fail("Cannot find VCVARSALL.BAT script under %s" % vc_path) + + # Getting Windows SDK version set by user. + # Only supports VC 2017 & 2019 and VC 2015 with full VS installation. + winsdk_version = _get_winsdk_full_version(repository_ctx) + if winsdk_version and not _is_support_winsdk_selection(repository_ctx, vc_path): + auto_configure_warning(("BAZEL_WINSDK_FULL_VERSION=%s is ignored, " + + "because standalone Visual C++ Build Tools 2015 doesn't support specifying Windows " + + "SDK version, please install the full VS 2015 or use VC 2017/2019.") % winsdk_version) + winsdk_version = "" + + # Get VC version set by user. Only supports VC 2017 & 2019. vcvars_ver = "" if _is_vs_2017_or_2019(vc_path): full_version = _get_vc_full_version(repository_ctx, vc_path) if full_version: vcvars_ver = "-vcvars_ver=" + full_version + + cmd = "\"%s\" amd64 %s %s" % (vcvars_script, winsdk_version, vcvars_ver) repository_ctx.file( "get_env.bat", "@echo off\n" + - ("call \"%s\" amd64 %s > NUL \n" % (vcvarsall, vcvars_ver)) + + ("call %s > NUL \n" % cmd) + "echo PATH=%PATH%,INCLUDE=%INCLUDE%,LIB=%LIB%,WINDOWSSDKDIR=%WINDOWSSDKDIR% \n", True, ) @@ -267,8 +293,17 @@ for env in envs: key, value = env.split("=", 1) env_map[key] = escape_string(value.replace("\\", "\\\\")) + _check_env_vars(env_map, cmd) return env_map +def _check_env_vars(env_map, cmd): + envs = ["PATH", "INCLUDE", "LIB", "WINDOWSSDKDIR"] + for env in envs: + if not env_map.get(env): + auto_configure_fail( + "Setting up VC environment variables failed, %s is not set by the following command:\n %s" % (env, cmd), + ) + def _get_latest_subversion(repository_ctx, vc_path): """Get the latest subversion of a VS 2017/2019 installation. @@ -300,6 +335,10 @@ return repository_ctx.os.environ["BAZEL_VC_FULL_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 = "") + 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.""" tool_path = None @@ -320,7 +359,7 @@ def _find_missing_vc_tools(repository_ctx, vc_path): """Check if any required tool is missing under given VC path.""" missing_tools = [] - if not _find_vcvarsall_bat_script(repository_ctx, vc_path): + 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"]: