1. 程式人生 > >Makefile 編譯動態庫檔案及連結動態庫

Makefile 編譯動態庫檔案及連結動態庫

原文轉自 :http://www.cnblogs.com/ljtknowns/p/5647793.html

檔案目錄結構如下

複製程式碼
1 dynamiclibapp.c
2 Makefile
3 comm/inc/apue.h
4 comm/errorhandle.c
5 dynamiclib/Makefile
6 dynamiclib/dynamiclib_add.c
7 dynamiclib/dynamiclib_mul.c
8 dynamiclib/inc/dynamiclibs.h
9 dynamiclib/libs/
複製程式碼

1. dynamiclib目錄

    dynamiclib/inc/dynamiclibs.h 檔案內容如下:

複製程式碼
1 #ifndef __dynamic_libs_h__
2 #define __dynamic_libs_h__
3 
4 #include "apue.h"
5 int dynamic_lib_func_add(int i1, int i2);
6 int dynamic_lib_func_mul(int i1, int i2);
7 
8 #endif
複製程式碼

    dynamiclib/dynamiclib_add.c 檔案內容如下:

複製程式碼
1 #include "dynamiclibs.h"
2 
3 int dynamic_lib_func_add(int i1, int i2) 
4 { 5 int iret = i1 + i2; 6 printf("... in .so func, %d add %d,return %d\n", i1, i2, iret); 7 return iret; 8 }
複製程式碼

    dynamiclib/dynamiclib_mul.c 檔案內容如下:

複製程式碼
1 #include "dynamiclibs.h"
2 
3 int dynamic_lib_func_mul(int i1, int i2) 
4 {
5     int iret = i1 * i2; 
6     printf("... in .so func, %d multiplys %d, retun %d\n
", i1, i2, iret); 7 return iret; 8 }
複製程式碼

    dynamiclib/Makefile 檔案內容如下:

複製程式碼
 1 CC       = gcc 
 2 CFLAGS   = -Wall -g -O -fPIC     需要加上 -fPIC
 3 CXXFLAGS = 
 4 INCLUDE  = -I ./inc -I ../comm/inc
 5 TARGET   = libmytest.so
 6 LIBPATH  = ./libs/
 7 
 8 vpath %.h ./inc
 9 
10 OBJS     = dynamiclib_add.o dynamiclib_mul.o
11 SRCS     = dynamiclib_add.c dynamiclib_mul.c
12 
13 $(OBJS):$(SRCS)
14    $(CC) $(CFLAGS) $(INCLUDE) -c $^
15 
16 all:$(OBJS)
17    $(CC) -shared -fPIC -o $(TARGET) $(OBJS)    需要加上 -shared -fPIC
18    mv $(TARGET) $(LIBPATH)
19 
20 clean:
21    rm -f *.o
22    rm -f $(LIBPATH)*
複製程式碼

    以上檔案,就可以生成動態庫檔案 libmytest.so,應用程式以兩種方式載入動態庫函式,如下

2. 在編譯應用程式時載入動態庫

    dynamiclibapp.c 檔案內容如下:

複製程式碼
 1 #include "apue.h"
 2 #include "dynamiclibs.h"
 3 
 4 int main(int argc, char *argv[])
 5 {
 6     err_msg("step in main\n");
 7     dynamic_lib_func_add(1, 9); 
 8     dynamic_lib_func_mul(1, 9); 
 9     err_msg("step out main\n");
10 
11     return 0;
12 }
複製程式碼

    Makefile 檔案內容如下:

複製程式碼
 1 CC       = gcc 
 2 CFLAGS   = -Wall -O -g
 3 CXXFLAGS = 
 4 INCLUDE  = -I ./comm/inc -I ./dynamiclib/inc
 5 TARGET   = dynamiclibapp
 6 LIBVAR   = -lmytest             指明需要連結動態庫 libmytest.so
 7 LIBPATH  = -L./dynamiclib/libs  指明 libmytest.so 的路徑
 8 #search paths for errorhandler.c
 9 vpath %.c ./comm
10 #下行是為依賴項 apue.h 準備的,比如 [errorhandler.o:errorhandler.c apue.h] 裡的 apue.h
11 vpath %.h ./comm/inc
12 
13 OBJS     = errorhandler.o dynamiclibapp.o
14 #下行的 apue.h,可以不必寫出來
15 errorhandler.o:errorhandler.c apue.h
16    $(CC) $(CFLAGS) $(INCLUDE) -c $^
17 dynamiclibapp.o:dynamiclibapp.c apue.h
18    $(CC) $(CFLAGS) $(INCLUDE) -c $^
19 
20 all:$(OBJS) $(LIB)
21    cd ./dynamiclib && make all
22    $(CC) $(CFLAGS) $(INCLUDE) -o $(TARGET) $(OBJS) $(LIBPATH) $(LIBVAR)
23    在上行中,在執行編譯時,載入了 libmytest.so 中函式
24 clean:
25    rm -f *.o
26    rm -f comm/inc/*.gch
27    rm -f $(TARGET)
28    cd ./dynamiclib && make clean
複製程式碼

    對於這種方式編譯出來的動態庫檔案,還需要在 /etc/ld.so.conf.d/ 目錄中新增 libmytest.so 庫檔案的路徑說明,

    即在 /etc/ld.so.conf.d/ 目錄中新建配置檔案 mytest.conf,且執行 ldconfig, /etc/ld.so.conf.d/mytest.conf 的文

    件內容為 libmytest.so 庫檔案的絕對路徑,例如:

1 /home/lijiangtao/dynamiclib/libs

    如果不在編譯應用程式時載入動態庫檔案裡的函式,而是改為在應用程式執行時(比如:程式的main函式啟動期

    間,或在程式執行期間)載入 libmytest.so 裡函式,那麼就可以不需在 /etc/ld.so.conf.d/ 目錄中配置 libmytest.so

    路徑,具體如下所述。

3. 在應用程式執行時載入動態庫

    dynamiclibapp.c 檔案內容如下:

複製程式碼
 1 #include "apue.h"
 2 #include "dynamiclibs.h"
 3 #include <dlfcn.h>
 4 
 5 typedef int (*fp_lib_add)(int, int);
 6 typedef int (*fp_lib_mul)(int, int);
 7 typedef void* dlhandle;
 8 
 9 dlhandle      dll      = NULL;
10 fp_lib_add    func_add = NULL;
11 fp_lib_mul    func_mul = NULL;
12 
13 dlhandle load_dynamic_func(char *psopath, fp_lib_add *padd, fp_lib_mul *pmul);
14 
15 int main(int argc, char *argv[])
16 {
17     char *pso = "/home/lijiangtao/dynamiclib/libs/libmytest.so";//指定 .so 路徑
18     dll = load_dynamic_func(pso, &func_add, &func_mul);//程式執行時,載入動態函式
19     err_msg("step in main\n");
20     func_add(1, 9);//執行 add 函式
21     func_mul(1, 9);//執行 mul 函式
22     err_msg("step out main\n");
23 
24     return 0;
25 }
26 
27 dlhandle load_dynamic_func(char *psopath, fp_lib_add *padd, fp_lib_mul *pmul)
28 {
29     if(NULL == psopath ||'\0' == psopath[0])
30         return NULL;
31     char *perrormsg = NULL;
32     dlhandle dllhandle = dlopen(psopath, RTLD_LAZY);
33     if(NULL == dllhandle) 
34     {   
35         printf("%s\n", dlerror());
36         return NULL;
37     } 
38     if(NULL != padd)
39     {
40         *padd = dlsym(dllhandle, "dynamic_lib_func_add");//載入 add 函式
41         perrormsg = dlerror();
42         if(NULL != perrormsg)
43             printf("%s\n", perrormsg);
44     }
45     if(NULL != pmul)
46     {
47         *pmul = dlsym(dllhandle, "dynamic_lib_func_mul");//載入 mul 函式
48         perrormsg = dlerror();
49         if(NULL != perrormsg)
50             printf("%s\n", perrormsg);
51     }
52     return dllhandle;
53 }
複製程式碼

    Makefile 檔案內容如下:

複製程式碼
 1 CC       = gcc 
 2 CFLAGS   = -Wall -O -g
 3 CXXFLAGS = 
 4 INCLUDE  = -I ./comm/inc -I ./dynamiclib/inc
 5 TARGET   = dynamiclibapp
 6 LIBVAR   = -ldl    需要連結 libdl.so 庫
 7 LIBPATH  = 
 8 #search paths for errorhandler.c
 9 vpath %.c ./comm
10 #下行是為依賴項 apue.h 準備的,比如 [errorhandler.o:errorhandler.c apue.h] 裡的 apue.h
11 vpath %.h ./comm/inc
12 
13 OBJS     = errorhandler.o dynamiclibapp.o
14 #下行的 apue.h,可以不必寫出來
15 errorhandler.o:errorhandler.c apue.h
16    $(CC) $(CFLAGS) $(INCLUDE) -c $^
17 dynamiclibapp.o:dynamiclibapp.c apue.h
18    $(CC) $(CFLAGS) $(INCLUDE) -c $^
19 
20 all:$(OBJS) $(LIB)
21    cd ./dynamiclib && make all
22    $(CC) $(CFLAGS) -rdynamic $(INCLUDE) -o $(TARGET) $(OBJS) $(LIBPATH) $(LIBVAR)
23    上行,執行編譯時並沒有載入動態介面函式,而是在應用程式執行時載入的;需要 -rdynamic 選項,
      以確保 dlopen 這些介面可用
24 clean: 25 rm -f *.o 26 rm -f $(TARGET) 27 cd ./dynamiclib && make clean
複製程式碼

    對於這種方式編譯出來的動態庫檔案,不需要在 /etc/ld.so.conf.d/ 目錄中配置 libmytest.so 庫檔案的路徑說明