Clang
查看编译的过程
clang -ccc-print-phases main.m
0: input, "main.m", objective-c
1: preprocessor, {0}, objective-c-cpp-output
2: compiler, {1}, ir
3: backend, {2}, assembler
4: assembler, {3}, object
5: linker, {4}, image
6: bind-arch, "x86_64", {5}, image
查看预处理
clang -E main.m
将OC代码转换为CPP代码
clang -rewrite-objc main.m
如果有依赖Foundation,需要指定依赖
clang -rewrite-objc -F Foundation main.m
如果还依赖了UIKit等,那么需要指定isysroot,设置系统的根路径
clang -rewrite-objc -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk main.m
词法分析
clang -fmodules -E -Xclang -dump-tokens main.m
源程序代码
int myFunction(int a, int b) {
return a + b + 3;
}
int main(int argc, char * argv[]) {
int a = 5;
int b = 6;
int sum = myFunction(a, b);
return 0;
}
词法分析后
int myFunction(int a, int b) {
return a + b - 3;
}
int main(int argc, char * argv[]) {
int a = 5;
int b = 6;' Loc=<main.m:9:1>
int 'int' [StartOfLine] Loc=<main.m:11:1>
identifier 'myFunction' [LeadingSpace] Loc=<main.m:11:5>
l_paren '(' Loc=<main.m:11:15>
int 'int' Loc=<main.m:11:16>
identifier 'a' [LeadingSpace] Loc=<main.m:11:20>
comma ',' Loc=<main.m:11:21>
int 'int' [LeadingSpace] Loc=<main.m:11:23>
identifier 'b' [LeadingSpace] Loc=<main.m:11:27>
r_paren ')' Loc=<main.m:11:28>
l_brace '{' [LeadingSpace] Loc=<main.m:11:30>
return 'return' [StartOfLine] [LeadingSpace] Loc=<main.m:12:5>
identifier 'a' [LeadingSpace] Loc=<main.m:12:12>
plus '+' [LeadingSpace] Loc=<main.m:12:14>
identifier 'b' [LeadingSpace] Loc=<main.m:12:16>
minus '-' [LeadingSpace] Loc=<main.m:12:18>
numeric_constant '3' [LeadingSpace] Loc=<main.m:12:20>
semi ';' Loc=<main.m:12:21>
r_brace '}' [StartOfLine] Loc=<main.m:13:1>
int 'int' [StartOfLine] Loc=<main.m:15:1>
identifier 'main' [LeadingSpace] Loc=<main.m:15:5>
l_paren '(' Loc=<main.m:15:9>
int 'int' Loc=<main.m:15:10>
identifier 'argc' [LeadingSpace] Loc=<main.m:15:14>
comma ',' Loc=<main.m:15:18>
char 'char' [LeadingSpace] Loc=<main.m:15:20>
star '*' [LeadingSpace] Loc=<main.m:15:25>
identifier 'argv' [LeadingSpace] Loc=<main.m:15:27>
l_square '[' Loc=<main.m:15:31>
r_square ']' Loc=<main.m:15:32>
r_paren ')' Loc=<main.m:15:33>
l_brace '{' [LeadingSpace] Loc=<main.m:15:35>
int 'int' [StartOfLine] [LeadingSpace] Loc=<main.m:16:5>
identifier 'a' [LeadingSpace] Loc=<main.m:16:9>
equal '=' [LeadingSpace] Loc=<main.m:16:11>
numeric_constant '5' [LeadingSpace] Loc=<main.m:16:13>
semi ';' Loc=<main.m:16:14>
int 'int' [StartOfLine] [LeadingSpace] Loc=<main.m:17:5>
identifier 'b' [LeadingSpace] Loc=<main.m:17:9>
equal '=' [LeadingSpace] Loc=<main.m:17:11>
numeric_constant '6' [LeadingSpace] Loc=<main.m:17:13>
semi ';' Loc=<main.m:17:14>
int 'int' [StartOfLine] [LeadingSpace] Loc=<main.m:18:5>
identifier 'sum' [LeadingSpace] Loc=<main.m:18:9>
equal '=' [LeadingSpace] Loc=<main.m:18:13>
identifier 'myFunction' [LeadingSpace] Loc=<main.m:18:15>
l_paren '(' Loc=<main.m:18:25>
identifier 'a' Loc=<main.m:18:26>
comma ',' Loc=<main.m:18:27>
identifier 'b' [LeadingSpace] Loc=<main.m:18:29>
r_paren ')' Loc=<main.m:18:30>
semi ';' Loc=<main.m:18:31>
return 'return' [StartOfLine] [LeadingSpace] Loc=<main.m:20:5>
numeric_constant '0' [LeadingSpace] Loc=<main.m:20:12>
semi ';' Loc=<main.m:20:13>
r_brace '}' [StartOfLine] Loc=<main.m:21:1>
eof '' Loc=<main.m:22:1>
语法分析
clang -fmodules -fsyntax-only -Xclang -ast-dump main.m
打印出的语法树
TranslationUnitDecl 0x7fd4ce82e408 <<invalid sloc>> <invalid sloc> <undeserialized declarations>
|-TypedefDecl 0x7fd4ce82eca0 <<invalid sloc>> <invalid sloc> implicit __int128_t '__int128'
| `-BuiltinType 0x7fd4ce82e9a0 '__int128'
|-TypedefDecl 0x7fd4ce82ed10 <<invalid sloc>> <invalid sloc> implicit __uint128_t 'unsigned __int128'
| `-BuiltinType 0x7fd4ce82e9c0 'unsigned __int128'
|-TypedefDecl 0x7fd4ce82edb0 <<invalid sloc>> <invalid sloc> implicit SEL 'SEL *'
| `-PointerType 0x7fd4ce82ed70 'SEL *'
| `-BuiltinType 0x7fd4ce82ec00 'SEL'
|-TypedefDecl 0x7fd4ce82ee98 <<invalid sloc>> <invalid sloc> implicit id 'id'
| `-ObjCObjectPointerType 0x7fd4ce82ee40 'id'
| `-ObjCObjectType 0x7fd4ce82ee10 'id'
|-TypedefDecl 0x7fd4ce82ef78 <<invalid sloc>> <invalid sloc> implicit Class 'Class'
| `-ObjCObjectPointerType 0x7fd4ce82ef20 'Class'
| `-ObjCObjectType 0x7fd4ce82eef0 'Class'
|-ObjCInterfaceDecl 0x7fd4ce82efd0 <<invalid sloc>> <invalid sloc> implicit Protocol
|-TypedefDecl 0x7fd4ce82f348 <<invalid sloc>> <invalid sloc> implicit __NSConstantString 'struct __NSConstantString_tag'
| `-RecordType 0x7fd4ce82f140 'struct __NSConstantString_tag'
| `-Record 0x7fd4ce82f0a0 '__NSConstantString_tag'
|-TypedefDecl 0x7fd4ce86ba00 <<invalid sloc>> <invalid sloc> implicit __builtin_ms_va_list 'char *'
| `-PointerType 0x7fd4ce82f3a0 'char *'
| `-BuiltinType 0x7fd4ce82e4a0 'char'
|-TypedefDecl 0x7fd4ce86bce8 <<invalid sloc>> <invalid sloc> implicit __builtin_va_list 'struct __va_list_tag [1]'
| `-ConstantArrayType 0x7fd4ce86bc90 'struct __va_list_tag [1]' 1
| `-RecordType 0x7fd4ce86baf0 'struct __va_list_tag'
| `-Record 0x7fd4ce86ba58 '__va_list_tag'
|-ImportDecl 0x7fd4ce86c510 <main.m:9:1> col:1 implicit Darwin.C.stdio
|-FunctionDecl 0x7fd4ce86c6f0 <line:11:1, line:13:1> line:11:5 used myFunction 'int (int, int)'
| |-ParmVarDecl 0x7fd4ce86c568 <col:16, col:20> col:20 used a 'int'
| |-ParmVarDecl 0x7fd4ce86c5e8 <col:23, col:27> col:27 used b 'int'
| `-CompoundStmt 0x7fd4ce86c8e0 <col:30, line:13:1>
| `-ReturnStmt 0x7fd4ce86c8d0 <line:12:5, col:20>
| `-BinaryOperator 0x7fd4ce86c8b0 <col:12, col:20> 'int' '-'
| |-BinaryOperator 0x7fd4ce86c870 <col:12, col:16> 'int' '+'
| | |-ImplicitCastExpr 0x7fd4ce86c840 <col:12> 'int' <LValueToRValue>
| | | `-DeclRefExpr 0x7fd4ce86c800 <col:12> 'int' lvalue ParmVar 0x7fd4ce86c568 'a' 'int'
| | `-ImplicitCastExpr 0x7fd4ce86c858 <col:16> 'int' <LValueToRValue>
| | `-DeclRefExpr 0x7fd4ce86c820 <col:16> 'int' lvalue ParmVar 0x7fd4ce86c5e8 'b' 'int'
| `-IntegerLiteral 0x7fd4ce86c890 <col:20> 'int' 3
`-FunctionDecl 0x7fd4d0862380 <line:15:1, line:21:1> line:15:5 main 'int (int, char **)'
|-ParmVarDecl 0x7fd4ce86c910 <col:10, col:14> col:14 argc 'int'
|-ParmVarDecl 0x7fd4d0862230 <col:20, col:32> col:27 argv 'char **':'char **'
`-CompoundStmt 0x7fd4d08627b8 <col:35, line:21:1>
|-DeclStmt 0x7fd4d08624e8 <line:16:5, col:14>
| `-VarDecl 0x7fd4d0862460 <col:5, col:13> col:9 used a 'int' cinit
| `-IntegerLiteral 0x7fd4d08624c8 <col:13> 'int' 5
|-DeclStmt 0x7fd4d08625a0 <line:17:5, col:14>
| `-VarDecl 0x7fd4d0862518 <col:5, col:13> col:9 used b 'int' cinit
| `-IntegerLiteral 0x7fd4d0862580 <col:13> 'int' 6
|-DeclStmt 0x7fd4d0862770 <line:18:5, col:31>
| `-VarDecl 0x7fd4d08625d0 <col:5, col:30> col:9 sum 'int' cinit
| `-CallExpr 0x7fd4d0862710 <col:15, col:30> 'int'
| |-ImplicitCastExpr 0x7fd4d08626f8 <col:15> 'int (*)(int, int)' <FunctionToPointerDecay>
| | `-DeclRefExpr 0x7fd4d0862638 <col:15> 'int (int, int)' Function 0x7fd4ce86c6f0 'myFunction' 'int (int, int)'
| |-ImplicitCastExpr 0x7fd4d0862740 <col:26> 'int' <LValueToRValue>
| | `-DeclRefExpr 0x7fd4d0862658 <col:26> 'int' lvalue Var 0x7fd4d0862460 'a' 'int'
| `-ImplicitCastExpr 0x7fd4d0862758 <col:29> 'int' <LValueToRValue>
| `-DeclRefExpr 0x7fd4d0862690 <col:29> 'int' lvalue Var 0x7fd4d0862518 'b' 'int'
`-ReturnStmt 0x7fd4d08627a8 <line:20:5, col:12>
`-IntegerLiteral 0x7fd4d0862788 <col:12> 'int' 0
生成中间代码LLVM IR
clang -S -emit-llvm main.m
xcrun
xcrun是Xcode命令行工具(Command Line Tools)中的一个工具,Xcode命令行工具还包括像xcode-select
以及xcodebuild
等工具。xcodebuild
主要用来编译、打包等事情。
xcrun是对clang的一层封装,通过xcrun --help
可以查看其用法,相对于clang要简便很多
dangguo@localhost ObjcStudy % xcrun --help
Usage: xcrun [options] <tool name> ... arguments ...
Find and execute the named command line tool from the active developer
directory.
The active developer directory can be set using `xcode-select`, or via the
DEVELOPER_DIR environment variable. See the xcrun and xcode-select manual
pages for more information.
Options:
-h, --help show this help message and exit
--version show the xcrun version
-v, --verbose show verbose logging output
--sdk <sdk name> find the tool for the given SDK name
--toolchain <name> find the tool for the given toolchain
-l, --log show commands to be executed (with --run)
-f, --find only find and print the tool path
-r, --run find and execute the tool (the default behavior)
-n, --no-cache do not use the lookup cache
-k, --kill-cache invalidate all existing cache entries
--show-sdk-path show selected SDK install path
--show-sdk-version show selected SDK version
--show-sdk-build-version show selected SDK build version
--show-sdk-platform-path show selected SDK platform path
--show-sdk-platform-version show selected SDK platform version
将OC代码转换为CPP代码
xcrun --sdk iphoneos clang -rewrite-objc main.m -o main.cpp
--sdk iphoneos
就可以替代 -sysroot /Applicaiton/Xcode/Content/Developer...
等一大串。
指定CPU架构
针对不同的cpu体系,编译出的产物是不一样的,我们的iOS程序现在一般是跑在arm64上,所以可以直接指定架构。
xcrun --sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main.cpp
总结
目前我们比较倾向于使用xcrun以及指定cpu架构,所以通常将.m转换为.cpp使用的命令为:
xcrun --sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main.cpp
__weak弱引用
弱引用不仅仅需要静态编译,还需要运行时的支持。如果不指定会报错
error: cannot create
__weak reference because the current deployment target does not support weak references
__attribute__((objc_ownership(weak))) NSObject *weakObj = obj;
^
所以需要额外添加参数fobjc-runtime=ios-8.0.0
。而且__weak是在ARC下才支持的,所以我们还需要指定使用arc-fobjc-arc
。
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc -fobjc-arc -fobjc-runtime=ios-8.0.0 **.m -o **.cpp