在命令行下用CMake交叉編譯可在android中運(yùn)行的so包

在命令行下用CMake交叉編譯可在android中運(yùn)行的so包

最近在寫一個(gè)通過(guò)錄屏生成gif的小應(yīng)用,由于要用到NDK,所以開(kāi)始去解這方面的知識(shí),總的來(lái)講也還算簡(jiǎn)單,不過(guò)對(duì)于之前從沒(méi)接觸過(guò)ndk的小白來(lái)說(shuō),一切都是需要摸索的,在一個(gè)不熟悉的領(lǐng)域有時(shí)候一個(gè)微小的問(wèn)題也能讓你摸個(gè)半天才能搞明白。我寫博客的大部分原因就是為了記錄下這些摸索的過(guò)程,以后要是忘記了還可以翻出來(lái)看,當(dāng)然,要是還能幫到其他跟我一樣的小白那就更好了。

下面進(jìn)入正題,對(duì)于陌生的東西,當(dāng)然是先google一翻了,隨后發(fā)現(xiàn)Android Studio已經(jīng)幫我們做了很多工作了,我們只需要做些簡(jiǎn)單的配置就可以做NDK開(kāi)發(fā)了。大致有以下幾步(具體的細(xì)節(jié)這里不講):

  • 1、下載好NDK、CMake
  • 2、新建一個(gè)android工程
  • 3、在build.gradle文件中配置c文件相關(guān)的路徑以及CMakelists.txt路徑等等
  • 4、創(chuàng)建一個(gè)帶native方法的java類
  • 5、再編寫一個(gè)與上述類對(duì)應(yīng)的c文件
  • 6、編寫CMakeLists.txt文件

然后跑起來(lái)就差不多了,流程基本上就這樣了,剩下的就是業(yè)務(wù)上的事了。

不過(guò)對(duì)于小白來(lái)說(shuō),照著教程做了一遍,工程跑起來(lái)了,預(yù)期結(jié)果也達(dá)到了,但還是一臉懵懂,不知道來(lái)龍去脈。用Android Studio的好處是高度智能化,開(kāi)發(fā)者借助它可以快速地完成一些與業(yè)務(wù)無(wú)關(guān)的事,但也有一點(diǎn)我個(gè)人不喜歡,那就是不知道它到底做了些什么,像個(gè)黑盒子,只看到結(jié)果,看不到過(guò)程。所以幾乎從一開(kāi)始我就很想知道如果不依賴android studio 怎么才能把我要的so包編譯出來(lái)呢?就好比不需要eclipse,直接在命令行下編譯運(yùn)行java程序一樣。不得不說(shuō),為了搞明白這點(diǎn)事,我摸了很久,并且曾暫停了一段時(shí)間。下面就來(lái)說(shuō)一下不用android studio怎么編譯so包,說(shuō)出來(lái)之后會(huì)覺(jué)得很簡(jiǎn)單,但沒(méi)搞清楚之前卻是讓我非常抓狂。

在命令行下執(zhí)行交叉編譯有兩種方式

  • 一是用NDK自帶的工具鏈
  • 二是使用獨(dú)立工具鏈

第一種簡(jiǎn)單點(diǎn),第二種麻煩點(diǎn),不過(guò)簡(jiǎn)單的卻花了我更多的時(shí)間和精力,因?yàn)闆](méi)有在網(wǎng)上找到現(xiàn)成的資料。本文講第一種,使用獨(dú)立工具鏈的方式再另寫一文來(lái)介紹。

注:本文的例子是在Ubuntu操作系統(tǒng)下完成的

一、按照J(rèn)NI的實(shí)現(xiàn)方式建一個(gè)工程

JNI的實(shí)現(xiàn)大概有以下幾步:

  • 編寫帶有 native 方法的 Java 類
  • 生成該類擴(kuò)展名為 .h 的頭文件
  • 創(chuàng)建該頭文件的 C/C++ 文件,實(shí)現(xiàn) native 方法
  • 將該 C/C++ 文件編譯成動(dòng)態(tài)鏈接庫(kù)
  • 在Java 程序中加載該動(dòng)態(tài)鏈接庫(kù)

最后建好的工程目錄如下圖所示

[圖片上傳失敗...(image-5ac0c9-1514633487045)]

MyJni類是一個(gè)帶native方法的java類

Navive.c是實(shí)現(xiàn)native方法的本地類
內(nèi)容如下:
[圖片上傳失敗...(image-c530bc-1514633487045)]

僅打印了一句日志。

CMakeLists.txt的內(nèi)容如下:
[圖片上傳失敗...(image-a71634-1514633487045)]

添加了一個(gè)myso的動(dòng)態(tài)庫(kù),輸出到c目錄下的lib目錄中(實(shí)際輸出的名字叫:libmyso.so)

至此,如果不需要交叉編譯的話進(jìn)入build目錄下執(zhí)行下面兩條命令就可以生成so包了(目前build只是個(gè)空目錄)

$ cmake ..

$ make

不過(guò)這個(gè)so包只能在當(dāng)前pc上使用,不能用在手機(jī)上(實(shí)際上這個(gè)例子按上面的方法執(zhí)行是會(huì)報(bào)錯(cuò)的,因?yàn)橛玫搅薬ndroid的日志,會(huì)找不到頭文件的,這里只是說(shuō)明一下本地編譯與交叉編譯的區(qū)別)。如果要交叉編譯就要配置交叉編譯環(huán)境,這就是今天的重頭戲。

二、配置交叉編譯環(huán)境

寫一個(gè)腳本來(lái)記錄這些參數(shù),在build目錄下新建configuer.sh文件,內(nèi)容如下:
[圖片上傳失敗...(image-e22098-1514633487045)]

這里對(duì)各個(gè)參數(shù)作個(gè)解釋:

ANDROID_ABI 是cpu架構(gòu)

ANDROID_PLATFORM是支持的最低android平臺(tái)

ANDROID_NDK是ndk的根目錄

CMAKE_TOOLCHAIN _FILE是工具鏈文件,這個(gè)參數(shù)非常重要,這里面還配置了很多其它參數(shù)。

ANDROID_TOOLCHAIN是C/C++編譯器,可選Clang和gcc,官網(wǎng)推薦clang

最后還有兩個(gè)點(diǎn),代表上一級(jí)目錄,即CMakeLists.txt所在的目錄

在build目錄下執(zhí)行這個(gè)腳本,再執(zhí)行make命令,可用于android的so包就出來(lái)了。
[圖片上傳失敗...(image-d9de94-1514633487045)]

[圖片上傳失敗...(image-8a6948-1514633487045)]





驗(yàn)證

下面來(lái)驗(yàn)證一下,看看這個(gè)so能否在android工程中使用。
創(chuàng)建一個(gè)android工程,將so包拷到j(luò)niLibs目錄下,MyJni.java拷到對(duì)應(yīng)的目錄下。
[圖片上傳失敗...(image-a1c59b-1514633487045)]

在MainActivity中調(diào)用:

[圖片上傳失敗...(image-c18471-1514633487045)]

看一下日志:

[圖片上傳失敗...(image-119460-1514633487045)]

可以看到已經(jīng)成功調(diào)到了so包里的方法,第一句就是從Native.c文件輸出的。第二句是在MainActivity里面輸出的。

源碼

https://github.com/MingHuang1024/CrossCompileForAndroidUseCommand

驗(yàn)證的那個(gè)android工程就不上了,如果要的話就聯(lián)系我。




由于水平有限,如果文中存在錯(cuò)誤之處,請(qǐng)大家批評(píng)指正,歡迎大家一起來(lái)分享、探討!

博客:http://blog.csdn.net/MingHuang2017

GitHub:https://github.com/MingHuang1024

Email:MingHuang1024@foxmail.com

微信:724360018

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容