如何在 Visual Studio 中使用 LibTooling/Clang?
How can I use LibTooling/Clang in Visual Studio?
我正在尝试使用 LibTooling 替换 C 代码文件中的函数和变量名称。因此,我下载了 llvm 并按照说明在 windows 中使用 GMake 和 Visual Studio 2015.
进行了设置。
我想学习很多教程(例如 this one),但它们都假定您使用的是 Linux/Make,因此它们提供了一个 Makefile,以某种方式管理集成到llvm 源代码。
我想做的是在 Visual Studio 中使用这些示例,但我不知道从哪里开始 - 我可以在给定的 (llvn.sln) 解决方案中创建一个新项目并在那里添加代码?我如何告诉 Visual Studio 包含 clang 源(如我提到的那些 Makefile 中所定义)?
使用 VisualGDB 或类似的应用程序,可以在 Visual Studio 上编写代码并在 linux 机器上编译。这就是我现在正在做的。
我已经在 linux 虚拟机和我的 windows 7 OS 中安装了 clang,我有一个 Visual studio 2010。它运行良好。
最好使用 Cmake 生成 visual studio 项目文件,然后您可以使用 visual studio 构建这些文件。
本教程向您展示了它是如何完成的:
https://llvm.org/docs/CMake.html
环境:Windows10 X64,VS2017,CMake 3.9.3
参考:
https://clang.llvm.org/get_started.html
创建工作目录,如D:\software\LLVM
下载 LLVM 和 Clang 源代码(版本 6.0.0):
http://releases.llvm.org/6.0.0/llvm-6.0.0.src.tar.xz
http://releases.llvm.org/6.0.0/cfe-6.0.0.src.tar.xz
将它们解压到工作目录,并将它们重命名为 llvm 和 clang(删除版本代码):
D:\software\LLVM\llvm
D:\software\LLVM\clang
如果你在文件夹名称中保留版本代码,那么稍后 CMake 会说找不到文件夹 "clang"
在工作目录下创建一个构建输出目录,如:
D:\software\LLVM\build-x86
对于 x64(仅当您需要 x64 构建时):
D:\software\LLVM\build-x64
进入构建输出目录:
cd D:\software\LLVM\build-x86
运行 cmake,对于 x86 构建:
cmake -DLLVM_ENABLE_PROJECTS=clang -G "Visual Studio 15 2017" -A Win32 -Thost=x64 ..\llvm
对于 x64 构建:
cmake -DLLVM_ENABLE_PROJECTS=clang -G "Visual Studio 15 2017" -A x64 -Thost=x64 ..\llvm
注意:最好只启用你的clang需要支持的目标,否则构建过程会很慢。要仅构建您的 clang 将支持的目标,请使用
-DLLVM_TARGETS_TO_BUILD=target_list
例如:
-DLLVM_TARGETS_TO_BUILD="X86;ARM"
所有目标的列表似乎在:
D:\software\LLVM\llvm\bindings\python\llvm\disassembler.py
他们是:
_targets = ['AArch64', 'ARM', 'Hexagon', 'MSP430', 'Mips', 'NVPTX', 'PowerPC', 'R600', 'Sparc', 'SystemZ', 'X86', 'XCore']
所以x86好像同时包含了x86和x64。
CMake 将生成一个 VS 解决方案文件:
D:\software\LLVM\build-x86\LLVM.sln
用VS2017打开,只需要构建子组"Clang libraries",我的构建是默认的Debug构建
现在引用是https://kevinaboos.wordpress.com/2013/07/23/clang-tutorial-part-ii-libtooling-example/
但该页面中的代码适用于旧版本的 LLVM,因此无法编译。
这是 LLVM6.0.0 的工作代码:
在 VS2017 中创建一个 C++ 控制台应用程序。
进入debug/x86配置。
在项目属性对话框中,对于 debug/win32 配置,
修改"Disable Specific Warnings"为:
4146
修改"Additional Include Directories"为:
D:\software\LLVM\clang\include;D:\software\LLVM\llvm\include;D:\software\LLVM\build-x86\include;D:\software\LLVM\build-x86\tools\clang\include;%(AdditionalIncludeDirectories)
修改"Additional Library Directories"为:
D:\software\LLVM\build-x86\Debug\lib;%(AdditionalLibraryDirectories)
修改"Additional Dependencies"为:
Mincore.lib;clangAnalysis.lib;clangARCMigrate.lib;clangAST.lib;clangASTMatchers.lib;clangBasic.lib;clangCodeGen.lib;clangCrossTU.lib;clangDriver.lib;clangDynamicASTMatchers.lib;clangEdit.lib;clangFormat.lib;clangFrontend.lib;clangFrontendTool.lib;clangHandleCXX.lib;clangIndex.lib;clangLex.lib;clangParse.lib;clangRewrite.lib;clangRewriteFrontend.lib;clangSema.lib;clangSerialization.lib;clangStaticAnalyzerCheckers.lib;clangStaticAnalyzerCore.lib;clangStaticAnalyzerFrontend.lib;clangTooling.lib;clangToolingASTDiff.lib;clangToolingCore.lib;clangToolingRefactor.lib;libclang.lib;LLVMAArch64AsmParser.lib;LLVMAArch64AsmPrinter.lib;LLVMAArch64CodeGen.lib;LLVMAArch64Desc.lib;LLVMAArch64Disassembler.lib;LLVMAArch64Info.lib;LLVMAArch64Utils.lib;LLVMAMDGPUAsmParser.lib;LLVMAMDGPUAsmPrinter.lib;LLVMAMDGPUCodeGen.lib;LLVMAMDGPUDesc.lib;LLVMAMDGPUDisassembler.lib;LLVMAMDGPUInfo.lib;LLVMAMDGPUUtils.lib;LLVMAnalysis.lib;LLVMARMAsmParser.lib;LLVMARMAsmPrinter.lib;LLVMARMCodeGen.lib;LLVMARMDesc.lib;LLVMARMDisassembler.lib;LLVMARMInfo.lib;LLVMARMUtils.lib;LLVMAsmParser.lib;LLVMAsmPrinter.lib;LLVMBinaryFormat.lib;LLVMBitReader.lib;LLVMBitWriter.lib;LLVMBPFAsmParser.lib;LLVMBPFAsmPrinter.lib;LLVMBPFCodeGen.lib;LLVMBPFDesc.lib;LLVMBPFDisassembler.lib;LLVMBPFInfo.lib;LLVMCodeGen.lib;LLVMCore.lib;LLVMDebugInfoCodeView.lib;LLVMDebugInfoMSF.lib;LLVMDemangle.lib;LLVMGlobalISel.lib;LLVMHexagonAsmParser.lib;LLVMHexagonCodeGen.lib;LLVMHexagonDesc.lib;LLVMHexagonDisassembler.lib;LLVMHexagonInfo.lib;LLVMInstCombine.lib;LLVMInstrumentation.lib;LLVMipo.lib;LLVMIRReader.lib;LLVMLanaiAsmParser.lib;LLVMLanaiAsmPrinter.lib;LLVMLanaiCodeGen.lib;LLVMLanaiDesc.lib;LLVMLanaiDisassembler.lib;LLVMLanaiInfo.lib;LLVMLinker.lib;LLVMMC.lib;LLVMMCDisassembler.lib;LLVMMCParser.lib;LLVMMipsAsmParser.lib;LLVMMipsAsmPrinter.lib;LLVMMipsCodeGen.lib;LLVMMipsDesc.lib;LLVMMipsDisassembler.lib;LLVMMipsInfo.lib;LLVMMSP430AsmPrinter.lib;LLVMMSP430CodeGen.lib;LLVMMSP430Desc.lib;LLVMMSP430Info.lib;LLVMNVPTXAsmPrinter.lib;LLVMNVPTXCodeGen.lib;LLVMNVPTXDesc.lib;LLVMNVPTXInfo.lib;LLVMObject.lib;LLVMOption.lib;LLVMPowerPCAsmParser.lib;LLVMPowerPCAsmPrinter.lib;LLVMPowerPCCodeGen.lib;LLVMPowerPCDesc.lib;LLVMPowerPCDisassembler.lib;LLVMPowerPCInfo.lib;LLVMProfileData.lib;LLVMScalarOpts.lib;LLVMSelectionDAG.lib;LLVMSparcAsmParser.lib;LLVMSparcAsmPrinter.lib;LLVMSparcCodeGen.lib;LLVMSparcDesc.lib;LLVMSparcDisassembler.lib;LLVMSparcInfo.lib;LLVMSupport.lib;LLVMSystemZAsmParser.lib;LLVMSystemZAsmPrinter.lib;LLVMSystemZCodeGen.lib;LLVMSystemZDesc.lib;LLVMSystemZDisassembler.lib;LLVMSystemZInfo.lib;LLVMTableGen.lib;LLVMTarget.lib;LLVMTransformUtils.lib;LLVMVectorize.lib;LLVMX86AsmParser.lib;LLVMX86AsmPrinter.lib;LLVMX86CodeGen.lib;LLVMX86Desc.lib;LLVMX86Disassembler.lib;LLVMX86Info.lib;LLVMX86Utils.lib;LLVMXCoreAsmPrinter.lib;LLVMXCoreCodeGen.lib;LLVMXCoreDesc.lib;LLVMXCoreDisassembler.lib;LLVMXCoreInfo.lib;
因为我找不到关于包含哪个库的信息,所以我将所有库都包含在 D:\software\LLVM\build-x86\Debug\lib,plus Mincore.lib
这是生成库引用的 C# 代码:
static void buildLLVMLibList()
{
string s = "";
foreach (string fn in Directory.GetFiles(
//@"D:\software\LLVM\build-x64\Debug\lib"
@"D:\software\LLVM\build-x86\Debug\lib"
, "*.lib"))
{
s += new FileInfo(fn).Name + ";";
}
return;//break here
}
修改pch.h为:
#ifndef PCH_H
#define PCH_H
// TODO: add headers that you want to pre-compile here
// Declares clang::SyntaxOnlyAction.
#include "clang/Frontend/FrontendActions.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Tooling.h"
// Declares llvm::cl::extrahelp.
#include "llvm/Support/CommandLine.h"
#include "clang/Driver/Options.h"
#include "clang/AST/AST.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Frontend/ASTConsumers.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Tooling.h"
#include "clang/Rewrite/Core/Rewriter.h"
using namespace std;
using namespace clang;
using namespace clang::driver;
using namespace clang::tooling;
using namespace llvm;
#endif //PCH_H
修改主cpp文件为:
#include "pch.h"
#include <iostream>
Rewriter rewriter;
int numFunctions = 0;
llvm::cl::OptionCategory MyToolCategory("my-tool options");
class ExampleVisitor : public RecursiveASTVisitor<ExampleVisitor> {
private:
ASTContext *astContext; // used for getting additional AST info
public:
explicit ExampleVisitor(CompilerInstance *CI)
: astContext(&(CI->getASTContext())) // initialize private members
{
rewriter.setSourceMgr(astContext->getSourceManager(),
astContext->getLangOpts());
}
virtual bool VisitFunctionDecl(FunctionDecl *func) {
numFunctions++;
string funcName = func->getNameInfo().getName().getAsString();
if (funcName == "do_math") {
rewriter.ReplaceText(func->getLocation(), funcName.length(), "add5");
errs() << "** Rewrote function def: " << funcName << "\n";
}
return true;
}
virtual bool VisitStmt(Stmt *st) {
if (ReturnStmt *ret = dyn_cast<ReturnStmt>(st)) {
rewriter.ReplaceText(ret->getRetValue()->getLocStart(), 6, "val");
errs() << "** Rewrote ReturnStmt\n";
}
if (CallExpr *call = dyn_cast<CallExpr>(st)) {
rewriter.ReplaceText(call->getLocStart(), 7, "add5");
errs() << "** Rewrote function call\n";
}
return true;
}
};
class ExampleASTConsumer : public ASTConsumer {
private:
ExampleVisitor *visitor; // doesn't have to be private
public:
// override the constructor in order to pass CI
explicit ExampleASTConsumer(CompilerInstance *CI)
: visitor(new ExampleVisitor(CI)) // initialize the visitor
{ }
// override this to call our ExampleVisitor on the entire source file
virtual void HandleTranslationUnit(ASTContext &Context) {
/* we can use ASTContext to get the TranslationUnitDecl, which is
a single Decl that collectively represents the entire source file */
visitor->TraverseDecl(Context.getTranslationUnitDecl());
}
};
class ExampleFrontendAction : public ASTFrontendAction {
public:
void EndSourceFileAction() override {
llvm::outs() << "END OF FILE ACTION:\n";
rewriter.getEditBuffer(rewriter.getSourceMgr().getMainFileID()).write(errs());
}
virtual std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, StringRef file) {
return std::unique_ptr<ASTConsumer>(new ExampleASTConsumer(&CI)); // pass CI pointer to ASTConsumer
}
};
extern llvm::cl::OptionCategory MyToolCategory;
int main(int argc, const char **argv) {
// parse the command-line args passed to your code
CommonOptionsParser op(argc, argv, MyToolCategory);
// create a new Clang Tool instance (a LibTooling environment)
ClangTool Tool(op.getCompilations(), op.getSourcePathList());
// run the Clang Tool, creating a new FrontendAction (explained below)
int result = Tool.run(newFrontendActionFactory<ExampleFrontendAction>().get());
errs() << "\nFound " << numFunctions << " functions.\n\n";
// print out the rewritten source code ("rewriter" is a global var.)
std::cin.get();
return result;
}
然后创建一个testC++文件,如:
D:\LLVM\TestSource.cpp
它的内容是这样的:
void do_math(int *x) {
*x += 5;
}
int main(void) {
int result = -1, val = 4;
do_math(&val);
return result;
}
然后在项目属性中,将"Command Arguments"修改为:
"D:\LLVM\TestSource.cpp"
然后项目将构建并调试成功。
对于debug/x64配置,修改项目属性为:
包含路径:
D:\software\LLVM\clang\include;D:\software\LLVM\llvm\include;D:\software\LLVM\build-x64\include;D:\software\LLVM\build-x64\tools\clang\include;%(AdditionalIncludeDirectories)
库路径:
D:\software\LLVM\build-x64\Debug\lib;%(AdditionalLibraryDirectories)
库(不同于x86库):
Mincore.lib;clangAnalysis.lib;clangARCMigrate.lib;clangAST.lib;clangASTMatchers.lib;clangBasic.lib;clangCodeGen.lib;clangCrossTU.lib;clangDriver.lib;clangDynamicASTMatchers.lib;clangEdit.lib;clangFormat.lib;clangFrontend.lib;clangFrontendTool.lib;clangHandleCXX.lib;clangIndex.lib;clangLex.lib;clangParse.lib;clangRewrite.lib;clangRewriteFrontend.lib;clangSema.lib;clangSerialization.lib;clangStaticAnalyzerCheckers.lib;clangStaticAnalyzerCore.lib;clangStaticAnalyzerFrontend.lib;clangTooling.lib;clangToolingASTDiff.lib;clangToolingCore.lib;clangToolingRefactor.lib;gtest.lib;libclang.lib;LLVMAArch64AsmParser.lib;LLVMAArch64AsmPrinter.lib;LLVMAArch64CodeGen.lib;LLVMAArch64Desc.lib;LLVMAArch64Disassembler.lib;LLVMAArch64Info.lib;LLVMAArch64Utils.lib;LLVMAMDGPUAsmParser.lib;LLVMAMDGPUAsmPrinter.lib;LLVMAMDGPUCodeGen.lib;LLVMAMDGPUDesc.lib;LLVMAMDGPUDisassembler.lib;LLVMAMDGPUInfo.lib;LLVMAMDGPUUtils.lib;LLVMAnalysis.lib;LLVMARMAsmParser.lib;LLVMARMAsmPrinter.lib;LLVMARMCodeGen.lib;LLVMARMDesc.lib;LLVMARMDisassembler.lib;LLVMARMInfo.lib;LLVMARMUtils.lib;LLVMAsmParser.lib;LLVMAsmPrinter.lib;LLVMBinaryFormat.lib;LLVMBitReader.lib;LLVMBitWriter.lib;LLVMBPFAsmParser.lib;LLVMBPFAsmPrinter.lib;LLVMBPFCodeGen.lib;LLVMBPFDesc.lib;LLVMBPFDisassembler.lib;LLVMBPFInfo.lib;LLVMCodeGen.lib;LLVMCore.lib;LLVMDebugInfoCodeView.lib;LLVMDebugInfoDWARF.lib;LLVMDebugInfoMSF.lib;LLVMDebugInfoPDB.lib;LLVMDemangle.lib;LLVMGlobalISel.lib;LLVMHexagonAsmParser.lib;LLVMHexagonCodeGen.lib;LLVMHexagonDesc.lib;LLVMHexagonDisassembler.lib;LLVMHexagonInfo.lib;LLVMInstCombine.lib;LLVMInstrumentation.lib;LLVMipo.lib;LLVMIRReader.lib;LLVMLanaiAsmParser.lib;LLVMLanaiAsmPrinter.lib;LLVMLanaiCodeGen.lib;LLVMLanaiDesc.lib;LLVMLanaiDisassembler.lib;LLVMLanaiInfo.lib;LLVMLinker.lib;LLVMMC.lib;LLVMMCDisassembler.lib;LLVMMCParser.lib;LLVMMipsAsmParser.lib;LLVMMipsAsmPrinter.lib;LLVMMipsCodeGen.lib;LLVMMipsDesc.lib;LLVMMipsDisassembler.lib;LLVMMipsInfo.lib;LLVMMSP430AsmPrinter.lib;LLVMMSP430CodeGen.lib;LLVMMSP430Desc.lib;LLVMMSP430Info.lib;LLVMNVPTXAsmPrinter.lib;LLVMNVPTXCodeGen.lib;LLVMNVPTXDesc.lib;LLVMNVPTXInfo.lib;LLVMObject.lib;LLVMOption.lib;LLVMPowerPCAsmParser.lib;LLVMPowerPCAsmPrinter.lib;LLVMPowerPCCodeGen.lib;LLVMPowerPCDesc.lib;LLVMPowerPCDisassembler.lib;LLVMPowerPCInfo.lib;LLVMProfileData.lib;LLVMScalarOpts.lib;LLVMSelectionDAG.lib;LLVMSparcAsmParser.lib;LLVMSparcAsmPrinter.lib;LLVMSparcCodeGen.lib;LLVMSparcDesc.lib;LLVMSparcDisassembler.lib;LLVMSparcInfo.lib;LLVMSupport.lib;LLVMSymbolize.lib;LLVMSystemZAsmParser.lib;LLVMSystemZAsmPrinter.lib;LLVMSystemZCodeGen.lib;LLVMSystemZDesc.lib;LLVMSystemZDisassembler.lib;LLVMSystemZInfo.lib;LLVMTableGen.lib;LLVMTarget.lib;LLVMTransformUtils.lib;LLVMVectorize.lib;LLVMX86AsmParser.lib;LLVMX86AsmPrinter.lib;LLVMX86CodeGen.lib;LLVMX86Desc.lib;LLVMX86Disassembler.lib;LLVMX86Info.lib;LLVMX86Utils.lib;LLVMXCoreAsmPrinter.lib;LLVMXCoreCodeGen.lib;LLVMXCoreDesc.lib;LLVMXCoreDisassembler.lib;LLVMXCoreInfo.lib;
禁用特定警告:
4146
命令参数:
"D:\LLVM\TestSource.cpp"
最重要的是你要搬代码
rewriter.getEditBuffer(rewriter.getSourceMgr().getMainFileID()).write(errs());
上面从main函数引用到ExampleFrontendAction::EndSourceFileAction否则会出现奇怪的访问异常
我正在尝试使用 LibTooling 替换 C 代码文件中的函数和变量名称。因此,我下载了 llvm 并按照说明在 windows 中使用 GMake 和 Visual Studio 2015.
进行了设置。我想学习很多教程(例如 this one),但它们都假定您使用的是 Linux/Make,因此它们提供了一个 Makefile,以某种方式管理集成到llvm 源代码。
我想做的是在 Visual Studio 中使用这些示例,但我不知道从哪里开始 - 我可以在给定的 (llvn.sln) 解决方案中创建一个新项目并在那里添加代码?我如何告诉 Visual Studio 包含 clang 源(如我提到的那些 Makefile 中所定义)?
使用 VisualGDB 或类似的应用程序,可以在 Visual Studio 上编写代码并在 linux 机器上编译。这就是我现在正在做的。 我已经在 linux 虚拟机和我的 windows 7 OS 中安装了 clang,我有一个 Visual studio 2010。它运行良好。
最好使用 Cmake 生成 visual studio 项目文件,然后您可以使用 visual studio 构建这些文件。 本教程向您展示了它是如何完成的: https://llvm.org/docs/CMake.html
环境:Windows10 X64,VS2017,CMake 3.9.3 参考: https://clang.llvm.org/get_started.html
创建工作目录,如D:\software\LLVM
下载 LLVM 和 Clang 源代码(版本 6.0.0):
http://releases.llvm.org/6.0.0/llvm-6.0.0.src.tar.xz http://releases.llvm.org/6.0.0/cfe-6.0.0.src.tar.xz
将它们解压到工作目录,并将它们重命名为 llvm 和 clang(删除版本代码):
D:\software\LLVM\llvm
D:\software\LLVM\clang
如果你在文件夹名称中保留版本代码,那么稍后 CMake 会说找不到文件夹 "clang"
在工作目录下创建一个构建输出目录,如:
D:\software\LLVM\build-x86
对于 x64(仅当您需要 x64 构建时):
D:\software\LLVM\build-x64
进入构建输出目录:
cd D:\software\LLVM\build-x86
运行 cmake,对于 x86 构建:
cmake -DLLVM_ENABLE_PROJECTS=clang -G "Visual Studio 15 2017" -A Win32 -Thost=x64 ..\llvm
对于 x64 构建:
cmake -DLLVM_ENABLE_PROJECTS=clang -G "Visual Studio 15 2017" -A x64 -Thost=x64 ..\llvm
注意:最好只启用你的clang需要支持的目标,否则构建过程会很慢。要仅构建您的 clang 将支持的目标,请使用
-DLLVM_TARGETS_TO_BUILD=target_list
例如:
-DLLVM_TARGETS_TO_BUILD="X86;ARM"
所有目标的列表似乎在:
D:\software\LLVM\llvm\bindings\python\llvm\disassembler.py
他们是:
_targets = ['AArch64', 'ARM', 'Hexagon', 'MSP430', 'Mips', 'NVPTX', 'PowerPC', 'R600', 'Sparc', 'SystemZ', 'X86', 'XCore']
所以x86好像同时包含了x86和x64。
CMake 将生成一个 VS 解决方案文件:
D:\software\LLVM\build-x86\LLVM.sln
用VS2017打开,只需要构建子组"Clang libraries",我的构建是默认的Debug构建
现在引用是https://kevinaboos.wordpress.com/2013/07/23/clang-tutorial-part-ii-libtooling-example/ 但该页面中的代码适用于旧版本的 LLVM,因此无法编译。
这是 LLVM6.0.0 的工作代码:
在 VS2017 中创建一个 C++ 控制台应用程序。
进入debug/x86配置。
在项目属性对话框中,对于 debug/win32 配置,
修改"Disable Specific Warnings"为:
4146
修改"Additional Include Directories"为:
D:\software\LLVM\clang\include;D:\software\LLVM\llvm\include;D:\software\LLVM\build-x86\include;D:\software\LLVM\build-x86\tools\clang\include;%(AdditionalIncludeDirectories)
修改"Additional Library Directories"为:
D:\software\LLVM\build-x86\Debug\lib;%(AdditionalLibraryDirectories)
修改"Additional Dependencies"为:
Mincore.lib;clangAnalysis.lib;clangARCMigrate.lib;clangAST.lib;clangASTMatchers.lib;clangBasic.lib;clangCodeGen.lib;clangCrossTU.lib;clangDriver.lib;clangDynamicASTMatchers.lib;clangEdit.lib;clangFormat.lib;clangFrontend.lib;clangFrontendTool.lib;clangHandleCXX.lib;clangIndex.lib;clangLex.lib;clangParse.lib;clangRewrite.lib;clangRewriteFrontend.lib;clangSema.lib;clangSerialization.lib;clangStaticAnalyzerCheckers.lib;clangStaticAnalyzerCore.lib;clangStaticAnalyzerFrontend.lib;clangTooling.lib;clangToolingASTDiff.lib;clangToolingCore.lib;clangToolingRefactor.lib;libclang.lib;LLVMAArch64AsmParser.lib;LLVMAArch64AsmPrinter.lib;LLVMAArch64CodeGen.lib;LLVMAArch64Desc.lib;LLVMAArch64Disassembler.lib;LLVMAArch64Info.lib;LLVMAArch64Utils.lib;LLVMAMDGPUAsmParser.lib;LLVMAMDGPUAsmPrinter.lib;LLVMAMDGPUCodeGen.lib;LLVMAMDGPUDesc.lib;LLVMAMDGPUDisassembler.lib;LLVMAMDGPUInfo.lib;LLVMAMDGPUUtils.lib;LLVMAnalysis.lib;LLVMARMAsmParser.lib;LLVMARMAsmPrinter.lib;LLVMARMCodeGen.lib;LLVMARMDesc.lib;LLVMARMDisassembler.lib;LLVMARMInfo.lib;LLVMARMUtils.lib;LLVMAsmParser.lib;LLVMAsmPrinter.lib;LLVMBinaryFormat.lib;LLVMBitReader.lib;LLVMBitWriter.lib;LLVMBPFAsmParser.lib;LLVMBPFAsmPrinter.lib;LLVMBPFCodeGen.lib;LLVMBPFDesc.lib;LLVMBPFDisassembler.lib;LLVMBPFInfo.lib;LLVMCodeGen.lib;LLVMCore.lib;LLVMDebugInfoCodeView.lib;LLVMDebugInfoMSF.lib;LLVMDemangle.lib;LLVMGlobalISel.lib;LLVMHexagonAsmParser.lib;LLVMHexagonCodeGen.lib;LLVMHexagonDesc.lib;LLVMHexagonDisassembler.lib;LLVMHexagonInfo.lib;LLVMInstCombine.lib;LLVMInstrumentation.lib;LLVMipo.lib;LLVMIRReader.lib;LLVMLanaiAsmParser.lib;LLVMLanaiAsmPrinter.lib;LLVMLanaiCodeGen.lib;LLVMLanaiDesc.lib;LLVMLanaiDisassembler.lib;LLVMLanaiInfo.lib;LLVMLinker.lib;LLVMMC.lib;LLVMMCDisassembler.lib;LLVMMCParser.lib;LLVMMipsAsmParser.lib;LLVMMipsAsmPrinter.lib;LLVMMipsCodeGen.lib;LLVMMipsDesc.lib;LLVMMipsDisassembler.lib;LLVMMipsInfo.lib;LLVMMSP430AsmPrinter.lib;LLVMMSP430CodeGen.lib;LLVMMSP430Desc.lib;LLVMMSP430Info.lib;LLVMNVPTXAsmPrinter.lib;LLVMNVPTXCodeGen.lib;LLVMNVPTXDesc.lib;LLVMNVPTXInfo.lib;LLVMObject.lib;LLVMOption.lib;LLVMPowerPCAsmParser.lib;LLVMPowerPCAsmPrinter.lib;LLVMPowerPCCodeGen.lib;LLVMPowerPCDesc.lib;LLVMPowerPCDisassembler.lib;LLVMPowerPCInfo.lib;LLVMProfileData.lib;LLVMScalarOpts.lib;LLVMSelectionDAG.lib;LLVMSparcAsmParser.lib;LLVMSparcAsmPrinter.lib;LLVMSparcCodeGen.lib;LLVMSparcDesc.lib;LLVMSparcDisassembler.lib;LLVMSparcInfo.lib;LLVMSupport.lib;LLVMSystemZAsmParser.lib;LLVMSystemZAsmPrinter.lib;LLVMSystemZCodeGen.lib;LLVMSystemZDesc.lib;LLVMSystemZDisassembler.lib;LLVMSystemZInfo.lib;LLVMTableGen.lib;LLVMTarget.lib;LLVMTransformUtils.lib;LLVMVectorize.lib;LLVMX86AsmParser.lib;LLVMX86AsmPrinter.lib;LLVMX86CodeGen.lib;LLVMX86Desc.lib;LLVMX86Disassembler.lib;LLVMX86Info.lib;LLVMX86Utils.lib;LLVMXCoreAsmPrinter.lib;LLVMXCoreCodeGen.lib;LLVMXCoreDesc.lib;LLVMXCoreDisassembler.lib;LLVMXCoreInfo.lib;
因为我找不到关于包含哪个库的信息,所以我将所有库都包含在 D:\software\LLVM\build-x86\Debug\lib,plus Mincore.lib
这是生成库引用的 C# 代码:
static void buildLLVMLibList()
{
string s = "";
foreach (string fn in Directory.GetFiles(
//@"D:\software\LLVM\build-x64\Debug\lib"
@"D:\software\LLVM\build-x86\Debug\lib"
, "*.lib"))
{
s += new FileInfo(fn).Name + ";";
}
return;//break here
}
修改pch.h为:
#ifndef PCH_H
#define PCH_H
// TODO: add headers that you want to pre-compile here
// Declares clang::SyntaxOnlyAction.
#include "clang/Frontend/FrontendActions.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Tooling.h"
// Declares llvm::cl::extrahelp.
#include "llvm/Support/CommandLine.h"
#include "clang/Driver/Options.h"
#include "clang/AST/AST.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Frontend/ASTConsumers.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Tooling.h"
#include "clang/Rewrite/Core/Rewriter.h"
using namespace std;
using namespace clang;
using namespace clang::driver;
using namespace clang::tooling;
using namespace llvm;
#endif //PCH_H
修改主cpp文件为:
#include "pch.h"
#include <iostream>
Rewriter rewriter;
int numFunctions = 0;
llvm::cl::OptionCategory MyToolCategory("my-tool options");
class ExampleVisitor : public RecursiveASTVisitor<ExampleVisitor> {
private:
ASTContext *astContext; // used for getting additional AST info
public:
explicit ExampleVisitor(CompilerInstance *CI)
: astContext(&(CI->getASTContext())) // initialize private members
{
rewriter.setSourceMgr(astContext->getSourceManager(),
astContext->getLangOpts());
}
virtual bool VisitFunctionDecl(FunctionDecl *func) {
numFunctions++;
string funcName = func->getNameInfo().getName().getAsString();
if (funcName == "do_math") {
rewriter.ReplaceText(func->getLocation(), funcName.length(), "add5");
errs() << "** Rewrote function def: " << funcName << "\n";
}
return true;
}
virtual bool VisitStmt(Stmt *st) {
if (ReturnStmt *ret = dyn_cast<ReturnStmt>(st)) {
rewriter.ReplaceText(ret->getRetValue()->getLocStart(), 6, "val");
errs() << "** Rewrote ReturnStmt\n";
}
if (CallExpr *call = dyn_cast<CallExpr>(st)) {
rewriter.ReplaceText(call->getLocStart(), 7, "add5");
errs() << "** Rewrote function call\n";
}
return true;
}
};
class ExampleASTConsumer : public ASTConsumer {
private:
ExampleVisitor *visitor; // doesn't have to be private
public:
// override the constructor in order to pass CI
explicit ExampleASTConsumer(CompilerInstance *CI)
: visitor(new ExampleVisitor(CI)) // initialize the visitor
{ }
// override this to call our ExampleVisitor on the entire source file
virtual void HandleTranslationUnit(ASTContext &Context) {
/* we can use ASTContext to get the TranslationUnitDecl, which is
a single Decl that collectively represents the entire source file */
visitor->TraverseDecl(Context.getTranslationUnitDecl());
}
};
class ExampleFrontendAction : public ASTFrontendAction {
public:
void EndSourceFileAction() override {
llvm::outs() << "END OF FILE ACTION:\n";
rewriter.getEditBuffer(rewriter.getSourceMgr().getMainFileID()).write(errs());
}
virtual std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, StringRef file) {
return std::unique_ptr<ASTConsumer>(new ExampleASTConsumer(&CI)); // pass CI pointer to ASTConsumer
}
};
extern llvm::cl::OptionCategory MyToolCategory;
int main(int argc, const char **argv) {
// parse the command-line args passed to your code
CommonOptionsParser op(argc, argv, MyToolCategory);
// create a new Clang Tool instance (a LibTooling environment)
ClangTool Tool(op.getCompilations(), op.getSourcePathList());
// run the Clang Tool, creating a new FrontendAction (explained below)
int result = Tool.run(newFrontendActionFactory<ExampleFrontendAction>().get());
errs() << "\nFound " << numFunctions << " functions.\n\n";
// print out the rewritten source code ("rewriter" is a global var.)
std::cin.get();
return result;
}
然后创建一个testC++文件,如:
D:\LLVM\TestSource.cpp
它的内容是这样的:
void do_math(int *x) {
*x += 5;
}
int main(void) {
int result = -1, val = 4;
do_math(&val);
return result;
}
然后在项目属性中,将"Command Arguments"修改为:
"D:\LLVM\TestSource.cpp"
然后项目将构建并调试成功。
对于debug/x64配置,修改项目属性为:
包含路径:
D:\software\LLVM\clang\include;D:\software\LLVM\llvm\include;D:\software\LLVM\build-x64\include;D:\software\LLVM\build-x64\tools\clang\include;%(AdditionalIncludeDirectories)
库路径:
D:\software\LLVM\build-x64\Debug\lib;%(AdditionalLibraryDirectories)
库(不同于x86库):
Mincore.lib;clangAnalysis.lib;clangARCMigrate.lib;clangAST.lib;clangASTMatchers.lib;clangBasic.lib;clangCodeGen.lib;clangCrossTU.lib;clangDriver.lib;clangDynamicASTMatchers.lib;clangEdit.lib;clangFormat.lib;clangFrontend.lib;clangFrontendTool.lib;clangHandleCXX.lib;clangIndex.lib;clangLex.lib;clangParse.lib;clangRewrite.lib;clangRewriteFrontend.lib;clangSema.lib;clangSerialization.lib;clangStaticAnalyzerCheckers.lib;clangStaticAnalyzerCore.lib;clangStaticAnalyzerFrontend.lib;clangTooling.lib;clangToolingASTDiff.lib;clangToolingCore.lib;clangToolingRefactor.lib;gtest.lib;libclang.lib;LLVMAArch64AsmParser.lib;LLVMAArch64AsmPrinter.lib;LLVMAArch64CodeGen.lib;LLVMAArch64Desc.lib;LLVMAArch64Disassembler.lib;LLVMAArch64Info.lib;LLVMAArch64Utils.lib;LLVMAMDGPUAsmParser.lib;LLVMAMDGPUAsmPrinter.lib;LLVMAMDGPUCodeGen.lib;LLVMAMDGPUDesc.lib;LLVMAMDGPUDisassembler.lib;LLVMAMDGPUInfo.lib;LLVMAMDGPUUtils.lib;LLVMAnalysis.lib;LLVMARMAsmParser.lib;LLVMARMAsmPrinter.lib;LLVMARMCodeGen.lib;LLVMARMDesc.lib;LLVMARMDisassembler.lib;LLVMARMInfo.lib;LLVMARMUtils.lib;LLVMAsmParser.lib;LLVMAsmPrinter.lib;LLVMBinaryFormat.lib;LLVMBitReader.lib;LLVMBitWriter.lib;LLVMBPFAsmParser.lib;LLVMBPFAsmPrinter.lib;LLVMBPFCodeGen.lib;LLVMBPFDesc.lib;LLVMBPFDisassembler.lib;LLVMBPFInfo.lib;LLVMCodeGen.lib;LLVMCore.lib;LLVMDebugInfoCodeView.lib;LLVMDebugInfoDWARF.lib;LLVMDebugInfoMSF.lib;LLVMDebugInfoPDB.lib;LLVMDemangle.lib;LLVMGlobalISel.lib;LLVMHexagonAsmParser.lib;LLVMHexagonCodeGen.lib;LLVMHexagonDesc.lib;LLVMHexagonDisassembler.lib;LLVMHexagonInfo.lib;LLVMInstCombine.lib;LLVMInstrumentation.lib;LLVMipo.lib;LLVMIRReader.lib;LLVMLanaiAsmParser.lib;LLVMLanaiAsmPrinter.lib;LLVMLanaiCodeGen.lib;LLVMLanaiDesc.lib;LLVMLanaiDisassembler.lib;LLVMLanaiInfo.lib;LLVMLinker.lib;LLVMMC.lib;LLVMMCDisassembler.lib;LLVMMCParser.lib;LLVMMipsAsmParser.lib;LLVMMipsAsmPrinter.lib;LLVMMipsCodeGen.lib;LLVMMipsDesc.lib;LLVMMipsDisassembler.lib;LLVMMipsInfo.lib;LLVMMSP430AsmPrinter.lib;LLVMMSP430CodeGen.lib;LLVMMSP430Desc.lib;LLVMMSP430Info.lib;LLVMNVPTXAsmPrinter.lib;LLVMNVPTXCodeGen.lib;LLVMNVPTXDesc.lib;LLVMNVPTXInfo.lib;LLVMObject.lib;LLVMOption.lib;LLVMPowerPCAsmParser.lib;LLVMPowerPCAsmPrinter.lib;LLVMPowerPCCodeGen.lib;LLVMPowerPCDesc.lib;LLVMPowerPCDisassembler.lib;LLVMPowerPCInfo.lib;LLVMProfileData.lib;LLVMScalarOpts.lib;LLVMSelectionDAG.lib;LLVMSparcAsmParser.lib;LLVMSparcAsmPrinter.lib;LLVMSparcCodeGen.lib;LLVMSparcDesc.lib;LLVMSparcDisassembler.lib;LLVMSparcInfo.lib;LLVMSupport.lib;LLVMSymbolize.lib;LLVMSystemZAsmParser.lib;LLVMSystemZAsmPrinter.lib;LLVMSystemZCodeGen.lib;LLVMSystemZDesc.lib;LLVMSystemZDisassembler.lib;LLVMSystemZInfo.lib;LLVMTableGen.lib;LLVMTarget.lib;LLVMTransformUtils.lib;LLVMVectorize.lib;LLVMX86AsmParser.lib;LLVMX86AsmPrinter.lib;LLVMX86CodeGen.lib;LLVMX86Desc.lib;LLVMX86Disassembler.lib;LLVMX86Info.lib;LLVMX86Utils.lib;LLVMXCoreAsmPrinter.lib;LLVMXCoreCodeGen.lib;LLVMXCoreDesc.lib;LLVMXCoreDisassembler.lib;LLVMXCoreInfo.lib;
禁用特定警告:
4146
命令参数:
"D:\LLVM\TestSource.cpp"
最重要的是你要搬代码
rewriter.getEditBuffer(rewriter.getSourceMgr().getMainFileID()).write(errs());
上面从main函数引用到ExampleFrontendAction::EndSourceFileAction否则会出现奇怪的访问异常