diff --git a/recipes/README.recipes.md b/recipes/README.recipes.md
index 0ae0f00f1..bdc84101b 100644
--- a/recipes/README.recipes.md
+++ b/recipes/README.recipes.md
@@ -14,7 +14,7 @@
* [osx_sdk](#recipe_modules-osx_sdk) (Python3 ✅) — The `osx_sdk` module provides safe functions to access a semi-hermetic XCode installation.
* [presubmit](#recipe_modules-presubmit) (Python3 ✅)
* [tryserver](#recipe_modules-tryserver) (Python3 ✅)
- * [windows_sdk](#recipe_modules-windows_sdk) (Python3 ✅) — The `windows_sdk` module provides safe functions to access a hermetic Microsoft Visual Studio installation.
+ * [windows_sdk](#recipe_modules-windows_sdk) (Python3 ✅) — The `windows_sdk` module provides safe functions to access a hermetic Microsoft Visual Studio installation which is derived from Chromium's MSVC toolchain.
**[Recipes](#Recipes)**
* [bot_update:examples/full](#recipes-bot_update_examples_full) (Python3 ✅)
@@ -920,15 +920,20 @@ timeout.
PYTHON_VERSION_COMPATIBILITY: PY2+3
The `windows_sdk` module provides safe functions to access a hermetic
-Microsoft Visual Studio installation.
+Microsoft Visual Studio installation which is derived from Chromium's MSVC
+toolchain.
-Available only to Google-run bots.
+See (internal):
+ * go/chromium-msvc-toolchain
+ * go/windows-sdk-cipd-update
+
+Available only on Google-run bots.
-#### **class [WindowsSDKApi](/recipes/recipe_modules/windows_sdk/api.py#17)([RecipeApi][recipe_engine/wkt/RecipeApi]):**
+#### **class [WindowsSDKApi](/recipes/recipe_modules/windows_sdk/api.py#22)([RecipeApi][recipe_engine/wkt/RecipeApi]):**
API for using Windows SDK distributed via CIPD.
- **@contextmanager**
— **def [\_\_call\_\_](/recipes/recipe_modules/windows_sdk/api.py#27)(self, path=None, version=None, enabled=True, target_arch='x64'):**
+ **@contextmanager**
— **def [\_\_call\_\_](/recipes/recipe_modules/windows_sdk/api.py#32)(self, path=None, version=None, enabled=True, target_arch='x64'):**
Sets up the SDK environment when enabled.
diff --git a/recipes/recipe_modules/windows_sdk/api.py b/recipes/recipe_modules/windows_sdk/api.py
index 2d0e1aab2..6249c9a7c 100644
--- a/recipes/recipe_modules/windows_sdk/api.py
+++ b/recipes/recipe_modules/windows_sdk/api.py
@@ -3,9 +3,14 @@
# found in the LICENSE file.
"""The `windows_sdk` module provides safe functions to access a hermetic
-Microsoft Visual Studio installation.
+Microsoft Visual Studio installation which is derived from Chromium's MSVC
+toolchain.
-Available only to Google-run bots.
+See (internal):
+ * go/chromium-msvc-toolchain
+ * go/windows-sdk-cipd-update
+
+Available only on Google-run bots.
"""
import collections
@@ -94,27 +99,21 @@ class WindowsSDKApi(recipe_api.RecipeApi):
env = {}
env_prefixes = {}
- # Load .../win_sdk/bin/SetEnv.${arch}.json to extract the required
- # environment. It contains a dict that looks like this:
- # {
- # "env": {
- # "VAR": [["..", "..", "x"], ["..", "..", "y"]],
- # ...
- # }
- # }
- # All these environment variables need to be added to the environment
- # for the compiler and linker to work.
- assert target_arch in ('x86', 'x64')
- filename = 'SetEnv.%s.json' % target_arch
- step_result = self.m.json.read(
- 'read %s' % filename, sdk_dir.join('win_sdk', 'bin', filename),
- step_test_data=lambda: self.m.json.test_api.output({
- 'env': {
- 'PATH': [['..', '..', 'win_sdk', 'bin', 'x64']],
- 'VSINSTALLDIR': [['..', '..\\']],
- },
- }))
- data = step_result.json.output.get('env')
+ if target_arch not in ('x86', 'x64', 'arm64'):
+ raise ValueError('unknown architecture {!r}'.format(target_arch))
+
+ data = self.m.step('read SetEnv json', [
+ 'python3',
+ self.resource('find_env_json.py'), '--sdk_root', sdk_dir,
+ '--target_arch', target_arch,
+ self.m.json.output()
+ ],
+ step_test_data=lambda: self.m.json.test_api.output({
+ 'env': {
+ 'PATH': [['..', '..', 'win_sdk', 'bin', 'x64']],
+ 'VSINSTALLDIR': [['..', '..\\']],
+ },
+ })).json.output.get('env')
for key in data:
# recipes' Path() does not like .., ., \, or /, so this is cumbersome.
# What we want to do is:
diff --git a/recipes/recipe_modules/windows_sdk/examples/full.expected/linux.json b/recipes/recipe_modules/windows_sdk/examples/full.expected/linux.json
index 5b0f35212..ff5de65d2 100644
--- a/recipes/recipe_modules/windows_sdk/examples/full.expected/linux.json
+++ b/recipes/recipe_modules/windows_sdk/examples/full.expected/linux.json
@@ -15,6 +15,45 @@
],
"name": "ninja"
},
+ {
+ "cmd": [
+ "cipd",
+ "ensure",
+ "-root",
+ "[CACHE]/windows_sdk",
+ "-ensure-file",
+ "chrome_internal/third_party/sdk/windows uploaded:2018-06-13",
+ "-max-threads",
+ "0",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "infra_step": true,
+ "name": "ensure_installed",
+ "~followup_annotations": [
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"\": [@@@",
+ "@@@STEP_LOG_LINE@json.output@ {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"resolved-instance_id-of-uploaded:2018-06\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"chrome_internal/third_party/sdk/windows\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@ ]@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "taskkill.exe",
+ "/f",
+ "/t",
+ "/im",
+ "mspdbsrv.exe"
+ ],
+ "name": "taskkill mspdbsrv"
+ },
{
"name": "$result"
}
diff --git a/recipes/recipe_modules/windows_sdk/examples/full.expected/mac.json b/recipes/recipe_modules/windows_sdk/examples/full.expected/mac.json
index 5b0f35212..ff5de65d2 100644
--- a/recipes/recipe_modules/windows_sdk/examples/full.expected/mac.json
+++ b/recipes/recipe_modules/windows_sdk/examples/full.expected/mac.json
@@ -15,6 +15,45 @@
],
"name": "ninja"
},
+ {
+ "cmd": [
+ "cipd",
+ "ensure",
+ "-root",
+ "[CACHE]/windows_sdk",
+ "-ensure-file",
+ "chrome_internal/third_party/sdk/windows uploaded:2018-06-13",
+ "-max-threads",
+ "0",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "infra_step": true,
+ "name": "ensure_installed",
+ "~followup_annotations": [
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"\": [@@@",
+ "@@@STEP_LOG_LINE@json.output@ {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"resolved-instance_id-of-uploaded:2018-06\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"chrome_internal/third_party/sdk/windows\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@ ]@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "taskkill.exe",
+ "/f",
+ "/t",
+ "/im",
+ "mspdbsrv.exe"
+ ],
+ "name": "taskkill mspdbsrv"
+ },
{
"name": "$result"
}
diff --git a/recipes/recipe_modules/windows_sdk/examples/full.expected/win.json b/recipes/recipe_modules/windows_sdk/examples/full.expected/win.json
index a9f859347..4de24c915 100644
--- a/recipes/recipe_modules/windows_sdk/examples/full.expected/win.json
+++ b/recipes/recipe_modules/windows_sdk/examples/full.expected/win.json
@@ -30,13 +30,15 @@
},
{
"cmd": [
- "python",
- "-u",
- "\nimport shutil\nimport sys\nshutil.copy(sys.argv[1], sys.argv[2])\n",
- "[CACHE]\\windows_sdk\\win_sdk\\bin\\SetEnv.x64.json",
+ "python3",
+ "RECIPE_MODULE[depot_tools::windows_sdk]\\resources\\find_env_json.py",
+ "--sdk_root",
+ "[CACHE]\\windows_sdk",
+ "--target_arch",
+ "x64",
"/path/to/tmp/json"
],
- "name": "read SetEnv.x64.json",
+ "name": "read SetEnv json",
"~followup_annotations": [
"@@@STEP_LOG_LINE@json.output@{@@@",
"@@@STEP_LOG_LINE@json.output@ \"env\": {@@@",
@@ -102,6 +104,45 @@
],
"name": "taskkill mspdbsrv"
},
+ {
+ "cmd": [
+ "cipd.bat",
+ "ensure",
+ "-root",
+ "[CACHE]\\windows_sdk",
+ "-ensure-file",
+ "chrome_internal/third_party/sdk/windows uploaded:2018-06-13",
+ "-max-threads",
+ "0",
+ "-json-output",
+ "/path/to/tmp/json"
+ ],
+ "infra_step": true,
+ "name": "ensure_installed (2)",
+ "~followup_annotations": [
+ "@@@STEP_LOG_LINE@json.output@{@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"result\": {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"\": [@@@",
+ "@@@STEP_LOG_LINE@json.output@ {@@@",
+ "@@@STEP_LOG_LINE@json.output@ \"instance_id\": \"resolved-instance_id-of-uploaded:2018-06\", @@@",
+ "@@@STEP_LOG_LINE@json.output@ \"package\": \"chrome_internal/third_party/sdk/windows\"@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@ ]@@@",
+ "@@@STEP_LOG_LINE@json.output@ }@@@",
+ "@@@STEP_LOG_LINE@json.output@}@@@",
+ "@@@STEP_LOG_END@json.output@@@"
+ ]
+ },
+ {
+ "cmd": [
+ "taskkill.exe",
+ "/f",
+ "/t",
+ "/im",
+ "mspdbsrv.exe"
+ ],
+ "name": "taskkill mspdbsrv (2)"
+ },
{
"name": "$result"
}
diff --git a/recipes/recipe_modules/windows_sdk/examples/full.py b/recipes/recipe_modules/windows_sdk/examples/full.py
index 64648f20e..e3792597b 100644
--- a/recipes/recipe_modules/windows_sdk/examples/full.py
+++ b/recipes/recipe_modules/windows_sdk/examples/full.py
@@ -17,6 +17,13 @@ def RunSteps(api):
api.step('gn', ['gn', 'gen', 'out/Release'])
api.step('ninja', ['ninja', '-C', 'out/Release'])
+ # bad arch
+ try:
+ with api.windows_sdk(target_arch='lolnope'):
+ assert False, "never here" # pragma: no cover
+ except ValueError:
+ pass
+
def GenTests(api):
for platform in ('linux', 'mac', 'win'):
diff --git a/recipes/recipe_modules/windows_sdk/resources/find_env_json.py b/recipes/recipe_modules/windows_sdk/resources/find_env_json.py
new file mode 100755
index 000000000..70dc1af6b
--- /dev/null
+++ b/recipes/recipe_modules/windows_sdk/resources/find_env_json.py
@@ -0,0 +1,70 @@
+#!/usr/bin/env python3
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""
+This script finds the SetEnv.*.json file from an unpacked Windows SDK.
+"""
+
+import argparse
+import os
+import sys
+
+POSSIBLE_BASE_LOCATIONS = [
+ # Older SDKs just used the raw 'bin' directory
+ os.path.join("win_sdk", "bin"),
+
+ # SDK versions after 19041
+ os.path.join("win_sdk", "Windows Kits", "10", "bin"),
+]
+
+SDK_ARCHITECTURES = frozenset([
+ "x86",
+ "x64",
+ "arm64",
+])
+
+
+def main():
+ parser = argparse.ArgumentParser(
+ description='Find the SetEnv from a windows SDK')
+ parser.add_argument('--sdk_root',
+ metavar='PATH',
+ required=True,
+ help='The absolute path to the root of the unpacked SDK')
+ parser.add_argument('--target_arch',
+ choices=SDK_ARCHITECTURES,
+ required=True,
+ help='The target architecture')
+ parser.add_argument('--output_json',
+ required=True,
+ help='The absolute path to an output json file')
+ args = parser.parse_args()
+
+ if not os.path.isabs(args.sdk_root):
+ parser.error("sdk_root must be absolute, got {!r}".format(args.sdk_root))
+
+ if not os.path.isabs(args.output_json):
+ parser.error("output_json must be absolute, got {!r}".format(
+ args.output_json))
+
+ with open(args.output_json, 'w', encoding="utf-8") as outf:
+ tail = "SetEnv.{}.json".format(args.target_arch)
+ for loc in POSSIBLE_BASE_LOCATIONS:
+ full = os.path.join(args.sdk_root, loc, tail)
+ print("Attempting:", full)
+ try:
+ with open(full, encoding="utf-8") as set_env_json:
+ print("> Found it!")
+ outf.write(set_env_json.read())
+ return
+ except OSError as ex:
+ print("> Failed:", ex)
+ continue
+
+ print("Unable to locate SetEnv file")
+ sys.exit(1)
+
+
+if __name__ == '__main__':
+ main()