Skip to content

Commit 3ba5090

Browse files
committed
Always use a param file when calling into rustc.
The argument list seems to constantly overflow on Windows (for reasons that I don't really understand since `use_param_file` should dynamically switch to using a param file in these cases), so always generate a param file.
1 parent 8205991 commit 3ba5090

File tree

6 files changed

+116
-44
lines changed

6 files changed

+116
-44
lines changed

rust/private/rustc.bzl

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -484,7 +484,8 @@ def construct_arguments(
484484
force_all_deps_direct = False,
485485
force_link = False,
486486
stamp = False,
487-
remap_path_prefix = "."):
487+
remap_path_prefix = ".",
488+
use_param_file_for_rustc_args = True):
488489
"""Builds an Args object containing common rustc flags
489490
490491
Args:
@@ -510,6 +511,7 @@ def construct_arguments(
510511
stamp (bool, optional): Whether or not workspace status stamping is enabled. For more details see
511512
https://docs.bazel.build/versions/main/user-manual.html#flag--stamp
512513
remap_path_prefix (str, optional): A value used to remap `${pwd}` to. If set to a falsey value, no prefix will be set.
514+
use_param_file_for_rustc_args(bool, optional): Whether Bazel should use a param file to pass the arguments to rustc.
513515
514516
Returns:
515517
tuple: A tuple of the following items
@@ -584,8 +586,11 @@ def construct_arguments(
584586

585587
# Rustc arguments
586588
rustc_flags = ctx.actions.args()
587-
rustc_flags.set_param_file_format("multiline")
588-
rustc_flags.use_param_file("@%s", use_always = False)
589+
590+
if use_param_file_for_rustc_args:
591+
rustc_flags.set_param_file_format("multiline")
592+
rustc_flags.use_param_file("@%s", use_always = True)
593+
589594
rustc_flags.add(crate_info.root)
590595
rustc_flags.add("--crate-name=" + crate_info.name)
591596
rustc_flags.add("--crate-type=" + crate_info.type)

rust/private/rustdoc.bzl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ def rustdoc_compile_action(
4848
toolchain,
4949
crate_info,
5050
output = None,
51-
rustdoc_flags = []):
51+
rustdoc_flags = [],
52+
use_param_file_for_rustc_args = True):
5253
"""Create a struct of information needed for a `rustdoc` compile action based on crate passed to the rustdoc rule.
5354
5455
Args:
@@ -57,6 +58,7 @@ def rustdoc_compile_action(
5758
crate_info (CrateInfo): The provider of the crate passed to a rustdoc rule.
5859
output (File, optional): An optional output a `rustdoc` action is intended to produce.
5960
rustdoc_flags (list, optional): A list of `rustdoc` specific flags.
61+
use_param_file_for_rustc_args(bool, optional): Whether Bazel should use a param file to pass the arguments to rustc.
6062
6163
Returns:
6264
struct: A struct of some `ctx.actions.run` arguments.
@@ -117,6 +119,7 @@ def rustdoc_compile_action(
117119
emit = [],
118120
remap_path_prefix = None,
119121
force_link = True,
122+
use_param_file_for_rustc_args = use_param_file_for_rustc_args,
120123
)
121124

122125
return struct(

rust/private/rustdoc_test.bzl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,9 @@ def _rust_doc_test_impl(ctx):
117117
toolchain = find_toolchain(ctx),
118118
crate_info = crate_info,
119119
rustdoc_flags = rustdoc_flags,
120+
# The arguments are written to a script file that is used to run the
121+
# tests and the args point to a param file outside of the `runfiles`.
122+
use_param_file_for_rustc_args = False,
120123
)
121124

122125
tools = action.tools + [ctx.executable._process_wrapper]

util/process_wrapper/process_wrapper.cc

Lines changed: 69 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,6 @@ int PW_MAIN(int argc, const CharType* argv[], const CharType* envp[]) {
3838

3939
System::EnvironmentBlock environment_file_block;
4040

41-
using Subst = std::pair<System::StrType, System::StrType>;
42-
4341
System::StrType exec_path;
4442
std::vector<Subst> subst_mappings;
4543
std::vector<Subst> stamp_mappings;
@@ -79,7 +77,8 @@ int PW_MAIN(int argc, const CharType* argv[], const CharType* envp[]) {
7977
if (value == PW_SYS_STR("${pwd}")) {
8078
value = System::GetWorkingDirectory();
8179
}
82-
subst_mappings.push_back({std::move(key), std::move(value)});
80+
subst_mappings.push_back({PW_SYS_STR("${") + key + PW_SYS_STR("}"),
81+
std::move(value)});
8382
} else if (arg == PW_SYS_STR("--volatile-status-file")) {
8483
if (!volatile_status_file.empty()) {
8584
std::cerr << "process wrapper error: \"--volatile-status-file\" can "
@@ -90,11 +89,11 @@ int PW_MAIN(int argc, const CharType* argv[], const CharType* envp[]) {
9089
return -1;
9190
}
9291
} else if (arg == PW_SYS_STR("--env-file")) {
93-
if (!ReadFileToArray(argv[i], environment_file_block)) {
92+
if (!ReadFileToVec(argv[i], environment_file_block)) {
9493
return -1;
9594
}
9695
} else if (arg == PW_SYS_STR("--arg-file")) {
97-
if (!ReadFileToArray(argv[i], file_arguments)) {
96+
if (!ReadFileToVec(argv[i], file_arguments)) {
9897
return -1;
9998
}
10099
} else if (arg == PW_SYS_STR("--touch-file")) {
@@ -143,24 +142,77 @@ int PW_MAIN(int argc, const CharType* argv[], const CharType* envp[]) {
143142
for (++i; i < argc; ++i) {
144143
arguments.push_back(argv[i]);
145144
}
146-
// after we consume all arguments we append the files arguments
147-
for (const System::StrType& file_arg : file_arguments) {
148-
arguments.push_back(file_arg);
149-
}
150145
} else {
151146
std::cerr << "process wrapper error: unknow argument \"" << ToUtf8(arg)
152147
<< "\"." << '\n';
153148
return -1;
154149
}
155150
}
156151

152+
// Expand tokens into the file arguments (since some paths might embed
153+
// `${pwd}` that we need to resolve from the subsitution mappings).
154+
for (System::StrType& file_arg : file_arguments) {
155+
ReplaceTokens(file_arg, subst_mappings);
156+
}
157+
158+
// Process the arguments, making sure that we don't have paths to param files
159+
// within another param file (that is an arg composed of `@` + a path), which
160+
// rustc doesn't support.
161+
System::StrVecType param_file_arguments;
162+
for (auto arg_it = arguments.begin(); arg_it != arguments.end(); arg_it++) {
163+
System::StrType& arg = *arg_it;
164+
ReplaceTokens(arg, subst_mappings);
165+
166+
// Check whether this is a regular argument or a path to a param file.
167+
if (arg.size() > 0 && arg.substr(0, 1) == PW_SYS_STR("@")) {
168+
System::StrType path = arg.substr(1);
169+
170+
// Read the actual params off the param file so that we can 1) extract
171+
// potential other param files inside and 2) substitute mappings.
172+
System::StrVecType params;
173+
if (!ReadFileToVec(path, params)) {
174+
std::cerr << "Cannot read param file " << ToUtf8(path) << "\n";
175+
return -1;
176+
}
177+
178+
for (auto par_it = params.begin(); par_it != params.end(); par_it++) {
179+
System::StrType& param = *par_it;
180+
ReplaceTokens(param, subst_mappings);
181+
182+
// If we find a path to a param file, move it to the top-level file
183+
// arguments instead (we cannot have nested param files).
184+
if (param.size() > 0 && param.substr(0, 1) == PW_SYS_STR("@")) {
185+
param_file_arguments.push_back(param);
186+
params.erase(par_it--);
187+
}
188+
}
189+
190+
// Create a new param file so that we don't need to edit the original one
191+
// that Bazel created.
192+
System::StrType new_path = path + PW_SYS_STR(".expanded");
193+
if (!WriteVecToFile(new_path, params)) {
194+
std::cerr << "Cannot write params to file " << ToUtf8(new_path) << "\n";
195+
return -1;
196+
}
197+
198+
param_file_arguments.push_back(PW_SYS_STR("@") + new_path);
199+
arguments.erase(arg_it--);
200+
}
201+
}
202+
203+
// After we consume all arguments we append the param files arguments and the
204+
// remaining of the files arguments
205+
for (const System::StrType& file_arg : param_file_arguments) {
206+
arguments.push_back(file_arg);
207+
}
208+
for (const System::StrType& file_arg : file_arguments) {
209+
arguments.push_back(file_arg);
210+
}
211+
157212
// Stamp any format string in an environment variable block
158-
for (const Subst& stamp : stamp_mappings) {
159-
System::StrType token = PW_SYS_STR("{");
160-
token += stamp.first;
161-
token.push_back('}');
213+
if (stamp_mappings.size()) {
162214
for (System::StrType& env : environment_file_block) {
163-
ReplaceToken(env, token, stamp.second);
215+
ReplaceTokens(env, stamp_mappings);
164216
}
165217
}
166218

@@ -171,19 +223,9 @@ int PW_MAIN(int argc, const CharType* argv[], const CharType* envp[]) {
171223
environment_file_block.begin(),
172224
environment_file_block.end());
173225

174-
if (subst_mappings.size()) {
175-
for (const Subst& subst : subst_mappings) {
176-
System::StrType token = PW_SYS_STR("${");
177-
token += subst.first;
178-
token.push_back('}');
179-
for (System::StrType& arg : arguments) {
180-
ReplaceToken(arg, token, subst.second);
181-
}
182-
183-
for (System::StrType& env : environment_block) {
184-
ReplaceToken(env, token, subst.second);
185-
}
186-
}
226+
// Expand tokens in environment
227+
for (System::StrType& env : environment_block) {
228+
ReplaceTokens(env, subst_mappings);
187229
}
188230

189231
// Have the last values added take precedence over the first.

util/process_wrapper/utils.cc

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,16 +41,17 @@ std::string ToUtf8(const System::StrType& string) {
4141
#endif // defined(PW_WIN_UNICODE)
4242
}
4343

44-
void ReplaceToken(System::StrType& str, const System::StrType& token,
45-
const System::StrType& replacement) {
46-
std::size_t pos = str.find(token);
47-
if (pos != std::string::npos) {
48-
str.replace(pos, token.size(), replacement);
44+
void ReplaceTokens(System::StrType& str, const std::vector<Subst>& substs) {
45+
for (const Subst& subst : substs) {
46+
std::size_t pos = str.find(subst.first);
47+
if (pos != std::string::npos) {
48+
str.replace(pos, subst.first.size(), subst.second);
49+
}
4950
}
5051
}
5152

52-
bool ReadFileToArray(const System::StrType& file_path,
53-
System::StrVecType& vec) {
53+
bool ReadFileToVec(const System::StrType& file_path,
54+
System::StrVecType& vec) {
5455
std::ifstream file(file_path);
5556
if (file.fail()) {
5657
std::cerr << "process wrapper error: failed to open file: "
@@ -101,12 +102,25 @@ bool ReadFileToArray(const System::StrType& file_path,
101102
return true;
102103
}
103104

105+
bool WriteVecToFile(const System::StrType& file_path, const System::StrVecType& vec) {
106+
std::ofstream file(file_path, std::ofstream::out | std::ofstream::trunc);
107+
if (file.fail()) {
108+
std::cerr << "process wrapper error: failed to open file: "
109+
<< ToUtf8(file_path) << '\n';
110+
return false;
111+
}
112+
for (const System::StrType& line : vec) {
113+
file << ToUtf8(line) << std::endl;
114+
}
115+
return true;
116+
}
117+
104118
bool ReadStampStatusToArray(
105119
const System::StrType& stamp_path,
106120
std::vector<std::pair<System::StrType, System::StrType>>& vec) {
107121
// Read each line of the stamp file and split on the first space
108122
System::StrVecType stamp_block;
109-
if (!ReadFileToArray(stamp_path, stamp_block)) {
123+
if (!ReadFileToVec(stamp_path, stamp_block)) {
110124
return false;
111125
}
112126

@@ -118,7 +132,8 @@ bool ReadStampStatusToArray(
118132
<< ToUtf8(stamp_block[i]) << "\".\n";
119133
return false;
120134
}
121-
System::StrType key = stamp_block[i].substr(0, space_pos);
135+
System::StrType key =
136+
PW_SYS_STR("{") + stamp_block[i].substr(0, space_pos) + PW_SYS_STR("}");
122137
System::StrType value =
123138
stamp_block[i].substr(space_pos + 1, stamp_block[i].size());
124139
vec.push_back({std::move(key), std::move(value)});

util/process_wrapper/utils.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,20 @@
2121

2222
namespace process_wrapper {
2323

24+
using Subst = std::pair<System::StrType, System::StrType>;
25+
2426
// Converts to and frin the system string format
2527
System::StrType FromUtf8(const std::string& string);
2628
std::string ToUtf8(const System::StrType& string);
2729

28-
// Replaces a token in str by replacement
29-
void ReplaceToken(System::StrType& str, const System::StrType& token,
30-
const System::StrType& replacement);
30+
// Replaces tokens in str by replacement
31+
void ReplaceTokens(System::StrType& str, const std::vector<Subst>& substs);
3132

3233
// Reads a file in text mode and feeds each line to item in the vec output
33-
bool ReadFileToArray(const System::StrType& file_path, System::StrVecType& vec);
34+
bool ReadFileToVec(const System::StrType& file_path, System::StrVecType& vec);
35+
36+
// Write the content of an array file as lines in a file
37+
bool WriteVecToFile(const System::StrType& file_path, const System::StrVecType& vec);
3438

3539
// Reads a workspace status stamp file to an array of key value pairs
3640
bool ReadStampStatusToArray(

0 commit comments

Comments
 (0)