Skip to content

Commit 4c8d004

Browse files
authored
Changes to support RBE in Windows builds (#820)
This PR does a few things: 1. It changes how the Windows toolchain and SDK are fetched and where they are stored. Previously, the Windows toolchain and SDK were downloaded under `depot_tools`, which typically exists outside of the engine source root both locally and in CI. That setup makes the Windows SDK inaccessible to RBE builds. Instead, this PR checks out `depot_tools` under `flutter/third_party/depot_tools` by listing it in the `DEPS` file. This location is under the engine source root, and is therefore accessible to RBE builds. This change has the downside of breaking how CI does caching of the `depot_tools` Windows toolchain and SDK, which will add some time to builds. 2. It updates Windows GN toolchain setup logic to match what is in the Chrome tree. Updates to `build/find_depot_tools.py`, `build/toolchain/win/BUILD.gn`, and `build/toolchain/win/setup_toolchain.py` are copied from there and adapted to the Flutter engine repo.
1 parent 97f7dc4 commit 4c8d004

7 files changed

+407
-146
lines changed

build/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
# Generated file containing information about the VS toolchain on Windows
22
win_toolchain.json
3+
new_win_toolchain.json
34
/linux/debian_*-sysroot/

build/config/BUILDCONFIG.gn

+5-12
Original file line numberDiff line numberDiff line change
@@ -526,13 +526,9 @@ if (custom_toolchain != "") {
526526
host_toolchain = "//build/toolchain/linux:clang_$host_cpu"
527527
set_default_toolchain("//build/toolchain/custom")
528528
} else if (is_win) {
529-
if (is_clang) {
530-
host_toolchain = "//build/toolchain/win:clang_$host_cpu"
531-
set_default_toolchain("//build/toolchain/win:clang_$current_cpu")
532-
} else {
533-
host_toolchain = "//build/toolchain/win:$host_cpu"
534-
set_default_toolchain("//build/toolchain/win:$current_cpu")
535-
}
529+
assert(is_clang)
530+
host_toolchain = "//build/toolchain/win:clang_$host_cpu"
531+
set_default_toolchain("//build/toolchain/win:clang_$current_cpu")
536532
} else if (is_android) {
537533
if (host_os == "linux") {
538534
# Use clang for the x86/64 Linux host builds.
@@ -544,11 +540,8 @@ if (custom_toolchain != "") {
544540
} else if (host_os == "mac") {
545541
host_toolchain = "//build/toolchain/mac:clang_$host_cpu"
546542
} else if (host_os == "win") {
547-
if (is_clang) {
548-
host_toolchain = "//build/toolchain/win:clang_$host_cpu"
549-
} else {
550-
host_toolchain = "//build/toolchain/win:$host_cpu"
551-
}
543+
assert(is_clang)
544+
host_toolchain = "//build/toolchain/win:clang_$host_cpu"
552545
} else {
553546
assert(false, "Unknown host for android cross compile")
554547
}

build/find_depot_tools.py

+33-4
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,41 @@
1-
# Copyright (c) 2011 The Chromium Authors. All rights reserved.
1+
#!/usr/bin/env python3
2+
# Copyright 2011 The Chromium Authors
23
# Use of this source code is governed by a BSD-style license that can be
34
# found in the LICENSE file.
45
"""Small utility function to find depot_tools and add it to the python path.
56
67
Will throw an ImportError exception if depot_tools can't be found since it
78
imports breakpad.
9+
10+
This can also be used as a standalone script to print out the depot_tools
11+
directory location.
812
"""
913

14+
1015
import os
1116
import sys
1217

1318

19+
# Path to //src
20+
SRC = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir))
21+
22+
1423
def IsRealDepotTools(path):
15-
return os.path.isfile(os.path.join(path, 'gclient.py'))
24+
expanded_path = os.path.expanduser(path)
25+
return os.path.isfile(os.path.join(expanded_path, 'gclient.py'))
1626

1727

1828
def add_depot_tools_to_path():
1929
"""Search for depot_tools and add it to sys.path."""
20-
# First look if depot_tools is already in PYTHONPATH.
30+
# First, check if we have a DEPS'd in "depot_tools".
31+
deps_depot_tools = os.path.join(SRC, 'flutter', 'third_party', 'depot_tools')
32+
if IsRealDepotTools(deps_depot_tools):
33+
# Put the pinned version at the start of the sys.path, in case there
34+
# are other non-pinned versions already on the sys.path.
35+
sys.path.insert(0, deps_depot_tools)
36+
return deps_depot_tools
37+
38+
# Then look if depot_tools is already in PYTHONPATH.
2139
for i in sys.path:
2240
if i.rstrip(os.sep).endswith('depot_tools') and IsRealDepotTools(i):
2341
return i
@@ -39,7 +57,18 @@ def add_depot_tools_to_path():
3957
print('Failed to find depot_tools', file=sys.stderr)
4058
return None
4159

42-
add_depot_tools_to_path()
60+
DEPOT_TOOLS_PATH = add_depot_tools_to_path()
4361

4462
# pylint: disable=W0611
4563
import breakpad
64+
65+
66+
def main():
67+
if DEPOT_TOOLS_PATH is None:
68+
return 1
69+
print(DEPOT_TOOLS_PATH)
70+
return 0
71+
72+
73+
if __name__ == '__main__':
74+
sys.exit(main())

build/toolchain/win/BUILD.gn

+76-55
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
# Use of this source code is governed by a BSD-style license that can be
33
# found in the LICENSE file.
44

5+
import("//build/toolchain/rbe.gni")
6+
import("//build/toolchain/win/win_toolchain_data.gni")
7+
58
default_clang_base_path = "//buildtools/windows-x64/clang"
69

710
declare_args() {
@@ -31,23 +34,18 @@ assert(is_win)
3134
# This tool will is used as a wrapper for various commands below.
3235
tool_wrapper_path = rebase_path("tool_wrapper.py", root_build_dir)
3336

34-
toolchain_data = exec_script("setup_toolchain.py",
35-
[
36-
visual_studio_path,
37-
windows_sdk_path,
38-
visual_studio_runtime_dirs,
39-
current_cpu,
40-
],
41-
"scope")
42-
43-
if (vc_bin_dir == "") {
44-
vc_bin_dir = toolchain_data.vc_bin_dir
45-
}
46-
4737
if (use_goma) {
48-
goma_prefix = "$goma_dir/gomacc.exe "
38+
compiler_prefix = "$goma_dir/gomacc.exe "
39+
asm_prefix = "$goma_dir/gomacc.exe "
40+
} else if (use_rbe) {
41+
compiler_args = rewrapper_command + [
42+
"--labels=type=compile,compiler=clang-cl,lang=cpp ",
43+
]
44+
compiler_prefix = string_join(" ", compiler_args)
45+
asm_prefix = " "
4946
} else {
50-
goma_prefix = ""
47+
compiler_prefix = ""
48+
asm_prefix = ""
5149
}
5250

5351
if (current_toolchain == default_toolchain) {
@@ -80,48 +78,73 @@ template("msvc_toolchain") {
8078
}
8179
}
8280

81+
# TODO(zanderso): Assert that clang is always used or remove this logic.
82+
if (defined(toolchain_args.is_clang)) {
83+
toolchain_is_clang = toolchain_args.is_clang
84+
} else {
85+
toolchain_is_clang = is_clang
86+
}
87+
8388
env = invoker.environment
89+
env_path = "$root_out_dir/$env"
90+
print(env_path)
91+
env_file = read_file(env_path, "string")
92+
print(env_file)
8493

8594
cl = invoker.cl
8695

8796
# Make these apply to all tools below.
8897
lib_switch = ""
8998
lib_dir_switch = "/LIBPATH:"
9099

91-
tool("cc") {
92-
rspfile = "{{output}}.rsp"
100+
# If possible, pass system includes as flags to the compiler. When that's
101+
# not possible, load a full environment file (containing %INCLUDE% and
102+
# %PATH%) -- e.g. 32-bit MSVS builds require %PATH% to be set and just
103+
# passing in a list of include directories isn't enough.
104+
if (defined(invoker.sys_include_flags)) {
105+
assert(toolchain_is_clang)
106+
env_wrapper = ""
107+
sys_include_flags =
108+
"${invoker.sys_include_flags} " # Note trailing space.
109+
} else {
110+
# clang-cl doesn't need this env hoop, so omit it there.
111+
assert(!toolchain_is_clang)
112+
env_wrapper = "ninja -t msvc -e $env -- " # Note trailing space.
113+
sys_include_flags = ""
114+
}
93115

94-
# TODO(brettw) enable this when GN support in the binary has been rolled.
95-
#precompiled_header_type = "msvc"
96-
pdbname = "{{target_out_dir}}/{{target_output_name}}_c.pdb"
97-
command = "ninja -t msvc -e $env -- $cl /nologo /showIncludes @$rspfile /c {{source}} /Fo{{output}} /Fd$pdbname"
116+
tool("cc") {
117+
precompiled_header_type = "msvc"
118+
pdbname = "{{target_out_dir}}/{{label_name}}_c.pdb"
98119
depsformat = "msvc"
99120
description = "CC {{output}}"
100-
outputs = [
101-
"{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.obj",
102-
]
103-
rspfile_content = "{{defines}} {{include_dirs}} {{cflags}} {{cflags_c}}"
121+
outputs = [ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.obj" ]
122+
123+
# Label names may have spaces in them so the pdbname must be quoted. The
124+
# source and output don't need to be quoted because GN knows they're a
125+
# full file name and will quote automatically when necessary.
126+
command = "$env_wrapper$cl /c {{source}} /nologo /showIncludes:user $sys_include_flags{{defines}} {{include_dirs}} {{cflags}} {{cflags_c}} /Fo{{output}} /Fd\"$pdbname\""
104127
}
105128

106129
tool("cxx") {
107-
rspfile = "{{output}}.rsp"
108-
109-
# TODO(brettw) enable this when GN support in the binary has been rolled.
110-
#precompiled_header_type = "msvc"
130+
precompiled_header_type = "msvc"
111131

112132
# The PDB name needs to be different between C and C++ compiled files.
113-
pdbname = "{{target_out_dir}}/{{target_output_name}}_cc.pdb"
133+
pdbname = "{{target_out_dir}}/{{label_name}}_cc.pdb"
134+
135+
# TODO(zanderso): This logic should be moved to be with the other compiler
136+
# flag logic in build/config/compiler/BUILD.gn or so.
114137
flags = ""
115138
if (is_clang && invoker.current_cpu == "x86") {
116139
flags = "-m32"
117140
}
118-
command = "ninja -t msvc -e $env -- $cl $flags /nologo /showIncludes @$rspfile /c {{source}} /Fo{{output}} /Fd$pdbname"
141+
119142
depsformat = "msvc"
120143
description = "CXX {{output}}"
121-
outputs = [
122-
"{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.obj",
123-
]
124-
rspfile_content = "{{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}}"
144+
outputs = [ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.obj" ]
145+
146+
# See comment in CC tool about quoting.
147+
command = "$env_wrapper$cl /c {{source}} /Fo{{output}} $flags /nologo /showIncludes:user $sys_include_flags{{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}} /Fd\"$pdbname\""
125148
}
126149

127150
tool("rc") {
@@ -141,7 +164,7 @@ template("msvc_toolchain") {
141164
} else if (toolchain_args.current_cpu == "arm64") {
142165
is_msvc_assembler = false
143166
prefix = rebase_path("$clang_base_path/bin", root_build_dir)
144-
ml = "${goma_prefix}${prefix}/clang-cl.exe --target=arm64-windows"
167+
ml = "${compiler_prefix}${prefix}/clang-cl.exe --target=arm64-windows"
145168
x64 = ""
146169
} else {
147170
ml = "ml.exe"
@@ -175,14 +198,11 @@ template("msvc_toolchain") {
175198
}
176199

177200
tool("solink") {
178-
dllname = "{{root_out_dir}}/{{target_output_name}}{{output_extension}}" # e.g.
179-
# foo.dll
180-
libname = "{{root_out_dir}}/{{target_output_name}}{{output_extension}}.lib" # e.g.
181-
# foo.dll.lib
182-
expname = "{{root_out_dir}}/{{target_output_name}}{{output_extension}}.exp" # e.g.
183-
# foo.dll.exp
184-
pdbname = "{{root_out_dir}}/{{target_output_name}}{{output_extension}}.pdb" # e.g.
185-
# foo.dll.pdb
201+
# E.g. "foo.dll":
202+
dllname = "{{root_out_dir}}/{{target_output_name}}{{output_extension}}"
203+
libname = "${dllname}.lib" # e.g. foo.dll.lib
204+
expname = "${dllname}.exp"
205+
pdbname = "${dllname}.pdb"
186206
rspfile = "${dllname}.rsp"
187207

188208
link_command = "$python_path $tool_wrapper_path link-wrapper $env False link.exe /nologo /IMPLIB:$libname /DLL /OUT:$dllname /PDB:${dllname}.pdb @$rspfile"
@@ -253,21 +273,22 @@ template("win_toolchains") {
253273
assert(defined(invoker.toolchain_arch))
254274
toolchain_arch = invoker.toolchain_arch
255275

256-
msvc_toolchain(target_name) {
257-
environment = "environment." + toolchain_arch
258-
cl = "${goma_prefix}\"${vc_bin_dir}/cl.exe\""
259-
toolchain_args = {
260-
if (defined(invoker.toolchain_args)) {
261-
forward_variables_from(invoker.toolchain_args, "*")
262-
}
263-
current_cpu = toolchain_arch
264-
is_clang = false
265-
}
276+
# The toolchain data for `msvc_toolchain()`.
277+
if (toolchain_arch == "x86") {
278+
win_toolchain_data = win_toolchain_data_x86
279+
} else if (toolchain_arch == "x64") {
280+
win_toolchain_data = win_toolchain_data_x64
281+
} else if (toolchain_arch == "arm64") {
282+
win_toolchain_data = win_toolchain_data_arm64
283+
} else {
284+
error("Unsupported toolchain_arch, add it to win_toolchain_data.gni")
266285
}
286+
267287
msvc_toolchain("clang_" + target_name) {
268288
environment = "environment." + toolchain_arch
269289
prefix = rebase_path("$clang_base_path/bin", root_build_dir)
270-
cl = "${goma_prefix}$prefix/clang-cl.exe"
290+
cl = "${compiler_prefix}$prefix/clang-cl.exe"
291+
sys_include_flags = "${win_toolchain_data.include_flags_imsvc}"
271292
toolchain_args = {
272293
if (defined(invoker.toolchain_args)) {
273294
forward_variables_from(invoker.toolchain_args, "*")

0 commit comments

Comments
 (0)