[Note] CMake的简单使用

当前环境 macOScmake 3.9.4

一 gcc, make, cmake 的区别

  1. gcc 是一个编译器套件,用于编译多种语言的源文件
  2. gcc 需要编译多个文件时,编译指令很多时,则会使用 makefile 按照特定规则来对指令(gcc操作指令)进行整合,使用 make 工具来执行指令组。
  3. 由于 makefile 依赖于确定的编译器套件(如指令中的gcc ...),这时出现了通用工具CMake(根据实际的平台/环境选择编译套件并进行编译),与之搭配的是 CMakeLists.txt,输出是makefile
  4. 依次次进化和依赖的关系

二 编译一个 .cpp/.c 文件

随便在一个文件夹中新建两个文件,命令行cd到这个文件夹中

$ touch CMakeLists.txt test.cpp # CMakeLists.txt 必须
$ tree
.
├── CMakeLists.txt
└── test.cpp

CMakeLists.txt

# 添加需要编译的源文件 test.cpp 和 输出的可执行文件名字 exe_main
ADD_EXECUTABLE(exe_main test.cpp)

test.cpp

#include<stdio.h>

int main(int argc, char const *argv[])
{
    printf("Using cmake ...\n");
    return 0;
}

文件准备完毕,接着就是编译了

$ cmake ./
$ make
$./exe_main

看到最后效果,其实也是$ gcc test.cpp -o exe_main 一样的效果嘛,不过像上面说的,cmake加入了跨平台/环境

最后奉上全部材料


一个简单的例子.png

因为执行编译动作时,产生了很多文件,所以建议新建一个build目录,到里面执行编译指令,以免混乱了我们的源文件目录。也想说的是,这里的CMakeLists.txt写法并不标准哦,仅供学习 ~

三 编译多个.c/.cpp文件

经过上面简单粗暴的方法之后,总感觉文件一多了不稳妥,所以接下来吧源文件和头文件分开(注意:多文件连接,容易出现名字冲突:duplicate symbol ...

新建文件u.cpp u.h 分别放到对应的文件夹中,最后目录结构为

.
├── CMakeLists.txt
├── build
├── include
│   └── u.h
└── src
    ├── test.cpp
    └── u.cpp

u.h 文件

int add(int i, int j);

u.cpp文件

#include "../include/u.h"

int add(int i, int j) {
    return i + j;
}

test.cpp文件

#include<stdio.h>
#include "../include/u.h"

int main(int argc, char const *argv[])
{
    printf("Using cmake ...%d\n", add(13, 14));
    return 0;
}

CMakeLists.txt 文件修改成

# 指定 cmake 版本,预防某些用户使用较低版本的来编译该项目
cmake_minimum_required(VERSION 3.2)

# 指定一个项目名称,后面可以通过 `${PROJECT_NAME}` 来引用
PROJECT(my_project)

# 指定头文件目录,改参数为头文件所在的文件夹名字
INCLUDE_DIRECTORIES(include)

# 源文件目录
AUX_SOURCE_DIRECTORY(src DIR_SRCS)

# 选择性设置环境变量,然后通过 ${CUSTOM_VAR} 来引用
# SET(CUSTOM_VAR ${DIR_SRCS})

# 添加需要编译的源文件 test.cpp 和 输出的可执行文件名字 exe_main
ADD_EXECUTABLE(${PROJECT_NAME} ${DIR_SRCS})

文件准备完毕,cdbuild目录执行

$ cmake ../
$ make
$ ./my_project
Using cmake ...27 # 输出

四 编译动态库态库

在上面的基础上继续,当前的目录结构为($ tree -L 2)

.
├── CMakeLists.txt
├── build
│   ├── CMakeCache.txt
│   ├── CMakeFiles
│   ├── Makefile
│   └── cmake_install.cmake
├── include
│   └── u.h
└── src
    ├── test.cpp
    └── u.cpp

我们把 u.cpp 编译成动态库,则修改 CMakeLists.txt 如:

# 指定 cmake 版本,预防某些用户使用较低版本的来编译该项目
cmake_minimum_required(VERSION 3.2)

# 指定一个项目名称,后面可以通过 `${PROJECT_NAME}` 来引用
PROJECT(my_project)

# 指定头文件目录,改参数为头文件所在的文件夹名字
INCLUDE_DIRECTORIES(include)

# 源文件目录
AUX_SOURCE_DIRECTORY(src DIR_SRCS)

# 选择性设置环境变量,然后通过 ${CUSTOM_VAR} 来引用
# SET(CUSTOM_VAR ${DIR_SRCS})

# 添加需要编译的源文件 test.cpp 和 输出的可执行文件名字 exe_main
# ADD_EXECUTABLE(${PROJECT_NAME} ${DIR_SRCS})

# 设置一个动态库名字,因为 `ADD_LIBRARY` 中的参数不给设置字符常量
SET(DYLIB_NAME dytest)

# 生成一个动态库
ADD_LIBRARY(${DYLIB_NAME}
            SHARED
            src/u.cpp include/u.h)

文件准备完毕,像上面在build目录进行编译就行。

五 连接动态库

同样是修改 CMakeLists.txt

# 增加下面两行

# 添加需要编译的源文件 test.cpp 和 输出的可执行文件名字 exe_main
ADD_EXECUTABLE(exe_main src/test.cpp)

# 连接
TARGET_LINK_LIBRARIES(exe_main ${DYLIB_NAME})

文件准备完毕,到 build 里编译

六 编译并连接静态库(静态库部分合并了 四、五)

和动态库的编译和链接只相差一个单词,那就是将 SHARED 改成 STATIC,然后改一下库的名字statictest,完结!

这里提醒一下就是,产生的库就在执行 make 指令的目录,动态库是libxxx.dylib,静态库就是libstatictest.a

七 连接现有的(第三方)静态库和动态库

我们就就地取材,将上面输出的静态库和动态库直接拿来用,这里折腾了好久,因为导入第三方库时的语句选择问题,所以贴完整的 CMakeLists.txt 吧,静态库和动态库是差不多的,换一下名字就可以了

# 指定 cmake 版本,预防某些用户使用较低版本的来编译该项目
cmake_minimum_required(VERSION 3.2)

# 指定一个项目名称,后面可以通过 `${PROJECT_NAME}` 来引用
PROJECT(my_project)

# 指定头文件目录,改参数为头文件所在的文件夹名字
INCLUDE_DIRECTORIES(include)

# 源文件目录
AUX_SOURCE_DIRECTORY(src DIR_SRCS)

# 选择性设置环境变量,然后通过 ${CUSTOM_VAR} 来引用
# SET(CUSTOM_VAR ${DIR_SRCS})

# 添加需要编译的源文件 test.cpp 和 输出的可执行文件名字 exe_main
# ADD_EXECUTABLE(${PROJECT_NAME} ${DIR_SRCS})

# 设置一个动态库名字,因为 `ADD_LIBRARY` 中的参数不给设置字符常量
SET(LIB_NAME statictest)

# 生成一个库
# ADD_LIBRARY(${LIB_NAME}
#           SHARED
#           src/u.cpp include/u.h)

# 连接一个现有的库
# 这种方法是可以的
LINK_DIRECTORIES(lib)

# ADD_LIBRARY(${LIB_NAME}
#           SHARED
#           IMPORTED)

# 这里以 `${CMAKE_CURRENT_SOURCE_DIR}` 为目录开始
#SET_TARGET_PROPERTIES(${LIB_NAME}
#        PROPERTIES IMPORTED_LOCATION 
#        ${CMAKE_CURRENT_SOURCE_DIR}/lib/libdytest.dylib)

# 添加需要编译的源文件 test.cpp 和 输出的可执行文件名字 exe_main
ADD_EXECUTABLE(exe_main 
            src/test.cpp)

# 连接
TARGET_LINK_LIBRARIES(exe_main 
                    ${LIB_NAME})

和目录 ($ tree -L 2)

.
├── CMakeLists.txt
├── build
│   ├── CMakeCache.txt
│   ├── CMakeFiles
│   ├── Makefile
│   ├── cmake_install.cmake
│   └── exe_main
├── include
│   └── u.h
├── lib
│   ├── libdytest.dylib
│   └── libstatictest.a
└── src
    ├── test.cpp
    └── u.cpp

最后发现,macOS命令行上对.so文件链接不成功,总会报一个库没有加载的错误,这大概就是macOS.dylib 和 .so的不同处理吧!很多细节还需要补充,有空再继续吧 ~
[Note] Android Studio 中的 CMake 简单使用
Github

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