Cmake文件

使用AndroidStudio3.4創(chuàng)建一個(gè)C/C++Support的項(xiàng)目,默認(rèn)在app/src/main目錄下會(huì)生成cpp目錄欲低,里面包含CMakeList.txt和native-lib.cpp。下面代碼為CMakeList.txt去掉英文注釋格式化后的內(nèi)容。

#指定cmake最小支持版本
cmake_minimum_required(VERSION 3.4.1)

#添加一個(gè)庫,根據(jù)native-lib.cpp源文件編譯一個(gè)native-lib的動(dòng)態(tài)庫
add_library(
        native-lib
        SHARED
        native-lib.cpp)

#查找系統(tǒng)庫,這里查找的是日志庫,賦值給log-lib
#ndk路徑\platforms\android-21\arch-arm\usr\lib下查找系統(tǒng)庫
find_library(
        log-lib
        log)

#設(shè)置依賴的庫 (第一個(gè)參數(shù)必須為目標(biāo)模塊, 順序不能換)
target_link_libraries(
        native-lib
        ${log-lib})

CMakeList中的常用命令:

cmake_minimum_required
cmake_minimum_required(VERSION 3.4.1)

指定最低支持的版本,可選,可不寫,如果我們使用了一些高版本特有的命令,那就需要指明最低支持版本

aux_ source_ directory
#.表示當(dāng)前目錄
aux_source_directory(.DIR_SRCS)

查找當(dāng)前目錄所有源文件并將源文件名稱列表保存到DIR_SRCS變量
不能查找子目錄

add_library

添加一個(gè)庫或者導(dǎo)入預(yù)編譯庫

添加一個(gè)庫

添加一個(gè)庫文件,名為<name>。指定STATIC,SHARED,MODULE參數(shù)來指定庫的類型油猫。
STATIC: 靜態(tài)庫;
SHARED: 動(dòng)態(tài)庫;
MODULE:使用dyld的系統(tǒng)有效,若不支持dyld,等同于SHARED
EXCLUDE_FROM_ALL: 表示該庫不會(huì)被默認(rèn)構(gòu)建柠偶。
source1 source2... sourceN:用來指定庫的源文件

格式:

add_ library(<name> [STATIC | SHARED | MODULE]
[EXCLUDE_ FROM_ ALL] source1 source2 ...sourceN)

導(dǎo)入預(yù)編譯庫

添加一個(gè)已存在的預(yù)編譯庫情妖,名為<name>。
一般配合set_target_properties使用
格式:
add library (<name>
<SHARED | STATIC | MODULE | UNKNOWN> IMPORTED)

示例:

add library(test SHARED IMPORTED)
set_target_properties (
test #指明目標(biāo)庫名
PROPERTIES IMPORTED_ LOCATION #指明要設(shè)置的參數(shù)
庫路徑/${ANDROID_ ABI}/libtest.so #導(dǎo)入庫的路徑
)
set命令

set用于設(shè)置Cmake的變量,常用舉例:

#設(shè)置可執(zhí)行文件的輸出路徑( EXCUTABLE_OUTPUT_PATH是全局變量)
set ( EXECUTABLE_OUTPUT_PATH [output_path])
#設(shè)置庫文件的輸出路徑 (LIBRARY OUTPUT PATH是全局變量 )
set (LIBRARY_OUTPUT_PATH [output_path])
#設(shè)置C++編譯參數(shù)(CMAKE_CXX_FLAGS是全局變量)
set(CMAKE CXX_FLAGS "-Wall std=c++11" )
#設(shè)置源文件集合( SOURCE_FILES是本地變量即自定義變量)
set ( SOURCE_FILES main. cpp test.cpp ... )
include_directories

設(shè)置頭文件目錄
相當(dāng)于g++選項(xiàng)中的-I參數(shù)

#可以用相對或絕對路徑诱担, 也可以用自定義的變量值
include_directories(./include ${MY_INCLUDE})
add_executable

用于添加可執(zhí)行文件

#第一個(gè)參數(shù)是文件名,第二個(gè)參數(shù)是源文件
add_executable(<name> ${SRC_LIST})
target_link_libraries

將若干庫鏈接到目標(biāo)庫文件
鏈接的順序應(yīng)當(dāng)符合gcc鏈接順序規(guī)則毡证,被鏈接的庫放在依賴它的庫的后面,即如果下面的命令中蔫仙,lib1依賴于lib2, lib2又依賴于lib3料睛,則在.上面命令中必須嚴(yán)格按照(lib1
lib2 lib3的順序排列,否則會(huì)報(bào)錯(cuò)

target_link_libraries(<name> lib1 lib2 lib3)
#如果出現(xiàn)互相依賴的靜態(tài)庫摇邦,CMake會(huì)允許依賴圖中包含循環(huán)依賴恤煞,如:
add library(A STATIC a.c)
add_library(B STATIC b.c)
target_link_libraries(A B)
target_link_libraries(B A)
add_executable(main main.c )
target_tink_libraries (main A)
add_definitions

通常用于添加編譯參數(shù):

#為當(dāng)前路徑以及子目錄的源文件加入由-D引入的define flag
add definitions( -DF00  -DDEBUG ...)
add_subdirectory

如果當(dāng)前目錄下還有子目錄時(shí)可以使用add_subdirectory, 子目錄中也需要包含有
CMakeLists.txt

# sub_dir指定包含CMakeLists.txt和源碼文件的子目錄位置
# binary_dir是輸出路徑,一般可以不指定 
add_subdirecroty(sub_dir [binary_dir])
file

文件操作命令,常見用法
使用者中方式添加文件,需要注意,在沒有改動(dòng)CMakeLists.txt文件的情況下,重新編譯會(huì)報(bào)錯(cuò),需要改動(dòng)CMakeLists.txt文件,使其重新編譯,比如添加一個(gè)空格,然后在編譯就會(huì)重新生成makefile文件

#將message寫入filename文件中,會(huì)覆蓋文件原有內(nèi)容
file(WRITE filename "message" )
#將message寫入filename文件中施籍,會(huì)追加在文件末尾
file (APPEND filename "message" )
#從filename文件中讀取內(nèi)容并存儲(chǔ)到var變量中居扒,如果指定了numBytes和offset,
#則從offset處開始最多讀numBytes個(gè)字節(jié)丑慎,另外如果指定了HEX參數(shù)苔货,則內(nèi)容會(huì)以十六進(jìn)制形式存儲(chǔ)在var變量中
file (READ filename var [LIMIT numBytes] [OFFSET offset] [HEX] )
#重命名文件
file (RENAME <oldname> <newname> )
#刪除文件,等于rm命令
file(REMOVE [file ...])
#遞歸的執(zhí)行刪除文件命令立哑,等于rm -r
file(REMOVE RECURSE [filel ...])
#根據(jù)指定的url下載文件
# timeout超時(shí)時(shí)間; 下載的狀態(tài)會(huì)保存到status中; 下載日志會(huì)被保存到log; sum指定所下載文件預(yù)期的MD5值, 如果指定會(huì)自動(dòng)進(jìn)行比對姻灶,
#如果不一致铛绰,則返回一個(gè)錯(cuò)誤; SHOW_PROGRESS, 進(jìn)度信息會(huì)以狀態(tài)信息的形式被打印出來
file(DOWNLOAD url file [TIMEOUT timeout] [STATUS status] [LOG log] [EXPECTED_MD5 sum] [SHOW_PROGRESS])
#創(chuàng)建目錄
file(MAKE_DIRECTORY [dir1 dir2 ...])
#會(huì)把path轉(zhuǎn)換為以unix的/開頭的cmake風(fēng)格路徑,保存在result中
file(TO_CMAKE_PATH path result)
#它會(huì)把cmake風(fēng)格的路徑轉(zhuǎn)換為本地路徑風(fēng)格: windows 下用"\"产喉,而unix下用”/"
file(TO_NATIVE_PATH path result )
#將會(huì)為所有匹配查詢表達(dá)式的文件生成個(gè)文件list, 并將該list存儲(chǔ)進(jìn)變量variable里捂掰,如果一個(gè) 表達(dá)式指定了RELATIVE敢会,返回的結(jié)果
#將會(huì)是相對于給定路徑的相對路徑,查詢表達(dá)式例子: *.cxx, *.vt?
# NOTE: 按照官方文檔的說法这嚣,不建議使用file的GL0B指令來收集1程的源文件
file(GLOB variable [RELATIVE path] [globbing expressions]... )
set_directory_properties

設(shè)置某個(gè)路徑的一種屬性
prop1, prop2代表屬性鸥昏,取值為:INCLUDE_DIRECTORIES
LINK_DIRECTORIES
INCLUDE_REGUL AR_EXPRESSION
ADDITIONAL_MAKE_CLEAN_FILES

set_directory_properties (PROPERTIES prop1 value1 prop2 value2)
set_property

在給定的作用域內(nèi)設(shè)置一個(gè)命名的屬性
PROPERTY參數(shù)是必須的
第一個(gè)參數(shù)決定了屬性可以影響的作用域:
GLOBAL:全局作用域
DIRECTORY:默認(rèn)當(dāng)前路徑,也可以用[dir]指定路徑(可使用相對路徑/絕對路徑指定)
TARGET:目標(biāo)作用域,可以是0個(gè)或多個(gè)已有目標(biāo)
SOURCE:源文件作用域姐帚,可以是0個(gè)或多個(gè)源文件(源文件屬性只對同目錄下的CMakeLists中的目標(biāo)可見)
TEST:測試作用域吏垮,可以是0個(gè)或多個(gè)已有的測試
CACHE:必須指定0個(gè)或多個(gè)cache中已有的條目

set_property (<GL0BAL 
| DIRECTORY [dir] 
| TARGET [target ...] 
| SOURCE [src1...]
| TEST [test1...]  
| CACHE [entry1 ...] >
[APPEND]
PROPERTY <name> [value ...]
多個(gè)源文件處理

如果源文件很多,把所有文件一個(gè)個(gè)加入很麻煩罐旗,可以使用aux_source_directory命令或file命令膳汪,會(huì)查找指定目錄下的所有源文件,然后將結(jié)果存進(jìn)指定變量名九秀。

cmake_minimum_required (VERSION 3.4.1)
#查找當(dāng)前目錄所有源文件并將名稱保存到DIR_SRCS 變量
#不能查找子目錄
aux_source_directory(. DIR_SRCS)
#也可以使用
# file(GLOB DIR_ SRCS *.c *.cpp )
add_Library(
native-lib
SHARED
${DIR_SRCS})
多目錄多源文件處理
  1. 主目錄中的CMakeLists.txt中添加add_subdirectory(child)命令遗嗽,指明本項(xiàng)目包含一個(gè)子項(xiàng)目child。并在target_link_libraries指明本項(xiàng)目需要鏈接一個(gè)名為child的庫鼓蜒。
  2. 子目錄child中創(chuàng)建CMakeLists.txt,這里child編譯為共享庫痹换。
cmake_minimum_required (VERSION 3.4.1)
aux_source_directory(. DIR_SRCS)
#添加 child 子目錄下的cmakelist
add_subdirectory(child)

add_library(
native-lib
SHARED
${DIR_SRCS} )
target_link_libraries (native-lib child)
#-----------------------------------------
#child目錄下的CMakeLists.txt:
cmake_ minimum_required (VERSION 3.4.1)
aux_ source_ directory(. DIR_LIB_SRCS)
add_library(
child
SHARED
${DIR_LIB_SRCS})

添加預(yù)編譯庫(Android6.0版本以前)

  1. 假設(shè)我們本地項(xiàng)目引用了libimported-lib.so。
  2. 添加add_library命令都弹, 第一個(gè)參數(shù)是模塊名娇豫,第二個(gè)參數(shù)SHARED表示動(dòng)態(tài)庫,STATIC表示靜態(tài)庫缔杉,第三個(gè)參數(shù)IMPORTED表示以導(dǎo)入的形式添加锤躁。
  3. 添加set_target_properties命令設(shè)置導(dǎo)入路徑屬性。
    4.將import-lib添加到target_link_libraries命令參數(shù)中或详,表示native-lib需要鏈接imported-lib模塊
cmake_minimum_required(VERSION 3.4.1)
#使用IMPORTED 標(biāo)志告知CMake 只希望將庫導(dǎo)入到項(xiàng)目中
#如果是靜態(tài)庫則將shared改為static
add_library( imported-lib
  SHARED
  IMPORTED )
#參數(shù)分別為:庫系羞、屬性、導(dǎo)入地址霸琴、庫所在地址
set_target_properties(
  imported-lib 
  PROPERTIES
  IMPORTED_LOCATION
  <路徑>/libimported-lib. so)
aux_source_directory(. DIR_SRCS)

add_library(
  native-lib
  SHARED
  ${DIR_SRCS} )

target_link_libraries (native-lib imported-lib)

添加預(yù)編譯庫(Android6.0版本以后)

在Android 6.0及以上版本椒振,如果使用上述的方法添加預(yù)編譯動(dòng)態(tài)庫的話,會(huì)有問題梧乘。我們可以使用另外種方式來配置澎迎。

# set命令定義一個(gè)變量
# CMAKE_C_FLAGS: c的參數(shù),會(huì)傳遞給編譯器
#如果是c++文件,需要用CMAKE_CXX FLAGS
# -L: 庫的查找路徑
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -L [SO所在目錄]")

添加頭文件目錄

為了確保CMake可以在編譯時(shí)定位頭文件选调,使用include_directories, 相當(dāng)于g++選項(xiàng)中的-l參數(shù)夹供。這樣就可以使用#include<xx.h>,否則需要使用 #include"path/xx.h"

cmake_minimum_required(VERSION 3. 4.1)
#設(shè)置頭文件目錄
include_directories(<文件目錄>)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -L [SO所在目錄]")
aux_source_directory(. DIR_SRCS)
add_library(
  native-lib
  SHARED
  ${DIR_ SRCS})
target_link_libraries (native-lib imported-lib)

Build.gradle配置

可以在gradle中使用arguments設(shè)置一些配置

android{
    defaultConfig{
        cmake{
            // 使用的編譯器clang/gcc
            // cmake默認(rèn)就是 gnustl_static
            arguments "-DANDROID_TOOLCHAIN=clang","-DANDROID_STL=gnustl_static"
            // 指定cflags和cppflags,效果和cmakelist使用一樣
            cFlags ""
            cppFlags ""
            // 指定需要編譯的cpu架構(gòu)
            abiFilters "armeabi-v7a"
        }
    }
    externalNativeBuild{
        cmake{
            // 指定CMakeLists.txt文件相對當(dāng)前build.gradle的路徑
            path "xxx/CMakeLists.txt"
        }
    }
}

集成fomd為例

官網(wǎng):https://www.fmod.com/
SDK下載頁面:https://www.fmod.com/download(需要注冊登錄才能下載)

第一步: 集成頭文件,so文件
將下載的fmodstudioapi20000android.tar.gz 解壓仁堪,找到 api/core目錄下的inc文件夾哮洽,其中fmod的頭文件,lib是fmod預(yù)編譯好的so和jar文件弦聂。將inc整個(gè)文件夾copy到項(xiàng)目的cpp文件夾下:

inc

然后在CMakeLists文件中,設(shè)置頭文件目錄如下:

#設(shè)置頭文件路徑
#這里通過Cmake預(yù)置變量CMAKE_SOURCE_DIR拿到CMakeLists當(dāng)前路徑
#這里就是src/main/cpp
include_directories(${CMAKE_SOURCE_DIR}/inc)

然后在項(xiàng)目的main文件夾下,新建文件夾jniLibs,將 api/core/lib下的所有文件夾都copy到jniLibs下:

jniLibs

修改module的build.gradle文件中的defaultConfig:

 defaultConfig {
        applicationId "com.code.cmakedemo"
        minSdkVersion 14
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        externalNativeBuild {
            cmake {
                cppFlags ""
                abiFilters "x86" //本地庫的cpu架構(gòu) (模擬器所以選了x86)
            }
        }
        ndk{
            abiFilters "x86" //三方so庫的cpu架構(gòu) (模擬器所以選了x86)
        }
    }

然后修改CMakeLists文件,將libfomd.solibfomdL.so添加到依賴庫里:

#設(shè)置第三方so庫的路徑
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${CMAKE_SOURCE_DIR}/../jniLibs/${CMAKE_ANDROID_ARCH_ABI}}")

#設(shè)置依賴的庫 (第一個(gè)參數(shù)必須為目標(biāo)模塊, 順序不能換)
target_link_libraries(
        native-lib
        fmod
        fmodL
        ${log-lib})

這樣就配置完成了,然后可以在native-lib.cpp中導(dǎo)入和使用fmod

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末鸟辅,一起剝皮案震驚了整個(gè)濱河市氛什,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌匪凉,老刑警劉巖枪眉,帶你破解...
    沈念sama閱讀 212,454評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異再层,居然都是意外死亡贸铜,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評論 3 385
  • 文/潘曉璐 我一進(jìn)店門树绩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來萨脑,“玉大人,你說我怎么就攤上這事饺饭〔吃纾” “怎么了?”我有些...
    開封第一講書人閱讀 157,921評論 0 348
  • 文/不壞的土叔 我叫張陵瘫俊,是天一觀的道長鹊杖。 經(jīng)常有香客問我,道長扛芽,這世上最難降的妖魔是什么骂蓖? 我笑而不...
    開封第一講書人閱讀 56,648評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮川尖,結(jié)果婚禮上登下,老公的妹妹穿的比我還像新娘。我一直安慰自己叮喳,他們只是感情好被芳,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,770評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著馍悟,像睡著了一般畔濒。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上锣咒,一...
    開封第一講書人閱讀 49,950評論 1 291
  • 那天侵状,我揣著相機(jī)與錄音,去河邊找鬼毅整。 笑死趣兄,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的悼嫉。 我是一名探鬼主播艇潭,決...
    沈念sama閱讀 39,090評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了暴区?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,817評論 0 268
  • 序言:老撾萬榮一對情侶失蹤辛臊,失蹤者是張志新(化名)和其女友劉穎仙粱,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體彻舰,經(jīng)...
    沈念sama閱讀 44,275評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡伐割,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,592評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了刃唤。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片隔心。...
    茶點(diǎn)故事閱讀 38,724評論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖尚胞,靈堂內(nèi)的尸體忽然破棺而出硬霍,到底是詐尸還是另有隱情,我是刑警寧澤笼裳,帶...
    沈念sama閱讀 34,409評論 4 333
  • 正文 年R本政府宣布唯卖,位于F島的核電站,受9級特大地震影響躬柬,放射性物質(zhì)發(fā)生泄漏拜轨。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,052評論 3 316
  • 文/蒙蒙 一允青、第九天 我趴在偏房一處隱蔽的房頂上張望橄碾。 院中可真熱鬧,春花似錦颠锉、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至眉枕,卻和暖如春恶复,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背速挑。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評論 1 266
  • 我被黑心中介騙來泰國打工谤牡, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人姥宝。 一個(gè)月前我還...
    沈念sama閱讀 46,503評論 2 361
  • 正文 我出身青樓翅萤,卻偏偏與公主長得像,于是被迫代替她去往敵國和親腊满。 傳聞我的和親對象是個(gè)殘疾皇子套么,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,627評論 2 350