CMake
CMake是一個(gè)跨平臺(tái)的構(gòu)建工具寡壮,它是一個(gè)比make更高級(jí)的編譯配置工具贩疙,它可以根據(jù)不同平臺(tái)讹弯、不同的編譯器,生成相應(yīng)的Makefile或者vcproj項(xiàng)目这溅,從而達(dá)到跨平臺(tái)的目的组民。
Android Studio利用CMake生成的是ninja 。
CMake的腳本名默認(rèn)是CMakeLists.txt 悲靴。
#cmake最低版本
cmake_minimum_required(VERSION 3.6.0)
#指定項(xiàng)目
project(Main)
#生成可執(zhí)行文件 main
add_executable(main main.c)
#執(zhí)行cmake . 生成makefile
#再執(zhí)行make即可生成main程序
如果源文件很多臭胜,那么一個(gè)個(gè)寫(xiě)進(jìn)去是一件很麻煩的事情,這時(shí)候可以:
cmake_minimum_required(VERSION 3.6.0)
project(Main)
#查找當(dāng)前目錄所有源文件 并將名稱(chēng)保存到 DIR_SRCS 變量
#不能查找子目錄
aux_source_directory(. DIR_SRCS)
//message:打印
message(${DIR_SRCS})
#也可以
file(GLOB DIR_SRCS *.c)
add_executable(main ${DIR_SRCS})
如果在cmake中需要使用其他目錄的cmakelist:
cmake_minimum_required (VERSION 3.6.0)
project (Main)
aux_source_directory(. DIR_SRCS)
# 添加 child 子目錄下的cmakelist
add_subdirectory(child)
# 指定生成目標(biāo)
add_executable(main ${DIR_SRCS})
# 添加鏈接庫(kù)
target_link_libraries(main child)
#===========================================================================================
#child目錄下的cmake就是:
cmake_minimum_required (VERSION 3.6.0)
aux_source_directory(. DIR_LIB_SRCS)
# 生成鏈接庫(kù) 默認(rèn)生成靜態(tài)庫(kù)
add_library (child ${DIR_LIB_SRCS})
#指定編譯為靜態(tài)庫(kù)
add_library (child STATIC ${DIR_LIB_SRCS})
#指定編譯為動(dòng)態(tài)庫(kù)
add_library (child SHARED ${DIR_LIB_SRCS})
在上面的例子中都是生成可執(zhí)行文件对竣,讓我們對(duì)cmakelist有了一定的了解庇楞。
現(xiàn)在到android studio中使用cmakelist:
#NDK中已經(jīng)有一部分預(yù)構(gòu)建庫(kù) ndk庫(kù)已經(jīng)是被配置為cmake搜索路徑的一部分 所以可以
findLibrary(log-lib log)
target_link_libraries( native-lib
${log-lib} )
#設(shè)置cflag和cxxflag
#定義預(yù)編譯宏:TEST
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DTEST" )
set(CMAKE_Cxx_FLAGS "${CMAKE_Cxx_FLAGS} -DTEST" )
#其實(shí)直接這樣就行
target_link_libraries( native-lib
log )
添加其他預(yù)編譯庫(kù)(已經(jīng)提前編譯好的庫(kù)):
#使用 IMPORTED 標(biāo)志告知 CMake 只希望將庫(kù)導(dǎo)入到項(xiàng)目中
#如果是靜態(tài)庫(kù)則將shared改為static
add_library( imported-lib
SHARED
IMPORTED )
# 參數(shù)分別為:庫(kù)、屬性否纬、導(dǎo)入地址吕晌、so所在地址
set_target_properties(
imported-lib
PROPERTIES
IMPORTED_LOCATION
${CMAKE_SOURCE_DIR}/src/${ANDROID_ABI}/libimported-lib.so )
#為了確保 CMake 可以在編譯時(shí)定位頭文件
#這樣就可以使用 #include <xx> 引入
#否則需要使用 #include "path/xx"
include_directories( imported-lib/include/ )
#native-lib 是自己編寫(xiě)的源碼最終要編譯出的so庫(kù)
target_link_libraries(native-lib imported-lib)
#===========================================================================================
#添加其他預(yù)編譯庫(kù)還可以使用這種方式
#使用-L指導(dǎo)編譯時(shí)庫(kù)文件的查找路徑
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Lxx")
#為了確保 CMake 可以在編譯時(shí)定位您的標(biāo)頭文件
include_directories( imported-lib/include/ )
#native-lib 是自己編寫(xiě)的源碼最終要編譯出的so庫(kù)
target_link_libraries(native-lib imported-lib)
常用指令:
#set命令表示聲明一個(gè)變量source 變量的值是后面的可變參數(shù)
set(source a b c)
message(${source})
#邏輯判斷 計(jì)較字符串
set(ANDROID_ABI "areambi-v7a")
if(${ANDROID_ABI} STREQUAL "areambi")
message("armv5")
elseif(${ANDROID_ABI} STREQUAL "areambi-v7a")
message("armv7a")
else()
endif()
//還可以在gradle中使用 arguments 設(shè)置一些配置
externalNativeBuild {
cmake {
arguments "-DANDROID_TOOLCHAIN=clang", //使用的編譯器clang/gcc
"-DANDROID_STL=gnustl_static" //cmake默認(rèn)就是gnustl_static
cFlags "" //這里也可以指定cflag和cxxflag,效果和之前的cmakelist里使用一樣
cppFlags ""
}
}
5.0及以下與6.0及以上的注意事項(xiàng):
6.0以下 System.loadLibrary 不會(huì)自動(dòng)為我們加載依賴(lài)的動(dòng)態(tài)庫(kù)
6.0以上 System.loadLibrary 會(huì)自動(dòng)為我們加載依賴(lài)的動(dòng)態(tài)庫(kù)
使用NDK下的ndk-depends可查看依賴(lài)關(guān)系
使用Android.mk在 >=6.0 設(shè)備上不能再使用預(yù)編譯動(dòng)態(tài)庫(kù)(靜態(tài)庫(kù)沒(méi)問(wèn)題):
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := Test
#libTest.so放在當(dāng)前文件同目錄
LOCAL_SRC_FILES := libTest.so
#預(yù)編譯庫(kù)
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
#引入上面的Test模塊
LOCAL_SHARED_LIBRARIES := Test
LOCAL_MODULE := hello-jni
LOCAL_SRC_FILES := hello-jni.c
include $(BUILD_SHARED_LIBRARY)
上面這段配置生成的libhllo-jni
在>=6.0設(shè)備中無(wú)法執(zhí)行。
使用CMakeList.txt在 >=6.0 設(shè)備上引入預(yù)編譯動(dòng)態(tài)庫(kù):
cmake_minimum_required(VERSION 3.4.1)
file(GLOB SOURCE *.c )
add_library(
hello-jni
SHARED
${SOURCE} )
#這段配置在6.0依然沒(méi)問(wèn)題
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -L[SO所在目錄](méi)")
#這段配置只能在6.0以下使用 原因和android.mk一樣
#add_library(Test SHARED IMPORTED)
#set_target_properties(Test PROPERTIES IMPORTED_LOCATION [SO絕對(duì)地址])
target_link_libraries( hello-jni Test )