iOS程序員的自我修養-編譯、連接過程(一)

目錄

被隱藏了的過程

OC是用Clang/LLVM來編譯的。接下來我將用clang來展開整個過程。main.m文件源碼以下:程序員

//main.m文件
#import <stdio.h>

int main(int argc, const char * argv[]) {
    printf("hello ~");
    return 0;
}

複製代碼

平時用Xcode去Build,一鍵從源碼到程序。這個過程當中隱藏了預處理、編譯、彙編和連接4個過程以下:bash

預處理(預編譯Prepressing)

clang -E main.m -o main.i
複製代碼

處理源代碼文件中的以"#"開頭的預編譯指令。規則以下:markdown

  1. "#define"刪除並展開對應宏定義。
  2. 處理全部的條件預編譯指令。如#if/#ifdef/#else/#endif。
  3. "#include/#import"包含的文件遞歸插入到此處。
  4. 刪除全部的註釋"//或/**/"。
  5. 添加行號和文件名標識。如「# 1 "main.m"」,編譯調試會用到。

編譯(Compilation)

clang -S main.i -o main.s
複製代碼

編譯就是把上面獲得的.i文件進行:詞法分析、語法分析、靜態分析、優化生成相應的彙編代碼,獲得.s文件。函數

  1. 詞法分析:源代碼的字符序列分割成一個個token(關鍵字、標識符、字面量、特殊符號),好比把標識符放到符號表(靜態連接那篇,重點講符號表)。
  2. 語法分析:生成抽象語法樹 AST,此時運算符號的優先級肯定了;有些符號具備多重含義也肯定了,好比「*」是乘號仍是對指針取內容;表達式不合法、括號不匹配等,都會報錯。
  3. 靜態分析:分析類型聲明和匹配問題。好比整型和字符串相加,確定會報錯。
  4. 中間語言生成:CodeGen根據AST自頂向下遍歷逐步翻譯成 LLVM IR,而且在編譯期就能夠肯定的表達式進行優化,好比代碼裏t1=2+6,能夠優化t1=8。(假如開啓了bitcode,)
  5. 目標代碼生成與優化:根據中間語言生成依賴具體機器的彙編語言。並優化彙編語言。這個過程當中,假若有變量且定義在同一個編譯單元裏,那給這個變量分配空間,肯定變量的地址。假如變量或者函數不定義在這個編譯單元,得連接時候,才能肯定地址。

彙編(Assembly)

clang -c main.s -o main.o
複製代碼

彙編就是把上面獲得的.s文件裏的彙編指令一一翻譯成機器指令。獲得.o文件,也就是目標文件,後面會重點講的Mach-O文件。post

連接(Linking)

clang main.o -o main
複製代碼

遠古時代,一個程序只有一個源代碼文件,致使程序的維護很是困難。如今程序都是分模塊組成,好比一個App,對應有多個源代碼文件。每一個源代碼文件彙編成目標文件,根據上面流程A目標文件訪問B目標文件的函數或者變量,是不知道地址的,連接就是要解決這個問題。連接過程主要包括地址和空間分配、符號決議和重定位。優化

連接就是把目標文件(一個或多個)和須要的庫(靜態庫/動態庫)連接成可執行文件。後面會分別講靜態連接和動態連接。ui

引用

《程序員的自我修養-連接、裝載與庫》spa

相關文章
相關標籤/搜索