1, 获取llvm 仓库
从github上获取:
$ git clone --recursive https://github.com/llvm/llvm-project.git
2, 检出 llvmorg-3.4.0 tag
针对llvm 3.4.0版本,检出
$ cd llvm-project
$ git tag
$ git checkout llvmorg-3.4.0
3, 配置并编译llvm
使用 Makefile 编译 llvm 时 没有发现问题
先做配置
$ cd llvm
$ /bin/bash ./configure --prefix=/home/hipper/llvm_3_4_0_ex/local --cache-file=/dev/null --srcdir=.
然后开始编译:
$ make -j install
#大概几分钟
$ ls /home/hipper/llvm_3_4_0_ex/local/lib/
4, 拷贝并编译clang
在做完第3步编译llvm之前,不要做第4步(拷贝与编译clang),否则在编译llvm时会把clang一起编译,但是会发生问题。
拷贝
编译,不需要配置,llvm之前的配置会映射进来
但依然会发生找不到头文件的问题:
将 找不到头文件的地方改成 llvm/Config/config.h
然后执行make,还会出现几次同样的问题,都是改成 llvm/Config/config.h :
make
make
最后编译成功:
安装:
make -j install
至此, llvm + clang 3.4.0 开发环境已经准备好了。
5, llvm library 调用示例
将add.c 源文件编译成为 add.bc 文件,作为输入 input;
使用 llvm lib 的 app: helloworld 程序,读入 add.bc 源文件,分辨出 add.bc 中的函数名,并打印出来。
helloworld.cpp
#include "llvm/Bitcode/BitCodes.h"
#include "llvm/Bitcode/ReaderWriter.h"
//#include "llvm/Bitcode/BitcodeReader.h"
//#include "llvm/Bitcode/BitcodeWriter.h"
#include "llvm/Bitcode/BitstreamReader.h"
#include "llvm/Bitcode/BitstreamWriter.h"
#include "llvm/Bitcode/LLVMBitCodes.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_os_ostream.h"
#include "llvm/Support/system_error.h"
#include <iostream>
using namespace llvm;
static cl::opt<std::string> FileName(cl::Positional, cl::desc("Bitcode file"), cl::Required);
int main(int argc, char** argv)
{
cl::ParseCommandLineOptions(argc, argv, "LLVM hello world\n");
LLVMContext context;
std::string error;
OwningPtr<MemoryBuffer>mb;
MemoryBuffer::getFile(FileName, mb);
Module *m = ParseBitcodeFile(mb.get(), context, &error);
if(m==0){
std::cerr<<"Error reading bitcode:" << error << std::endl;
return -1;
}
raw_os_ostream O(std::cout);
for(Module::const_iterator i = m->getFunctionList().begin(), e=m->getFunctionList().end(); i!=e; ++i){
if(!i->isDeclaration()){
O<<i->getName() << " has "<<i->size() << "basic block(s).\n";
}
}
}
构建 上边的 helloworld.cpp 的Makefile:
LLVM_CONFIG ?= llvm-config
ifndef VERBOSE
QUIET:=@
endif
SRC_DIR ?= $(PWD)
LD_FLAGS+=$(shell $(LLVM_CONFIG) --ldflags)
COMMON_FLAGS=-Wall -Wextra
CXXFLAGS+=$(COMMON_FLAGS) $(shell $(LLVM_CONFIG) --cxxflags)
CPPFLAGS+=$(shell $(LLVM_CONFIG) --cppflags) -I$(SRC_DIR)
HELLO = helloworld
HELLO_OBJECTS=hello.o
default: $(HELLO)
%.o : $(SRC_DIR)/%.cpp
@echo Compiling $*.cpp
$(QUIET)$(CXX) -c $(CPPFLAGS) $(CXXFLAGS) $<
$(HELLO) : $(HELLO_OBJECTS)
@echo Linking $@
$(QUIET)$(CXX) -o $@ $(CXXFLAGS) $(LD_FLAGS) $^ `$(LLVM_CONFIG) --libs bitreader core support` -ltinfo
.PHONY: clean
clean:
${RM} $(HELLO) $(HELLO_OBJECTS)
6, 示例的输入示例
add.c
#include <stdio.h>
int add_int_type(int x, int y){
return x+y;
}
float float_add_3(float a, float b, float c){
return a+b+c;
}
double d_add(double s, double t)
{
return s + t;
}
int main()
{
int a =1, b= 2;
float c =3.0f, d = 4.0f, e = 5.0f;
double f = 6.0, g = 7.0;
printf("%d\n", add_int_type(a, b));
printf("%f", float_add_3(c, d, e));
printf("%f", d_add(f, g));
return 0;
}
编译生成 add.bc 字节码文件:
$ clang -emit-llvm -c add.c -o add.bc
7, 用helloworld 分析 add.bc
$ ./helloworld tmp_ex/add.bc
构建llvm 的app helloworld时,会使用到 llvm-config 程序,故需要设置 PATH 环境变量。
程序输出了 add.c 中的函数名,测试成功。
以上helloworld.c 代码,针对 llvm-project 3.4.0 的编译安装结果进行了调整,主要是Bitcode/ 中的头文件。