Fix response file support for batch jobs.

This commit is contained in:
Tony Allevato
2019-04-12 13:29:50 -07:00
committed by Tony Allevato
parent 9a6fa09729
commit 6d7223023d
5 changed files with 94 additions and 51 deletions

View File

@@ -62,6 +62,27 @@ ToolChain::JobContext::getTemporaryFilePath(const llvm::Twine &name,
return C.getArgs().MakeArgString(buffer.str());
}
Optional<Job::ResponseFileInfo>
ToolChain::getResponseFileInfo(const Compilation &C, const char *executablePath,
const ToolChain::InvocationInfo &invocationInfo,
const ToolChain::JobContext &context) const {
const bool forceResponseFiles =
C.getArgs().hasArg(options::OPT_driver_force_response_files);
assert((invocationInfo.allowsResponseFiles || !forceResponseFiles) &&
"Cannot force response file if platform does not allow it");
if (forceResponseFiles || (invocationInfo.allowsResponseFiles &&
!llvm::sys::commandLineFitsWithinSystemLimits(
executablePath, invocationInfo.Arguments))) {
const char *responseFilePath =
context.getTemporaryFilePath("arguments", "resp");
const char *responseFileArg =
C.getArgs().MakeArgString(Twine("@") + responseFilePath);
return {{responseFilePath, responseFileArg}};
}
return None;
}
std::unique_ptr<Job> ToolChain::constructJob(
const JobAction &JA, Compilation &C, SmallVectorImpl<const Job *> &&inputs,
ArrayRef<const Action *> inputActions,
@@ -114,28 +135,16 @@ std::unique_ptr<Job> ToolChain::constructJob(
}
}
const char *responseFilePath = nullptr;
const char *responseFileArg = nullptr;
// Determine if the argument list is so long that it needs to be written into
// a response file.
auto responseFileInfo =
getResponseFileInfo(C, executablePath, invocationInfo, context);
const bool forceResponseFiles =
C.getArgs().hasArg(options::OPT_driver_force_response_files);
assert((invocationInfo.allowsResponseFiles || !forceResponseFiles) &&
"Cannot force response file if platform does not allow it");
if (forceResponseFiles || (invocationInfo.allowsResponseFiles &&
!llvm::sys::commandLineFitsWithinSystemLimits(
executablePath, invocationInfo.Arguments))) {
responseFilePath = context.getTemporaryFilePath("arguments", "resp");
responseFileArg = C.getArgs().MakeArgString(Twine("@") + responseFilePath);
}
return llvm::make_unique<Job>(JA, std::move(inputs), std::move(output),
executablePath,
std::move(invocationInfo.Arguments),
std::move(invocationInfo.ExtraEnvironment),
std::move(invocationInfo.FilelistInfos),
responseFilePath,
responseFileArg);
return llvm::make_unique<Job>(
JA, std::move(inputs), std::move(output), executablePath,
std::move(invocationInfo.Arguments),
std::move(invocationInfo.ExtraEnvironment),
std::move(invocationInfo.FilelistInfos), responseFileInfo);
}
std::string
@@ -345,10 +354,12 @@ ToolChain::constructBatchJob(ArrayRef<const Job *> unsortedJobs,
*output, OI};
auto invocationInfo = constructInvocation(*batchCJA, context);
// Batch mode can produce quite long command lines; in almost every case these
// will trigger use of supplementary output file maps, but in some rare corner
// cases (very few files, very long paths) they might not. However, in those
// cases we _should_ degrade to using response files to pass arguments to the
// frontend, which is done automatically by code elsewhere.
// will trigger use of supplementary output file maps. However, if the driver
// command line is long for reasons unrelated to the number of input files,
// such as passing a large number of flags, then the individual batch jobs are
// also likely to overflow. We have to check for that explicitly here, because
// the BatchJob created here does not go through the same code path in
// constructJob above.
//
// The `allowsResponseFiles` flag on the `invocationInfo` we have here exists
// only to model external tools that don't know about response files, such as
@@ -356,9 +367,13 @@ ToolChain::constructBatchJob(ArrayRef<const Job *> unsortedJobs,
// should always be true. But double check with an assert here in case someone
// failed to set it in `constructInvocation`.
assert(invocationInfo.allowsResponseFiles);
auto responseFileInfo =
getResponseFileInfo(C, executablePath, invocationInfo, context);
return llvm::make_unique<BatchJob>(
*batchCJA, inputJobs.takeVector(), std::move(output), executablePath,
std::move(invocationInfo.Arguments),
std::move(invocationInfo.ExtraEnvironment),
std::move(invocationInfo.FilelistInfos), sortedJobs, NextQuasiPID);
std::move(invocationInfo.FilelistInfos), sortedJobs, NextQuasiPID,
responseFileInfo);
}