作为跨平台的通用且流行的编译辅助工具cmake,自然少不了对C/C++语言的支持。说实话,从老式的autoconf到新式的cmake,的确 感觉是换了时代,简单、易用、易扩展,好处真的不是一丁半点。
一、背景
一般而言,对于任意一个使用cmake的C/C++项目,涉及的CMakeLists.txt的文件主要分为以下5类:
1、项目CMakeListst.txt文件。该文件仅且只有1个,处于项目代码的根目录下,负责描述整个项目代码的编译配置信息。
2、目录CMakeLists.txt文件。该文件依据待编译代码涉及目录的层级数量而存在多个,每个目录存在1个该文件,负责描述该目录下所要编译的代码子目录列表。
3、库CMakeListst.txt文件。该文件的数量与代码中静态库和动态库的数量一致,每一个库代码对应1个该文件,负责描述所生成库文件的名称、类型(静态/动态库)、版本、依赖库、编译源码文件列表、安装路径等信息。
4、可执行程序CMakeListst.txt文件。该文件的数量与代码中可执行程序的数量一致,每一个可执行程序代码对应1个该文件,负责描述所生成可执行程序的名称、依赖库、编译源码文件列表、安装路径等信息。
5、工具CMakeLists.txt文件。该文件的数量不定,与具体实际需求相关,主要负责描述非上述行为的其它一些操作,列如安装特定文件等。
举个例子,假设在/code目录有以下层级目录的C/C++项目代码:
/code(项目代码根目录)
|—bin(可执行程序代码根目录)
|—service(可执行程序代码目录)
|—include(项目包含头文件代码目录)
|—lib(项目库代码目录)
|—util(工具库代码目录)
|—module(功能模块代码目录,一般以动态库的形式存在)
|—testnet(测试网络功能模块代码目录)
—script(脚本代码目录)
|—mysql.db.sql(mysql数据库建库脚本文件)
|—mysql.db.data.sql(mysql数据库数据脚本文件)
那么会涉及哪几类CMakeLists.txt文件?又有多少个CMakeListst.txt文件呢?我们按照前述CMakeLists.txt文件的分类进行列举如下:
1、项目CMakeLists.txt文件。有且只有1个,位于/code目录下。
2、目录CMakeLists.txt文件。有3个,分别位于/code/bin、/code/lib和/code/module目录下。
3、库CMakeListst.txt文件。有2个,分别位于/code/lib/util和/code/module/testnet目录下。
4、可执行程序CMakeLists.txt文件。有1个,位于/code/bin/service目录下。
5、工具CMakeLists.txt文件。有1个,位于/code/script目录下。
至于/code/include目录不需要CMakeListst.txt文件,由于该目录主要用于代码的编译,对于二进制目标程序的执行不需要头文件,自然也就无需CMakeListst.txt文件进行额外操作。
二、项目CMakeListst.txt通用模板
作为完整C/C++项目代码中有且只有1个的项目CMakeListst.txt文件来说,涉及的项目编译配置内容说多不多,说少不少,具体还是依据项目实际情况而定。而对于常规的C/C++项目来说,比较通用的项目CMakeLists.txt模板内容如下:
# 设置所需要的cmake最小版本
CMAKE_MINIMUM_REQUIRED(VERSION 3.5.0)
# 项目所需的固定配置
ADD_DEFINITIONS(-D__SERVICE__) # 定义__SERVICE__宏用于代码进行逻辑处理
# 自定义项目配置
# 配置项目所需的OPENSSL库版本,1表明v1.X版本,3表明v3.X版本
# 所定义的__OPENSSL_VERSION1__和__OPENSSL_VERSION3__宏用于代码进行逻辑处理
# 实际编译时通过传递参数-DOPENSSL_VERSION=1/3实现自定义编译选项配置
# STATUS模式表明正常显示信息,FATAL_ERROR显示后会停止编译操作
IF(“${OPENSSL_VERSION}” STREQUAL 1)
ADD_DEFINITIONS(-D__OPENSSL_VERSION1__)
MESSAGE(STATUS “__OPENSSL_VERSION1__ has defined”)
ELSEIF(“${OPENSSL_VERSION}” STREQUAL 3)
ADD_DEFINITIONS(-D__OPENSSL_VERSION3__)
MESSAGE(STATUS “__OPENSSL_VERSION3__ has defined”)
ELSE()
MESSAGE(FATAL_ERROR “can not find the option OPENSSL_VERSION”)
ENDIF()
# 设置项目名称
PROJECT(XXX)
# 设置项目安装路径
SET(CMAKE_INSTALL_PREFIX /opt/${PROJECT_NAME})
# 把共享库的编译搜索路径也加入到运行搜索路径中
SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH ON)
# 设置编译选项
SET(
GCC_COVERAGE_COMPILE_FLAGS “-m64”) # 设置编译64位程序
SET(CMAKE_C_FLAGS “${CMAKE_C_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}”)
SET(CMAKE_CXX_FLAGS “${CMAKE_CXX_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}”)
SET(CMAKE_CXX_FLAGS_DEBUG “$ENV{CXXFLAGS} -g -Wall -Werror”) # 强烈提议编译选项把-Wall和-Werror加上,前者标识显示所有告警信息,后者表明把告警当做错误处理
SET(CMAKE_CXX_FLAGS_RELEASE “$ENV{CXXFLAGS} -O2 -Wall -Werror”)
ADD_DEFINITIONS(-std=c++11) # 明确使用c++11标准
# 设置包含头文件路径,每行单独一个路径
INCLUDE_DIRECTORIES(
./include
./
)
# 设置待链接的库文件路径
LINK_DIRECTORIES(
/opt/${PROJECT_NAME}/lib
/opt/${PROJECT_NAME}/module
)
# 添加要处理的路径列表,每行单独一个路径
# 注意,不能在一个ADD_SUBDIRECTORY中存放多个目录
ADD_SUBDIRECTORY(lib)
ADD_SUBDIRECTORY(module)
ADD_SUBDIRECTORY(bin)
ADD_SUBDIRECTORY(script)
三、未完待续
因内容较多,遗留的目录CMakeLists.txt文件、库CMakeLists.txt文件、可执行程序CMakeLists.txt文件和工具CMakeListst.txt文件的模板内容待下次继续介绍。
四、联系
如果有任何疑问欢迎随时交流。学无止境,实事求是,每天进步一点点!