動態庫和靜態庫用法總結
# only if use dumlog audio will build this.
ifeq ($(strip $(BOARD_USES_YUSU_AUDIO)),true)
LOCAL_PATH:= $(call my-dir)
# The audio dump log
include $(CLEAR_VARS)
# shiyanhua
ifeq ($(strip $(XXX_FEATURE_DUMP_LOG)), yes)
LOCAL_CFLAGS += -DXXX_FEATURE_DUMP_LOG
endif
# end
LOCAL_MODULE := libaudio.dump.log
LOCAL_SRC_FILES := $(TOP)/mediatek/platform/mtXXXX/hardware/audio/libaudio.dump.log.a
# LOCAL_MODULE_TAGS := optional
include $(PREBUILD_STATIC_LIBRARY)
#audiohardware
include $(CLEAR_VARS)
......
# shiyanhua
# ifeq ($(strip $(XXX_FEATURE_DUMP_LOG)), yes)
# LOCAL_CFLAGS += -DXXX_FEATURE_DUMP_LOG
# LOCAL_SRC_FILES += aud_drv/AudioDumpLog.cpp.arm
# LOCAL_C_INCLUDES += $(TOP)/mediatek/platform/mtXXXX/hardware/audio/aud_drv
# endif
# end
# LOCAL_LDFLAGS := $(LOCAL_PATH)/libaudio.dump.log.a
# shiyanhua
ifeq ($(strip $(XXX_FEATURE_DUMP_LOG)), yes)
LOCAL_CFLAGS += -DXXX_FEATURE_DUMP_LOG
LOCAL_C_INCLUDES += $(TOP)/mediatek/platform/mtXXXX/hardware/audio/aud_drv
LOCAL_LDFLAGS += $(TOP)/mediatek/platform/mtXXXX/hardware/audio/libaudio.dump.log.a
endif
# end
.......
include $(BUILD_SHARED_LIBRARY)
# The default audio policy, for now still implemented on top of legacy
# policy code
include $(CLEAR_VARS)
......
include $(BUILD_SHARED_LIBRARY)
# The a2dp hardware interface
include $(CLEAR_VARS)
LOCAL_SHARED_LIBRARIES += \
libmedia \
libcutils \
libutils \
libbinder \
libhardware_legacy \
libhardware \
libaudio.primary.default
LOCAL_MODULE := libaudio.a2dp.default
include $(BUILD_SHARED_LIBRARY)
endif
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
NDK 中動態庫引用靜態庫的例子
以下是Android.mk 檔案
以下檔案是first.c#這個示例的目的是為了演示如何能夠產生兩種截然不同的共享庫 # #==================第一個庫編譯為靜態庫===================== LOCAL_PATH:= $(call my-dir) # first lib, which will be built statically # include $(CLEAR_VARS) LOCAL_MODULE := libtwolib-first LOCAL_SRC_FILES := first.c include $(BUILD_STATIC_LIBRARY) #======================================================================= #===============第二個庫編譯為動態庫,但依賴於第一個庫============== # second lib, which will depend on and include the first one # include $(CLEAR_VARS) LOCAL_MODULE := libtwolib-second LOCAL_SRC_FILES := second.c LOCAL_STATIC_LIBRARIES := libtwolib-first include $(BUILD_SHARED_LIBRARY)
#include "first.h"
int first(int x, int y)
{
return x + y;
}
以下檔案是sceond.c以下是java檔案#include "first.h" #include <jni.h> jint Java_com_example_twolibs_TwoLibs_add( JNIEnv* env, jobject this, jint x, jint y ) { return first(x, y); }
package com.example.twolibs;
import android.app.Activity;
import android.widget.TextView;
import android.os.Bundle;
public class TwoLibs extends Activity
{
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
TextView tv = new TextView(this);
int x = 1000;
int y = 42;
// here, we dynamically load the library at runtime
// before calling the native method.
//
System.loadLibrary("twolib-second");
int z = add(x, y);
tv.setText( "The sum of " + x + " and " + y + " is " + z );
setContentView(tv);
}
public native int add(int x, int y);
}
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------靜態庫和動態庫的區別
庫從本質上來說是一種可執行程式碼的二進位制格式,可以被載入記憶體中執行。庫分靜態庫和動態庫兩種1. 靜態函式庫
這類庫的名字一般是libxxx.a;利用靜態函式庫編譯成的檔案比較大,因為整個 函式庫的所有資料都會被整合進目的碼中,他的優點就顯而易見了,即編譯後的執行程式不需要外部的函式庫支援,因為所有使用的函式都已經被編譯進去了。當然這也會成為他的缺點,因為如果靜態函式庫改變了,那麼你的程式必須重新編譯。
2. 動態函式庫
這類庫的名字一般是libxxx.so;相對於靜態函式庫,動態函式庫在編譯的時候 並沒有被編譯進目的碼中,你的程式執行到相關函式時才呼叫該函式庫裡的相應函式,因此動態函式庫所產生的可執行檔案比較小。由於函式庫沒有被整合進你的程式,而是程式執行時動態的申請並呼叫,所以程式的執行環境中必須提供相應的庫。動態函式庫的改變並不影響你的程式,所以動態函式庫的升級比較方便。
linux系統有幾個重要的目錄存放相應的函式庫,如/lib /usr/lib。
靜態庫的使用
靜態庫的操作工具:gcc和ar 命令。
編寫及使用靜態庫
(1)設計庫原始碼 pr1.c 和 pr2.c
[[email protected] make_lib]# cat pr1.c
void print1()
{
printf("This is the first lib src!\n");
}
[[email protected] make_lib]# cat pr2.c
void print2()
{
printf("This is the second src lib!\n");
}
(2) 編譯.c 檔案
[[email protected] make_lib]$ cc -O -c pr1.c pr2.c
[[email protected] make_lib]$ ls -l pr*.o
-rw-rw-r-- 1 bill bill 804 4 月 15 11:11 pr1.o
-rw-rw-r-- 1 bill bill 804 4 月 15 11:11 pr2.o
(3) 連結靜態庫
為了在編譯程式中正確找到庫檔案,靜態庫必須按照 lib[name].a 的規則命名,如下例中[name]=pr.
[[email protected] make_lib]$ ar -rsv libpr.a pr1.o pr2.o
a - pr1.o
a - pr2.o
[[email protected] make_lib]$ ls -l *.a
-rw-rw-r-- 1 bill bill 1822 4 月 15 11:12 libpr.a
[[email protected] make_lib]$ ar -t libpr.a
pr1.o
pr2.o
(4) 呼叫庫函式程式碼 main.c
[[email protected] make_lib]$ cat main.c
int main()
{
print1();
print2();
return 0;
}
(5) 編譯連結選項
-L 及-l 引數放在後面.其中,-L 載入庫檔案路徑,-l 指明庫檔名字.
[[email protected] make_lib]$ gcc -o main main.c -L./ -lpr
[[email protected] make_lib]$ ls -l main*
-rwxrwxr-x 1 bill bill 11805 4 月 15 11:17 main
-rw-rw-r-- 1 bill bill 50 4 月 15 11:15 main.c
(6)執行目標程式
[[email protected] make_lib]$ ./main
This is the first lib src!
This is the second src lib!
[[email protected] make_lib]$
動態庫的使用
編寫動態庫
(1)設計庫程式碼
[[email protected] make_lib]$ cat pr1.c
int p = 2;
void print(){
printf("This is the first dll src!\n");
}
[[email protected] make_lib]$
(2)生成動態庫
[[email protected] make_lib]$ gcc -O -fpic -shared -o dl.so pr1.c
[[email protected] make_lib]$ ls -l *.so
-rwxrwxr-x 1 bill bill 6592 4 月 15 15:19 dl.so
[[email protected] make_lib]$
動態庫的隱式呼叫
在編譯呼叫庫函式程式碼時指明動態庫的位置及名字, 看下面例項
[[email protected] make_lib]$ cat main.c
int main()
{
print();
return 0;
}
[[email protected] make_lib]$ gcc -o tdl main.c ./dl.so
[[email protected] make_lib]$ ./tdl
This is the first dll src!
[[email protected] make_lib]$
當動態庫的位置活名字發生改變時, 程式將無法正常執行; 而動態庫取代靜態庫的好處之一則是通過更新動態庫而隨時升級庫的內容.
動態庫的顯式呼叫
顯式呼叫動態庫需要四個函式的支援, 函式 dlopen 開啟動態庫, 函式 dlsym 獲取動態庫中物件基址, 函式 dlerror 獲取顯式動態庫操作中的錯誤資訊, 函式 doclose 關閉動態庫.
[[email protected] make_lib]$ cat main.c
#include <dlfcn.h>
int main()
{
void *pHandle;
void (*pFunc)(); // 指向函式的指標
int *p;
pHandle = dlopen("./d1.so", RTLD_NOW); // 開啟動態庫
if(!pHandle){
printf("Can't find d1.so \n");
exit(1);
}
pFunc = (void (*)())dlsym(pHandle, "print"); // 獲取庫函式 print 的地址
if(pFunc)
pFunc();
else
printf("Can't find function print\n");
p = (int *)dlsym(pHandle, "p"); // 獲取庫變數 p 的地址
if(p)
printf("p = %d\n", *p);
else
printf("Can't find int p\n");
dlclose(pHandle); // 關閉動態庫
return 0;
}
[[email protected] make_lib]$ gcc -o tds main.c –ld1 –L.
此時還不能立即./tds,因為在動態函式庫使用時,會查詢/usr/lib、/lib目錄下的動態函式庫,而此時我們生成的庫不在裡邊。 這個時候有好幾種方法可以讓他成功執行: 最直接最簡單的方法就是把libstr_out.so拉到/usr/lib或/lib中去。 還有一種方法 export LD_LIBRARY_PATH=$(pwd) 另外還可以在/etc/ld.so.conf檔案里加入我們生成的庫的目錄,然後/sbin/ldconfig。 /etc/ld.so.conf是非常重要的一個目錄,裡面存放的是連結器和載入器搜尋共享庫時要檢查的目錄,預設是從/usr/lib /lib中讀取的,所以想要順利執行,我們也可以把我們庫的目錄加入到這個檔案中並執行/sbin/ldconfig 。另外還有個檔案需要了解/etc/ld.so.cache,裡面儲存了常用的動態函式庫,且會先把他們載入到記憶體中,因為記憶體的訪問速度遠遠大於硬碟的訪問速度,這樣可以提高軟體載入動態函式庫的速度了。
庫依賴的檢視
使用ldd命令來檢視執行檔案依賴於哪些庫。
該命令用於判斷某個可執行的 binary 檔案含有什麼動態函式庫。
[[email protected] root]# ldd [-vdr] [filename]
引數說明:
--version 列印ldd的版本號
-v --verbose 列印所有資訊,例如包括符號的版本資訊
-d --data-relocs 執行符號重部署,並報告缺少的目標物件(只對ELF格式適用)
-r --function-relocs 對目標物件和函式執行重新部署,並報告缺少的目標物件和函式(只對ELF格式適用)
--help 用法資訊。
如果命令列中給定的庫名字包含'/',這個程式的libc5版本將使用它作為庫名字;否則它將在標準位置搜尋庫。執行一個當前目錄下的共享庫,加字首"./"。
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
ARM_PLATFORM := armeabi
#-v7a
LOCAL_MODULE := libf2c
LOCAL_SRC_FILES := lib/libf2c.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := blas_LINUX
LOCAL_SRC_FILES := lib/blas_LINUX.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := lapack_LINUX
LOCAL_SRC_FILES := lib/lapack_LINUX.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := tmglib_LINUX
LOCAL_SRC_FILES := lib/tmglib_LINUX.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := libopencv_calib3d
LOCAL_SRC_FILES := lib/$(ARM_PLATFORM)/libopencv_calib3d.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := libopencv_contrib
LOCAL_SRC_FILES := lib/$(ARM_PLATFORM)/libopencv_contrib.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := libopencv_core
LOCAL_SRC_FILES := lib/$(ARM_PLATFORM)/libopencv_core.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := libopencv_features2d
LOCAL_SRC_FILES := lib/$(ARM_PLATFORM)/libopencv_features2d.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := libopencv_flann
LOCAL_SRC_FILES := lib/$(ARM_PLATFORM)/libopencv_flann.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := libopencv_highgui
LOCAL_SRC_FILES := lib/$(ARM_PLATFORM)/libopencv_highgui.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := libopencv_imgproc
LOCAL_SRC_FILES := lib/$(ARM_PLATFORM)/libopencv_imgproc.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := libopencv_legacy
LOCAL_SRC_FILES := lib/$(ARM_PLATFORM)/libopencv_legacy.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := libopencv_ml
LOCAL_SRC_FILES := lib/$(ARM_PLATFORM)/libopencv_ml.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := libopencv_objdetect
LOCAL_SRC_FILES := lib/$(ARM_PLATFORM)/libopencv_objdetect.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := libopencv_ts
LOCAL_SRC_FILES := lib/$(ARM_PLATFORM)/libopencv_ts.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := libopencv_video
LOCAL_SRC_FILES := lib/$(ARM_PLATFORM)/libopencv_video.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := liblibjasper
LOCAL_SRC_FILES := lib/$(ARM_PLATFORM)/liblibjasper.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := liblibjpeg
LOCAL_SRC_FILES := lib/$(ARM_PLATFORM)/liblibjpeg.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := liblibpng
LOCAL_SRC_FILES := lib/$(ARM_PLATFORM)/liblibpng.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := liblibtiff
LOCAL_SRC_FILES := lib/$(ARM_PLATFORM)/liblibtiff.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := libzlib
LOCAL_SRC_FILES := lib/$(ARM_PLATFORM)/libzlib.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_STATIC_LIBRARIES := \
libf2c \
blas_LINUX \
lapack_LINUX \
tmglib_LINUX \
libopencv_contrib \
libopencv_calib3d \
libopencv_objdetect \
libopencv_features2d \
libopencv_video \
libopencv_imgproc \
libopencv_highgui \
libopencv_ml \
libopencv_legacy \
libopencv_flann \
libopencv_core \
liblibjasper \
liblibjpeg \
liblibpng \
liblibtiff \
libzlib
#LOCAL_LDLIBS := -llog -lz -ldl -landroid
LOCAL_C_INCLUDES := \
$(LOCAL_PATH)/opencv \
$(LOCAL_PATH)/opencv2 \
$(LOCAL_PATH)/aamsrc \
$(LOCAL_PATH)/test
#LOCAL_ALLOW_UNDEFINED_SYMBOLS := true
LOCAL_MODULE := deteapp
LOCAL_SRC_FILES := \
aamsrc/AAM_Basic.cpp \
aamsrc/AAM_CAM.cpp \
aamsrc/AAM_IC.cpp \
aamsrc/AAM_PAW.cpp \
aamsrc/AAM_PDM.cpp \
aamsrc/AAM_Shape.cpp \
aamsrc/AAM_TDM.cpp \
aamsrc/AAM_Util.cpp \
aamsrc/AAM_VJFaceDetect.cpp \
test/cvTools.cpp \
test/FreqTools.cpp \
test/FaceAlign_Haar.cpp \
test/FaceFeature_GaborF.cpp \
test/LightPrep.cpp \
test/dggev.cpp \
test/Subspace.cpp \
Hopes.cpp
include $(BUILD_SHARED_LIBRARY)
-----------------------------------------------------------------------------------------------------------------------------------------------------------
http://www.2cto.com/kf/201206/136318.html
問題:
昨天除錯一個CA庫link失敗的問題:ca廠商一般提供的都是靜態ca庫,這樣子你直接將其與
你的庫link在一起即可使用,但由於apk在ndk中編譯器:android-ndk-r6b\arm-linux-androideabi-4.4.3
而ca庫使用hisi編譯器:arm-eabi-4.4.0_hisi 兩者使用的編譯不同,所以需要在linux android環境
下將ca靜態庫打包成動態庫,而且使用者實現的ca函式將會link失敗,生成的動態庫將在ndk中使用。
下面是一個簡單的測試例子,用於說明一下如何做到相互依賴而編譯生成動態庫的方法
1、首先編譯生成動態庫
首先定義標頭檔案:test.h
1. <span style="font-size:16px;">#ifndef XXX_TEST_H___
2. #define XXX_TEST_H___
3.
4. /* 由link的庫實現 */
5. extern void testA();
6. extern void testB();
7.
8. /* 由本身庫實現而由外部呼叫 */
9. extern void testC();
10. extern void testD();
11.
12. struct AAInterface{
13. void (*testA)();
14. void (*testB)();
15. };
16.
17. extern void setInterface(struct AAInterface *cb);
18.
19. #endif /* XXX_TEST_H___ */
20. </span>
然後實現檔案:testA.c
1. <span style="font-size:16px;">#include <assert.h>
2. #include <stdlib.h>
3. #include <string.h>
4. #include <cutils/log.h>
5. #include "test.h"
6.
7. static struct AAInterface g_aa_interface ;
8.
9. /* 由link的庫實現 */
10. extern void testA(){
11. g_aa_interface.testA();
12. }
13.
14. extern void testB(){
15. g_aa_interface.testB();
16. }
17.
18. extern void testCall(){
19. LOGI("testCall 111");
20. testA();
21. LOGI("testCall 222");
22. testB();
23. LOGI("testCall 333");
24. }
25.
26. /* 由本身庫實現而由外部呼叫 */
27. extern void testC(){
28. LOGI("testC call in--->");
29. testCall();
30. LOGI("testC call out<---");
31. }
32.
33. extern void testD(){
34. LOGI("testD call in--->");
35. testCall();
36. LOGI("testD call out<---");
37. }
38.
39. extern void setInterface(struct AAInterface *cb){
40. LOGI("setInterface call in -->");
41. memset((void*)&g_aa_interface,0x00,sizeof(g_aa_interface));
42. g_aa_interface.testA = cb->testA;
43. g_aa_interface.testB = cb->testB;
44. LOGI("setInterface call out <--");
45. }
46. </span>
這裡最重要的是利用setInterface介面解決相互link的問題,這就是本質所在。大家一看就明白了,這也是動態
庫匯出函式的最好方法,一般使用QueryInterface及enumInterface即可,使用結構將
編譯方法:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE:= libtestASO
LOCAL_SRC_FILES:= \
testA.c \
LOCAL_SHARED_LIBRARIES := liblog\
LOCAL_C_INCLUDES += \
$(TOP)/frameworks/base/test/testA \
LOCAL_CFLAGS += -D_cplusplus
LOCAL_PRELINK_MODULE := false
include $(BUILD_SHARED_LIBRARY)
2、使用生成的動態庫
1. <span style="font-size:16px;">#include <assert.h>
2. #include <stdlib.h>
3. #include <string.h>
4. #include <cutils/log.h>
5. #include <test.h>
6.
7. /* 由link的庫實現 */
8. extern void testA(){
9. LOGI("testA call ...");
10. }
11.
12. extern void testB(){
13. LOGI("testB call ...");
14. }
15.
16. int main(void){
17. struct AAInterface *itf = (struct AAInterface*)calloc(1,sizeof(struct AAInterface));
18. itf->testA = testA;
19. itf->testB = testB;
20. setInterface(itf);
21. www.2cto.com
22. testC();
23. testD();
24. return 0;
25. }
26. </span>
ok,知道了如何解決這種相互依賴的方法,解決方法相當解決。。對於這種A需要link B,而B又需要link A的相互關係,這種方法就會起到很好的作用了。