LLVM IR pass中,如何提取当前Module的绝对路径?
In LLVM IR pass, how to extract an absolute path of the current Module?
标题说明了一切。我正在编写一个 LLVM IR 模块通道,需要知道与当前模块对应的源代码的绝对路径。我知道如何提取源代码的 name(通过 Module 中的 getSourceFileName()),但我需要的是源代码的完整路径,包括绝对目录路径。我怎样才能找到这个?如果有解决方法,那也行。
好的,我要在这里回答我自己的问题。您可以在 IR/CodeGen/AsmWriter/AsmWriter.cpp:emitRemarksSection()
中找到 LLVM 如何在内部恢复绝对路径。基本上把源码的路径还原成现在clang是运行的当前路径。执行此操作的 API 函数已由 LLVM 提供。
参照此,我们将一个模块的文件名转换为它的完整路径。
- 获取文件名。
std::string Filename = M.getSourceFileName();
- 将其转换为
char
向量。
llvm::SmallString<128> FilenameVec = StringRef(Filename);
- 使其成为完整路径。
llvm::sys::fs::make_absolute(FilenameVec);
文件完整路径直接存储到 FilenameVec
。您需要包含 llvm/Support/FileSystem.h
才能使用 make_absolute()
.
您可以通过将以下代码(正确地)粘贴到任何工作的 IR pass 来尝试。
#include <string>
#include "llvm/Support/FileSystem.h"
...
std::string Filename = M.getSourceFileName(); // e.g., Filename = aaa.c
llvm::SmallString<128> FilenameVec = StringRef(Filename);
llvm::sys::fs::make_absolute(FilenameVec); // e.g., FilenameVec = /path/to/aaa.c
非常感谢@Gwangmu 提出和回答这个问题。为确保生成的完整路径不包含相关组件(例如 /path/to/../aaa.c)并且跨平台一致(例如包括 Windows),您可以调用 real_path 函数,然后将其转换为通用格式。整个片段看起来像:
std::string relFilename = M.getSourceFileName(); // e.g., relFilename = ..\aaa.c
llvm::SmallString<128> FilenameVec = StringRef(Filename);
llvm::SmallString<128> RealPath;
llvm::sys::fs::real_path(FilenameVec, RealPath); // e.g., RealPath = \path\to\aaa.c <-- in Windows
//
filesystem::path fp {string(RealPath)};
string genericFilePath = fp.generic_string(); // genericFilePath = /path/to/aaa.c
标题说明了一切。我正在编写一个 LLVM IR 模块通道,需要知道与当前模块对应的源代码的绝对路径。我知道如何提取源代码的 name(通过 Module 中的 getSourceFileName()),但我需要的是源代码的完整路径,包括绝对目录路径。我怎样才能找到这个?如果有解决方法,那也行。
好的,我要在这里回答我自己的问题。您可以在 IR/CodeGen/AsmWriter/AsmWriter.cpp:emitRemarksSection()
中找到 LLVM 如何在内部恢复绝对路径。基本上把源码的路径还原成现在clang是运行的当前路径。执行此操作的 API 函数已由 LLVM 提供。
参照此,我们将一个模块的文件名转换为它的完整路径。
- 获取文件名。
std::string Filename = M.getSourceFileName();
- 将其转换为
char
向量。
llvm::SmallString<128> FilenameVec = StringRef(Filename);
- 使其成为完整路径。
llvm::sys::fs::make_absolute(FilenameVec);
文件完整路径直接存储到 FilenameVec
。您需要包含 llvm/Support/FileSystem.h
才能使用 make_absolute()
.
您可以通过将以下代码(正确地)粘贴到任何工作的 IR pass 来尝试。
#include <string>
#include "llvm/Support/FileSystem.h"
...
std::string Filename = M.getSourceFileName(); // e.g., Filename = aaa.c
llvm::SmallString<128> FilenameVec = StringRef(Filename);
llvm::sys::fs::make_absolute(FilenameVec); // e.g., FilenameVec = /path/to/aaa.c
非常感谢@Gwangmu 提出和回答这个问题。为确保生成的完整路径不包含相关组件(例如 /path/to/../aaa.c)并且跨平台一致(例如包括 Windows),您可以调用 real_path 函数,然后将其转换为通用格式。整个片段看起来像:
std::string relFilename = M.getSourceFileName(); // e.g., relFilename = ..\aaa.c
llvm::SmallString<128> FilenameVec = StringRef(Filename);
llvm::SmallString<128> RealPath;
llvm::sys::fs::real_path(FilenameVec, RealPath); // e.g., RealPath = \path\to\aaa.c <-- in Windows
//
filesystem::path fp {string(RealPath)};
string genericFilePath = fp.generic_string(); // genericFilePath = /path/to/aaa.c