CMake入门笔记

2019-09-04 16:50:35

参考地址  CMake入门笔记

什么是CMake

CMake


CMake是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装(编译过程)。他能够输出各种各样的makefile或者project文件,能测试编译器所支持的C++特性,类似UNIX下的automake。只是 CMake 的组态档取名为 CMakeLists.txt。Cmake 并不直接建构出最终的软件,而是产生标准的建构档(如 Unix 的 Makefile 或 Windows Visual C++ 的 projects/workspaces),然后再依一般的建构方式使用。这使得熟悉某个集成开发环境(IDE)的开发者可以用标准的方式建构他的软件,这种可以使用各平台的原生建构系统的能力是 CMake 和 SCons 等其他类似系统的区别之处。


Make


make工具是一个简化编译工作程序,有了它我们可以进行所谓的“自动化编译”,极大地提高了软件开发的效率。make工具相当于一个Shell,通过解释Makefile的中的命令进行工作。大多数IDE都有这个工具,比如:Visual C++的nmake,Linux下GNU的make。 

make工具最主要也是最基本的功能就是通过makefile文件来描述源程序之间的相互关系并自动维护编译工作。而makefile 文件需要按照某种语法进行编写,文件中需要说明如何编译各个源文件并连接生成可执行文件,并要求定义源文件之间的依赖关系。


直白点说就是,CMake用来生成makefile或者是工程文件,make是用来解释makefile的。 

以Linux平台下使用gcc编译为例,我们想要编译源文件可以直接在命令行中执行gcc test.c -o test之类的命令,可是文件多了,工程复杂,而且文件不时的还会变,每次这样输多麻烦。 

这个时候make就有了用武之地,写个makefile,以后编译就直接make解释下makefile,根据makefile来执行编译命令。这样在linux上是很好,在windows上或者其他平台上怎么办呢? 

这时候就到cmake出马了,构建工程的时候,不在写makefile,而写CMakeLists.txt。需要编译的时候,先用Cmake解释CMakeLists.txt。如果在Windows平台上,设置编译器是VS,CMake就生成一个VS的工程,然后用VS来运行编译项目。如果是在Linux平台上,编译器是gcc,CMake就生成makefile,然后用make来解释makefile编译项目。 

如图,分别为原始目录、在Linux下选择gcc为编译工具生成的工程文件和在WIndows下选用Visual Studio为编译器生成的工程文件: 



cmake执行后会在cmake执行时所在的目录生成许多文件,根据cmake执行目录是否与源文件同目录,将构建方式分为两种:


out-of-source build,构建输出文件与源文件放到不同目录中;

in-source build :构建输出文件与源文件放到相同目录中。

一般选择out-of-source方式,可以在项目目录下建立一个build文件,然后进入build下,执行cmake ../,使生成的文件都在build文件夹下,以便后期清理。


示例

为了编译与演示方便,示例全部在Linux下进行。


Hello, CMake!

CMake最简单的实例,目录结构如下: 

 

main.c文件:


 #include <stdio.h>


int main(int argc, char *argv[])

{

    printf("Hello, CMake!\r\n");


    return 0;

}

1

2

3

4

5

6

7

8

CMakeLists.txt文件


 # 版本限定

CMAKE_MINIMUM_REQUIRED(VERSION 2.8)                      

# 项目名称

PROJECT(Test1)

# 添加源文件列表变量

SET(SRC_LIST main.cpp)

# 打印编译目录和项目目录路径

MESSAGE(STATUS "This is SOURCE dir " ${PROJECT_SOURCE_DIR})

# 生成可执行文件

ADD_EXECUTABLE(HelloCMake ${SRC_LIST})

1

2

3

4

5

6

7

8

9

10

然后进入项目目录,依次执行(需要确保linux下安装了gcc、make等):


mkdir build

cd build

cmake ../

1

2

3

此时,build文件夹内容如下: 

 

。然后键入make命令,即解析了Makefile文件,build目录下的内容变为: 

 

可以看到,生成了一个HelloCMake的可执行文件,键入./HelloCMake可以运行HelloCMake文件。 

bash执行输出过程如下: 



同一目录多个源文件

在实际使用中,很少会出现这么简单的情况,往往在一个文件夹中会存在多个源文件要求编译,目录如下,这时候只需要在SET后面加上需要编译的源文件就可以了。 

 

CMakeLists.txt文件:


# 版本限定

CMAKE_MINIMUM_REQUIRED(VERSION 2.8)                      

# 项目名称

PROJECT(Test2)

# 添加源文件列表变量

SET(SRC_LIST Stupid.cpp main.cpp)

# 打印编译目录和项目目录路径

MESSAGE(STATUS "This is BINARY dir " ${PROJECT_BINARY_DIR})

MESSAGE(STATUS "This is SOURCE dir " ${PROJECT_SOURCE_DIR})

# 生成可执行文件

ADD_EXECUTABLE(Test2 ${SRC_LIST})

1

2

3

4

5

6

7

8

9

10

11

上述方式虽然可行,但是如果源文件过多,CMakeLists.txt文件编写起来也是一件很吃力的事情,这时候,可以用aux_source_directory来解决这个问题。aux_source_directory可以遍历指定文件夹的下源文件,将它们统一复制给一个变量,然后进行编译。


CMakeLists.txt文件2:


# 版本限定

CMAKE_MINIMUM_REQUIRED(VERSION 2.8)                      

# 项目名称

project(Test3)


# 遍历当前目录所有的源文件,赋值给test3src

aux_source_directory(. test3src)

message(STATUS "src file : " ${test3src})

# 生成可执行文件

add_executable(Test3 ${test3src})

1

2

3

4

5

6

7

8

9

10

不同目录下的多个源文件

为了使源码更为清晰,源码往往会根据不同的功能,将代码放在不同的文件夹下,结构如图: 

 

这时候CmakeLists.txt文件又该如何编写呢?答案如下:


# 版本限定

CMAKE_MINIMUM_REQUIRED(VERSION 2.8)                      

# 项目名称

project(Test3)


# 遍历当前目录所有的源文件,赋值给test3src

aux_source_directory(. main)

aux_source_directory(./stupid stupid)

set(test4src ${main} ${stupid})

message(STATUS "src file : " ${test4src})


# 生成可执行文件

add_executable(Test4 ${test4src})

1

2

3

4

5

6

7

8

9

10

11

12

13

编译动态库与静态库

在前面的示例中,我们都是直接生成了可执行文件,而更多的时候,我们需要生成的不是可执行文件,而是一个可以让复用的库文件,这时候只需要将add_executable(Name ${srcTemp})修改为add_library(Name ${srcTemp})就可以了。add_library可以在中间增加一个参数表示动态库或静态库,默认无参数为静态库。


# 版本限定

cmake_minimum_required(VERSION 2.8)


# 遍历当前目录所有的源文件,赋值给STUPID_SRC

aux_source_directory(. STUPID_SRC)

# 编译STUPID_SRC为静态库

add_library(stupid STATIC ${STUPID_SRC})

# 编译STUPID_SRC为动态库

# add_library(stupid SHARED ${STUPID_SRC})

1

2

3

4

5

6

7

8

9

库文件和头文件导出到指定位置

编译出的库文件是要使用的,而库文件的使用一般需要库文件和头文件。虽然可以编译出库后自己整理库文件和头文件,但是终归是一件麻烦事,尤其是工程比较庞大的时候。这时候,我们可以使用INSTALL来将库文件和头文件导出到指定位置。


# 版本限定

CMAKE_MINIMUM_REQUIRED(VERSION 2.8)

SET(OUTPUT ${CMAKE_CURRENT_BINARY_DIR})

AUX_SOURCE_DIRECTORY(. STUPID_SRC)

# 设置库文件输出目录

# SET(LIBRARY_OUTPUT_PATH ${LIB_DIRS})

# 创建动态库

ADD_LIBRARY(stupid SHARED ${STUPID_SRC})

# 导出动态库

INSTALL(TARGETS stupid DESTINATION ${OUTPUT}/libs)

# 导出头文件

INSTALL(DIRECTORY . DESTINATION ${OUTPUT}/include/stupid 

    FILES_MATCHING PATTERN "*.h")

1

2

3

4

5

6

7

8

9

10

11

12

13

然后进入项目目录/build/ 目录下,依次执行:


cmake ../

make 

make install

1

2

3

即可在build下生成以下结构: 

 

include为头文件目录,其中包含了stupid/stupid.h文件。libs为库文件目录,其中包含了libstupid.so文件。


使用动态库/静态库

在上一个示例中,我们生成并导出了动态库,现在来使用它。复制出上个示例导出的libs及include文件夹,形成以下结构: 

 

CMakeLists.txt文件内容如下:


# 版本限定

CMAKE_MINIMUM_REQUIRED(VERSION 2.8)                      

# 项目名称

PROJECT(Test8)

# 遍历当前目录所有的源文件,赋值给test3src

AUX_SOURCE_DIRECTORY(. main)

MESSAGE(STATUS "src file : " ${main})

# 指定库文件搜索目录,必须为绝对路径

LINK_DIRECTORIES(${PROJECT_SOURCE_DIR}/libs)

# 生成可执行文件

ADD_EXECUTABLE(Test8 ${main})

# 指定头文件目录

INCLUDE_DIRECTORIES(./include)

# 指定目标需要连接的库

TARGET_LINK_LIBRARIES(Test8 stupid)


  • 2020-05-06 14:43:53

    bootstrap @media尺寸

    超大屏,1100分辨率,880分辨率,720分辨率,440分辨率以下

  • 2020-05-06 22:23:15

    使用querySelector添加移除style和class

    document.querySelector(selector).style.styleName = 样式 使用这个方法可以对dom节点添加和移除style样式,其中的styleName可以为css样式的任何值,如:display、color

  • 2020-05-07 13:05:28

    JavaScript中批量设置Css样式

    setAttribute() 方法添加指定的属性,并为其赋指定的值。 如果这个指定的属性已存在,则仅设置/更改值

  • 2020-05-07 13:07:21

    scrollBox 跑马灯滚动js

    ​这个插件可以很好的实现跑马灯,以及轮播图等效果,scrollBox js