@@ -62,6 +62,27 @@ ToolChain::JobContext::getTemporaryFilePath(const llvm::Twine &name,
62
62
return C.getArgs ().MakeArgString (buffer.str ());
63
63
}
64
64
65
+ Optional<Job::ResponseFileInfo>
66
+ ToolChain::getResponseFileInfo (const Compilation &C, const char *executablePath,
67
+ const ToolChain::InvocationInfo &invocationInfo,
68
+ const ToolChain::JobContext &context) const {
69
+ const bool forceResponseFiles =
70
+ C.getArgs ().hasArg (options::OPT_driver_force_response_files);
71
+ assert ((invocationInfo.allowsResponseFiles || !forceResponseFiles) &&
72
+ " Cannot force response file if platform does not allow it" );
73
+
74
+ if (forceResponseFiles || (invocationInfo.allowsResponseFiles &&
75
+ !llvm::sys::commandLineFitsWithinSystemLimits (
76
+ executablePath, invocationInfo.Arguments ))) {
77
+ const char *responseFilePath =
78
+ context.getTemporaryFilePath (" arguments" , " resp" );
79
+ const char *responseFileArg =
80
+ C.getArgs ().MakeArgString (Twine (" @" ) + responseFilePath);
81
+ return {{responseFilePath, responseFileArg}};
82
+ }
83
+ return None;
84
+ }
85
+
65
86
std::unique_ptr<Job> ToolChain::constructJob (
66
87
const JobAction &JA, Compilation &C, SmallVectorImpl<const Job *> &&inputs,
67
88
ArrayRef<const Action *> inputActions,
@@ -114,28 +135,16 @@ std::unique_ptr<Job> ToolChain::constructJob(
114
135
}
115
136
}
116
137
117
- const char *responseFilePath = nullptr ;
118
- const char *responseFileArg = nullptr ;
119
-
120
- const bool forceResponseFiles =
121
- C.getArgs ().hasArg (options::OPT_driver_force_response_files);
122
- assert ((invocationInfo.allowsResponseFiles || !forceResponseFiles) &&
123
- " Cannot force response file if platform does not allow it" );
124
-
125
- if (forceResponseFiles || (invocationInfo.allowsResponseFiles &&
126
- !llvm::sys::commandLineFitsWithinSystemLimits (
127
- executablePath, invocationInfo.Arguments ))) {
128
- responseFilePath = context.getTemporaryFilePath (" arguments" , " resp" );
129
- responseFileArg = C.getArgs ().MakeArgString (Twine (" @" ) + responseFilePath);
130
- }
138
+ // Determine if the argument list is so long that it needs to be written into
139
+ // a response file.
140
+ auto responseFileInfo =
141
+ getResponseFileInfo (C, executablePath, invocationInfo, context);
131
142
132
- return llvm::make_unique<Job>(JA, std::move (inputs), std::move (output),
133
- executablePath,
134
- std::move (invocationInfo.Arguments ),
135
- std::move (invocationInfo.ExtraEnvironment ),
136
- std::move (invocationInfo.FilelistInfos ),
137
- responseFilePath,
138
- responseFileArg);
143
+ return llvm::make_unique<Job>(
144
+ JA, std::move (inputs), std::move (output), executablePath,
145
+ std::move (invocationInfo.Arguments ),
146
+ std::move (invocationInfo.ExtraEnvironment ),
147
+ std::move (invocationInfo.FilelistInfos ), responseFileInfo);
139
148
}
140
149
141
150
std::string
@@ -345,20 +354,26 @@ ToolChain::constructBatchJob(ArrayRef<const Job *> unsortedJobs,
345
354
*output, OI};
346
355
auto invocationInfo = constructInvocation (*batchCJA, context);
347
356
// Batch mode can produce quite long command lines; in almost every case these
348
- // will trigger use of supplementary output file maps, but in some rare corner
349
- // cases (very few files, very long paths) they might not. However, in those
350
- // cases we _should_ degrade to using response files to pass arguments to the
351
- // frontend, which is done automatically by code elsewhere.
357
+ // will trigger use of supplementary output file maps. However, if the driver
358
+ // command line is long for reasons unrelated to the number of input files,
359
+ // such as passing a large number of flags, then the individual batch jobs are
360
+ // also likely to overflow. We have to check for that explicitly here, because
361
+ // the BatchJob created here does not go through the same code path in
362
+ // constructJob above.
352
363
//
353
364
// The `allowsResponseFiles` flag on the `invocationInfo` we have here exists
354
365
// only to model external tools that don't know about response files, such as
355
366
// platform linkers; when talking to the frontend (which we control!) it
356
367
// should always be true. But double check with an assert here in case someone
357
368
// failed to set it in `constructInvocation`.
358
369
assert (invocationInfo.allowsResponseFiles );
370
+ auto responseFileInfo =
371
+ getResponseFileInfo (C, executablePath, invocationInfo, context);
372
+
359
373
return llvm::make_unique<BatchJob>(
360
374
*batchCJA, inputJobs.takeVector (), std::move (output), executablePath,
361
375
std::move (invocationInfo.Arguments ),
362
376
std::move (invocationInfo.ExtraEnvironment ),
363
- std::move (invocationInfo.FilelistInfos ), sortedJobs, NextQuasiPID);
377
+ std::move (invocationInfo.FilelistInfos ), sortedJobs, NextQuasiPID,
378
+ responseFileInfo);
364
379
}
0 commit comments