Clangen使用 ClangSharp解析头文件来完成一些中间代码的生成(如Rpc的注册代码, 桩代码, C++类导出到Lua的代码等). 而ClangSharp本身依赖了llvm, 以及自己的一个libClangSharp的库, windows和linux下需要编译一下llvm和这个库, 一般来说系统没变的情况下, 直接使用已经编译好的libclang.so/dll即可, 但有些时候遇到需要升级llvm到高版本的情况, 比如说我们之前碰到的情况 , llvm9在linux下运行速度异常(Windows下10S的流程, 在linux下处理同样的任务要快3分钟, 最后发现可能之前编译使用的是debug版本), 我们需要编译LLVM, 并且编译依赖llvm的libClangSharp, 官方文件比较简单, 而且配置项有一些问题, 可能导致不能正常编译, 所以这里记录下过程方便后续有相关需求的时候可以参照处理.
因为我们并不直接使用clang编译代码, 而只是使用libclang来生成AST, 所以此处我们需要的产物其实是libclang.so/dll.
llvm的编译原来是一件复杂的事情, 不过使用者众多, 所以官方也提供了比较便利的方式. 这个便利的方式就是llvm-project, 有它的存在, 整个过程变得比较简单, 不需要下载多个项目放到不同的位置,git clone 一个仓库即可.
llvm-project是GitHub上的一个开源项目, 项目地址为:
Windows上直接使用CMake和VS2019即可完成LLVM的编译,
因为有两个工程需要编译, 我们一般建立一个统一的目录, 然后如下图所示在其中创建两个bat:
bat的内容如下:
llvm_generate_project.bat:
git clone -b release/11.x https://github.com/llvm/llvm-project
cd llvm-project
mkdir artifacts/bin
cd artifacts/bin
cmake -DLLVM_ENABLE_PROJECTS=clang -DCMAKE_INSTALL_PREFIX="../install" -G "Visual Studio 16 2019" -A x64 -Thost=x64 ../../llvm
此处需要注意的是检出的是当前ClangSharp源码支持的llvm版本, llvm11, 注意别检出master, 一定要检出对应的版本, 不然C#相关代码无法工作.
clangsharp_generate_project.bat:
git clone https://github.com/microsoft/clangsharp
mkdir artifacts/bin/native
cd artifacts/bin/native
cmake -DPATH_TO_LLVM=../../../../llvm-project/artifacts/install/ -G "Visual Studio 16 2019" -A x64 -Thost=x64 ../../..
先执行llvm_generate_project.bat , 脚本执行完成没有报错的话, 这个时候 "llvm\llvm-project\artifacts\bin" 目录下会成功生成LLVM的sln文件, 如下图所示:
打开LLVM.sln, 正确设置工程到Release(我们一般不需要调试LLVM, 生成尺寸更小的Release版LLVM即可), 如下图所示:
接下来在Solution Explorer中选中INSTALL项目, 右击执行Build, 经过漫长的等待(机器好点其实挺快的, 像我AMD3970的机器10来分钟就好了^_^), 整个工程的编译和Install即完成了.
项目编译输出窗口大致内容如下:
记得一定要检查Install过程是否成功执行, libClangSharp依赖Install过程, 笔者操作第一次失败了, 原因是cmake的install路径没有正确配置, 也就没有正确执行llvm的install, 这里一定是要检查的, 或者我们切到 "llvm/llvm-project/artifacts/install" 目录下检查所有编译的内容是否有被正确的install, 正确执行install过程的目录如下图所示:
请必须确保1.1.1相关的步骤都执行完成再进行本步操作, 不然会报一些奇怪的*.cmake找不到的问题, 一般如果build正确执行但依然报错, 一般就是intall过程没有被正确执行了(笔者很久之前踩过这个坑, 后面是纯手动改了好几个路径, 最后编译成功了, 非常折腾.)
执行clangsharp_generate_project.bat, 这个一般llvm配置没错误的话, 是不会有啥问题的, 正确执行后, 会在"llvm/clangsharp/artifacts/bin/native"下生成VS的工程, 如下图所示:
打开ClangSharp.sln, 选中libClangSharp, build, 即可完成相关的编译操作.
以lura-tool为例 , 我们其实需要的是如下图所示的so/dll:
这里处理的是windows版, 所以是libclang.dll和libClangSharp.dll, 两个文件的目录分别在:
libclang.dll: llvm\llvm-project\artifacts\install\bin\libclang.dll
libClangSharp.dll: llvm\clangsharp\artifacts\bin\native\bin\Release\libClangSharp.dll
一般正确拷贝这两者到工具目录下即可完成相关llvm二进制文件的替换, 至此windows版本的llvm和libclangsharp二进制处理完毕, 我们接下来看linux版本的编译.
整个过程与Windows版类似, 需要注意的是LLVM本身对GCC的版本有要求, 笔者直接使用的是GCC8.3, 相关的目录结构和脚本如下:
build_llvm.sh:
```shell git clone -b release/11.x https://github.com/llvm/llvm-project mkdir -p artifacts/bin cd artifacts/bin cmake -DCMAKE_BUILD_TYPE=MinSizeRel -DLLVM_ENABLE_PROJECTS="clang" -DLLVM_ENABLE_RTTI=ON -DCMAKE_INSTALL_PREFIX=../install ../../llvm -D CMAKE_C_COMPILER=/usr/local/gcc-8.3.0/bin/gcc -D CMAKE_CXX_COMPILER=/usr/local/gcc-8.3.0/bin/g++ make -j48 make install
```
同样注意检出正确的分支.
build_clang_sharp.sh:
git clone https://github.com/microsoft/clangsharp
mkdir -p artifacts/bin/native
cd artifacts/bin/native
cmake -DCMAKE_BUILD_TYPE=MinSizeRel -DPATH_TO_LLVM=/data/workspace/llvm11/llvm-project/artifacts/install/ ../../.. -D CMAKE_C_COMPILER=/usr/local/gcc-8.3.0/bin/gcc -D CMAKE_CXX_COMPILER=/usr/local/gcc-8.3.0/bin/g++
make -j48
此处注意PATH_TO_LLVM宏, 记得修改为自己llvm的install目录, 直接使用了绝对路径(相对路径有报错, 没有细查原因)
与Windows版本一样, 执行完成build_llvm.sh后, 再执行build_clang_sharp.sh, 成功执行得到相关的二进制文件路径为:
libclang.so: llvm11/llvm-project/artifacts/install/lib/libclang.so (实际是libclang.so.11.1的软链)
libClangSharp.so: llvm11/clangsharp/artifacts/bin/native/lib/libClangSharp.so
得益于llvm编译方式的进化, 整个过程还是比较顺的, 最后lura-tool经过调整, 解析头文件的速度也得到了很大的提高, llvm9的时候是如图所示的2分多钟:
llvm11 执行同样的处理任务耗时大概是20多秒, 已经跟Windows版的处理时间比较接近了.