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"]: