系列文章目录
LLVM系列第一章:编译LLVM源码
LLVM系列第二章:模块Module
LLVM系列第三章:函数Function
LLVM系列第四章:逻辑代码块Block
LLVM系列第五章:全局变量Global Variable
LLVM系列第六章:函数返回值Return
LLVM系列第七章:函数参数Function Arguments
LLVM系列第八章:算术运算语句Arithmetic Statement
LLVM系列第九章:控制流语句if-else
LLVM系列第十章:控制流语句if-else-phi
LLVM系列第十一章:写一个Hello World
LLVM系列第十二章:写一个简单的词法分析器Lexer
LLVM系列第十三章:写一个简单的语法分析器Parser
LLVM系列第十四章:写一个简单的语义分析器Semantic Analyzer
LLVM系列第十五章:写一个简单的中间代码生成器IR Generator
LLVM系列第十六章:写一个简单的编译器
LLVM系列第十七章:for循环
LLVM系列第十八章:写一个简单的IR处理流程Pass
LLVM系列第十九章:写一个简单的Module Pass
LLVM系列第二十章:写一个简单的Function Pass
LLVM系列第二十一章:写一个简单的Loop Pass
LLVM系列第二十二章:写一个简单的编译时函数调用统计器(Pass)
LLVM系列第二十三章:写一个简单的运行时函数调用统计器(Pass)
LLVM系列第二十四章:用Xcode编译调试LLVM源码
LLVM系列第二十五章:简单统计一下LLVM源码行数
LLVM系列第二十六章:理解LLVMContext
LLVM系列第二十七章:理解IRBuilder
LLVM系列第二十八章:写一个JIT Hello World
LLVM系列第二十九章:写一个简单的常量加法“消除”工具(Pass)
flex&bison系列
在此记录下基于LLVM写一个Hello World的过程,以备查阅。
开发环境的配置请参考第一章 《LLVM系列第一章:编译LLVM源码》。
我们把这个简单的项目命名为SimpleLang。可以参考LLVM及Clang的源码组织结构,来组织我们自己的代码(示例):
% tree -I "build|build-simplelang|llvm-12"
.
├── CMakeLists.txt
├── README.md
├── cmake
│ └── modules
│ └── AddSimpleLang.cmake
├── include
│ └── simplelang
│ └── Basic
│ ├── Version.h
│ └── Version.inc.in
├── lib
│ ├── Basic
│ │ ├── CMakeLists.txt
│ │ └── Version.cpp
│ └── CMakeLists.txt
└── tools
├── CMakeLists.txt
└── driver
├── CMakeLists.txt
└── Driver.cpp
9 directories, 11 files
注意我们自己的项目可以放在任何位置,没有必要放在LLVM的源码目录下。
这个简单的项目只包含了两个模块:
simplelang将会调用simplelangBasic中的函数,并把结果打印出来。simplelang需要链接simplelangBasic,才能调用其函数。
以下是跟项目组织结构相关的部分CMake脚本。
(1) 项目根目录(示例):
# CMakeLists.txt
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
project(SimpleLang)
...
endif()
add_subdirectory(lib)
add_subdirectory(tools)
(2) lib目录(示例):
# lib/CMakeLists.txt
add_subdirectory(Basic)
# lib/Basic/CMakeLists.txt
add_simplelang_library(simplelangBasic
....cpp
)
注意到这里会构建出simplelangBasic library。
(3) tools目录(示例):
# tools/CMakeLists.txt
add_simplelang_subdirectory(driver)
# tools/driver/CMakeLists.txt
set(LLVM_LINK_COMPONENTS
Support
)
add_simplelang_tool(simplelang
....cpp
)
target_link_libraries(simplelang
PRIVATE
simplelangBasic
)
注意到这里会构建出simplelang, 并且让其链接simplelangBasic。
我们需要做一些与LLVM相关的配置,才能顺利地使用LLVM(示例):
find_package(LLVM REQUIRED HINTS "${LLVM_CMAKE_PATH}")
list(APPEND CMAKE_MODULE_PATH ${LLVM_DIR})
include(AddLLVM)
include(HandleLLVMOptions)
include_directories("${LLVM_BINARY_DIR}/include" "${LLVM_INCLUDE_DIR}")
link_directories("${LLVM_LIBRARY_DIR}")
set(SIMPLELANG_BUILT_STANDALONE 1)
我们的C++代码放在两个文件中:
main函数在Driver.cpp中(示例):
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/raw_ostream.h"
#include "simplelang/Basic/Version.h"
int main(int argc, const char **argv)
{
llvm::InitLLVM llvmInitializer(argc, argv);
llvm::outs() << "Hello World! (version " << simplelang::getSimpleLangVersion() << ")\n";
}
我们看到以上代码调用了函数getSimpleLangVersion()
,它来自于Version.cpp(示例):
std::string simplelang::getSimpleLangVersion()
{
return SIMPLELANG_VERSION_STRING;
}
其中SIMPLELANG_VERSION_STRING
仅仅是个string而已,它的值为"0.1"。
用CMake工具生成项目文件(示例):
mkdir build
cd build
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release \
-DLLVM_EXTERNAL_PROJECTS=simplelang \
-DLLVM_EXTERNAL_SIMPLELANG_SOURCE_DIR=../simplelang \
-DCMAKE_INSTALL_PREFIX=../llvm-12 \
/path/to/llvm-project/llvm
注意/path/to/llvm-project
代表的是llvm-project的源代码路径。
输出log如下(示例):
-- The C compiler identification is AppleClang 13.0.0.13000029
-- The CXX compiler identification is AppleClang 13.0.0.13000029
-- The ASM compiler identification is Clang with GNU-like command-line
-- Found assembler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found libtool - /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool
...
-- Configuring done
-- Generating done
-- Build files have been written to: /path/to/hello-world/build
用ninja工具进行编译(示例):
ninja
输出log如下(示例):
[2996/2996] Linking CXX executable bin/obj2yaml
用ninja进行安装(示例):
ninja install
输出log如下(示例):
[0/1] Install the project...
-- Install configuration: "Release"
-- Installing: /path/to/hello-world/llvm-12/include/llvm
...
用CMake生成项目文件(示例):
mkdir build-simplelang
cd build-simplelang
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release \
-DLLVM_DIR=../llvm-12/lib/cmake/llvm \
-DCMAKE_INSTALL_PREFIX=../llvm-12 \
../
输出log如下(示例):
-- The C compiler identification is AppleClang 13.0.0.13000029
-- The CXX compiler identification is AppleClang 13.0.0.13000029
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found ZLIB: /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.1.sdk/usr/lib/libz.tbd (found version "1.2.11")
-- Found LibXml2: /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.1.sdk/usr/lib/libxml2.tbd (found version "2.9.4")
-- Linker detection: ld64
...
...
-- Building with -fPIC
-- Configuring done
-- Generating done
-- Build files have been written to: /path/to/hello-world/build-simplelang
用ninja进行编译(示例):
ninja
输出log如下(示例):
[4/4] Linking CXX executable tools/driver/simplelang
用ninja进行安装(示例):
ninja install
输出log如下(示例):
[0/1] Install the project...
-- Install configuration: "Release"
-- Installing: /path/to/hello-world/llvm-12/lib/libsimplelangBasic.a
-- Installing: /path/to/hello-world/llvm-12/bin/simplelang
运行Hello World(示例):
../llvm-12/bin/simplelang
输出结果如下(示例):
Hello World! (version 0.1)
我们参考LLVM的项目组织结构,基于LLVM提供的API,用C++写了一个Hello World,并且编译运行成功。完整源码示例请参看:
https://github.com/wuzhanglin/llvm-hello-world