# 最低支持的版本,注意:这里并不能代表最终的版本,最终版本在app.build.gradle中设置的
cmake_minimum_required(VERSION 3.10.2)
build.gradle 中是cmake 的版本
# 当前工程名,以前的旧版本,是没有设置的,这个可以设置,也可以不设置
project("ndk28_cmake")
# 批量导入 cpp c源文件
# file 可以定义一个变量 SOURCE, GLOB(使用GLOB从源树中收集源文件列表,就可以开心的 *.cpp *.c *.h)
# https://www.imooc.com/wenda/detail/576408
file(GLOB SOURCE *.cpp *.c *.h *.hpp)
# 添加一个库(动态库SHARED,静态库STATIC)
add_library(native-lib # 库的名字 ---> libnative-lib.so
SHARED # 动态库
# cpp的源文件:把cpp源文件编译成 libnative-lib.so 库
${SOURCE}
)
# 查找一个 NDK工具中的 动态库(liblog.so)
# 思考:我如何知道 哪些库是可以写的,你怎么知道些一个log就可以?
# 答:请查看 D:\Android\Sdk\ndk\21.4.7075529\build\cmake\system_libs.cmake
# 思考:D:\Android\Sdk\ndk\21.0.6113669\toolchains\llvm\prebuilt\windows-x86_64\sysroot\usr\lib\arm-linux-androideabi\16\liblog.so
# 答:你怎么知道是在 21.4.7075529?,arm-linux-androideabi?,16?
# 答:?1(因为local.properties知道了NDK版本,或者是你当前的NDK版本)
# 答:?2(因为我的手机是arm32的 所以 == arm-linux-androideabi 而且还我运行过)
# 答:?3(因为 minSdkVersion 16)
find_library(log-lib
log )
# native-lib是我们的总库,也就是我们在 apk/lib/libnative-lib.so
# 然后 把log库链接到 总库中去,总库的cpp代码就可以使用 android/log.h的库实现代码了
target_link_libraries(native-lib # 被链接的总库
${log-lib} # 链接的具体库
# getndk
)
# TODO CMake变量
# 声明变量:set(变量名 变量值)
set(var 666)
# 引用变量:message 命令用来打印
message("var = ${var}")
# CMake中所有变量都是string类型。可以使用set()和unset()命令来声明或移除一个变量
# 移除变量
unset(var)
message("my_var = ${var}") # 会取不到值,因为被移除了
# TODO CMake列表(lists)
# 声明列表:set(列表名 值1 值2 ... 值N) 或 set(列表名 "值1;值2;...;值N")
set(list_var 1 2 3 4 5) # 字符串列表呢? CMake中所有变量都是string类型
# 或者
set(list_var2 "1;2;3;4;5") # 字符串列表呢? CMake中所有变量都是string类型
message("list_var = ${list_var}")
message("list_var2 = ${list_var2}")
# TODO CMake流程控制-条件命令
# true(1,ON,YES,TRUE,Y,非0的值)
# false(0,OFF,NO,FALSE,N,IGNORE,NOTFOUND)
set(if_tap OFF) # 定义一个变量if_tap,值为false
set(elseif_tap ON) # 定义一个变量elseif_tap,值为ture
if(${if_tap})
message("if")
elseif(${elseif_tap})
message("elseif")
else(${if_tap}) # 可以不加入 ${if_tap}
message("else")
# endif(${if_tap}) # 结束if
endif() # 结束if 可以不加
# 注意:elseif和else部分是可选的,也可以有多个elseif部分,缩进和空格对语句解析没有影响
# TODO CMake流程控制-循环命令
set(a "")
# a STREQUAL "xxx"(a等不等xxx,不等于)
# NOT == !
while(NOT a STREQUAL "xxx")
set(a "${a}x")
message(">>>>>>a = ${a}")
endwhile()
#[[ 注意:
break()命令可以跳出整个循环
continue()可以继续当前循环
]]
foreach(item 1 2 3)
message("1item = ${item}")
endforeach(item) # 结束for
foreach(item RANGE 2) # RANGE 默认从0开始, 所以是:0 1 2
message("2item = ${item}")
endforeach(item)
foreach(item RANGE 1 6 2) # 1 3 5 每次跳级2
message("3item = ${item}")
endforeach(item)
set(list_va3 1 2 3) # 列表
# foreach(item IN LISTS ${list_va3}) 没有报错,没有循环
foreach(item IN LISTS list_va3)
message("4item = ${item}")
endforeach(item)
# TODO CMake自定义函数 Shell的函数很类似
#[[
ARGC:表示传入参数的个数
ARGV0:表示第一个参数,ARGV1、ARGV2以此类推即可
ARGV:表示所有参数
]]
function(num_method n1 n2 n3)
message("call num_method method")
message("n1 = ${n1}")
message("n2 = ${n2}")
message("n3 = ${n3}")
message("ARGC = ${ARGC}")
message("arg1 = ${ARGV0} arg2 = ${ARGV1} arg3 = ${ARGV2}")
message("all args = ${ARGV}")
endfunction(num_method)
num_method(1 2 3) # 调用num_method函数
# 静态库和动态库本质
// AS gradle:3.x 旧版本没有任何问题
// 新版本的才有 gradle:4.2.0,自动去寻找jniLibs文件夹 处理和优化 ,旧版本没有任何问题
// 编译报错: If you are using jniLibs and CMake IMPORTED targets, see
// 解决方案如下:
// https://blog.csdn.net/qq_33750826/article/details/107518573
// 在模块的build.gradle中设置第三方库的加载路径:
// 在gradle plugln 4.0开始,无需指定第三库加载路径,gradle自动会帮助我们寻找,否则会出现以下错
sourceSets.main.jniLibs.srcDirs = ['libs']
# 批量导入 cpp c源文件
file(GLOB SOURCE ${CMAKE_SOURCE_DIR}/cpp/*.cpp ${CMAKE_SOURCE_DIR}/cpp/*.c)
# TODO 方式一:推荐的方式
#[[
# 第一步:导入fmod头文件
include_directories("${CMAKE_SOURCE_DIR}/cpp/inc")
# 第二步:导入库文件 (方式一)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${CMAKE_SOURCE_DIR}/jniLibsaaa/${CMAKE_ANDROID_ARCH_ABI}")
# 第三步链接到总库中去
target_link_libraries( # native-lib是我们的总库
native-lib # 被链接的总库
log # 自动寻找 # 具体的库 链接到 libnative-lib.so里面去
fmod # 具体的库 链接到 libnative-lib.so里面去
fmodL # 具体的库 链接到 libnative-lib.so里面去
)
]]
# TODO 方式二:以前更多使用的方式,老程序员使用的方式
#[[
# 第一步:导入fmod头文件
include_directories("${CMAKE_SOURCE_DIR}/cpp/inc")
# 第二步:导入库文件 (方式二)
add_library(fmod SHARED IMPORTED)
set_target_properties(fmod PROPERTIES
IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/jniLibsaaa/${CMAKE_ANDROID_ARCH_ABI}/libfmod.so)
add_library(fmodL SHARED IMPORTED)
set_target_properties(fmodL PROPERTIES
IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/jniLibsaaa/${CMAKE_ANDROID_ARCH_ABI}/libfmodL.so)
# 第三步链接到总库中去
target_link_libraries( # native-lib是我们的总库
native-lib # 被链接的总库
log # 自动寻找 # 具体的库 链接到 libnative-lib.so里面去
fmod # 具体的库 链接到 libnative-lib.so里面去
fmodL # 具体的库 链接到 libnative-lib.so里面去
)
]]
## OFF=0=false ON=1=true
# set(isSTATIC OFF)
set(isSTATIC ON)
if(${isSTATIC})
# 导入静态库
add_library(getndk STATIC IMPORTED)
# 开始真正导入 静态库 System.loadLibrary("getndk"); // 如果是动态库,这里需要加载,否则注释
set_target_properties(getndk PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/cpp/libgetndk.a)
message("isSTATIC == static")
else(${isSTATIC})
# 导入动态库
add_library(getndk SHARED IMPORTED)
# 开始真正导入 动态库 System.loadLibrary("getndk"); // 如果是动态库,这里需要加载,否则注释
set_target_properties(getndk PROPERTIES
IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/jniLibsaaa/${CMAKE_ANDROID_ARCH_ABI}/libgetndk.so)
message("isSTATIC == shared")
endif(${isSTATIC})
#引入get子目录下的CMakeLists.txt
add_subdirectory(${CMAKE_SOURCE_DIR}/cpp/libget)
#引入count子目录下的CMakeLists.txt
add_subdirectory(${CMAKE_SOURCE_DIR}/cpp/libcount)
target_link_libraries( # native-lib是我们的总库
native-lib # 被链接的总库
log # 自动寻找 # 具体的库 链接到 libnative-lib.so里面去
get # 具体的库 链接到 libnative-lib.so里面去
count # 具体的库 链接到 libnative-lib.so里面去
)