android預編譯動態庫
Ⅰ Android.mk介紹(一)
在linux下,可以通過Makefile來對源碼工程進行管理,Android.mk文件是Makefile的一小部分,它用來對Android程序進行編譯。Android.mk文件中描述了哪些C文件將被編譯且指明了如何編譯。Android.mk文件用來告知NDK Build 系統關於Source的信息。
1、編譯可執行程序
2、編譯動態庫或靜態庫
3、預編譯文件(APK或java庫)
以上三種是Android.mk的主要用法,我們寫mk文件時也就是以上三種目的。
首先看一個最簡單的Android.mk的例子:
講解:
每個Android.mk文件必須以定義 LOCAL_PATH 為開始。它用於在開發tree中查找源文件。
宏 my-dir 由Build System提供。返回包含Android.mk的目錄路徑。
CLEAR_VARS 變數由Build System提供。並指向一個指定的GNU Makefile,由它負責清理很多LOCAL_xxx.
例如:LOCAL_MODULE, LOCAL_SRC_FILES, LOCAL_STATIC_LIBRARIES等等。但不清理 LOCAL_PATH .
這個清理動作是必須的,因為所有的編譯控制文件由同一個GNU Make解析和執行,其變數是全局的。所以清理後才能避免相互影響。
LOCAL_MODULE 模塊必須定義,以表示Android.mk中的每一個模塊。名字必須唯一且不包含空格。
Build System會自動添加適當的前綴和後綴。例如,foo,要產生動態庫,則生成libfoo.so.
但請注意:如果模塊名被定為:libfoo.則生成libfoo.so. 不再加前綴。
LOCAL_SRC_FILES變數必須包含將要打包如模塊的C/C++ 源碼。
不必列出頭文件,build System 會自動幫我們找出依賴文件。
預設的C++源碼的擴展名為.cpp. 也可以修改,通過LOCAL_CPP_EXTENSION。
BUILD_SHARED_LIBRARY:是Build System提供的一個變數,指向一個GNU Makefile Script。
它負責收集自從上次調用include $(CLEAR_VARS) 後的所有LOCAL_XXX信息。並決定編譯為什麼。
BUILD_STATIC_LIBRARY:編譯為靜態庫。
BUILD_SHARED_LIBRARY :編譯為動態庫
BUILD_EXECUTABLE:編譯為Native C可執行程序
BUILD_PACKAGE(既可以編apk,也可以編資源包文件,但是需要指定LOCAL_EXPORT_PACKAGE_RESOURCES:=true)
BUILD_JAVA_LIBRARY(Java共享庫)
BUILD_STATIC_JAVA_LIBRARY(java靜態庫)
Android源碼中有大量的mk文件,Android系統的編譯就是靠著這些mk文件的,所以學好是非常有必要的哦!
Ⅱ 怎麼重新編譯android 下面的動態庫
使用動態庫來編譯動態庫
A項目的android.mk文件如下:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := testa
LOCAL_SRC_FILES := testa.c
include $(BUILD_SHARED_LIBRARY)
生成的libtesta.so加入到E:\workspace\android-ndk-r8e\platforms\android-8\arch-arm\usr\lib\下面
項目B的文件目錄結構如下:
jni
jni/jni/
jni/prebuilt/
jni目錄下的mk文件如下:
include $(all-subdir-makefiles)
jni/prebuilt目錄下的mk文件如下:
LOCAL_PATH := $(call my-dir)
#include $(CLEAR_VARS)
LOCAL_MODULE := libtesta
LOCAL_SRC_FILES := libtesta.so
include $(PREBUILT_SHARED_LIBRARY)
同時把libtesta.so也放入該目錄下.
jni/jni目錄下的mk文件內容:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_LDLIBS := -ltesta
LOCAL_MODULE := testb
LOCAL_SRC_FILES := testb.c
include $(BUILD_SHARED_LIBRARY)
這樣生成libtestb.so文件, 同時eclipse在打包時會把libtesta.so, libtestb.so都加入到apk文件中,如果沒有prebuilt那一步,那麼在打包時會漏掉libtesta.so, 但編譯會通過,因為編譯讀取的是編譯系統的庫文件目錄(LOCAL_LDLIBS := -ltesta), 這點需要注意
java代碼:
System.loadLibrary("testa");
System.loadLibrary("testb");
注意先後關系
Ⅲ 使用cmake/make打包Android 動態庫
打包需要使用cmake是AndroidSdk目錄下的
${ANDROID_HOME}/cmake/3.6.4111459/bin/cmake
參數:
-H
-B
-DANDROID_NDK
-DCMAKE_LIBRARY_OUTPUT_DIRECTORY
-DCMAKE_MAKE_PROGRAM
-DCMAKE_TOOLCHAIN_FILE
-DANDROID_ABI
-DCMAKE_BUILD_TYPE
-DANDROID_NATIVE_API_LEVEL 最低支持的Api版本
-DANDROID_TOOLCHAIN
-DCMAKE_GENERATOR
打包所有abi的腳本例子:
Ⅳ Android常見的預編譯(prebuilt)
android常用的預編譯方法(prebuilt)
1.framework引入靜態jar包
2.編譯共享jar包
3.編譯so庫
方法1 : 單獨編譯
方法2 : 輪詢編譯
4.預編譯apk
預置apk至系統,如果apk含有so庫的話,也需要提前編譯到系統中,解壓apk文件,將so提取出來放置某一文件夾中,通過LOCAL_PREBUILT_JNI_LIBS將so編譯至system/app/package/lib/arm目錄
Ⅳ 如何在Android平台下編譯帶STL的C++程序
1、下載最新的Android SDK,下載Android NDK R9C版本。
2、如是在windows平台下需要在PATH中設置環境變數,以便於直接調用NDK來編譯C++程序。
將如下兩個路徑加入到PATH中:<ANDROID_NDK>;<ANDROID_SDK>\platform-tools
其中<NDK>為你的計算機上Android NDK的安裝路徑,<SDK>為Android SDK的安裝路徑
如果在你的SDK下沒有platform-tools目錄,則在Eclipse中按照如下截圖進行操作:
3、為要編譯的C++程序建一個文件夾,如myproject。在myproject下再建一個jni文件夾,將源代碼放在這個文件夾下,myproject/jni。
mkdir myproject
mkdir myproject/jni
4、在jni文件夾下建兩個分別名為:android.mk和
application.mk文件。android.mk類以於C++程序的makefile,application.mk則指明當前程序依賴的庫。
android.mk的示例為:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := my_first_app #指明C++程序編譯出的可執行程序的名稱
LOCAL_SRC_FILES:= my_first_app0.cpp \ #指明要編譯的源文件,可以有很多個
my_first_app1.cpp\
…
include$(BUILD_EXECUTABLE)#表明編譯的是可執行程序
/**************************************************************************/
application.mk的示例為:(在application.mk中指明STL庫)
APP_STL:= gnustl_static
這里選STL庫時有四個選項:
system - 使用默認最小的C++運行庫,這樣生成的應用體積小,內存佔用小,但部分功能將無法支持
stlport_static - 使用STLport作為靜態庫,這項是Android開發網極力推薦的
stlport_shared - STLport 作為動態庫,這個可能產生兼容性和部分低版本的Android固件,目前不推薦使用。
gnustl_static - 使用 GNU libstdc++ 作為靜態庫
默認情況下STLPORT是不支持C++異常處理和RTTI,所以不要出現 -fexceptions 或 -frtti ,如果真的需要可以使用gnustl_static來支持標准C++的特性,但生成的文件體積會偏大,運行效率會低一些。
支持C++異常處理,在Application.mk中加入 LOCAL_CPPFLAGS +=
-fexceptions這句,同理支持RTTI,則加入LOCAL_CPPFLAGS +=
-frtti,這里再次提醒大家,第二條說的使用gnustl靜態庫,而不是stlport。
強制重新編譯 STLPort ,在Application.mk中加入 STLPORT_FORCE_REBUILD := true 可以強制重新編譯STLPort源碼,由於一些原因可能自己需要修改下STLPort庫,一般普通的開發者無需使用此項
5、打開控制台(cmd),在myproject目錄下用android的NDK build工具編譯C++程序:
cd myproject
$NDK/ndk-build
如果程序沒錯的話,會編譯出android的可執行程序,位置在myproject/libs/armeabi/my_first_app
8、將編譯出來的my_first_app放到手機或是模擬器上運行。在windows的cmd上運行adb.exe。
用adb.exe將my_first_app程序push到手機或模擬器的/data/local目錄上:
adb.exepush myproject\libs\armeabi\my_first_app /data/local。
9、通過adb,在手機上運行my_frist_app:
在cmd上運行:
adb.exe shell
由此進入到手機的linux終端上,接下來再更改my_first_app的許可權使其可以運行:
cd /data/local
chmod 777 my_first_app
./my_first_app//如果沒錯的話,這一步即可運行my_first_app
至此在android上編譯含STL的C++程序的過程結束。
Ⅵ 第二章:Android.bp語法
注意 :關於Android.bp的權威解釋可以參見 android.bp權威文檔
Google官方語法文檔 https://android.googlesource.com/platform/build/soong
從前面的列子可以看出定義一個模塊從模塊的類型開始,模塊有不同的類型,如前面例子中的cc_library_shared,當然類型還有很多種,譬如 cc_binary、android_app 、cc_library_static 等等。模塊包含一些屬性格式為「property-name:property-value」,其中name屬性必須指定,其屬性值必須是全局唯一的。
其中默認模塊可用於在多個模塊中重復相同的屬性
srcs 屬性以字元串列表的形式指定用於編譯模塊的源文件。您可以使用模塊引用語法 「:」 來引用生成源文件的其他模塊的輸出,如 genrule 或 filegroup。
實例說明:
我們知道Android.mk中可以定義變數,當然作為新編譯系統中替代Android.mk的Android.bp也是一定存在,更加何況Android.mk還可以一定條件的轉換成Android.bp。
變數范圍限定為聲明它們的文件的其餘部分,可以使用 「=」 號賦值, 但是不能使用 「:=」 賦值。變數是不可變的,但有一個例外它們可以附上+= 賦值,但僅在變數被引用之前。
下面我們看一下正確使用變數的列子:
我們知道Android.mk中可以進行注釋,當然Android.bp裡面也可以,Android.mk中使用 # 然後添加註釋,Android.bp使用單行注釋 // 和多行注釋 /* */ 兩種方式。
具體支持以下幾種類型:
String類型、字元串列表類型和Map類型支持操作符 + 。
Android.bp可以支持android_app、cc_binary、cc_binary_host等多種類型,具體定義在Android源碼的 build/soong/androidmk/cmd/androidmk/android.go 可以查看,具體如下:
Android.bp可以支持多種預編譯類型,具體定義在Android源碼的 build/soong/androidmk/cmd/androidmk/android.go 可以查看,如下圖所示:
例如: system/core/libusbhost/Android.bp aosp9.0開始
Android.bp是一門實戰性的東西,光說不練沒有啥用,說再多不如直接開練來得舒服。那就直接開始手撕實例了,讓我們開戰嗎!
下面幾種庫編譯類型:
2.1 動態庫類型
最終編譯為so包
**2.2 java庫類型: **
最終編譯為jar包
2.3 Andorid應用類型
最終編譯為apk包
轉自: https://blog.csdn.net/tkwxty/article/details/104395820
Ⅶ ndk-Android NDk 怎麼編譯時動態鏈接第三方so庫,有頭文件
問題描述:Android如何調用第三方SO庫;
已知條件:SO庫為Android版本連接庫(*.so文件),並提供了詳細的介面說明;
已了解解決方案:
1.將SO文件直接放到libs/armeabi下,然後代碼中System.loadLibrary("xxx");再public native static int xxx_xxx_xxx();接下來就可以直接調用xxx_xxx_xxx()方法;
2.第二種方案,創建自己的SO文件,在自己的SO文件里調用第三方SO,再在程序中調用自己的SO,這種比較復雜,需要建java類文件,生成.h文件,編寫C源文件include之前生成的.h文件並實現相應方法,最後用android NDK開發包中的ndk-build腳本生成對應的.so共享庫;
求解:
1.上面兩種方案是否可行?不可行的話存在什麼問題?
2.兩種方案有什麼區別?為什麼網上大部都是用的第二種方案?
3.只有一個*.so文件,並提供了詳細的介面說明,是否可在ANDROID中使用它?
首先要看這個SO是不是JNI規范的SO,比如有沒有返回JNI不直接支持的類型。也就是說這個SO是不是可以直接當作JNI來調用。如果答案是否定的,你只能選第二個方案。
如果答案是肯定的,還要看你是不是希望這個SO的庫直接暴露給JAVA層,如果答案是否定的,你只能選第二個方案,比如你本身也是一個庫的提供者。
一般如果你只有SO,就說明這個是別人提供給你的,你可以要求對方給你提供配套的JAVA調用文件。
1、這個要看這個SO是不是符合JNI調用的規范。還要看你自己的意願。
2、因為第二種方法最靈活,各種情況都可以實現。
3、可以
看能不能直接從JAVA調用的最簡單的方法就是看SO里的函數名是不是Java_XXX_XXX_XXX格式的
是就可以,你可以自己寫一個配套的JAVA文件,注意一下SO函數名和JAVA函數名的轉換規則,或者向SO提供方索要;
不是的話就選第二種方案吧。
1、檢查所需文件是否齊全
使用第三方動態庫,應該至少有2個文件,一個是動態庫(.so),另一個是包含
動態庫API聲明的頭文件(.h)
2、封裝原動態庫
原動態庫文件不包含jni介面需要的信息,所以我們需要對其進行封裝,所以我
們的需求是:將libadd.so 裡面的API封裝成帶jni介面的動態
3、編寫庫的封裝函數libaddjni.c
根據前面生成的com_android_libjni_LibJavaHeader.h 文件,編寫libaddjni.c,用
來生成libaddjni.so
Android中集成第三方軟體包(.jar, .so)
Android中可能會用到第三方的軟體包,這包括Java包.jar和Native包.so。jar包既可通過Eclipse開發環境集成,也可通過編譯源碼集成,看你的工作環境。
假定自己開發的程序為MyMaps,需要用到BaiMaps的庫,包括mapapi.jar和libBMapApiEngine_v1_3_1.so。
一、Eclipse中集成第三方jar包及.so動態庫
MyMaps工程下創建目錄libs以及libs/armeabi,把mapapi.jar放在的libs/目錄下,把libBMapApiEngine_v1_3_1.so放在libs/armeabi/下。
Eclipse中把第三方jar包mapapi.jar打包到MyMaps的步驟:
1. 右擊工程,選擇Properties;
2. Java Build Path,選擇Libraries;
3. Libraries頁面點擊右面按鈕「Add Library…」;
4. 選擇「User Library」,點擊「Next」;
5. 點擊「User Libraries」按鈕;
6. 在彈出界面中,點擊「New…」;
7. 輸入「User library name」,點擊「OK」確認;
8. 返回之後,選擇剛剛創建的User library,右面點擊「AddJARs」;
9. 選擇MyMaps/libs/下的mapapi.jar;
10. 確認,返回。
這樣,編譯之後,該jar包就會被打進MyMaps.apk中,libBMapApiEngine_v1_3_1.so也被打包在lib/armeabi/中。
程序運行過程中,libBMapApiEngine_v1_3_1.so被放在/data/data/<yourAppPackage>/lib/下,載入動態庫時系統會從程序的該lib/目錄下查找.so庫。
二、源碼中集成第三方集成jar包及.so動態庫
Android源碼中MyMaps放在packages/apps下。MyMaps下創建目錄libs以及libs/armeabi,並把mapapi.jar放在libs/,把libBMapApiEngine_v1_3_1.so放在libs/armeabi。
2.1 修改Android.mk文件
Android.mk文件如下:
[plain] view plain
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_STATIC_JAVA_LIBRARIES := libmapapi
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_PACKAGE_NAME := MyMaps
include $(BUILD_PACKAGE)
##################################################
include $(CLEAR_VARS)
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES :=libmapapi:libs/mapapi.jar
LOCAL_PREBUILT_LIBS :=libBMapApiEngine_v1_3_1:libs/armeabi/libBMapApiEngine_v1_3_1.so
LOCAL_MODULE_TAGS := optional
include $(BUILD_MULTI_PREBUILT)
# Use the following include to make our testapk.
include $(callall-makefiles-under,$(LOCAL_PATH))
1 集成jar包
LOCAL_STATIC_JAVA_LIBRARIES取jar庫的別名,可以任意取值;
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES指定prebuiltjar庫的規則,格式:別名:jar文件路徑。注意:別名一定要與LOCAL_STATIC_JAVA_LIBRARIES里所取的別名一致,且不含.jar;jar文件路徑一定要是真實的存放第三方jar包的路徑。
編譯用BUILD_MULTI_PREBUILT。
2 集成.so動態庫
LOCAL_PREBUILT_LIBS指定prebuilt so的規則,格式:別名:so文件路徑。注意:別名一般不可改變,特別是第三方jar包使用.so庫的情況,且不含.so;so文件路徑一定要是真實的存放第三方so文件的路徑。
編譯拷貝用BUILD_MULTI_PREBUILT。
2.2 加入到GRANDFATHERED_USER_MODULES
在文件user_tags.mk中,把libBMapApiEngine_v1_3_1加入到GRANDFATHERED_USER_MODULES中
[plain] view plain
GRANDFATHERED_USER_MODULES += \
… \
libBMapApiEngine_v1_3_1
user_tags.mk可以是build/core下的,也可以是$(TARGET_DEVICE_DIR)下的,推薦修改$(TARGET_DEVICE_DIR)下的。
2.3 編譯結果
MyMaps.apk編譯生成在out/target/proct/<YourProct>/system/app/下;
libBMapApiEngine_v1_3_1.so放在out/target/proct/<YourProct>/system/lib/下,這也是系統載入動態庫時搜索的路徑。
Ⅷ Android 怎麼簡單實現預編譯
可以巧妙地利用常量來實現類似的功能。編譯的時候,一般會把常量進行硬編碼,並把不能抵達的代碼進行刪減。因此,我們有了下面類似的代碼:
[java]
public final static boolean IsDebug= false;
if(IsDebug){
Log.i(tag,msg);
}
可以對編譯後的文件,進行反編譯
Ⅸ Android Studio手動配置Makefile、CMake
在Ubutu上編譯出來的.so文件,怎麼添加到Android項目中去使用呢?目前:可以通過
Makefile方式和CMake方式引入預編譯靜動態庫(靜態庫.a 動態庫.so)到項目中去使用。就目前而言CMake是Goole推薦使用方式,但是加入接手一個老的NDK項目是MakeFile方式,看不懂就GePi了,所以這里我們還是介紹一下MakeFile方式將靜動態庫加入到AS中,完成NDK項目的開發。廢話不多說,直接擼步驟了:
1、在src/main目錄下創建一個ndkBuild文件夾
2、在此文件中創建一個Android.mk文件
3、在此文件中創建一個test.c的源文件
4、將編譯好的的.so庫復制到src/main目錄下
如圖所示目錄結構:
1、編輯Android.mk文件
2、編輯grade(app)文件
3、編輯test.c文件
4、使用編譯好的.so庫裡面的函數
本結果運行在Android 5.1 系統上
再次運行在Android 8.0系統上
看以清楚知道,其實我們的APK包裡面就沒有libMainTest.so庫,所以APP在8.0上會出現奔潰的現象。so...
1、在src/main目錄下創建一個cmake文件夾
include:裡麵包含需要一些頭文件
cmakeTest.c:需要編譯的源文件
2、在app目錄下創建一個文件:CmakeLists.txt
3、編輯grade(app)
4、編輯cmakeTest.c文件
4、引用編譯好的libcmakeTest.so
Android 8.0.0系統:
Android 5.1.1系統: