内容简介:前面一篇文章在得到正确结果的过程中,必不可少的一步就是在使用
前面一篇文章 LLVM & Clang 入门 讲了如何编写一个 Clang 插件,然后将插件编译成一个 .dylib
的动态链接库。集成到 Xcode 中就可以看到效果(正确的结果)。
在得到正确结果的过程中,必不可少的一步就是 Debug
,没有任何程序是一蹴而就的,除非你 printf
一个 "Hello, World!"
,说不定你的 world
还写成了 word
。
在使用 Plugin
的模式下我们是不能打断点进行 Debug 的,但是我们可以在代码中加日志,然后在终端中执行命令看日志进行 Debug。这种低效率(Low)的方式是你想要的吗?显然不是。
我们只需要把 .dylib
动态库变成 可执行文件
就能打断点 debug。LibTooling 或许是一个不错的选择。使用 LibTooling 的话,我们只需要改动很少部分的代码就可以。
LibTooling 简介:
LibTooling 是一个独立的库,它允许使用者很方便地搭建属于你自己的编译器前端工具,它基于 C++ 接口,提供给使用者强大全面的 AST 解析和控制能力,同时由于它与 Clang 的内核过于接近导致它的版本兼容能力比 libclang 差得多,Clang 的变动很容易影响到 LibTooling。libTooling 还提供了完整的参数解析方案,可以很方便的构建一个独立的命令行工具。
创建 LibTooling 项目及代码调整
为了方便,我们直接创建一个可执行的 LibTooling
项目,我们可以创建一个名为 QTPluginTooling
的项目。
-
创建过程跟 创建插件 步骤差不多,前面 3 步都是一样的,只需要把
QTPlugin
替换为QTPluginTooling
就可以。 -
只是在第 4 步略有不同,
QTPluginTooling
目录下的CMakeLists.txt
的文件内容为set(LLVM_LINK_COMPONENTS Support ) add_clang_executable(QTPluginTooling QTPluginTooling.cpp ) target_link_libraries(QTPluginTooling PRIVATE clangAST clangBasic clangDriver clangFormat clangLex clangParse clangSema clangFrontend clangTooling clangToolingCore clangRewrite clangRewriteFrontend ) if (UNIX) set(CLANGXX__LING_OR_COPY create_symlink) else() set(CLANGXX_LINK_OR_COPY copy) endif() 复制代码
-
在
llvm_xcode
目录下执行$ cmake -G Xcode ../llvm
,重新生成一下Xcode
项目。Tooling
项目在 Xcode 的Clang executables
目录下可以找到。 -
将之前 Plugin 的代码复制过来,新增三个头文件
#include "clang/Tooling/CommonOptionsParser.h" #include "clang/Frontend/FrontendActions.h" #include "clang/Tooling/Tooling.h" 复制代码
-
新增一个命名空间
using namespace clang::tooling; 复制代码
-
将
QTASTAction
的继承改为继承至ASTFrontendAction
。 -
将
FrontendPluginRegistry
注册插件的方式注释。更改为main()
函数方式static llvm::cl::OptionCategory OptsCategory("QTPlugin"); int main(int argc, const char **argv) { CommonOptionsParser op(argc, argv, OptsCategory); ClangTool Tool(op.getCompilations(), op.getSourcePathList()); return Tool.run(newFrontendActionFactory<QTPlugin::QTASTAction>().get()); } 复制代码
最后整个文件的内容可以在 QTPluginTooling.cpp 看到。
输入源
如果这时候就 run
的话则会直接退出。这是因为没有“输入源”。我们可以在 QTPluginTooling
的 Scheme
加入。
/Users/laiyoung_/Desktop/Plugin/ViewController.m -- -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk -isystem -I/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/10.0.0/include -I/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1 -I/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include -F/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/Frameworks 复制代码
参数解释:
上面在 --
后面的参数,是传递给 CI
的 Compilation DataBase
的,而不是这个命令行 工具 本身的。比如我们的 ViewController.m
,因为有 #import <UIKit/UIKit.h>
这么一条语句,以及继承了 UIViewController
,那么语法分析器(Sema)读到这里的时候就需要知道 UIViewController
的定义是从哪里来的,换句话说就是它需要找到定义 UIViewController
的地方。怎么找呢?通过指定的 -I
、 -F
这些参数指定的目录来寻找。 --
后面的参数,可以理解为如果你要编译 ViewController.m
需要什么参数,那么这个后面就要传递什么参数给我们的 QTPlugin
,否则就会看到 Console
里打出找不到 xxx
定义或者 xxx.h
文件的错误。当然因为一般的编译指令,会有 -c
参数指定源文件,但是 --
后面并不需要,因为我们在 --
前面就指定了。 --
这种传参的方式还有另外一种方法,使用 -extra-arg="xxxx"
的方式指定编译参数,这样就不需要 --
了。
-extra-arg="-Ixxxxxx" -extra-arg="-Fxxxxxx" -extra-arg="-isysroot xxxxxx" xxxxxx表示的路径 复制代码
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
系统程序员成长计划
李先静 / 人民邮电出版社 / 2010-04 / 45.00
在学习程序开发的过程中,你是否总是为自己遇到的一些问题头疼不已,你是否还在为写不出代码而心急如焚?作为软件开发人员,你是否时时为自己如何成为一名合格的程序员而困惑不已?没关系,本书将为你排忧解难。 这是一本介绍系统程序开发方法的书。书中结合内容详尽的代码细致讲述了不少底层程序开发基础知识,并在逐步深入的过程中介绍了一些简单实用的应用程序,最后还讲述了一些软件工程方面的内容,内容全面,语言生动......一起来看看 《系统程序员成长计划》 这本书的介绍吧!