LLVM & Clang

Clang 是作为常规 LLVM 版本的一部分发布的,你可以从 https://LLVM.org/releases/下载版本。
1.下载LLVM工程
1 | git clone git@github.com:llvm/llvm-project.git |
其中包含
- LLVM (release notes)
- Clang (release notes)
- clang-tools-extra (release notes)
- LLD (release notes)
- libc++ (release notes)
- Polly (release notes)
- Flang (release notes)
下载完成后,将根目录的clang文件夹移到/拷贝到llvm/tools中。
2.安装CMake
由于最新的LLVM只支持cmake来编译,所以需要安装cmake
- 查看brew是否安装cmake,如果已经安装,则跳过下面步骤 – brew list
- 通过brew安装cmake –
brew install cmake
3.编译LLVM
有两种编译方式
- 通过Xcode编译LLVM
- 通过ninja编译LLVM
为了方便,这里我们选择Xcode
通过Xcode编译
在llvm同级目录创建llvm_xcode文件夹,cd到llvm_xcode文件夹,运行cmake命令,将llvm编译成Xcode项目
1 | cmake -G Xcode ../llvm |
编译命令:cmake -G
- Unix Makefiles — 生成和 make 兼容的并行的 makefile。
- Ninja — 生成一个 Ninja 编译文件,大多数 LLVM 开发者使用 Ninja。
- Visual Studio — 生成一个 Visual Studio 项目。
- Xcode — 生成一个 Xcode 项目。
- -DCMAKE_INSTALL_PREFIX=”directory” — 安装 LLVM 工具和库的完整路径,默认/usr/local。
- -DCMAKE_BUILD_TYPE=”type” — type 的值为Debug,Release, RelWithDebInfo和MinSizeRel,默认Debug。
- -DLLVM_ENABLE_ASSERTIONS=”On” — 在启用断言检查的情况下编译,默认为Yes。
- 这里我们使用
$ cmake -G Xcode ../llvm
命令生成一个Xcode项目。
创建完成后,打开生成的Xcode,选择手动设置schems,添加clang和clangTools这个两个target(这里有个坑,选择自动schems可能会造成创建的自定义插件找不到)。
编译,选择自动schems选择ALL_BUILD这个Scheme进行编译,手动的选择clang进行编译,预计1小时左右。
4.新建插件配置及源码文件
llvm/tools/clang/tools/目录下,新增cmake需要的配置:
在CMakeLists.txt文件添加插件信息
1 | add_clang_subdirectory(YCPlugin) |
新建YCPlugin目录,在其中新建一个CMakeLists.txt文件和YCPlugin.cpp文件:
add_llvm_library( YCPlugin MODULE BUILDTREE_ONLY YCPlugin.cpp )
cpp代码中注意保持与plugin名称一致。
注意:这里CMakeLists.txt文件中填写的不是网上到处说的命令 add_llvm_loadable_module。 而是应该 仿照Loadable modules中的LLVMHello中的格式填写。
如:
1 | add_llvm_library( YCPlugin MODULE BUILDTREE_ONLY |
然后需要重新生成一遍llvm_xcode中的工程,建议清空一遍之前创建的工程,从头重新生成
1 | cmake -G Xcode ../llvm |
与第一次编译时一样,手动管理schems,这个时候打开工程,在Loadable modules文件夹下就可以看到YCPlugin了,然后在Manage Schemes中添加我们的YCPlugin。
之后就可以进入YCPlugin.cpp中开始写插件代码了,已测试插件为例
1 |
|
5.验证
在YCPlugin.cpp中写完插件代码后,CMD+B编译生成.dylib文件,找到插件对应的.dylib,右键show in finder。
在llvm的同级目录创建我们的ClangDemo(一个新的Xcode工程),cd到ClangDemo文件夹执行下面指令
1 | 自己编译的clang文件路径 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator14.3.sdk/ -Xclang -load -Xclang 插件(.dylib)路径 -Xclang -add-plugin -Xclang 插件名 -c 资源文件(.h或者.m) |
6.集成到Xcode
加载插件
新建一个测试项目,打开测试项目,在target->Build Settings -> other Flags添加已下内容
-Xclang -load -Xclang /Users/shevakuilin/Desktop/llvm-project/llvm_xcode/Debug/lib/YCPlugin.dylib -Xclang -add-plugin -Xclang YCPlugin
设置编译器
Command + B进行编译,会报错。因为由于clang插件需要使用对应的版本去加载,如果版本不一致会导致编译失败。
在Build Settings栏目新增两项用户定义的设置分别是CC和CXX。
- CC 对应的是自己编译的clang的绝对路径
- CXX 对应的是自己编译的clang++的绝对路径
接下来在Build Settings中搜索index,将Enable Index-Wihle-Building Functionality的Default改为NO。
最后重新编译即可看到插件提示效果。
最后有一个小问题,由于将
Index-Wihle-Building Functionality
设置为NO
了,会导致 Xcode 的自动补全功能和代码颜色提醒失效,其作用是使用Xcode时会顺便建立索引。目前没有太好的解决办法。也许可以将插件做成工具形式,需要时再执行
最终效果

问题 & 解决方案
1.如果 cmake -G Xcode ../llvm 命令生成的工程里找不到插件
- 清空llvc_xcode文件夹内的全部内容
- 选择手动设置schems,添加clang和clangTools这个两个target
2.llvm-project下载下来之后llvm/tools中找不到clang文件夹
- 将根目录的clang文件夹移到/拷贝到llvm/tools中
3.cmake -G Xcode ../llvm 命令报错提示当前Xcode无法支持
- Xcode12及以上需要使用llvm 11.0及以上版本
4.插件内的C++代码报错,如:Cannot initialize object parameter of type ‘const clang::Decl’ with an expression of type ‘const clang::ObjCPropertyDecl’
- Build Settings -> C++ Language Dialect -> 设置成C++ 14即可解决报错问题
参考文章
- LLVM & Clang 入门
- iOS-LLVM的编译以及Clang的插件编写
- iOS 开发 Clang 插件的配置及流程
- 清华大学LLVM镜像
- iOS之武功秘籍⑰: Clang插件开发
- 编译原理:如何制作clang插件来为iOS开发提效
- LLVM-Clang插件开发
- Cannot initialize object parameter of type ‘UActorComponent’ with an expression of type ‘UPositionReport’
- Clang 代码规范检查插件
- iOS 编译时间优化
- 微信团队分享:极致优化,iOS版微信编译速度3倍提升的实践总结
- Clang 之旅–实现一个自定义检查规范的 Clang 插件
- AST Matcher Reference
- 彻底理解c++的隐式类型转换