9、Cmakelists使用小记

前言:最近安卓上面集成ffmpeg库,需要使用CMakeLists,之前VSCode中写过,时间有点长,忘记了,现记录下。

一、简介

cmake 是一个跨平台、开源的构建系统。它是一个集软件构建、测试、打包于一身的软件。它使用与平台和编译器独立的配置文件来对软件编译过程进行控制。

二、语法介绍

2.1 基本变量

CMAKE_SOURCE_DIR:CMakeLists.txt所在目录
比如:src/main/cpp/CMakeLists.txt


PROJECT_SOURCE_DIR:工程源文件目录,
比如..app/src/main/cpp


CMAKE_CXX_FLAGS: 用户配置的编译器参数


ANDROID_ABI:对应的ABI架构,
比如arm64-v8a文件夹下该值为arm64-v8a


PROJECT_SOURCE_DIR:工程根目录


CMAKE_CURRENT_SOURCE_DIR:当前处理的CMakeLists.txt文件所在路径


2.2 set 

设置正常变量、缓存变量或环境变量的值

set(arg value)
自定义变量,arg是变量名,value是变量值,
引用变量方式${arg}

2.3 message 

message(STATUS  "打印的数据")
打印信息,存在于build_output.txt日志文件中,
一般测试变量、路径是否正确,类似于Java代码中的print方法

2.4 add_library、set_target_properties

用法1

原型:add_library(< name> [STATIC | SHARED | MODULE]
[EXCLUDE_FROM_ALL]
[source1] [source2 …])
参数:
 name:被构建库目标名称
 [STATIC | SHARED ..:被构建库的类型,STATIC为静态库,生成的库 以libname.a形式存在,SHARED 为动态库,生成的库以libname.so形式存在;
 EXCLUDE_FROM_ALL:对应的一些属性会在目标被创建时被设置;
 [source1] [source2 ...]:指定源文件,多个文件由一个空格隔开;
作用:添加一个库
实例: add_library(LameMp3 SHARED src/main/cpp/LameMp3.c ${SRC_LIST})
用法2

原型:add_library(< name> <SHARED|STATIC|MODULE|OBJECT|UNKNOWN> IMPORTED
[GLOBAL])
参数:
 name:导入已知库的名称;
 SHARED|STATIC|IMPORTED..:通常为SHARED IMPORTED;
作用:导入一个已经存在的库。注:导入库一般配合set_target_properties使用
实例: add_library(libswscale-4 SHARED IMPORTED )
find_library
原型:find_library (<VAR> name1 [path1 path2 …])
参数:
 name1 :
作用:在path1查找相关库,并将其路径保存到指定变量name中
实例:find_library( log-lib log )

原型:set_target_properties(target1 target2 …
PROPERTIES prop1 value1
prop2 value2 …)
参数:
 target1 target2 ...:目标名称;
 prop1 prop2 ...:代表属性,取值为INCLUDE_DIRECTORIES、IMPORTED_LOCATION、LINK_DIRECTORIES等;
 value1 value2 ...:被设置的属性值;
作用:设置目标属性值
实例:set_target_properties(libavcodec-57 PROPERTIES IMPORTED_LOCATION "${libs}/${ANDROID_ABI}/libavcodec-57.so")

add_library
1、添加源代码生成.a或.so库(注意此处会生成新的库文件)
add_library(HELLO [STATIC/SHARED] hello.cpp) ,
若 [STATIC/SHARED]不填写,据测试默认为STATIC

2、添加已有的或者第三方提供的.so或.a库(注意此处是已有的库文件)
add_library(faac [STATIC/SHARED] IMPORTED) ,IMPORTED告知CMake:
faac是第三方导入的库,按路径去找,
这个功能会和set_target_properties()一起使用

set_target_properties()
设置目标属性如:
1.指定导入库路径
set_target_properties(
HELLO
PROPERTIES IMPORTED_LOCATION  //CMake中的关键字
import-lib/src/${ANDROID_ABI}/libHELLO.so//指定你要导入库的路径.
)
2.指定生成的库名称为hell0z注意生成的为libhell0z.so
set_target_properties(
HELLO PROPERTIES OUTPUT_NAME "hell0"
)

2.5  include_directories

原型:include_directories([AFTER|BEFORE] [SYSTEM] dir1 [dir2 …])
参数:
 AFTER|BEFORE:指定源文件目录后,通常会被附加到编译的当前目录列表中,但也可以通过AFTER或BEFORE来改变这种行为方式;
 SYSTEM:如果给出SYSTEM选项,编译器将被告知该目录是系统包含目录。
 dir1:源文件目录路径,可多个,用一个空格隔开;
作用:导入给定源文件目录
实例:include_directories(src/main/cpp/lame)

这个命令不建议使用了,但是在我们的项目中顶级目录并没有定义任何 target,因此也没有想到更好的办法。

include_directories(includeDir1 includeDir2...)
指定原生或第三方库的头文件,为了CMake在编译阶段定位我们的头文件

2.6  target_link_libraries

原型:target_link_libraries(< target> … < item>… …)
参数:
 target:目标库
 item:被连接的库
作用:将若干库链接到目标库文件,需要注意的是链接的顺序应该符合gcc链接的顺序规则,即被链接的库放在依赖它的库的后面,比如lib1依赖于lib2,lib2依赖于lib3,那么target_link_libraries(name lib1 lib2 lib3)。
实例:target_link_libraries(LameMp3 ${log-lib} )

如果 target 是一个 library,该命令可以用来指定依赖本仓库的 target 还需要链接另外的仓库,用于解决循环依赖。

target_link_libraries(mylib INTERFACE anotherlib)

如果 target 是可执行文件,则该命令用于指定其需要链接的库。

list(APPEND EXTRA_LIBS gcov mylib)
target_link_libraries(mymain ${EXTRA_LIBS})
target_link_libraries(obj lib1 lib2 lib3...)
将预构建或第三方库 lib1 lib2 lib3链接到obj中,对应预处理-编译=汇编-链接过程中的链接阶段,
那么obj中就可以正常调用库里的函数,obj即可以是可执行文件也可以是库

2.7 target_link_directories

指定链接路径,该命令在3.12以下版本没有,笔者在项目中使用如下命令设置库的路径,其实更好的方法是用find_library.

# bad way
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${CMAKE_CURRENT_SOURCE_DIR}/../dependentLibs"
# good way
find_library(mylib ../dependentLibs)

 2.8 file

file的用法很多,这里仅说明如何使用它来查找C文件

file(GLOB_RECURSE SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.c")

2.9 add_subdirectory

添加一个子目录到构建,该目录下必须有CMakeLists.txt文件

三、实例

#这个没什么可说的,就是指定cmake构建的最小版本号,
#因为随着版本更新有些语法、命令可能变了,所以这里需要设置下版本
cmake_minimum_required(VERSION 3.4.1)

#设置项目的名称,这个是可选的,
#如果设置了,会自动给你定义两个变量:demo_SOURCE_DIR,demo_BINARY_DIR。其中demo是你设置的#peoject名
#不过不指定的话默认有PROJECT_SOURCE__DIR ,PROJECT_BINARY_DIR,
#分别代表项目的源文件目录,项目编译后生成的二进制目录。
project("demo")

set(CMAKE_VERBOSE_MAKEFILE on)
# 设置so输出路径
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI})
# 赋值变量libs 
#第一个参数:libs是变量名,第二个是变量值
set(libs "${CMAKE_SOURCE_DIR}/src/main/jniLibs")
# 导入ffmpeg相关头文件
include_directories(${CMAKE_SOURCE_DIR}/src/main/cpp/include)

#-----------------------------导入ffmpeg库--------------------------------------
add_library(libavcodec-57 SHARED IMPORTED )
set_target_properties(libavcodec-57 PROPERTIES
    IMPORTED_LOCATION "${libs}/${ANDROID_ABI}/libavcodec-57.so")

add_library(libavdevice-57 SHARED IMPORTED )
set_target_properties(libavdevice-57 PROPERTIES
    IMPORTED_LOCATION "${libs}/${ANDROID_ABI}/libavdevice-57.so")

add_library(libavfilter-6 SHARED IMPORTED )
set_target_properties(libavfilter-6 PROPERTIES
    IMPORTED_LOCATION "${libs}/${ANDROID_ABI}/libavfilter-6.so")

add_library(libavformat-57 SHARED IMPORTED )
set_target_properties(libavformat-57 PROPERTIES
    IMPORTED_LOCATION "${libs}/${ANDROID_ABI}/libavformat-57.so")

add_library(libavutil-55 SHARED IMPORTED )
set_target_properties(libavutil-55 PROPERTIES
    IMPORTED_LOCATION "${libs}/${ANDROID_ABI}/libavutil-55.so")

add_library(libpostproc-54 SHARED IMPORTED )
set_target_properties(libpostproc-54 PROPERTIES
    IMPORTED_LOCATION "${libs}/${ANDROID_ABI}/libpostproc-54.so")

add_library(libswresample-2 SHARED IMPORTED )
set_target_properties(libswresample-2 PROPERTIES
    IMPORTED_LOCATION "${libs}/${ANDROID_ABI}/libswresample-2.so")

add_library(libswscale-4 SHARED IMPORTED )
set_target_properties(libswscale-4 PROPERTIES
    IMPORTED_LOCATION "${libs}/${ANDROID_ABI}/libswscale-4.so")

#------------------------------配置、链接动态库--------------------------------
#设置变量CMAKE_CXX_FLAGG修改编译选项[只针对c和c++编译器]
#这里使cmkae编译带有c++11特性,其中-std用于指定c/c++标准;
# -fexceptions用于开启编译器异常捕获机制;-frtti用于支持RTTI,配合异常处理
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11 -fexceptions -frtti")
#指定自定义构建库信息
add_library( # 库名称
             decstream

             # 库类型为动态库
             SHARED

             # 将被编译的源文件
             src/main/cpp/nativesurface.cpp
             src/main/cpp/vdecode.cpp
             src/main/cpp/util.cpp
             src/main/cpp/openstream.cpp)
#查找NDK中原生库log-lib
find_library( # Sets the name of the path variable.
              log-lib

              # Specifies the name of the NDK library that
              # you want CMake to locate.
              log)
#将ffmpeg库、原生库android、log链接到自定义库decstream 
target_link_libraries(decstream android log
    libavcodec-57
    libavdevice-57
    libavfilter-6
    libavformat-57
    libavutil-55
    libpostproc-54
    libswresample-2
    libswscale-4
    ${log-lib}
    )

四、总结

如果在使用时有什么不对的,很大的可能是语法和路径问题,慢慢排查就可以。

五、引用文献

1、CMake 基本用法介绍

2、 CMakeList常用命令 - 简书

3、Android NDK开发之旅(5):Android Studio中使用CMake进行NDK/JNI开发(高级)_无名之辈FTER的博客-CSDN博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值