Clang is the LLVM compiler front end and is ideal for source analysis. The current open source oCLINt is based on clANG code static inspection. I encountered some problems in my work and needed to conduct code analysis, so I learned the development process of plug-ins. Since developing plugins requires a proper IDE, xcode is the perfect one for the Mac. This article explains how to use Xcode to develop a plug-in for Clang. Learn about Clang first.
1. Compile the plug-in
1.1 code download
A. look at corresponding clang xcode version trac.macports.org/wiki/XcodeV…
B. Query the version on the official websiteOpensource.apple.com/source/clan…
C. Locate the branch on Github according to the code used on the official website and download the codeGithub.com/llvm-mirror…
1.2. Add plug-in code
A. Create the folder where the plug-in resides (see Demo for the example code)
B. Preparation of cmakelists documents
C. Add plug-in code
1.3 compile the code
There are two ways to compile, one directly using cmake and the other using an IDE. Here’s how to compile using Xcode.
A. Generate the xcodeProj file
cd /opt sudo mkdir llvm sudo chown `whoami` llvm cd llvm export LLVM_HOME=`pwd` git clone -b release_39 [email protected]:llvm-mirror/llvm.git llvm git clone -b release_39 [email protected]:llvm-mirror/clang.git llvm/tools/clang git clone -b release_39 [email protected]:llvm-mirror/clang-tools-extra.git llvm/tools/clang/tools/extra git clone -b release_39 [email protected]:llvm-mirror/compiler-rt.git llvm/projects/compiler-rt mkdir llvm_build cd llvm_build cmake -G Xcode .. /llvm -DCMAKE_BUILD_TYPE:STRING=MinSizeRelCopy the code
Note: official website tutorial llvm.org/docs/CMake….
B. Select Automatic SchmemA generationC. Compile clang, myplugin, and libclang
D. Final effect
2. Use plug-ins
2.1, hook xcode
A. Run the following two commands
sudo mv HackedClang.xcplugin `xcode-select -print-path`/.. /PlugIns/Xcode3Core.ideplugin/Contents/SharedSupport/Developer/Library/Xcode/Plug-insCopy the code
sudo mv HackedBuildSystem.xcspec `xcode-select -print-path`/Platforms/iPhoneSimulator.platform/Developer/Library/Xcode/Specifications
Copy the code
If you customize the CLang path and display name, modify the following files
B. the Xcode configurationC. add other_flags
-Xclang -load -Xclang /opt/llvm/clangplugin/libONEExtractVCPlugin.dylib -Xclang -add-plugin -Xclang ONEExtractVCPlugin -I/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1
Copy the code
/ opt/LLVM clangplugin/libMyPlugin dylib: is MyPlugin dynamic libraries address: The plug-in name/Applications/Xcode. App/Contents/Developer/Toolchains/XcodeDefault xctoolchain/usr/include/c + + / v1: using c + + library
2.2. Invoke the Clang plug-in from the command line
Replace the clang in the red box with the clang compiled by yourself
2.2 Common apis
A. Register the plug-in
static clang::FrontendPluginRegistry::Add<my::MyASTAction> X("MyPluginName", "MyPlugin description");
The first parameter is the plug-in name and the second is the plug-in description
B. Pass parameters to the plug-in
bool MyASTAction::ParseArgs(const CompilerInstance &CI, const std::vector<std::string>& args) { size_t cnt = args.size(); for(int i = 0; i < cnt; i++){ cout<<"myparam:"<<args.at(i)<<endl; } return true; }Copy the code
If the plugin is added at compile time, the param can be obtained by using this method. For example, add -xclang -plugin-arg-MyPlugin -Xclang $SRCROOT/.. , you can print out the srcroot path
- Ast parsing completes the call
void MyASTConsumer::HandleTranslationUnit(ASTContext &context){}
- InterfDecl ->getSuperClass()->>getNameAsString()
`
-
If (isa
(decl)){}
-
If (isa
(decl)){}
-
If (isa
(decl)){}
-
If (isa
(decl)){}
ObjcIsInstanceMethod = propertyDecl->isInstanceProperty(); Property type (modifier such as NSString):propertyDecl->getType().getasString (); PropertyDecl ->getGetterName().getAsString() propertyDecl->getGetterName().getAsString() PropertyDecl ->isAtomic() propertyDecl->isAtomic() propertyDecl->isAtomic()Copy the code
If (isa
(decl)) {} ivarDecl->getNameAsString()
If (isa
(decl)){}
@interface NSDictionary<Key: id<NSCopying>, Value>@end Key, Value is paramterCopy the code
- Is it a method:
if(isa<ObjCMethodDecl>(decl)){}
MethodDecl ->isInstanceMethod() Selector name MethodDecl ->getSelector().getAsString() Returns a value type :methodDecl->getReturnType().getasString () for(ArrayRef<ParmVarDecl *>::iterator it = methodDecl->param_begin(); it! =methodDecl->param_end(); It++) {cout < < "parameters:" < < ((* it) - > getNameAsString ()) < < "parameter types:" < < (* it) - > getType (). The getAsString () < < endl; }Copy the code
If (isa
(s)){}
Declare name :callExpr->getDecl()->->getNameAsString() :isa<VarDecl>(decl) Isa <EnumConstantDecl>(decl)Copy the code
E. Send a message to object-c isa
(s)
ObjcExpr ->getSelector().getAsString() ObjcExpr ->getSelector().getAsString() accept message types :objcExpr->getReceiverType().getAsString()Copy the code
3. Obtain the compilation command
3.1. Obtain compilation commands
xcodebuild clean xcodebuild -workspace OneTravel.xcworkspace -scheme OneTravel CODE_SIGN_IDENTITY=”” CODE_SIGNING_REQUIRED = NO – dry – run – configuration Release | ruby onepretty explanation: **CODE_SIGN_IDENTITY=”” CODE_SIGNING_REQUIRED=NO :** Indicates that certificate compilation is not required **-dry-run:** Only obtain the compilation command and run it
Onepretty: A tool extracted from XCpretty that removes useless code and adds a soft link to copy header files
3.2. Modify compilation commands
This parameter applies to the libtool command. For other parameters, seelink
A. Remove -gmodules: this command packages compilation information, which is not supported by custom libtools and is useless.
B. Remove -c and -o and their parameters: Only ast is parsed. These parameters are useless
C. Add a reference to the C ++ library (if you want to parse some.cpp and.mm files) : -I/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1
D. Replace tools: Replace Clang with your own tools, such as onec — -x — and see the double horizontal lines
The following is an example (Compact version) :
/Users/xx/Documents/plugin/bin/bin/onec /Users/xx/Documents/conn_connection.cpp -outdir=~/Desktop -- -x c++ -arch armv7 - isysroot/Applications/Xcode. App/Contents/Developer/Platforms/iPhoneOS platform/Developer/SDKs/iPhoneOS10.3. The SDK -I/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1Copy the code
4. Libtool development
4.1 Adding code and CMake files
[Img – wplfxrs7-1628248114419] [img- wplfxrs7-1628248114419]
Go to the llVM_build folder, empty the original files, and recompile the code cmake -g Xcode.. /llvm -DCMAKE_BUILD_TYPE:STRING=MinSizeRel
4.2 Introduction to some modules
Some clang components are used: libclangLex: preprocessing, lexical analysis, macro processing, tokens, syntax construction; LibclangAST: this library is used to set up, manage, and traverse the AST. LibclangParse: parsing parsing results. LibclangSema: parsing semantics. LibclangAnaylysis: Code analyses for static analysis libclangRewrite: libclangBasic: Miscellaneous libraries for clang
Clang.llvm.org/docs/Intern…
5. Compare plugins with libTool
The plug-in | libtool | |
---|---|---|
Parsing speed | Slightly faster | A bit slow |
Packet size | big | small |
Get the compilation command | Commands generated directly using xcodeBuild | Stitch or transform yourself |
With the integration of xcode | can | Can not be |
Since most of the API for the libTool and Clang plug-ins are common, you can use either of them for your actual work, and if something goes wrong, your code can be cheaply migrated from one to the other.
links
- CLANG Technology Sharing Series 1: Write your first CLANG plugin
- How To Setup Clang Tooling For LLVM
- clang-tutorial
- Demo code download