Cmake詳解

一、Cmake語法詳解

1捏萍、什么是CMake

  • 在Android Studio 2.2及以上,構(gòu)建原生庫的默認(rèn)工具是CMake旷余。
  • CMake是一個跨平臺的構(gòu)建工具,可以用簡單的語句來描述所有平臺的安裝(編譯過程)扁达。能夠輸出各種各樣的makefile或者project文件正卧。CMake并不直接構(gòu)建出最終的軟件,而是產(chǎn)生其他工具的腳本(如makefile)跪解,然后再依據(jù)這個工具的構(gòu)建方式使用炉旷。
  • CMake是一個比make更高級的編譯配置工具,它可以根據(jù)不同的平臺叉讥、不同的編譯器窘行,生成相應(yīng)的makefile或vcproj項目,從而達到跨平臺的目的图仓。Android Studio利用CMake生成的是ninja罐盔。ninja是一個小型的關(guān)注速度的構(gòu)建系統(tǒng)。我們不需要關(guān)心ninja的腳本救崔,知道怎么配置CMake就可以了惶看。
  • CMake其實是一個跨平臺的支持產(chǎn)出各種不同的構(gòu)建腳本的一個工具。

2六孵、CMake源文件

  • CMake的源碼文件可以包含命令纬黎、注釋、空格和換行劫窒。
  • 以CMake編寫的源文件以CmakeLists.txt命名或以.cmake為擴展名莹桅。
  • 可以通過add_subdirectory()命令把子目錄的CMake源文件添加進來。
  • CMake源文件中所有有效的語句都是命令烛亦,可以是內(nèi)置命令或自定義的函數(shù)/宏命令诈泼。

3、CMake注釋

# 單行注釋

#[[多行注釋
多行注釋
多行注釋]]
復(fù)制代碼
  • 單行注釋:#注釋內(nèi)容(注釋從#開始到行尾結(jié)束)
  • 釣竿注釋:可以使用括號來實現(xiàn)多行注釋:#[[多行注釋]]

4煤禽、CMake變量

# 聲明變量:set(變量名 變量值)
set(var 123)
# 引用變量:message 命令用來打印
message("var = ${var}")
復(fù)制代碼
  • CMake中所有變量都是string類型铐达。可以使用set()unset()命令來聲明或移除一個變量
  • 變量的引用:${變量名}

5檬果、CMake列表(lists)

# 聲明列表:set(列表名 值1 值2 ... 值N)
# 或set(列表名 "值1;值2;...;值N")
set(list_var 1 2 3 4 5)
# 或者
set(list_var2 "1;2;3;4;5")

message("list_var = ${list_var}")
復(fù)制代碼
  • 列表也是字符串瓮孙,可以把列表看作一個特殊的變量,這個變量有多個值选脊。
  • 語法格式:set(列表名 值1 值2 ... 值N)杭抠、set(列表名 "值1;值2;...;值N")
  • 列表的引用:${列表名}

6、CMake流程控制-操作符

類型 名稱
一元 EXIST,COMMAND,DEFINED
二元 EQUAL,LESS,LESS_EQUAL,GREATER,GREATER_EQUAL,STREQUAL,STRLESS,

STRLESS_EQUAL,STRGREATER,STRGREATER_EQUAL,VERSION_EQUAL,VERSION_LESS,
VERSION_LESS_EQUAL,VERSION_GREATER,VERSION_GREATER_EQUAL,MATCHES |
| 邏輯 | NOT,AND,OR |

7恳啥、CMake流程控制-布爾常量值

類型
true 1,ON,YES,TRUE,Y,非0的值
false 0,OFF,NO,FALSE,N,IGNORE,NOTFOUND,空字符串偏灿,
以-NOTFOUND結(jié)尾的字符串

8、CMake流程控制-條件命令

set(if_tap OFF)
set(elseif_tap ON)

if(${if_tap})
    message("if")
elseif(${elseif_tap})
    message("elseif")
else(${if_tap})
    message("else")
endif(${if_tap})
復(fù)制代碼
  • 語法格式:
if(表達式)
    COMMAND(ARGS...)
elseif(表達式)
    COMMAND(ARGS...)
else(表達式)
    COMMAND(ARGS...)
endif(表達式)
復(fù)制代碼
  • elseif和else部分是可選的钝的,也可以有多個elseif部分翁垂,縮進和空格對語句解析沒有影響铆遭。

9、CMake流程控制-循環(huán)命令

set(a "")
while(NOT a STREQUAL "xxx")
    set(a "${a}x")
    message("a = ${a}")
endwhile()
復(fù)制代碼
  • 語法格式:
while(表達式)
    COMMAND(ARGS...)
endwhile(表達式)
復(fù)制代碼
  • break()命令可以跳出整個循環(huán)沿猜。
  • continue()可以跳出當(dāng)前循環(huán)枚荣。

10、CMake流程控制-循環(huán)遍歷

1)格式一

foreach(item 1 2 3)
    message("item = ${item}")
endforeach(item)
復(fù)制代碼
  • 語法格式:
foreach(循環(huán)變量 參數(shù)1 參數(shù)2 ... 參數(shù)N)
    COMMAND(ARGS...)
endforeach(循環(huán)變量)
復(fù)制代碼
  • 每次迭代設(shè)置循環(huán)變量為參數(shù)啼肩。
  • foreach也支持break()和continue()命令跳出循環(huán)橄妆。

2)格式二

foreach(item RANGE 3)
    message("item = ${item}")
endforeach(item)
復(fù)制代碼
  • 語法格式:
foreach(循環(huán)變量 RANGE total)
    COMMAND(ARGS...)
endforeach(循環(huán)變量)
復(fù)制代碼
  • 循環(huán)范圍從0到total。

3)格式三

foreach(item RANGE 1 5 2)
    message("item = ${item}")
endforeach(item)
復(fù)制代碼
  • 語法格式:
foreach(循環(huán)變量 RANGE start stop step)
    COMMAND(ARGS...)
endforeach(循環(huán)變量)
復(fù)制代碼
  • 循環(huán)范圍從start到stop祈坠,循環(huán)增量為step呼畸。

4)格式四

set(list_var 1 2 3)

foreach(item IN LISTS list_var)
    message("item = ${item}")
endforeach(item)
復(fù)制代碼
  • foreach還支持對列表的循環(huán)。
  • 語法格式:
foreach(循環(huán)變量 IN LISTS 列表)
    COMMAND(ARGS...)
endforeach(循環(huán)變量)
復(fù)制代碼

11颁虐、CMake自定義函數(shù)命令

function(func x y z)
    message("call function func")
    message("x = ${x}")
    message("y = ${y}")
    message("z = ${z}")
    message("ARGC = ${ARGC}")
    message("arg1 = ${ARGV0} arg2 = ${ARGV1} arg3 = ${ARGV2}")
    message("all args = ${ARGV}")
endfunction(func)

func(1 2 3)
復(fù)制代碼

ARGC:表示傳入?yún)?shù)的個數(shù)蛮原。 ARGV:表示所有參數(shù)。 ARGV0:表示第一個參數(shù)另绩,ARGV1儒陨、ARGV2以此類推。

  • 自定義函數(shù)命令格式:
function(<name> [arg1[arg2[arg3...]]])
    COMMAND()
endfunction(<name>)
復(fù)制代碼
  • 函數(shù)命令調(diào)用格式:name(實參列表)

12笋籽、CMake自定義宏命令

macro(ma x y z)
    message("call macro ma")
    message("x = ${x}")
    message("y = ${y}")
    message("z = ${z}")
endmacro(ma)

ma(1 2 3)
復(fù)制代碼

函數(shù)命令有自己的作用域蹦漠。 宏命令跟調(diào)用者的作用域一樣。

  • 自定義宏命令格式:
macro(<name> [arg1[arg2[arg3...]]])
    COMMAND()
endmacro(<name>)
復(fù)制代碼
  • 宏命令調(diào)用格式:name(實參列表)

13车海、CMake變量的作用域

  • 全局層:cache變量笛园,在整個項目范圍可見,一般在set定義變量時侍芝,指定CACHE參數(shù)就能定義cache變量研铆。
  • 目錄層:在當(dāng)前目錄CMakeLists.txt中定義,以及在該文件包含的其他cmake源文件中定義的變量州叠。
  • 函數(shù)層:在命令函數(shù)中定義的變量棵红,屬于函數(shù)作用域內(nèi)的變量。

變量查找優(yōu)先級:函數(shù)層 優(yōu)于 目錄層咧栗,目錄層 優(yōu)于 全局層逆甜,即:函數(shù)層 --> 目錄層 --> 全局層

二、CMakeList.txt文件詳解

1致板、CMakeLists.txt簡析

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

cmake_minimum_required(VERSION 3.4.1)

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

# 查找系統(tǒng)庫,這里查找的是系統(tǒng)日志庫,并賦值給變量log-lib
find_library(
    log-lib
    log)

# 設(shè)置依賴的庫(第一個參數(shù)必須為目標(biāo)模塊稚茅,順序不能換)
target_link_libraries(
    native-lib
    ${log-lib})
復(fù)制代碼
  • cmake_minimum_required:指定cmake最低支持的版本。這個命令是可選的平斩,如果在CMakeLists.txt文件中使用了高版本特有的命令的話亚享,就需要加上這條命令,來指定CMake的最低支持版本绘面,如果CMake當(dāng)前版本低于我們指定的版本就會報錯欺税。
  • aux_source_directory(. DIR_SRCS):查找當(dāng)前目錄所有源文件,并將源文件名稱列表保存到DIR_SRCS變量揭璃;但不能查找子目錄中的源文件晚凿。
  • find_library:查找系統(tǒng)庫,默認(rèn)會在AndroidNDK目錄\platforms\android-xx\arch-arm\usr\lib下查找瘦馍。

2歼秽、常用命令-add_library

1)添加一個庫

  • 添加一個庫文件,名為<name>情组。
  • 指定STATIC燥筷,SHARED,MODULE參數(shù)來指定庫的類型院崇。STATIC:靜態(tài)庫肆氓,SHARED:動態(tài)庫,MODULE:在使用dyld的系統(tǒng)有效底瓣,若不支持dyld谢揪,等同于SHARED。
  • EXCLUDE_FROM_ALL:表示該庫不會被默認(rèn)構(gòu)建捐凭。
  • source1 source2 ... sourceN:用來指定庫的源文件拨扶。
add_library(<name> [STATIC | SHARED | MODULE]
 [EXCLUDE_FROM_ALL] source1 source2 ... sourceN)
復(fù)制代碼

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

  • 添加一個已存在的預(yù)編譯庫,名為<name>茁肠。
  • 一般配合set_target_properties使用屈雄。
add_library(<name> <SHARED|STATIC|MODULE|UNKNOW> IMPORTED)

# 比如
add_library(test SHARED IMPORTED)
set_target_properties(
    test # 指明目標(biāo)庫名
    PROPERTIES IMPORTED_LOCATION # 指明要設(shè)置的參數(shù)
    庫路徑/${ANDROID_ABI}/libtest.so # 導(dǎo)入庫的路徑
)
復(fù)制代碼

3、常用命令-set

設(shè)置CMake變量:

# 設(shè)置可執(zhí)行文件的輸出路徑(EXECUTABLE_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 ...)
復(fù)制代碼

4官套、常用命令-include_directories

設(shè)置頭文件目錄酒奶。

# 可以用相對或絕對路徑,也可以用自定義的變量值
include_directories(./include ${MY_INCLUDE})
復(fù)制代碼

相當(dāng)于g++選項中的-l參數(shù)奶赔。

5惋嚎、常用命令-add_executable

添加可執(zhí)行文件:

add_executable(<name> ${SRC_LIST})
復(fù)制代碼

6、常用命令-target_link_libraries

target_link_libraries(<name> lib1 lib2 lib3)

# 如果出現(xiàn)互相依賴的靜態(tài)庫站刑,CMake會允許依賴圖中包含循環(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_link_libraries(main A)
復(fù)制代碼
  • 將若干庫鏈接到目標(biāo)庫文件。
  • 鏈接的順序應(yīng)當(dāng)符合gcc鏈接順序規(guī)則,被鏈接的庫放在依賴它的庫的后面摆尝,即如果上面的命令中温艇,lib1依賴于lib2,lib2又依賴于lib3堕汞,則在上面命令中必須嚴(yán)格按照lib1 lib2 lib3的順序排列勺爱,否則會報錯。

7讯检、常用命令-add_definitions

為當(dāng)前路徑以及子目錄的源文件加入由-D引入的define flag

add_definitions(-DF00 -DDEBUG ...)
復(fù)制代碼

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

8琐鲁、常用命令-add_subdirectory

用于添加子目錄的CMake源文件:

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

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

9、常用命令-file

文件操作命令:

# 將message寫入filename文件中投放,會覆蓋文件原有內(nèi)容
file(WRITE filename "message")
# 將message寫入filename文件中奈泪,會追加在文件末尾
file(APPEND filename "message")
# 從filename文件中讀取內(nèi)容并存儲到var變量中,如果指定了numBytes和offset灸芳,
# 則從offset處開始最多讀numBytes個字節(jié)段磨,另外如果指定了HEX參數(shù),則內(nèi)容會以十六進制形式存儲在var變量中
file(READ filename var [LIMIT numbytes] [OFFSET offset] [HEX])
# 重命名文件
file(RENAME <oldname> <newname>)
# 刪除文件耗绿,等于rm命令
file(REMOVE [file1 ...])
# 遞歸的執(zhí)行刪除文件命令苹支,等于rm -r
file(REMOVE_RECURSE [file1...])
# 根據(jù)指定的url下載文件
# timeout超時時間;下載的狀態(tài)會保存到status中误阻;下載日志會被保存到log债蜜;sum指定所下載文件預(yù)期的MD5值,如果指定會自動進行比對究反,
# 如果不一致寻定,則返回一個錯誤;SHOW_PROGRESS精耐,進度信息會以狀態(tài)信息的形式被打印出來
file(DOWNLOAD url file [TIMEOUT timeout] [STATUS status] [LOG log] [EXPECTED_MD5 sum] [SHOW_PROGRESS])
# 創(chuàng)建目錄
file(MAKE_DIRECTORY [dir1 dir2 ...])
# 會把path轉(zhuǎn)換為以unix的/開頭的cmake風(fēng)格路徑狼速,保存到result中
file(TO_CMAKE_PATH path result)
# 它會把cmake風(fēng)格的路徑轉(zhuǎn)換為本地路徑風(fēng)格:windows下用"\",而unix下用"/"
file(TO_NATIVE_PATH path result)
# 將會為所有匹配查詢表達式的文件生成一個文件list卦停,并將該list存儲進變量variable里向胡,如果一個表達式指定了RELATIVE,返回的結(jié)果
# 將會是相對于定路徑的相對路徑惊完,查詢表達式例子:*.cxx僵芹,*.vt?
# NOTE:按照官方文檔的說法,不建議使用file的GLOB指令來收集工程的源文件
file(GLOB variable [RELATIVE path] [globbing expressions]...)
復(fù)制代碼

使用這種方式來指定源文件的話小槐,如果后面項目需要增加源文件拇派,比如項目中原本有2個源文件a.c和b.c,后面新增一個c.c,如果我們直接增加c.c件豌,然后進行編譯是會報錯的疮方,因為CMakeLists文件沒有改動,所以cmake不會重新生成makefile文件茧彤,所以我們需要簡單的改動一下CMakeLists文件骡显,可以在CMakeLists文件中添加一個空格,然后再編譯棘街,它就會生成makefile文件蟆盐。

9承边、常用命令-set_directory_properties

設(shè)置某個路徑的一種屬性:

set_directory_properties(PROPERTIES prop1 value1 prop2 value2)
復(fù)制代碼

prop1遭殉,prop2代表屬性,取值為:

  • INCLUDE_DIRECTORIES
  • LINK_DIRECTORIES
  • INCLUDE_REGULAR_EXPRESSION
  • ADDITIONAL_MAKE_CLEAN_FILES

10博助、常用命令-set_property

在給定的作用域內(nèi)設(shè)置一個命名的屬性:

set_property(<GLOBAL |
            DIRECTORY [dir] |
            TARGET [target ...] |
            SOURCE [src1 ...] |
            TEST [test1 ...] |
            CACHE [entry1 ...]>
            [APPEND]
            PROPERTY <name> [value ...])
復(fù)制代碼

PROPERTY 參數(shù)是必須的险污。第一個參數(shù)決定了屬性可以影響的作用域:

  • GLOBAL:全局作用域
  • DIRECTORY:默認(rèn)當(dāng)前路徑,也可以用[dir]指定路徑富岳。
  • TARGET:目標(biāo)作用域蛔糯,可以是0個或多個已有目標(biāo)。
  • SOURCE:源文件作用域窖式,可以是0個或多個源文件蚁飒。
  • TEST:測試作用域,可以是0個或多個已有的測試萝喘。
  • CACHE:必須指定0個或多個cache中已有的條目淮逻。

11、多個源文件處理

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})
復(fù)制代碼

如果源文件很多爬早,把所有文件一個個加入很麻煩,可以使用aux_source_directory命令或file命令启妹,會查找指定目錄下的所有源文件筛严,然后將結(jié)果存進指定變量名。

12饶米、多目錄多源文件處理

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})
復(fù)制代碼
  • 主目錄中的CMakeLists.txt中添加add_subdirectory(child)命令桨啃,指明本項目包含一個子項目child。并在target_link_libraries指明本項目需要鏈接一個名為child的庫檬输。
  • 子目錄child中創(chuàng)建CMakeLists.txt优幸,這里child編譯為共享庫。

13褪猛、添加預(yù)編譯庫

1)Android6.0版本以前

假設(shè)我們本地項目引用了libimported-lib.so:

cmake_minimum_required(VERSION 3.4.1)
# 使用 IMPORTED 標(biāo)志告知 CMake 只希望將庫導(dǎo)入到項目中
# 如果是靜態(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)
復(fù)制代碼
  • 添加add_library命令碳却,第一個參數(shù)是模塊名队秩,第二個參數(shù)SHARED表示動態(tài)庫,STATIC表示靜態(tài)庫昼浦,第三個參數(shù)IMPORTED表示以導(dǎo)入的形式添加馍资。
  • 添加set_target_properties命令設(shè)置導(dǎo)入路徑屬性。
  • import-lib添加到target_link_libraries命令參數(shù)中关噪,表示native-lib需要鏈接imported-lib模塊

2)Android6.0版本以后

在Android6.0及以上版本鸟蟹,如果使用上節(jié)的方法添加預(yù)編譯動態(tài)庫的話,會有問題使兔,我們可以使用另外一種方式來配置:

# set命令定義一個變量
# CMAKE_C_FLAGS:c的參數(shù)建钥,會傳遞給編譯器
# 如果是c++文件,需要用CMAKE_CXX_FLAGS
# -L:庫的查找路徑
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -L[so所在目錄")
復(fù)制代碼

14虐沥、添加頭文件目錄

為了確保CMake可以在編譯時定位頭文件熊经,使用include_directories,相當(dāng)于g++選項中的-I參數(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)
復(fù)制代碼

15、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"
        }
    }
}
復(fù)制代碼

三槐壳、實操

官網(wǎng):www.fmod.com/ SDK下載頁面:www.fmod.com/download

需要先注冊登錄后,才能下載

1喜每、庫文件集成

在fmod官網(wǎng)下載好 fmodstudioapi20000android.tar.gz 后务唐,解壓,找到 api/core目錄灼卢,其中inc是fmod的頭文件绍哎,lib是fmod預(yù)編譯好的so和jar文件璧亮。

1)集成so與jar

image.png

2)集成.h頭文件

image.png

2携龟、CMakeLists.txt文件配置:

fmod提供的so文件屬于預(yù)編譯庫,需要在自己的工程中集成fmod并使用俄烁,大概可分為2步驟:

  1. 指定頭文件目錄涩咖。方便在native-lib.cpp中可以使用include <fmod.hpp>
  2. 指定預(yù)編譯庫目錄海诲。讓native-lib在編譯時,可以成功鏈接fmod檩互。
# 指定cmake最小支持版本
cmake_minimum_required(VERSION 3.4.1)

# 設(shè)置頭文件目錄
include_directories(${CMAKE_SOURCE_DIR}/inc)

# 設(shè)置第三方so庫路徑(android6.0以后需要這樣設(shè)置)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${CMAKE_SOURCE_DIR}/../jniLibs/${CMAKE_ANDROID_ARCH_ABI}")

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

# 查找系統(tǒng)庫,這里查找的是系統(tǒng)日志庫闸昨,并賦值給變量log-lib
find_library(
        log-lib
        log)

# 設(shè)置以來的庫(第一個參數(shù)必須為目標(biāo)模塊蚯斯,順序不能換)
target_link_libraries(
        native-lib
        fmod
        fmodL
        ${log-lib})
復(fù)制代碼

${CMAKE_SOURCE_DIR} 可以獲取到CMakeLists.txt文件當(dāng)前所在目錄路徑薄风。

3、build.gradle配置

因為該工具只在模擬器上運行拍嵌,所以只需要x86平臺的so庫文件遭赂,可以使用 abiFilters 進行過濾。

手機一般都是arm平臺横辆,可根據(jù)實際情況修改abiFilters撇他。

android {
    defaultConfig {
        ...
        externalNativeBuild {
            cmake {
                cppFlags ""
                abiFilters "x86" // 指定本地庫的cpu架構(gòu)
            }
        }
        ndk {
            abiFilters "x86" // 指定第三方庫的cpu架構(gòu)
        }
    }
    externalNativeBuild {
        cmake {
            path "src/main/cpp/CMakeLists.txt"
            version "3.10.2"
        }
    }
}
復(fù)制代碼

4、編寫native-lib.cpp

使用日志輸出fmod版本號:

#include <jni.h>
#include <string>
#include <android/log.h>
#include <fmod.hpp>

using namespace FMOD;

extern "C" JNIEXPORT jstring JNICALL
Java_com_lqr_cmakefmod_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject /* this */) {
    System *system;
    System_Create(&system);
    unsigned int version;
    system->getVersion(&version);
    __android_log_print(ANDROID_LOG_ERROR, "TEST", "FMOD Version: %08x", version);

    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}
復(fù)制代碼

最終狈蚤,在觸發(fā)stringFromJNI()方法后困肩,就可以在控制臺看到fmod版本號的輸出了。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末脆侮,一起剝皮案震驚了整個濱河市锌畸,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌他嚷,老刑警劉巖蹋绽,帶你破解...
    沈念sama閱讀 217,406評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件芭毙,死亡現(xiàn)場離奇詭異筋蓖,居然都是意外死亡,警方通過查閱死者的電腦和手機退敦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評論 3 393
  • 文/潘曉璐 我一進店門粘咖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人侈百,你說我怎么就攤上這事瓮下。” “怎么了钝域?”我有些...
    開封第一講書人閱讀 163,711評論 0 353
  • 文/不壞的土叔 我叫張陵讽坏,是天一觀的道長。 經(jīng)常有香客問我例证,道長路呜,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,380評論 1 293
  • 正文 為了忘掉前任织咧,我火速辦了婚禮胀葱,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘笙蒙。我一直安慰自己抵屿,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,432評論 6 392
  • 文/花漫 我一把揭開白布捅位。 她就那樣靜靜地躺著轧葛,像睡著了一般搂抒。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上尿扯,一...
    開封第一講書人閱讀 51,301評論 1 301
  • 那天燕耿,我揣著相機與錄音,去河邊找鬼姜胖。 笑死誉帅,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的右莱。 我是一名探鬼主播蚜锨,決...
    沈念sama閱讀 40,145評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼慢蜓!你這毒婦竟也來了亚再?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,008評論 0 276
  • 序言:老撾萬榮一對情侶失蹤晨抡,失蹤者是張志新(化名)和其女友劉穎氛悬,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體耘柱,經(jīng)...
    沈念sama閱讀 45,443評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡如捅,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,649評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了调煎。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片镜遣。...
    茶點故事閱讀 39,795評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖士袄,靈堂內(nèi)的尸體忽然破棺而出悲关,到底是詐尸還是另有隱情,我是刑警寧澤娄柳,帶...
    沈念sama閱讀 35,501評論 5 345
  • 正文 年R本政府宣布寓辱,位于F島的核電站,受9級特大地震影響赤拒,放射性物質(zhì)發(fā)生泄漏秫筏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,119評論 3 328
  • 文/蒙蒙 一需了、第九天 我趴在偏房一處隱蔽的房頂上張望跳昼。 院中可真熱鬧,春花似錦肋乍、人聲如沸鹅颊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽堪伍。三九已至锚烦,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間帝雇,已是汗流浹背涮俄。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留尸闸,地道東北人彻亲。 一個月前我還...
    沈念sama閱讀 47,899評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像吮廉,于是被迫代替她去往敵國和親苞尝。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,724評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 概念 在Android Studio 2.2以上宦芦,構(gòu)建原生庫的默認(rèn)工具是CMake宙址。CMake是一個跨平臺的構(gòu)建工...
    Lucky胡閱讀 394評論 0 0
  • 一 CMake是誰 在版本2.2及以上,構(gòu)建原生庫的默認(rèn)工具變成了CMake.CMake是一個跨平臺的構(gòu)建工具调卑,能...
    叨碼閱讀 909評論 0 1
  • 什么是CMake .在Android studio2.2及以上抡砂,構(gòu)建原生庫的默認(rèn)工具是CMake. .CMake是...
    佼佼者Mr閱讀 738評論 0 0
  • 使用AndroidStudio3.4創(chuàng)建一個C/C++Support的項目,默認(rèn)在app/src/main目錄下會...
    劉小廚閱讀 863評論 0 1
  • 什么是CMake CMake是一個跨平臺的構(gòu)建工具,可以用簡單的語句來描述所有平臺的安裝(編譯過程)恬涧。能夠輸出各種...
    那就走吧玉二閱讀 569評論 0 1