一個C文件要變成可執行的文件,須要通過四個過程:linux
主要用到的工具叫作arm-linux-gcc,arm-linux-ld,本次學習的是gcc工具。編程
幾條經常使用命令選項:bash
-E:預處理後即中止dom
-S:編譯後不彙編編程語言
-c:預處理+編譯+彙編,但不鏈接函數
-o:指定輸出文件爲file。不管哪一個環節,這個選項均可以使用工具
編譯單個文件的語句,只須要一句話便可學習
gcc -o hello hello.c
這條指令,即直接將C文件生成成可執行文件"hello"優化
雖然這裏是一條指令,但已經包含了幾個步驟了。spa
gcc -E -o hello.i hello.c //對C文件作預處理 gcc -S -o hello.s hello.i //進行編譯,生成彙編文件 gcc -c -o hello.o hello.s //對彙編代碼編譯成目標文件 gcc -o hello hello.o //生成可執行程序hello
對於多個文件,須要進行逐個編譯,再作最後的鏈接。
gcc -c -o mian.o mian.c gcc -c -o sub.o sub.c gcc -o test mian.o sub.o
也能夠直接鏈接編譯生成
gcc -o test mian.c sub.c
基本格式:gcc [options] file1 file2... //若不加入參數,則按默認參數依次執行編譯、彙編和鏈接操做,生成的可執行文件名爲 a.out 經常使用參數:-E //只執行預處理操做 -S //只執行到編譯操做完成,不進行彙編操做,生成的是彙編文件(.s 或 .asm),內容爲彙編語言 -c //執行編譯和彙編,但不進行連接,即只生成可重定位目標文件(.o),爲二進制文件,不生成完整的可執行文件 -o filename //將操做後的內容輸出到filename指定的文件中 -static //對於支持動態連接的系統,使用靜態連接而不是動態連接進行連接操做 -g //編譯時生成debug有關的程序信息(供gdb使用) --save-temps //生成編譯過程的中間結果文件(包括預處理文件(x.ii)、彙編代碼(x.s)、目標文件(x.o)和最終的可執行文件) -I PATH //在PATH指定的目錄下尋找相關的include文件 -lxx //其中xx爲指定函數庫,對於Linux環境下的函數庫,靜態庫後綴爲.a,動態庫後綴爲.so,通常庫名爲libxx.a或libxx.so,如加入libm.so庫,則使用參數-lm(去除lib和後綴.a\so) -L PATH //在PATH指定的目錄下尋找相關的庫文件,即-lxx指定待連接的庫,-L指定尋找該庫的路徑。不指定時搜索默認的庫函數路徑。 -std=xx //指定編譯使用的語言標準 -x language //指定待編譯文件的語言,而不是由編譯器根據文件後綴自行判斷。即默認狀況下gcc根據文件後綴判斷使用的編程語言。例如使用文件名hello做爲源文件名是不合適的,應使用hello.c -Wall //輸出一些簡單的錯誤以及一些可能存在問題的警告 -Wextra //輸出-Wall不包含的警告等 -Werror //將警告視爲錯誤輸出 -D name=definition //加入宏定義,若不指定def,則默認爲1 -O一、-O2 //規定編譯器的優化等級,優化級數越高執行效率通常越好,可是優化會改變原有程序結構,使得其彙編不易理解 //一些進行緩衝區溢出實驗時可能須要的選項 -fstack-protector\-fno-stack-protector //是否開啓堆棧保護,這裏的保護是在返回地址以前加入一個驗證值來確保返回地址不被破壞 -z execstack //啓用可執行棧,默認是禁用的 //(echo 0 >/proc/sys/kernel/randomize_va_space 關閉地址隨機化,這是一個單獨的命令,操做須要root權限)
gcc -static hello.o world.o -lm -L /usr/lib //以靜態連接的方式,將hello.o、world.o以及libm.a庫中的相關目標文件連接,在/usr/lib文件夾下尋找目標庫