Skip to content

Commit 87d0b80

Browse files
authored
[libclang][reproducers] Redirect writing output to the reproducer cache directory. (#11853)
The intention is to keep reproducers relocatable. Without redirection we are trying to write output to "/some/path/existing/only/where/reproducer/generated.o" and failing to do so. Instead we redirect the output to the reproducer cache directory which is a relative path that is guaranteed to exist. .pcm files are the output too but we don't redirect them because they should be written and read from a specific place which is controlled by `LookupOutput` callback.
1 parent ebacbc3 commit 87d0b80

File tree

2 files changed

+16
-4
lines changed

2 files changed

+16
-4
lines changed

clang/test/Modules/reproducer-with-module-dependencies.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ void test(void) {
6767

6868
//--- script-expectations.txt
6969
CHECK: CLANG:-clang-executable
70+
CHECK: "-o" "reproducer.cache/reproducer.o"
7071
CHECK: -fmodule-file=Test=reproducer.cache/explicitly-built-modules/Test-{{.*}}.pcm
7172
Verify the reproducer VFS overlay is added before the existing overlay provided on a command line.
7273
CHECK: -ivfsoverlay "reproducer.cache/vfs/vfs.yaml"

clang/tools/libclang/CDependencies.cpp

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -835,7 +835,8 @@ enum CXErrorCode clang_experimental_DependencyScanner_generateReproducer(
835835
std::string ReproExecutable = "\"${CLANG:-" + Opts.BuildArgs.front() + "}\"";
836836
auto PrintArguments = [&ReproExecutable, &FileCacheName,
837837
&ClangOpts](llvm::raw_fd_ostream &OS,
838-
ArrayRef<std::string> Arguments) {
838+
ArrayRef<std::string> Arguments,
839+
bool RedirectOutput) {
839840
std::vector<const char *> CharArgs(Arguments.size());
840841
for (const std::string &Arg : Arguments)
841842
CharArgs.push_back(Arg.c_str());
@@ -853,11 +854,19 @@ enum CXErrorCode clang_experimental_DependencyScanner_generateReproducer(
853854
DidAddVFSOverlay = true;
854855
}
855856
}
857+
bool IsOutputArg = Arg->getOption().matches(options::OPT_o);
856858
llvm::opt::ArgStringList OutArgs;
857859
Arg->render(ParsedArgs, OutArgs);
860+
bool IsArgValue = false;
858861
for (const auto &OutArg : OutArgs) {
859862
OS << ' ';
860-
llvm::sys::printArg(OS, OutArg, /*Quote=*/true);
863+
if (RedirectOutput && IsOutputArg && IsArgValue) {
864+
StringRef OutputFileName = llvm::sys::path::filename(OutArg);
865+
OS << " \"" << FileCacheName << '/' << OutputFileName << '"';
866+
} else {
867+
llvm::sys::printArg(OS, OutArg, /*Quote=*/true);
868+
}
869+
IsArgValue = true;
861870
}
862871
}
863872
if (!DidAddVFSOverlay) {
@@ -866,11 +875,13 @@ enum CXErrorCode clang_experimental_DependencyScanner_generateReproducer(
866875
}
867876
OS << '\n';
868877
};
878+
// Redirect the output to keep reproducers relocatable. But don't redirect
879+
// modules as they are already in the appropriate place (see `LookupOutput`).
869880
for (ModuleDeps &Dep : TU.ModuleGraph)
870-
PrintArguments(ScriptOS, Dep.getBuildArguments());
881+
PrintArguments(ScriptOS, Dep.getBuildArguments(), /*RedirectOutput=*/false);
871882
ScriptOS << "\n# Translation unit:\n";
872883
for (const Command &BuildCommand : TU.Commands)
873-
PrintArguments(ScriptOS, BuildCommand.Arguments);
884+
PrintArguments(ScriptOS, BuildCommand.Arguments, /*RedirectOutput=*/true);
874885

875886
auto RealFS = llvm::vfs::getRealFileSystem();
876887
RealFS->setCurrentWorkingDirectory(*Opts.WorkingDirectory);

0 commit comments

Comments
 (0)