我正在使用一些LLVM工具(如llvm-nm
)作为静态库。即我复制了源llvm-nm.cpp,将main(..)
重命名为llvm_nm(..)
并将其编译为静态库。我想将标准输出转发到我的文件。
我尝试使用下一种方法:
int out_fd, err_fd;
fpos_t out_pos, err_pos;
// redirect out
fflush(stdout);
fgetpos(stdout, &out_pos);
out_fd = dup(fileno(stdout));
freopen(outFilename, "w", stdout);
// execute
int ret = llvm_nm(argc_, argv_);
// restore output
fflush(stdout);
dup2(out_fd, fileno(stdout));
close(out_fd);
clearerr(stdout);
fsetpos(stdout, &out_pos);
问题在于它没有被转发(如果我在nm源代码中添加printf()
但在nm
输出中没有添加它会有效)。我已经浏览了源代码,我可以看到输出是使用llvm::outs()
stream:
outs() << "Archive map" << "\n";
it's implemented下一个方式:
/// outs() - This returns a reference to a raw_ostream for standard output.
00702 /// Use it like: outs() << "foo" << "bar";
00703 raw_ostream &llvm::outs() {
00704 // Set buffer settings to model stdout behavior.
00705 // Delete the file descriptor when the program exits, forcing error
00706 // detection. If you don't want this behavior, don't use outs().
00707 static raw_fd_ostream S(STDOUT_FILENO, true);
00708 return S;
00709 }
如何将该输出重定向到我的文件?
答案 0 :(得分:5)
我意识到这是一个老问题,然而,我发现它查找了llvm&lt; out流()流的一些简单信息,我发现here。
llvm附带的一个例子&#34; BrainF&#34;像这样使用它:
...
raw_ostream *out = &outs();
if (!JIT) {
if (OutputFilename == "") {
std::string base = InputFilename;
if (InputFilename == "-") { base = "a"; }
// Use default filename.
OutputFilename = base+".bc";
}
if (OutputFilename != "-") {
std::error_code EC;
out = new raw_fd_ostream(OutputFilename, EC, sys::fs::F_None);
}
}
...
if (out != &outs())
delete out;
...
所以它似乎表明您可以安全地重定向。
注意:在此示例中,OutputFilename / InputFilename是使用llvm&#39支持库CommandLine创建的std :: string类型。
答案 1 :(得分:2)
似乎没有一种简单的方法:llvm::raw_fd_ostream
和llvm::raw_ostream
中没有复制/作业构造函数。并且freopen
技巧无效,因为文件descritor整数用于初始化llvm::outs()
返回的对象。
我看到的唯一方法是使用LD_PRELOAD动态更改llvm::outs()
的实现,或类似的链接器技巧,但这对我来说听起来非常糟糕。也许将原始符号标记为弱,然后在库中覆盖它?