1.CMakeLists.txt配置解析
# 最低支持的版本,注意:这里并不能代表最终的版本,最终版本在app.build.gradle中设置的
cmake_minimum_required(VERSION 3.10.2)
# 当前工程名,以前的旧版本是没有设置的,这个可以设置也可以不设置
project("mscmake")
#批量导入源文件 源文件跟CMakeLists 在同一个目录的情况
file(GLOB SOURCE *.cpp *.c)
# 批量导入 cpp c源文件
file(GLOB SOURCE ${CMAKE_SOURCE_DIR}/cpp/*.cpp ${CMAKE_SOURCE_DIR}/cpp/*.c)
# 添加一个库(动态库SHARED,静态库STATIC)
add_library(native-lib # 库的名字 ---> libnative-lib.so
SHARED
# cpp的源文件:把cpp源文件编译成 libnative-lib.so 库
${SOURCE})
# 第一步:导入fmod头文件
include_directories("${CMAKE_SOURCE_DIR}/cpp/inc")
# 第二步:导入库文件 (方式一)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${CMAKE_SOURCE_DIR}/jniLibs/${CMAKE_ANDROID_ARCH_ABI}")
message(status "cmake日志-----------------------${CMAKE_SOURCE_DIR}" )
# 第三步链接到总库中去 # native-lib是我们的总库
target_link_libraries(
native-lib # 被链接的总库
log # 自动寻找 # 具体的库 链接到 libnative-lib.so里面去
fmod # 具体的库 链接到 libnative-lib.so里面去
fmodL # 具体的库 链接到 libnative-lib.so里面去
)
#另一种方式导入库的方式 通过条件判断 决定加载动态库还是静态库
# 另外一种导入的方式
include_directories("${CMAKE_SOURCE_DIR}/cpp/inc")
set(isSTATIC ON)
if(${isSTATIC})
# 导入静态库
add_library(postndk STATIC IMPORTED)
# 开始真正导入
set_target_properties(postndk PROPERTIES IMPORTED_LOCATION
${CMAKE_SOURCE_DIR}/cpp/libpostndk.a)
message("isSTATIC == static")
else(${isSTATIC})
# 导入动态库
add_library(postndk SHARED IMPORTED)
# 动态库 System.loadLibrary("postndk"); // 如果是动态库,这里需要加载,否则注释
set_target_properties(postndk PROPERTIES
IMPORTED_LOCATION
${CMAKE_SOURCE_DIR}/jniLibs/${CMAKE_ANDROID_ARCH_ABI}/libpostndk.so)
message("isSTATIC == shared")
endif(${isSTATIC})
2.动态库和静态库的区别
动态库.so后缀名,不会拷贝源代码,在运行的时候才会进行地址回填,所以so库必须能找到才行。
静态库.a后缀名,会直接将源码代码拷贝到总的so库里边,apk安装包里边看不到静态库。
3.Cmake工具介绍
CMake是一个跨平台的构建工具,可以用简单的语句来描述所有平台的安装(编译过程)。 能够输出各种各样的makefile或者project文件。CMake并不直接构建出最终的软件, 而是产生其他工具的脚本(如makefile),然后再依据这个工具的构建方式使用。
CMake是一个比make更高级的编译配置工具,它可以根据不同的平台、不同的编译器, 生成相应的makefile或vcproj项目,从而达到跨平台的目的。
Android Studio利用CMake生成的是ninja。ninja是一个小型的关注速度的构建系统。
CMake其实是一个跨平台的支持产出各种不同的构建脚本的一个工具。
4.Cmake语法解析
通过CMakeLists.txt学习cmake语法非常方便
# log 信息输出的查看
#Build --> Refresh Linked_C++_Projects 查看cmake_server_log.txt 就能看到cmake输出的日志了
#.cxx/cmake/debug/armeabi-v7a/cmake_server_log.txt (cmake_server_log.txt路径)
#[[
(无) = 重要消息;
STATUS = 非重要消息;
WARNING = CMake 警告, 会继续执行;
AUTHOR_WARNING = CMake 警告 (dev), 会继续执行;
SEND_ERROR = CMake 错误, 继续执行,但是会跳过生成的步骤;
FATAL_ERROR = CMake 错误, 终止所有处理过程;
]]
#日志输出
message(STATUS "这是cmake日志 STATUS 非重要消息 ")
message(WARNING "这是cmake日志 WARNING CMake 警告, 会继续执行 ")
message(AUTHOR_WARNING "这是cmake日志 AUTHOR_WARNING CMake 警告 (dev), 会继续执行 ")
#message(SEND_ERROR "这是cmake日志 SEND_ERROR CMake 错误, 继续执行,但是会跳过生成的步骤 ")
#message(FATAL_ERROR "这是cmake日志 FATAL_ERROR CMake 错误, 终止所有处理过程 ")
#CMake变量
# 声明变量:set(变量名 变量值)
set(number 999)
# CMake中所有变量都是string类型。可以使用set()和unset()命令来声明或移除一个变量
# 引用变量:message 命令用来打印
message("number = ${number}")
# 移除变量
unset(number)
message("my_number= ${number}") # 会取不到值,因为被移除了
# CMake列表(lists)
# 声明列表:set(列表名 值1 值2 ... 值N) 或 set(列表名 "值1;值2;...;值N")
set(list_var 1 2 3 4 5) # 字符串列表呢? CMake中所有变量都是string类型
message("list_var = ${list_var}")
# CMake流程控制-条件命令
# true(1,ON,YES,TRUE,Y,非0的值) === true
# false(0,OFF,NO,FALSE,N,IGNORE,NOTFOUND) === false
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 可以不加
# CMake流程控制-循环命令
# NOT! a STREQUAL "xxx" (a等不等于xxx,不等于)
set(a "")
while (NOT a STREQUAL "xxx")
set(a "${a}x")
message(">>>>>>a = ${a}")
endwhile ()
#[[ 注意:
break()命令可以跳出整个循环 Java有的,他也有
continue()可以继续当前循环 Java有的,他也有
]]
foreach (item 1 2 3)
message("foreach----1item = ${item}")
endforeach (item) # 结束for
# cmake RANGE
foreach (item RANGE 2) # RANGE 默认从0开始, 所以是:0 1 2
message("RANGE--------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("item IN LISTS-------》4item = ${item}")
endforeach (item)
# CMake自定义函数 Shell的函数很类似
#[[
ARGC:表示传入参数的个数
ARGV0:表示第一个参数,ARGV1、ARGV2以此类推即可
ARGV:表示所有参数
]]
function(cmake_method n1 n2 n3)
message("call cmake_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(cmake_method)
num_method(11 110 1110) # 调用cmake_method函数