一、安装LLVM
二、使用CLion创建demo工程
main.cpp代码如下:
#include "llvm/IR/Verifier.h"
#include "llvm/ExecutionEngine/GenericValue.h"
#include "llvm/ExecutionEngine/Interpreter.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/raw_ostream.h"
//#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/IR/ValueSymbolTable.h"
using namespace llvm;
void register_printf(llvm::Module *module) {
std::vector<llvm::Type*> printf_arg_types;
printf_arg_types.push_back(llvm::Type::getInt8PtrTy(module->getContext()));
llvm::FunctionType* printf_type =
llvm::FunctionType::get(
llvm::Type::getInt32Ty(module->getContext()), printf_arg_types, true);
llvm::Function *func = llvm::Function::Create(
printf_type, llvm::Function::ExternalLinkage,
llvm::Twine("printf"),
module
);
func->setCallingConv(llvm::CallingConv::C);
}
int main(){
InitializeNativeTarget();
LLVMContext Context;
Module* M = new Module("main", Context);
register_printf(M);
// 校验问题, 这个函数需要一个输出流来打印错误信息
if (verifyModule(*M, &errs())) {
errs() << "构建LLVM字节码出错!\n";
exit(1);
}
// 输出llvm字节码
outs() << "LLVM module:\n\n" << *M;
outs() << "\n\n";
outs().flush();
// 输出二进制BitCode到.bc文件
std::error_code ErrInfo;
raw_ostream *out = new raw_fd_ostream("a.bc", ErrInfo, sys::fs::F_None);
// WriteBitcodeToFile(M, *out);
out->flush(); delete out;
// 关闭LLVM释放内存
llvm_shutdown();
return 0;
}
CMakeLists.txt代码如下:
cmake_minimum_required(VERSION 3.14)
project(TestLLVM)
set(CMAKE_CXX_STANDARD 11)
## 定义需要的库
set(LLVM_LINK_COMPONENTS
all
)
# 使用llvm
find_package(LLVM REQUIRED CONFIG)
set(SOURCE_FILES main.cpp)
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")
# 添加头文件路径
message(STATUS "include path: ${LLVM_INCLUDE_DIRS}")
include_directories(${LLVM_INCLUDE_DIRS})
#add_definitions(${LLVM_DEFINITIONS})
#message(STATUS "LLVM_DEFINITIONS: ${LLVM_DEFINITIONS}")
add_executable(TestLLVM ${SOURCE_FILES})
# 寻找对应的库
llvm_map_components_to_libnames(llvm_libs ${LLVM_LINK_COMPONENTS})
# 将库与目标代码一起链接
target_link_libraries(TestLLVM ${llvm_libs})
三、关键点记录
1,set(CMAKE_CXX_STANDARD 11)
通过在cmake文件中添加该属性,可以设置采用c++ 11进行编译。另外还可以采用第二种方式,如下:
add_compile_options(-std=c++11)
add_compile_options是针对所有类型编译器的,在编译c代码时可能会有问题,所以还可以采用第三种方式,如下
add_definitions(${LLVM_DEFINITIONS} -std=c++11)
更多cmake命令可以参考:https://cmake.org/cmake/help/v3.1/manual/cmake-commands.7.html
2,llvm_map_components_to_libnames
它会将需要的库与目标代码进行连接,在上面的例子中,我们设置的属性为all,所有库都被链接。可以通过命令行执行llvm-config --components 命令来查看所有的components,按照自己需要进行链接