cheungmine
2012
c程式編譯過程**
windows7+cygwin+gcc
在同乙個目錄下準備好下面3個檔案,其中3-2,3-3用來生成動態庫或靜態庫:
主呼叫程式源**3-1:main.c
[cpp]view plain
copy
print?
/**
* main.c
*/
#include
#include
#include "hello_fn.h"
int
main ()
庫源**3-2:hello_fn.c
[cpp]view plain
copy
print?
/**
* hello_fn.c
*/
#include
void hello(const char *msg)
庫標頭檔案源**3-3:hello_fn.h
[cpp]view plain
copy
print?
/**
* hello_fn.h
*/
void hello(const char *msg);
[plain]view plain
copy
print?
$ gcc -w -wall -ansi -pedantic -i. -c main.c
$ gcc -w -wall -ansi -pedantic -i. -c hello_fn.c
[plain]view plain
copy
print?
$ gcc -shared hello_fn.o -o libhello.so
或者直接從源**編譯:
$ gcc -shared -i. hello_fn.c -o libhello.so
編譯靜態庫相對簡單,就是相當於目標檔案歸檔:
$ ar r libhello.a hello_fn.o
[plain]view plain
copy
print?
$ gcc main.o -o main
或者
$ gcc -c main.c -o main
但是由於我們在main.c的**中寫固定了呼叫庫的**(hello函式),所以,必須鏈結到這個庫才行。
[plain]view plain
copy
print?
$ gcc main.o -o main ./libhello.so
這樣在當前目錄下就生成了:main.exe(我的cygwin環境,linux環境下沒有副檔名)
執行這個main.exe:
[plain]view plain
copy
print?
$ ./main.exe
刪除libhello.so,再執行main.exe會報錯誤:error while loading shared libraries: libhello.so: cannot open shared object...
[plain]view plain
copy
print?
$ gcc main.o -o main2 ./libhello.a
刪除libhello.a,執行main2.exe,一切正常。說明程式的確鏈結到靜態庫了。
[plain]view plain
copy
print?
$ file main.exe main2.exe
$ ldd main.exe main2.exe
如果我們的動態庫libhello.so與主程式不在同乙個目錄下,怎麼辦?
複製libhello.so和libhello.a到另外乙個目錄,比如:/cygdrive/c/temp,那麼編譯主程式為:
[plain]view plain
copy
print?
$ gcc main.o -o main /cygdrive/c/temp/libhello.so
執行:
$ export path=/cygdrive/c/temp:$path
$ ./main.exe
修改main.c檔案為如下清單:
[cpp]view plain
copy
print?
/**
* main.c
*/
#include
#include
#include
#include "hello_fn.h"
void dl_hello()
fn_hello = dlsym(dp, "hello");
if(!fn_hello)
fn_hello("cheungmine: load library when running");
dlclose(dp);
} int
main ()
然後重新編譯main.exe和libhello.so如下:
[cpp]view plain
copy
print?
編譯原始檔
$ gcc -wall -i. -c main.c
$ gcc -wall -i. -c hello_fn.c
編譯動態庫
$ gcc -shared hello_fn.o -o libhello.so
鏈結主程式,但不鏈結到動態庫。
$ gcc main.o -o main.exe
執行下面的**可以看到libhello.so並不在main.exe的依存之列:
$ ldd main.exe
移動庫到其他目錄,通過修改環境變數,程式main.exe執行正確:
$ mv libhello.so /cygdrive/c/temp
$ export path=.:/cygdrive/c/temp:$path
$ ./main.exe
通過上面的練習,基本清楚了如何用gcc編譯程式,包括靜態鏈結庫和動態鏈結庫。通過下面的**可以看到
linux和windows的區別:
windows unix/linux
靜態鏈結庫 hello.lib libhello.a
動態鏈結庫 hello.dll libhello.so
延遲載入 loadlibrary dlopen
getprocaddress dlsym
freelibrary dlclose
本文全部內容在cygwin上執行的,和真實的linux環境還是存在差異的。gcc版本3.4.4。
原文:
gcc編譯動態庫和靜態庫
如果動態庫與靜態庫同時存在,未指明鏈結方式時,首先使用動態庫進行鏈結。我的 目錄 一 具體 1 include void a void b 2 lib include void a include void b 3 src include include include a.h include in...
gcc 編譯動態庫和靜態庫 2
在windows下動態鏈結庫是以.dll字尾的檔案,而在linux中,是以.so作字尾的檔案。動態鏈結庫的好處就是節省記憶體空間。1 linux下建立動態鏈結庫 在使用gcc編譯程式時,只需加上 shared選項即可,這樣生成的執行程式即為動態鏈結庫。例如有檔案 hello.c x.h main.c...
GCC編譯動態和靜態鏈結庫
我們通常把一些公用函式製作成函式庫,供其它程式使用。函式庫分為靜態庫和動態庫兩種。靜態庫在程式編譯時會被連線到目標 中,程式執行時將不再需要該靜態庫。動態庫在程式編譯時並不會被連線到目標 中,而是在程式執行是才被載入,因此在程式執行時還需要動態庫存在。本文主要通過舉例來說明在linux中如何建立靜態...