Cmake介绍及使用问题记录

CMake 是一个跨平台的安装(编译)工具。
Make工具有很多种,比如 GNU Make ,QT 的 qmake ,微软的 MS nmake,BSD Make(pmake)等等。这些 Make 工具遵循着不同的规范和标准,所执行的 Makefile 格式也千差万别。要想跨平台,每一种标准都要写一次Makefile。
CMake是一套伪代码,执行编译的不是 CMake,可能是 gcc 也可能是 clang 等等。CMake允许开发者编写一种平台无关的 CMakeList.txt 文件来定制整个编译流程,然后再根据目标用户的平台进一步生成所需的本地化 Makefile 和工程文件。

一、android下使用CMake简单示例

cmake_minimum_required(VERSION 3.4.1)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")
#设置项目的名称,并将其存储在变量project_name中
project(appfp-native)
#设置依赖的so库目录
set(jnilibs ${CMAKE_SOURCE_DIR}/../jniLibs)

set(libname learn-ffmpeg)

#头文件包含目录
include_directories(
        include)
#指定链接目录
link_directories(
        ${jnilibs}/${ANDROID_ABI})
#查找所有源文件,保存到GLOB变量中
file(GLOB src-files
        ${CMAKE_SOURCE_DIR}/*.cpp
        )
#或者替换为使用aux_source_directory        
//aux_source_directory(${CMAKE_SOURCE_DIR} src-files)        

#生成库文件
add_library( # Sets the name of the library.
        ${libname}
        # Sets the library as a shared library.
        SHARED
        # Provides a relative path to your source file(s).
        ${src-files}
        )

#将编译依赖的三方库保存到thrid-party-libs变量中
set(third-party-libs
        avformat
        avcodec
        avfilter
        swresample
        swscale
        avutil
        crypto
        ssl
        )

#将编译依赖的系统库保存到native-lib是变量中
set(native-libs
        android
        log
        m
        z
        )

find_library(log-lib log)


target_link_libraries( # Specifies the target library.
        ${libname}

        # Links the target library to the log library
        # included in the NDK.
        ${log-lib}
        ${third-party-libs}
        ${native-libs}
        )

二、如何查看哪些源文件参与了编译

image.png
image.png
image.png
image.png

DPlayer.cpp未通过CmakeLists.txt文件引入,所以调用其startPlay()函数报undefined reference 错误。而在.cxx目录下,可以看到也只有app_native.cpp.o一个.o文件,即只有app_native.cpp一个源文件参与了编译。修改后如下:


image.png

三、target_llink_libraries 链接静态库顺序

target_llink_libraries 指令的作用为将目标文件与库文件进行链接。但是如果链接的是.a静态库,则有可能会遇到类似“error: undefined reference to···”错误。
例如:

target_link_libraries(${PROJECT_NAME} ${log-lib}
...
ssl crypto curl
)

ssl、crypto、curl均是.a静态库。正确顺序为curl、ssl、crypto。curl链接依赖ssl。


image.png

静态库链接库顺序和gcc是一致的,即被链接的库放到后面。在链接静态库时,如果多个静态库之间存在依赖关系,则有依赖关系的静态库之间存在顺序问题,这个在使用静态库时需要注意,否则会报符号找不到问题。

target_link_libraries(native_lib
    libA.a
    libB.a
    libC.a
    )

编译native_lib依赖libA 编译libA依赖libB 编译libB依赖libC。
C/C++程序的许多同学被静态库的依赖折腾,因为默认情况下要求被依赖的库放在依赖它的库后面,当一个程序或共享库依赖的静态库较多时,可能会陷入解决链接问题的坑中。
但也可以偷懒,不关心静态库的顺序问题,ld为此提供了start-group和end-group两个选项,让包含在这两者间的静态库顺序可以随意。
可以采用如下的写法去掉静态库链接顺序影响:

target_link_libraries(native_lib
    -Wl,--start-group
    libB.a
    libA.a
    libC.a
    -Wl,--end-group
    )

这样可以完全不用关心顺序。start-group和end-group是ld的选项,是链接选项,不是gcc/g++的编译选项。

四、add_definitions

add_definitions的功能和C/C++中的#define是一样的
比如我有如下两个文件,一个源文件main.cpp,一个CMakeLists.txt
源文件main.cpp

#include <iostream>
int main()
{
#ifdef TEST_IT_CMAKE
    std::cout<<"in ifdef"<<std::endl;
#endif
    std::cout<<"not in ifdef"<<std::endl;
}

cmake文件CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(optiontest)

add_executable(optiontest main.cpp)
option(TEST_IT_CMAKE "test" ON)
message(${TEST_IT_CMAKE})
if(TEST_IT_CMAKE)
    message("itis" ${TEST_IT_CMAKE})
    add_definitions(-DTEST_IT_CMAKE)
endif()

通过option设置一个变量,并通过add_definitions将其转换为#define TEST_IT_CMAKE
当变量为ON时

option(TEST_IT_CMAKE "test" ON)

该程序的输出是

in ifdef
not in ifdef

当变量为OFF时

option(TEST_IT_CMAKE "test" OFF)

该程序的输出为

not in ifdef

五、 aux_source_directory

aux_source_directory(< dir > < variable >)

搜集所有在指定路径下的源文件的文件名,将输出结果列表储存在指定的变量中。
查找指定目录下的源文件并保存到相应的变量中,需要注意的是使用aux_source_directory不会递归查找目录,会且只会查找指定目录下的源文件。
aux_source_directory不能递归包含源文件

参考

https://blog.csdn.net/qq_35699473/article/details/115837708
https://blog.csdn.net/fb_941219/article/details/107376017
https://www.csdn.net/tags/MtTaMg3sNDMzMjE2LWJsb2cO0O0O.htmlhttps://www.csdn.net/tags/MtTaMg3sNDMzMjE2LWJsb2cO0O0O.html
https://www.cnblogs.com/aquester/p/10084070.html
https://www.jianshu.com/p/f196a6433c30
https://www.cnblogs.com/lidabo/p/13802537.html

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,470评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,393评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,577评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,176评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,189评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,155评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,041评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,903评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,319评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,539评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,703评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,417评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,013评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,664评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,818评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,711评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,601评论 2 353

推荐阅读更多精彩内容