一、問(wèn)題在linux下玩makefile玩的多了,發(fā)現(xiàn)一個(gè)問(wèn)題。程序總是越編越大,換句話說(shuō)就是程序編譯出來(lái)的可執(zhí)行文件總是在不停的增大,特別是加入了外部的靜態(tài)庫(kù)之后,程序文件顯著增大,造成程序下載耗時(shí)增大,甚至造成程序空間溢出,F(xiàn)LASH不夠用。 我分析了一下,雖然所引用的靜態(tài)庫(kù)本身確實(shí)很大,但是我的程序中只用到了其中幾個(gè)函數(shù),按理來(lái)說(shuō),它只取這幾個(gè)函數(shù)進(jìn)行鏈接,鏈接之后的可執(zhí)行文件不應(yīng)該那么大才對(duì),肯定是哪里沒(méi)有設(shè)置好。我記得在windows下的KEIL或者IAR就不會(huì)這樣,它們里面有一個(gè)設(shè)置選項(xiàng),可以指定“沒(méi)有使用的函數(shù)不參與鏈接”之類(lèi)的,那么makefile里面難道沒(méi)有類(lèi)似的功能嗎?于是,一番百度和CSDN之后,輕松搞定! 二、原理下文引自網(wǎng)絡(luò)博客: 因?yàn)镚CC鏈接操作以section作為最小的處理單元,一個(gè)section中可以包含很多個(gè)function,而一個(gè)section中只要有一個(gè)function被引用,該section就會(huì)被加入鏈接,最終生成可執(zhí)行文件。 換句話說(shuō)就是,在缺省情況下,某個(gè).c程序中的所有function,實(shí)際上都會(huì)編譯成同一個(gè)section。那么,只要你的代碼中用到這個(gè).c生成的.o的其中任何一個(gè)function,系統(tǒng)就會(huì)將這整個(gè)section進(jìn)行鏈接。這就導(dǎo)致,我們?cè)谝猛獠快o態(tài)庫(kù)時(shí),不管你是引用其中一個(gè)函數(shù),還是引用全部的函數(shù),你最終編譯鏈接出來(lái)的可執(zhí)行文件都一樣大,系統(tǒng)并不會(huì)自動(dòng)根據(jù)你所引用的函數(shù)個(gè)數(shù)的多少而動(dòng)態(tài)的調(diào)整鏈接方式。 三、辦法那么,要怎么修改呢?方法也很簡(jiǎn)單,兩個(gè)步驟即可: 編譯時(shí):使用"-ffunction-sections"和"-fdata-sections"將每個(gè)function/data創(chuàng)建為一個(gè)sections,sections名與function/data名保持一致。 鏈接時(shí):采用"-Wl, -gc-sections"申明,告訴系統(tǒng)去掉那些沒(méi)用用到的section。
四、示例main.c #include <stdio.h> #include <stdlib.h> #include <string.h> int fun_0() { printf("this is a test function. %s: %d\n", __FUNCTION__, __LINE__); return 0; } int fun_1() { printf("this is a test function. %s: %d\n", __FUNCTION__, __LINE__); return 0; } int fun_2() { printf("this is a test function. %s: %d\n", __FUNCTION__, __LINE__); return 0; } int fun_3() { printf("this is a test function. %s: %d\n", __FUNCTION__, __LINE__); return 0; } int fun_4() { printf("this is a test function. %s: %d\n", __FUNCTION__, __LINE__); return 0; } int fun_5() { printf("this is a test function. %s: %d\n", __FUNCTION__, __LINE__); return 0; }
int fun_6() { printf("this is a test function. %s: %d\n", __FUNCTION__, __LINE__); return 0; }
int main() { fun_0(); return 0; }
makefile optimized:
gcc -ffunction-sections -fdata-sections -c main.c
gcc -Wl,-gc-sections -o test_optimized main.o
normal:
gcc -c main.c
gcc -o test_normal main.o
clean:
-@rm *.o test_normal test_optimized
運(yùn)行結(jié)果對(duì)比: leon@Ubuntu:~/studytest/z_mydesign/section_test2$ make normal
gcc -c main.c
gcc -o test_normal main.o
leon@Ubuntu:~/studytest/z_mydesign/section_test2$ make optimized
gcc -ffunction-sections -fdata-sections -c main.c
gcc -Wl,-gc-sections -o test_optimized main.o
leon@Ubuntu:~/studytest/z_mydesign/section_test2$ ll
總用量 44
drwxrwxr-x 2 leon leon 4096 3月 20 14:02 ./
drwxrwxr-x 5 leon leon 4096 3月 20 13:45 ../
-rw-rw-r-- 1 leon leon 496 3月 20 14:02 main.c
-rw-rw-r-- 1 leon leon 3696 3月 20 14:02 main.o
-rw-rw-r-- 1 leon leon 206 3月 20 13:50 Makefile
-rwxrwxr-x 1 leon leon 8896 3月 20 14:02 test_normal*
-rwxrwxr-x 1 leon leon 8432 3月 20 14:02 test_optimized*
可以看出,優(yōu)化后的bin文件,減少了 8896-8432=464 bytes。 五、注意請(qǐng)注意: 1)使用了section選項(xiàng),當(dāng)函數(shù)被聲明了,但是函數(shù)沒(méi)有被調(diào)用,函數(shù)體不實(shí)現(xiàn)也編譯ok,但是函數(shù)體不能重復(fù)定義; 2)一但使用-Wl,-gc-sections選項(xiàng)之后,將無(wú)法使用gdb調(diào)試。也無(wú)法使用gprof工具;
|