參考書:《Getting Started with LLVM Core Libraries》
書里邊只介紹了makefile形式,我這里介紹了兩種方式,我自己覺得Xcode要方便一點,因為可以直接調(diào)試(純小白可能看起來費力一點)。
一、MakeFile項目:
包含一個makefile文件和一個cpp文件,書中的源代碼是基于llvm3的,我自己是基于llvm9.0的,所以基于他書中給出的代碼做了修改。
-
書中的源代碼:
image.png
image.png - 我貼一下我自己的代碼:
MakeFile 文件:
路徑根據(jù)自己電腦的llvm項目更改;
- LLVM_CONFIG 獲取編譯參數(shù)、鏈接參數(shù)
- CXXINCLUDE、ISYSROOT 是我自己根據(jù)電腦路徑添加的,因為我電腦上編譯的話會報錯,添加的C++標(biāo)準(zhǔn)庫頭文件路徑和mac上SDK的路徑,這樣才能編譯通過
- LIB 這個LLVM的庫
- 其余的設(shè)置參考書中就行,沒什么變化,路徑需要根據(jù)自己電腦上來設(shè)置。
(書中是只用到了幾個核心的llvm庫,我是直接用了整個庫libLLVM.dylib,因為我改了點代碼,為了方便)
LLVM_CONFIG ?= /Users/qinyao/LLVM/LLVM-9.0.0/build-release/bin/llvm-config
# CXX = /Users/qinyao/LLVM/LLVM-9.0.0/build-release/bin/clang++
CXXINCLUDE+=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1
# CXXINCLUDE+=/Users/qinyao/LLVM/LLVM-9.0.0/build-release/include/c++/v1
ISYSROOT+=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk
LIB+=/Users/qinyao/LLVM/LLVM-9.0.0/build-release/lib
ifndef VERBOSE
QUIET:=@
endif
SRC_DIR?=$(PWD)
LDFLAGS+=$(shell $(LLVM_CONFIG) --ldflags)
COMMON_FLAGS=-Wall -Wextra -I$(CXXINCLUDE) -isysroot $(ISYSROOT)
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) $(LDFLAGS) $^ -L$(LIB) -lLLVM
clean::
$(QUIET)rm -f $(HELLO) $(HELLO_OBJECTS)
#-DLLVM_ENABLE_PROJECTS="clang;libcxx;libcxxabi"
#$(QUIET)$(CXX) -o $@ $(CXXFLAGS) $(LDFLAGS) $^ `$(LLVM_CONFIG) --libs bitreader core support` `$(LLVM_CONFIG) --system-libs`
hello cpp 文件:
改了一點寫法,解析一個bc文件,遍歷module,拿到函數(shù)列表,遍歷這個函數(shù)迭代器,輸出函數(shù)名和函數(shù)包含的基礎(chǔ)塊。
#include "llvm/Bitcode/BitcodeReader.h"
#include "llvm/Bitcode/BitcodeWriter.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_os_ostream.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/Support/SourceMgr.h"
// #include "llvm/Support/system_error.h"
#include <iostream>
using namespace llvm;
static cl::opt<std::string> FileName("qy-file", cl::desc("input one Bitcodefile"), cl::Required);
int main(int argc, char** argv) {
cl::ParseCommandLineOptions(argc, argv, "LLVM hello world\n");
LLVMContext Context;
SMDiagnostic Err;
// std::cout<<FileName<<std::endl;
std::unique_ptr<Module> M = parseIRFile(FileName, Err, Context);
if (!M) {
Err.print(FileName.c_str(), errs());
return false;
}
for(auto &func : M->functions()){
llvm::StringRef func_name = func.getName();
}
raw_os_ostream OUT(std::cout);
for (Module::const_iterator i = M->getFunctionList().begin(),e = M->getFunctionList().end(); i != e; ++i) {
if (!i->isDeclaration()) {
OUT << i->getName() << " has " << i->size() << " basicblock(s).\n";
}
}
std::cout<<"hello,world."<<std::endl;
return 0;
}
-
上面沒問題了就直接make:
make可能會遇到各種問題,需要注意路徑正確。
image.png -
運行:
需要設(shè)置一下庫搜索路徑:
image.png

image.png
二、Xcode創(chuàng)建:
-
創(chuàng)建一個Xcode 命令行項目:
代碼直接貼進去,和上邊的cpp代碼一樣
image.png 環(huán)境配置:
-
頭文件路徑:使用llvm9.0編譯出來的debug模式的頭文件,后面方便調(diào)試
image.png -
庫搜索路徑:
image.png -
編譯參數(shù):這個是解決一個鏈接問題
image.png -
導(dǎo)入llvm的庫:
image.png
這些參數(shù)設(shè)置正確后應(yīng)該可以編譯通過。
運行參數(shù):
static cl::opt<std::string> FileName("qy-file", cl::desc("input one Bitcodefile"), cl::Required);

image.png
-
運行時庫搜索路徑:
image.png
至此,可以直接編譯運行了。

image.png
總結(jié):這里僅僅是熟悉了項目創(chuàng)建,代碼的編寫還需要實踐的更多才能熟悉。









