Android Studio NDK CMake 指定so輸出路徑以及生成多個so的案例與總結

前文
注意:此文的全部配置都是mac電腦下 
一直想用Android Studio的新方式Cmake來編譯JNI 代碼,以前也嘗試過,奈何有兩個難題擋住了我 
1. 只能生成一個 so庫,不能一次性生成多個 so庫,以前的mk是能夠有子模塊的。 
2. 每次生成的so所在的目錄不是在 jniLibs下,雖然知道若是打包,會將它打包進去,但就是以爲看不見它,想提供給別人用,還要去某個目錄找。java

通過嘗試,這兩個問題均可以解決了。android

生成單個so的案例
demo下載地址: http://download.csdn.net/detail/b2259909/9766081正則表達式

直接看CMakeLists.txt文件:gradle

#指定須要CMAKE的最小版本
cmake_minimum_required(VERSION 3.4.1)ui


#C 的編譯選項是 CMAKE_C_FLAGS
# 指定編譯參數,可選
SET(CMAKE_CXX_FLAGS "-Wno-error=format-security -Wno-error=pointer-sign").net

#設置生成的so動態庫最後輸出的路徑
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/../jniLibs/${ANDROID_ABI})插件

#設置頭文件搜索路徑(和此txt同個路徑的頭文件無需設置),可選
#INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/common)orm

#指定用到的系統庫或者NDK庫或者第三方庫的搜索路徑,可選。
#LINK_DIRECTORIES(/usr/local/lib)blog


add_library( native-lib
             SHARED
             src/main/cpp/native-lib.cpp )繼承

target_link_libraries( native-lib
                       log )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
其中 各個設置都有說明。主要看這個:

set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/../jniLibs/${ANDROID_ABI})
1
它將會把生成的so庫按照你在 build.gradle 指定的 abi分別放置在 jniLibs下 


很是好,先解決了第二個問題了。

生成多個so案例
仍是上面那個demo,從新建一個module。

cpp的目錄結構:

直接看CMakeLists.txt文件:

#指定須要CMAKE的最小版本
cmake_minimum_required(VERSION 3.4.1)


#C 的編譯選項是 CMAKE_C_FLAGS
# 指定編譯參數,可選
SET(CMAKE_CXX_FLAGS "-Wno-error=format-security -Wno-error=pointer-sign")

#設置生成的so動態庫最後輸出的路徑
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/../jniLibs/${ANDROID_ABI})

#設置頭文件搜索路徑(和此txt同個路徑的頭文件無需設置),可選
#INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/common)

#指定用到的系統庫或者NDK庫或者第三方庫的搜索路徑,可選。
#LINK_DIRECTORIES(/usr/local/lib)


#添加子目錄,將會調用子目錄中的CMakeLists.txt
ADD_SUBDIRECTORY(one)
ADD_SUBDIRECTORY(two)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
不一樣的地方是改成添加子目錄:

#添加子目錄,將會調用子目錄中的CMakeLists.txt
ADD_SUBDIRECTORY(one)
ADD_SUBDIRECTORY(two)
1
2
3
這樣就會先去跑到子目錄下的 one 和 two 的CmakeLists.txt,執行成功再返回。 
此時子目錄one下的CmakeLists.txt:

#繼承上一層的CMakeLists.txt的變量,也能夠在這裏從新賦值
#C 的編譯選項是 CMAKE_C_FLAGS
# 指定編譯參數,可選
#SET(CMAKE_CXX_FLAGS "-Wno-error=format-security -Wno-error=pointer-sign")

#生成so動態庫
ADD_LIBRARY(one-lib SHARED one.cpp)

target_link_libraries(one-lib log)
1
2
3
4
5
6
7
8
9
子目錄two下的CmakeLists.txt:

#繼承上一層的CMakeLists.txt的變量,也能夠在這裏從新賦值
#C 的編譯選項是 CMAKE_C_FLAGS
# 指定編譯參數,可選
#SET(CMAKE_CXX_FLAGS "-Wno-error=format-security -Wno-error=pointer-sign")

#生成so動態庫
ADD_LIBRARY(two-lib SHARED two.cpp)

target_link_libraries(two-lib log)
1
2
3
4
5
6
7
8
9
最後生成了如下兩個so文件,並自動按照abi分別放置在了 jniLibs下:

第一個問題也成功了。

總結
最後,除了 設定abiFilters 必須在 build.gradle 
主要是發現CmakeLists.txt裏 其實能夠指定不少東西: 
1. so輸出路徑 CMAKE_LIBRARY_OUTPUT_DIRECTORY 
2. .a 靜態庫輸出路徑 CMAKE_ARCHIVE_OUTPUT_DIRECTORY 
2. 獲取當前編譯的abi , ANDROID_ABI 
3. 編譯選項: 
CMAKE_C_FLAGS 
CMAKE_CXX_FLAGS 
CMAKE_CXX_FLAGS_DEBUG/CMAKE_CXX_FLAGS_RELEASE 
4. 子目錄編譯: ADD_SUBDIRECTORY 
5. #設置.c文件集合的變量

#當前cmakelists.txt所在目錄的全部.c .cpp源文件
AUX_SOURCE_DIRECTORY(. SRC_LIST)

#增長其餘目錄的源文件到集合變量中
list(APPEND SRC_LIST
        ../common/1.c
        ../common/2.c
        ../common/3.c
        ../common/4.c
        ../common/5.c
        ../common/WriteLog.c
    )

#生成so庫,直接使用變量表明那些.c文件集合
add_library(mylib SHARED ${SRC_LIST})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
6._執行自定義命令:

# copy頭文件到 靜態庫相同文件夾下
add_custom_command(TARGET myjni
  PRE_BUILD
  COMMAND echo "executing a copy command"
  COMMAND cp ${CMAKE_CURRENT_SOURCE_DIR}/myjni.h ${PROJECT_SOURCE_DIR}/../../../build/outputs/staticLib/myjni/${ANDROID_ABI}
  COMMENT "PRE_BUILD, so This command will be executed before building target myjni"
 )
1
2
3
4
5
6
7
最後,由於不少時候,JNI的參數還要轉爲C的方式,當咱們在JAVA層寫了native方法,android IDE自動提示紅色,這時按下 ALT + ENTER 能夠自動生成JNI下的方法聲明,而且入參也幫咱們轉換好了。不過有時候這個插件不生效。

因此我寫了一個JNI 的入參轉爲 C/C++的代碼插件: JNI-Convert-Var,直接在 plugin 的倉庫搜就有了。 
最近嘗試實現android studio的ALT + ENTER 能夠自動生成JNI下的方法聲明,結果發現好多IntelliJ IDEA的接口不熟悉。 只能先放棄了,如下是個人邏輯:

當鼠標點擊在 Native聲明方法上時: 
1. 檢查文件類型,若是爲java就繼續 
2. 獲取當前行的上下共三行字符串數據,使用正則表達式獲取native聲明的完整方法。 
3. 檢查當前模塊目錄下的jni或者cpp目錄下的.c或者.cpp文件。 
4. 若是沒有文件,彈窗讓用戶建立一個C/C++文件,並追加轉換後(如何轉換會有一個專門的類)的Java2C方法在文件末尾. 在IDE打開此文件。 
5. 若是JNI或者cpp目錄有一個以上的C/C++文件, 彈窗讓用戶選擇一個C/C++文件或者建立,以後打開文件追加轉換後(如何轉換會有一個專門的類)的Java2C方法在文件末尾. 。 在IDE打開此文件。

上面邏輯中:

文件類型 ,IntelliJ IDEA 的plugin開發API中能夠獲取到 獲取當前行的上下共三行字符串數據 ,IntelliJ IDEA 的plugin開發API中能夠獲取到 模塊目錄的API暫時沒找到 在IDE打開C/C++文件,不知道用什麼接口 ---------------------  做者:zhangbh2014  來源:CSDN  原文:https://blog.csdn.net/b2259909/article/details/58591898/  版權聲明:本文爲博主原創文章,轉載請附上博文連接!

相關文章
相關標籤/搜索