.cpp 编译成.a或是 .so
1.將.c 文件編譯成.o文件
gcc -c test1.c test2.c test3.c
2.然后用ar命令生成.a文件,ar crv test.a test1.o test2.o test3.o
3.在windows環境,我們有集成開發環境(IDE),使得我們對編譯器了解的很少。當我們專向linux時需要在命令行下編譯自己的程序需要對編譯器的
命令行參數比較熟悉。而如果是做嵌入開發構建自己的操作系統時失去了系統平臺,需要我們對編譯的過程以及可執行文件的內部結構有所了解。本文講述了如何編
譯可執行文件、靜態庫、動態庫,如何優化編譯器,如何編譯無操作系統環境下的程序(自己的OS)等。
? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ?
1.分析普通的helloworld程序
? ? 先書寫一下一個簡單的helloworld程序如下:
/* hello.c */
int main(int argc, char * argv[])
{
? ? return 0
}
? ? 編譯程序:
gcc -o hello hello.c
? ? 等價的編譯方法:
gcc -c hello.c
gcc -o hello.my -nostartfiles hello.o /usr/lib/crt1.o /usr/lib/crti.o /usr/lib/crtn.o
? ? 我在redflag workstation 5.0版本下用3.4.3版本GCC編譯器編譯出來的大小都是3589字節,并且用diff命令比較為相同的文件。由此證明gcc在編譯并鏈接 hello.c文件時先將hello.c編譯成hello.o,然后將它與crt1.o、crti.o、crtn.o鏈接在一起。
? ? 如果要寫一個沒有main函數的程序,就需要自己實現crt1.o。程序入口為符號“_start”處。代碼如下:
/* nomain.c */
void _start(void)
{
? ? _exit(0);
}
gcc -o nomain -nostartfiles hello.c
2.編譯和使用庫
? ? 除了直接編譯代碼外還會使用到函數庫。庫有靜態庫和動態庫之分。靜態庫是以.a結尾的文件,例如:libXXX.a;動態庫是以.so結尾的文件,例如: libXXX.so。XXX之后或者.so和.a之后會跟版本號,例如:libc-2.3.4.so,或者libuuid.so.1.2。
? ? 加入函數庫的代碼如下:
/* test.h */
int test1 (void);
/* test.c */
#include stdio.h>
#include "libtest.h"
int test1 (void)
{
? ? printf("test1 function is called.\n");
? ? return 0;
}
? ? 當要編譯成靜態庫的時候使用如下命令生成libtest.a:
gcc -c test.c
ar -r libtest.a test.o
? ? 當要編譯成動態鏈接庫的時候使用如下命令生成libtest.so
gcc -c -fpic test.c
gcc -shared test.o -o libtest.so
或
gcc -fpic -shered test.c -o libtest.so
? ? 當需要調用該庫時使用如下代碼。
/* calllib.c */
#include "test.h"
int main (int argc, char * argv[])
{
? ? test1();
}
? ? 按如下方式編譯:
gcc -o calllib.static calllib.c libtest.a
或
gcc -o calllib.dynamic calllib.c libtest.so
或
gcc -o calllib calllib.c -ltest
? ? 前提是libtest.a或libtest.so在當前編譯的目錄。
? ? 使用ldd顯示calllib.static依賴的庫只有libc和ld-linux,但calllib.dynamic就多了一個libtest.so。
3.庫文件和頭文件
? ? 在程序中,使用#include stdio.h>類似的頭文件stdio.h在編譯器的頭文件路徑中,#include "abc.h"中的stdio.h文件則應該在當前目錄。通過對編譯器指定參數-IPATH>來指定頭文件所在目錄,可以用 #include >來引用。例如:gcc -I./include hello.c,將從當前目錄下的include目錄下去尋找頭文件。
? ? 同理,程序中調用的庫函數在編譯時也需要指定路徑,同時指定庫。使用-LPATH>參數指定庫文件的目錄,-lFILE>指定包含的庫文件。例如,要使用libXXX.so庫,參數為-lXXX。
? ? 一般一個庫編譯完成后有庫文件和頭文件。如果要使用這個庫,可以將庫文件目錄和頭文件目錄分別用-I和-L參數指定,也可以將他們拷貝到編譯器的include和lib目錄下。
4.縮小程序體積
? ? 代碼如下:
/* nomain.c */
void _start(void)
{
? ? asm("movl , eax\n"
? ?? ???"movl {fckeditor}, ebx\n"
? ?? ???"int {fckeditor}x80"
? ? );
}
使用如下方法能使可執行文件體積最小(手工方法除外)。
gcc -o nomain -s -O3 nomain.c
objcopy -R .comment -R .data
? ? 由此得到可執行文件的體積為352字節。
? ? GCC能編譯出2種格式的可執行體:a.out格式、elf格式。其中.o目標文件、.a靜態庫文件
Appendix.1 常用命令
ldd:顯示可執行文件或者庫文件依賴的庫文件。
objdump:顯示elf可執行文件的內部信息。
? ? -h:顯示
? ? -t:顯示符號信息
? ? -T:顯示動態符號信息。(例如引用動態鏈接庫中的函數名稱)
? ? -r:顯示重定位入口信息。
? ? -R:顯示動態重定位入口信息。(例如:動態鏈接庫中的變量或者函數地址)
? ? -s:顯示所有section內容。
? ? -S:反匯編代碼段。
objcopy:copy elf文件內容
? ? -R:刪除某個section
? ? -j:僅僅復制指定的section
轉載于:https://www.cnblogs.com/angelpan1014/archive/2012/10/21/2733057.html
總結
以上是生活随笔為你收集整理的.cpp 编译成.a或是 .so的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CMS之图片管理(2)
- 下一篇: HDU 3032 Nim or not