NDK開發之編譯原理與語法

2021-09-29 21:50:35 字數 4598 閱讀 6204

1.編譯流程

預處理:就是對各種預處理命令的處理,主要是巨集替換、檔案引入、去除空行和注釋等。linux系統中預處理命令:gcc -e test.c -o test.i。-e表示gcc在預處理後停止編譯、彙編和鏈結操作。

編譯:將預處理後的**翻譯成組合語言。會先分析後綜合,分析就是進行詞法、語法、語義分析和中間**的生成,綜合就是**優化和**生成。編譯命令gcc -c test.i -o test.s。

彙編:把編譯生成的彙編**.s檔案轉化成為可執行的二進位制的目標檔案。gcc -c test.s -o test.o。

執行檔案:./test。刪除目標檔案:rm -rf test。生成可執行檔案:gcc -o test test.c。檢視檔案詳情ls -lh。

2.靜態庫和動態庫

靜態庫是目標檔案(.o)的集合,一般以.a結尾,只存在生成可執行檔案階段。鏈結器將從庫檔案中取得所需**複製到生成的可執行**中,可執行**中包含庫**的完整拷貝。多次使用就有多份拷貝,包會比較大;靜態庫有更新,所有使用它的程式都需要重新編譯。命令將目標檔案打包生成靜態庫:ar rcs libtest.a test.o。檢視靜態庫內容:ar t libtest.a。  

動態庫在鏈結階段沒有複製到目標**中,在執行階段才由系統動態到記憶體中。系統只要載入一次動態庫,系統中不同的程式都可以獲得記憶體中相同動態庫的副本,可以節省大量記憶體空間。生成動態庫:gcc -shared -fpic -o libtest.so test.o。

編譯可執行檔案並鏈結庫檔案tool:gcc -o main main.c -l. -ltool。-l.表示編譯程式按照指定目錄去找,.按照當前目錄去找。 -l指定要鏈結的庫。ldd main 可以檢視可執行檔案依賴的庫。當目錄中動態庫和靜態庫的名字相同時會優先載入動態庫,鏈結動態庫需要先設定環境變數,指定查詢共享庫,在預設目錄下找不到該庫時使用:ld_library_path=. ./main。

一、makefile語法詳解

makefile定義了一系列規則的去指定哪些檔案先編譯、是否需要重新編譯,如何鏈結等,是自動化編譯的指令碼,告訴make如何編譯和鏈結,生成目標檔案。

makefile規則:taget : prerequisites1 prerequisites2 command (command 和target在一行分號隔開;另起一行必須加tab;命令太長使用\換行)。命令.phony:clean     clean:    -rm main,*.o顯示指定clean是偽目標,不會生成clean檔案。-表示如果檔案執行不成功,則跳過繼續執行。

makefile工作原理:輸入make命令後,make會首先在當前目錄找makefile(makefile)檔案,在makefile中找到第乙個target並作為最終目標。如果target已經存在並且是最新的則執行檔案main。target不存在或者不是最新的,則需要判斷當前的依賴檔案是否是最新的,讓最新的依賴檔案根據依賴規則執行依賴命令重新生成最新的target。最後完成make的終極目標執行檔案main。如果在查詢依賴關係過程中,找不到被依賴檔案,則make報錯退出。

makefile中的變數:工程需要加入新的.o檔案,可能會忘記修改某處.o檔案,最好使用變數統一修改。定義object=main.o tool.o,使用$(object);。在makefile 中使用include類引入其他makefile檔案eg :-include foo.make *.mk,-表示找不到檔案也繼續執行。

函式:帶引數和不帶引數。不帶引數:define func $( info echo "hello") endef  ,呼叫$(call func)。帶引數:define func1 $( info echo $(1)$(2)) endef  ,呼叫$(call func,hello,world)。

makefile工作流程:讀入所有makefile,讀入被include的其他makefile檔案,初始化所有的變數,推導隱晦規則並分析所有規則,為所有的目標檔案建立依賴關係鏈;根據依賴關係,確定哪些目標檔案需要重新生成;執行生成命令。

二、shell語法詳解

shell執行在linux系統中,構建大型專案需要不斷的編譯、打包等,shell是構建專案命令的集合,能避免大量重複的操作,可以編譯大部分的第三方庫並合併到apk中。bin/bash是shell語法開發,在linux中使用的命令都對應乙個shell檔案。shell檔案是以#!bin/bash開頭,字尾是.sh的可執行檔案,執行shell檔案的指令是'chmod 777 a.sh ;./a.sh','/bin/bash a.sh','sh a.sh'。

1.變數

分為環境變數、區域性變數、系統變數。shell程式語言是弱型別,賦值的時候就定義了。定義:a=10(變數左右都不能有空格),引用:$a。$pwd輸出當前路徑,$0輸出當前專案名稱,$1輸出第乙個引數,$*是輸出所有的引數,$#是所有引數的個數,$?是返回前一條指令的返回結果。

2.迴圈

for格式:'for((i=0;i<$#;i++))do   ..done','for i in `seq 1 15` do ... done',。eg 累加:j=0 for((i=0;i<100;i++))do j=`expr $i + $j ` done echo $j。壓縮所有s**件: for i in `find /root -name "*.sh"` do   tar -czf *.tgz  $i done。

while格式:『while(條件)do .. done』。((i<100))算數邏輯,命令邏輯用[[ $i -lt 100 ]]。eg 讀檔案while read line do echo $line done3.條件

if格式:if(); fi。if() ;then ..else..fi。 沒有{},語句前必須加tab鍵,不能是空格,空格在shell中表示分割,不能隨便加。shell是非物件導向語言,很多操作是可以通過運算子實現,不僅可以使用算數比較,可以使用命令,-f檔案是否存在,-d目錄是否存在。eg:b=/root/a if [ !-d $b ] then  mkdir -p $b

4.運算子

算數運算子:+、-、*、/、% expr $a * $b;=、==、!=做條件表示式,中括號前後必須有空格。算數運算方式:(())、、let、expr外部程式。

關係運算子-eg是整形比較相等,-ne不等於,-ge是大於等於,-le是小於等於,-gt大於,-lt小於。

布林運算子!,-a單方成立,-o雙方成立。字串運算子有=、!=、-z、-n、$a(是否為空)。

5.重定向

輸出text.txt的內容到螢幕:cat 0test.txt。

6.函式

必須先定義,再使用。格式:定義函式fun(){} function fun(){},呼叫fun 10,函式中可以使用成員變數$a,也可以使用引數,shell語法沒有形參,使用$1、$2代替引數。有返回值的函式分為兩種return或者echo返回。return方式 最後使用$?返回最後一條的執行結果,結算結果必須小於255,eg:函式中最後一行新增**return $[$a*2] ,呼叫該函式後輸出$?即可獲得值 $[$a*2]。echo方式則不同,在函式最後一行新增** echo $[$a*2] ,呼叫該函式並將返回結果賦值給變數r=`fun()`,呼叫後輸出$r即可。

三、cmake詳解

android  studio 2.2以上版本預設的構建工具就是cmake。cmake是make的高階版,是乙個跨平台的編譯工具,能夠通過簡單的指令描述不同平台、不同編譯器上程式的編譯過程,產生平台對應的makefile和project檔案,但並不直接產生最終軟體,由其他軟體根據指令碼構建。android studio根據cmake產生的構建系統是ninja,我們不需要關心ninja指令碼,知道怎麼配置cmake就可以了。

cmake原始檔一般命名為cmakelists.txt或者以.cmake為拓展名。原始檔包含命令、注釋、空格和換行,命令是指所有能執行的語句,可以是系統內建函式、自定義函式和巨集定義等。可以通過add_subdirectory()新增子目錄的cmake檔案。

1.cmake的注釋

單行注釋以#開頭,多行注釋以#[[ ]]包裹。

2.cmake的語法

所有變數都是string型別,大小寫敏感。變數定義 set(a 1),set(list 1 2 3),set(list "1;2;3"),呼叫message("輸出a:$"),unset()來移除變數。作用域有全域性層、目錄層、函式層。函式層定義的變數會覆蓋目錄層,目錄層會覆蓋全域性層(cache變數),也就是系統在查詢變數的時候首先是從函式層開始查詢的,修改上層函式的作用域並不會真正修改上層函式的作用域,只是獲取上層函式的副本而已。

操作符優先順序:括號》一元(command define exist)>二元(比較運算子、str、version)>邏輯運算子(and or not)

條件語句:if()...else if()...else()...endif()

迴圈語句:while(not a strequal "***")....endwhile()

迴圈遍歷:foreach(item 1 2 3)....endforeach(item),foreach(item range 3),foreach(item range 1 9 3),foreach(item in lists list_v)。

自定義函式: function(func a b)...endfunction(func),呼叫:func 1 2。$(argc)表示輸入的有多少個引數,$(ar**)返回所有的輸入引數,$(ar**0)返回第乙個函式。

巨集定義:macro(m a b)...endmacro(m)。

NDK開發(五) Ubuntu編譯FFmpeg

ubuntu 14.0 amd64 64bit ffmpeg tag n2.6.9 ndk r15c cd usr mkdir ndk 建立ndk目錄 mkdir jason 建立ffmpeg目錄 1.目錄給許可權 chmod 777 r ndk 2.解壓android ndk r15c linux...

工作積累之NDK編譯STL

from 方法 system 使用預設最小的c 執行庫,這樣生成的應用體積小,記憶體占用小,但部分功能將無法支援 stlport static 使用stlport作為靜態庫,這項是android開發網極力推薦的 stlport shared stlport 作為動態庫,這個可能產生相容性和部分低版本...

工作積累之NDK編譯STL

方法 system 使用預設最小的c 執行庫,這樣生成的應用體積小,記憶體占用小,但部分功能將無法支援 stlport static 使用stlport作為靜態庫,這項是android開發網極力推薦的 stlport shared stlport 作為動態庫,這個可能產生相容性和部分低版本的andr...