iOS编译指令

1,654 阅读7分钟

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