CMake 是一个开源、跨平台的工具,旨在构建、测试和打包软件。CMake是makefile的上层工具,用于跨平台构建环境,生成可移植的makefile,并简化自己动手写makefile时的巨大工作量。
前言
工作已经接近三年时间,做过大项目也有三四个了,关于项目代码整体编译,一定是离不开CMake。之前一段时间,仅仅是能看懂一些简单的CMake命令,编写一些基础的CMakeLists文件。然而最近一段时间,项目代码需要重构,代码内容以及代码结构都进行了调整,与之伴随的任务就是要重新去构建CMakeLists文件,借此机会,也是想要更深入的了解一下CMake的使用,针对于本次重新构建CMakeLists文件遇到的问题和学到的一些有用的知识,都记录到了这篇文章中。
关于CMake的指令有很多,首先我想先将CMake各种命令,根据自己的理解,简单的分成四类,这种分类肯定不能涵盖全,仅仅是为了能够方便自己去记忆。
- 关于项目的总体定义,一些环境变量和路径的定义
- 添加一些编译选项
- 编译所需要用到的源文件以及头文件
- 编译依赖的库
1.
首先,CMakeLists最开始要先声明使用CMAKE的最低版本要求
cmake_minimum_required(VERSION 3.10)
然后定义项目的名字
project(MYPROJECT)
如果有一些环境变量需要定义,或者要指定某些路径,可以通过set指令进行设置
# 声明变量var_name,var_name的值为var_value,这里的var_value的值,可以是路径,
也可以是许多文件,这个命令可以灵活运用,比如当你想将许多源文件打包并重命名,就可以
用到set指令
set(var_name var_value)
# 将lib输出路径设置为当前工程顶层目录下的lib文件夹下
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY &{PROJECT_SOURCE_DIR}/lib)
2.
添加一些编译选项:
# 设置编译目标类型是release版还是debug版本
set(CMAKE_BUILD_TYPE "Release")
# 设置C++版本
set(CMAKE_CXX_STANDARD 17)
# 编译参数指定,如生成位置无关的动态库
set(CMAKE_CXX_FLAGS "-fPIC")
# 为当前目录及以下目录中的可执行文件、共享库或模块库目标的链接步骤添加选项,如链接phread库
add_link_options(-pthread)
3.
添加项目编译所需要引用到的头文件的目录
# 等价于gcc -I
include_directory(${PROJECT_SOURCE_DIR}/include)
添加cmake执行编译的子目录
add_subdirectory(${PROJECT_SOURCE_DIR}/src/base)
选取编译所用到的源文件。这里可以用两种方法,一种是用前面提到过的set命令,另一种是通过aux_source_directory
# 将main.cc test.cc存到变量SRC_FILE内
set(SRC_FILE ${PROJECT_SOURCE_DIR}/src/main.cc
${PROJECT_SOURCE_DIR}/src/test.cc)
# 自动扫描当前路径下的所有源文件存到变量SRC_FILE内
aux_source_directory(. SRC_FILE)
4.
最后一部分也就是添加一些编译过程中所要依赖的库,以及生成目标文件的一些命令
# 生成目标库文件,SHARED代表动态的,STATIC代表静态的
add_library(${PROJECT_NAME} SHARED ${SRC_FILE})
# 链接api.so,注意路径要写全
target_link_libraries(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/lib/api.so)
这里只是介绍了一少部分CMake常用的指令,其他更多的指令以及具体用法可以参考官方文档,里面都有详细的介绍。
最后再说一个最近用CMake的时候遇到的一个很严重的错误。我在自己工程顶层目录的CMake中,去将别人的一个模块的主CMake文件通过add_subdirectory添加进来,导致了严重的编译错误,一个项目只能有一个顶层的CMake文件,绝对不可以再引用其他模块的CMake文件。
以上就是最近用到CMake的一些经验心得,后续用到一些其他的指令可能还会继续补充到这篇文章中,欢迎大家一起学习讨论。