ndk与jni开发(3)CMakeList.txt文件详解

原文地址:http://www.javayihao.top/detail/176

 

1.概述

前面两篇文章介绍了ndk与jni开发过程,在使用CMake方式进行ndk与jni开发的过程中,主要有个文件是CMakeLists.txt。使用AndroidStudio3.4创建一个C/C++Support的项目,默认会在app/src/main目录下会生成cpp目录,里面包含CMakeLists.txt和native-lib.cpp。

#指定Cmake最低支持的版本
cmake_minimum_required(VERSION 3.4.1)
#查找当前目录所有源文件 并将源文件名称列表保存到 DIR_SRCS变量中
#不能查找子目录
aux_source_directory(. DIR_SRCS)

add_library(
        native-lib
        SHARED
        native-lib.cpp)
#查找系统库,这里是查找系统日志库,并赋值给变量 log-lib
find_library(
        log-lib
        log)

#设置依赖库(第一个参数必须是目标模块 顺序不能换)
target_link_libraries(
        native-lib
        ${log-lib})

2.常用命令add_library

 

     添加一个库

  • 添加一个库文件,名为<name>
  • 指定STATIC,SHARED,MODULE参数来指定库的类型。STATIC:静态库;SHARED:动态库;MODULE:在使用的dyld的系统有效,若不支持dyld,等同于SHARED;
  • EXCLUDE_FORM_ALL:表示该库不会被默认构建。
  • source1 source2 ··· sourceN:用来指定库的源文件。
  • add_library(<name> [STATIC | SHARED | MOUDLE]
     [EXCLUDE_FORM_ALL] source1 source2 ··· sourceN )

     

    添加预编译库

  • 添加一个已存在的预编译库,名为<name>。
  • 一般配合set_target_properties使用。
  •  

    add_library(<name> <STATIC | SHARED | MOUDLE|UNKNOW> IMPORTED)
    #比如
    add_library(test SHARED IMPORTED)
    set_target_properties(
    test #指明目标库名
    PROPERTIES IMPORTED_LOCATION #指明要设置的参数
    库路径/${ANDROID_ABI}/libtext.so  #导入库的路径
    )

3.常用命令set()

#设置可执行文件的输出路径(EXECUTABLE_OUTPUT_PATH是全局变量)
set(EXECUTABLE_OUTPUT_PATH [output_path])

#设置库文件的输出路径(LIBRARY_OUTPUT_PATH是全局变量)
set(LIBRARY_OUTPUT_PATH [output_path])

#设置c++编译参数(CMAKE_CXX_FLAGS是全局变量)
set(CMAKE_CXX_FLAGS "-Wall std=c++11")

#设置源文件集合(SOURCE_FILES是本地变量即自定义变量)
set(SOURCE_FILES main.cpp test.cpp ... )

4.常用命令include_directories

设置头文件目录

相当于g++选项中的-参数

#可以用相对或绝对路径,也可以用自定义的变量
include_directories(./include ${MY_INCLUDE})

 

5.常用命令add_executable

#添加可执行文件
add_executable(<name> ${SRC_LIST})

6. 常用命令target_link_libraries

target_link_libraries(<name> lib1 lib2 lib3)

将若干库连接到目标库文件

  • 连接的顺序应当符合gcc连接顺序规则,被链接的库放在依赖它的库的后面,即如果上面的命令中,lib1依赖于lib2,lib2又依赖于lib3,则在上面命令中必须严格按照 lib1 lib2 lib3的顺序排列,否则会报错
#如果出现互相依赖的静态库,CMake会允许依赖图中包含循环依赖,如:
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)

7. 常用命令add_definitions

为当前路径以及子目录的源文件加入由-D引入的define flag

 

add_definitions(-DFOO -DDEBUG ...)

8. 常用命令add_subdirectory

如果当前目录下还有子目录时可以使用add_subdirectory,子目录中也需要包含有CMakeLists.txt.

# sub_dir 指定包含CMakeLists.txt和源码文件的子目录位置
# binary_dir 是输出路径 一般可以不指定
add_subdirectory(sub_dir [binary_dir])

9. 常用命令文件操作命令

#将message写入filename文件中,会覆盖文件原有内容
file(WRITE filename "message")

#将message写入filename文件中,会追加在文件末尾
file(APPEND filename "message")

#从filename文件中读取内容并存储到var变量中,如果指定了numBytes和offset,
#则从offset处开始最多读numBytes个字节,另外如果指定了HEX参数,
#则内容会以十六进制形式存储在var变量中
file(REDA filename var [LIMIT numBytes] [OFFSET offset] [HEX])

#重命名文件
file(RENAME <oldname> <newname>)

#删除文件,等于rm命令
file(REMOVE [file1 ...])

#递归的执行删除文件命令,等于rm -r
file(REMOVE_RECURSE [file1 ...])

#根据指定的url下载文件
#timeout超时时间;下载的状态会保存到status中;下载日志会保存到log;
#sum指定所下载文件预期的MD5值,如果指定会自动进行比对,
#如果不一致,则返回一个错误;SHOW_PROGRESS,进度信息会以状态信息的形式被打印出来。
file(DOWNLOAD url file
        [TIMEOUT timeout]
        [STATUS status]
        [LOG log]
        [EXPECTED_MD5 sun]
        [SHOW_PROGRESS])

#创建目录
file(MAKE_DIRECTORY [dir1 dir2 ...])

#会把path转换为以unix的开头的cmake风格路径,保存在result中
file(TO_CMAKE_PATH path result)

#它会把cmake风格的路径转换为本地路径风格:windows下用"\",而unix下用"/"
file(TO_NATIVE_PATH path result)

#将会为所有匹配查询表达式的文件生成一个文件list,并将该list存储进变variable里,如果一个表达式指定了RELATIVE,返回的结果将会是相对于给定路径的相对路径,查询表达式例子:*.cxx,*.vt?
#NOTE:按照官方文档的说法,不建议使用file的GLOB指令来收集工程的源文件
file(GLOB variable [RELATIVE path] [globbing expressions] ...)

 

10. 常用命令set_directory_properties

 

  • 设置某个路径的一种属性
  • prop1,prop2代表属性,取值为:
    INCLUDE_DIRECTORIES
    LINK_DIRECTORIES
    INALUDE_REGULAR_EXPRESSION
    ADDITIONAL_MAKE_CLEAN_FILES
set_directory_properties(PROPERTIES prop1 value1 prop2 values2)

11.常用命令 set_property

在给定的作用域内设置一个命名的属性
PROPERTY参数是必须的
第一个参数决定了属性可以影响的作用域:
set_property(<GLOBAL |  #全局作用域
        DIRECTORY [dir] | #默认当前路径,也可以用[dir]指定路径
        TARGET [TARGET ...] | # 目标作用域,可以是0个或多个已有目标
        SOURCE [src1 ...] | # 源文件作用域,可以是0个或多个源文件
        TEST [test1 ...] # 测试作用域,可以是0个或多个已有的测试
        CACHE [entry1 ...] # 必须指定0
        >
        [APPEND]
        PROPERTY <name> [value ...])

12.多个源文件处理

如果源文件很多,把所有文件一个个加入很麻烦,可以使aux_source_directory命令或file命令,会查找指定目录下的所有源文件,然后将结果存进指定变量名查找当前目录所有源文件 并将源文件名称列表保存到 DIR_SRCS变量中不能查找子目录
cmake_minimum_required(VERSION 3.4.1)
#查找当前目录所有源文件 并将源文件名称列表保存到 DIR_SRCS变量中
#不能查找子目录
aux_source_directory(. DIR_SRCS)
#也可以使用
#file(GLOB DIR_SRCS *.c *.cpp)
add_library(
        native-lib
        SHARED
        ${DIR_SRCS})

13.多目录多源文件处理

  • 主目录中的CMakeLists.txt中添加add_subdirectory(child)命令,指明本项目包含一个子项目child。并在target_link_libraries指明本项目需要连接一个名为child的库。
  • 子目录child中创建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}
)

 

14.添加预编译库

Android6.0版本以前

  • 假如我们本地项目引用了libimported-lib.so。
  • 添加add_library命令,第一个是模块名,第二个参数SHARED表示动态库,STATIC表示静态库,第三个参数IMPORTED表示以导入的形式添加。
  • 添加set_target_properties命令设置导入路径属性。
  • 将imported-lib添加到target_link_libraries命令参数中,表示native-lib需要链接imported-lib模块。
 
cmake_minimum_required(VERSION 3.4.1)
#使用 IMPORTED 标志告知 CMake 只希望将库导入到项目中
# 如果是静态库 则将shared改为static
add_library(
        imported-lib
        SHARED
        IMPORTED )
#参数分别为:库、属性、导入地址、库所在地址
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)

 

Android6.0及以上版本

  • 在Android6.0及以上版本,如果使用上面的方法添加预编译动态库的话,会有问题,我们可以使用另外一种方式来配置。
# set命令定义一个变量
# CMAKE_C_FLAGS:c的参数,会传递给编译器
#如果是c++文件,需要用CMAKE_CXX_FLAGS
# -L :库的查找路径
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -L[SO所在目录]")

15.添加头文件目录

cmake_minimum_required(VERSION 3.4.1)
#设置头文件目录
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)

16.Build.gradle配置

还可以在gradle中使用arguments设置一些配置
android {
    defaultConfig {
        externalNativeBuild {
            cmake {
                //使用的编译器clang/gcc
                //cmake默认就是gnustl_static
                arguments "-DANDROID_TOOLCHAIN=CLANG","DANDROID_STL=gnustl_static"
                //指定cflags和cppflags,效果和cmakelist使用一样
                cFlags""
                cppFlags ""
                //指定需要编译的cpu架构
                abiFilters "armeabi-v7a"
            }
        }
    }
    externalNativeBuild {
        cmake {
            //指定CMakeLists.txt文件相对当前Build.gradle的路径
            path "src/main/cpp/CMakeLists.txt"
            version "3.10.2"
        }
    }
}

 

参考地址:https://www.jianshu.com/p/50f504118f9b

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序三两行

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值