cmake
TRANSCRIPT
在 linux 下使用 CMake 构建应用程序 级别 初级
王 程明 (wangchengmingjlugmailcom) 硕士研究生 吉林大学计算机科学与技术学院
2009 年 2 月 05 日
本文介绍了一个跨平台的自动化构建系统 CMake 在 linux 上的使用方法 CMake 是一个比
automake 更加容易使用的工具能够使程序员从复杂的编译连接过程中解脱出来文中通过一些例子介
绍使用 CMake 处理多源文件目录的方法查找并使用其他开发包的方法以及生成 debug 版和 release
版程序的方法
CMake 简介
CMake 是一个跨平台的自动化建构系统它使用一个名为 CMakeListstxt 的文件来描述构建过程可以
产生标准的构建文件如 Unix 的 Makefile 或 Windows Visual C++ 的 projectsworkspaces 文
件 CMakeListstxt 需要手工编写也可以通过编写脚本进行半自动的生成CMake 提供了比
autoconfig 更简洁的语法在 linux 平台下使用 CMake 生成 Makefile 并编译的流程如下
1 编写 CmakeListstxt
2 执行命令 ldquocmake PATHrdquo 或者 ldquoccmake PATHrdquo 生成 Makefile ( PATH 是 CMakeListstxt 所在
的目录 )
3 使用 make 命令进行编译
第一个工程
现假设我们的项目中只有一个源文件 maincpp
清单 1 源文件 maincpp
1 includeltiostreamgt
2
3 int main()
4
5 stdcoutltltHello wordltltstdendl
6 return 0
7
为了构建该项目我们需要编写文件 CMakeListstxt 并将其与 maincpp 放在 同一个目录下
清单 2 CMakeListstxt
1 PROJECT(main)
2 CMAKE_MINIMUM_REQUIRED(VERSION 26)
3 AUX_SOURCE_DIRECTORY( DIR_SRCS)
4 ADD_EXECUTABLE(main $DIR_SRCS)
CMakeListstxt 的语法比较简单由命令注释和空格组成其中命令是不区分大小写的符号后面的
内容被认为是注释命令由命令名称小括号和参数组成参数之间使用空格进行间隔例如对于清单 2 的
CMakeListstxt 文件第一行是一条命令名称是 PROJECT 参数是 main 该命令表示项目的名称是
main 第二行的命令限定了 CMake 的版本第三行使用命令 AUX_SOURCE_DIRECTORY 将当前
目录中的源文件名称赋值给变量 DIR_SRCS CMake 手册中对命令 AUX_SOURCE_DIRECTORY
的描述如下
aux_source_directory(ltdirgt ltvariablegt)
该命令会把参数 ltdirgt 中所有的源文件名称赋值给参数 ltvariablegt 第四行使用命令
ADD_EXECUTABLE 指示变量 DIR_SRCS 中的源文件需要编译 成一个名称为 main 的可执行文件
完成了文件 CMakeListstxt 的编写后需要使用 cmake 或 ccmake 命令生成 Makefile ccmake
与命令 cmake 的不同之处在于 ccmake 提供了一个图形化的操作界面cmake 命令的执行方式如下
cmake [options] ltpath-to-sourcegt
这里我们进入了 maincpp 所在的目录后执行 ldquocmake rdquo 后就可以得到 Makefile 并使用 make 进
行编译如下图所示
图 1 camke 的运行结果
处理多源文件目录的方法
CMake 处理源代码分布在不同目录中的情况也十分简单现假设我们的源代码分布情况如下
图 2 源代码分布情况
其中 src 目录下的文件要编译成一个链接库
第一步项目主目录中的 CMakeListstxt 在目录 step2 中创建文件 CMakeListstxt 文件内容如下
清单 3 目录 step2 中的 CMakeListstxt
1 PROJECT(main)
2 CMAKE_MINIMUM_REQUIRED(VERSION 26)
3 ADD_SUBDIRECTORY( src )
4 AUX_SOURCE_DIRECTORY( DIR_SRCS)
5 ADD_EXECUTABLE(main $DIR_SRCS )
6 TARGET_LINK_LIBRARIES( main Test )
相对于清单 2该文件添加了下面的内容 第三行使用命令 ADD_SUBDIRECTORY 指明本项目包含
一个子目录 src 第六行使用命令 TARGET_LINK_LIBRARIES 指明可执行文件 main 需要连接一
个名为 Test 的链接库
第二步子目录中的 CmakeListstxt 在子目录 src 中创建 CmakeListstxt文件内容如下
清单 4 目录 src 中的 CmakeListstxt
1 AUX_SOURCE_DIRECTORY( DIR_TEST1_SRCS)
2 ADD_LIBRARY ( Test $DIR_TEST1_SRCS)
在该文件中使用命令 ADD_LIBRARY 将 src 目录中的源文件编译为共享库
第三步执行 cmake
至此我们完成了项目中所有 CMakeListstxt 文件的编写进入目录 step2 中依次执行命令 ldquocmake rdquo
和 ldquomakerdquo 得到结果如下
图 3 处理多源文件目录时 cmake 的执行结果
在执行 cmake 的过程中首先解析目录 step2 中的 CMakeListstxt 当程序执行命令
ADD_SUBDIRECTORY( src ) 时进入目录 src 对其中的 CMakeListstxt 进行解析
在工程中查找并使用其他程序库的方法
在开发软件的时候我们会用到一些函数库这些函数库在不同的系统中安装的位置可能不同编译的时候需
要首先找到这些软件包的头文件以及链接库所在的目录以便生成编译选项例如一个需要使用博克利数据
库项目需要头文件 db_cxxh 和链接库 libdb_cxxso 现在该项目中有一个源代码文件 maincpp
放在项目的根目录中
第一步程序库说明文件
在项目的根目录中创建目录 cmakemodules 在 cmakemodules 下创建文件
Findlibdb_cxxcmake 内容如下
清单 5 文件 Findlibdb_cxxcmake
01 MESSAGE(STATUS Using bundled Findlibdbcmake)
02
03 FIND_PATH(
04 LIBDB_CXX_INCLUDE_DIR
05 db_cxxh
06 usrinclude
07 usrlocalinclude
08 )
09
10 FIND_LIBRARY(
11 LIBDB_CXX_LIBRARIES NAMES db_cxx
12 PATHS usrlib usrlocallib
13 )
文件 Findlibdb_cxxcmake 的命名要符合规范 FindlibNAMEcmake 其中 NAME 是函数库的名称
Findlibdb_cxxcmake 的语法与 CMakeListstxt 相同这里使用了三个命令 MESSAGE
FIND_PATH 和 FIND_LIBRARY
bull 命令 MESSAGE 会将参数的内容输出到终端
bull 命令 FIND_PATH 指明头文件查找的路径原型如下
find_path(ltVARgt name1 [path1 path2 ]) 该命令在参数 path 指示的目录中查找文件 name1
并将查找到的路径保存在变量 VAR 中清单 5第 3-8行的意思是在 usrinclude 和
usrlocalinclude 中查找文件 db_cxxh 并将 db_cxxh 所在的路径保存在
LIBDB_CXX_INCLUDE_DIR 中
bull 命令 FIND_LIBRARY 同 FIND_PATH 类似用于查找链接库并将结果保存在变量中清单 5第 10-13行
的意思是在目录 usrlib 和 usrlocallib 中寻找名称为 db_cxx 的链接库并将结果保存在
LIBDB_CXX_LIBRARIES
第二步 项目的根目录中的 CmakeListtxt 在项目的根目录中创建 CmakeListtxt
清单 6 可以查找链接库的 CMakeListtxt
01 PROJECT(main)
02 CMAKE_MINIMUM_REQUIRED(VERSION 26)
03 SET(CMAKE_SOURCE_DIR )
04 SET(CMAKE_MODULE_PATH $CMAKE_ROOTModules $CMAKE_SOURCE_DIRcmakemodules)
05 AUX_SOURCE_DIRECTORY( DIR_SRCS)
06 ADD_EXECUTABLE(main $DIR_SRCS)
07
08 FIND_PACKAGE( libdb_cxx REQUIRED)
09 MARK_AS_ADVANCED(
10 LIBDB_CXX_INCLUDE_DIR
11 LIBDB_CXX_LIBRARIES
12 )
13 IF (LIBDB_CXX_INCLUDE_DIR AND LIBDB_CXX_LIBRARIES)
14 MESSAGE(STATUS Found libdb libraries)
15 INCLUDE_DIRECTORIES($LIBDB_CXX_INCLUDE_DIR)
16 MESSAGE( $LIBDB_CXX_LIBRARIES )
17 TARGET_LINK_LIBRARIES(main $LIBDB_CXX_LIBRARIES
18 )
19 ENDIF (LIBDB_CXX_INCLUDE_DIR AND LIBDB_CXX_LIBRARIES)
在该文件中第 4 行表示到目录 cmakemodules 中查找 Findlibdb_cxxcmake 8-19 行表示查找
链接库和头文件的过程第 8 行使用命令 FIND_PACKAGE 进行查找这条命令执行后 CMake 会到变
量 CMAKE_MODULE_PATH 指示的目录中查找文件 Findlibdb_cxxcmake 并执行第 13-19 行是
条件判断语句表示如果 LIBDB_CXX_INCLUDE_DIR 和 LIBDB_CXX_LIBRARIES 都已经被赋值
则设置编译时到 LIBDB_CXX_INCLUDE_DIR 寻找头文件并且设置可执行文件 main 需要与链接库
LIBDB_CXX_LIBRARIES 进行连接
第三步执行 cmake
完成 Findlibdb_cxxcmake 和 CMakeListtxt 的编写后在项目的根目录依次执行 ldquocmake rdquo 和
ldquomake rdquo 可以进行编译结果如下图所示
图 4 使用其他程序库时 cmake 的执行结果
使用 cmake 生成 debug 版和 release 版的程序
在 Visual Studio 中我们可以生成 debug 版和 release 版的程序使用 CMake 我们也可以达到上述
效果debug 版的项目生成的可执行文件需要有调试信息并且不需要进行优化而 release 版的不需要调
试信息但需要优化这些特性在 gccg++ 中是通过编译时的参数来决定的如果将优化程度调到最高需
要设置参数-O3最低是 -O0 即不做优化添加调试信息的参数是 -g -ggdb 如果不添加这个参数调试
信息就不会被包含在生成的二进制文件中
CMake 中有一个变量 CMAKE_BUILD_TYPE 可以的取值是 Debug Release RelWithDebInfo 和
MinSizeRel当这个变量值为 Debug 的时候CMake 会使用变量 CMAKE_CXX_FLAGS_DEBUG 和
CMAKE_C_FLAGS_DEBUG 中的字符串作为编译选项生成 Makefile 当这个变量值为 Release 的时
候工程会使用变量 CMAKE_CXX_FLAGS_RELEASE 和 CMAKE_C_FLAGS_RELEASE 选项生成
Makefile
现假设项目中只有一个文件 maincpp 下面是一个可以选择生成 debug 版和 release 版的程序的
CMakeListtxt
清单 7
1 PROJECT(main)
2 CMAKE_MINIMUM_REQUIRED(VERSION 26)
3 SET(CMAKE_SOURCE_DIR )
4
5 SET(CMAKE_CXX_FLAGS_DEBUG $ENVCXXFLAGS -O0 -Wall -g -ggdb)
6 SET(CMAKE_CXX_FLAGS_RELEASE $ENVCXXFLAGS -O3 -Wall)
7
8 AUX_SOURCE_DIRECTORY( DIR_SRCS)
9 ADD_EXECUTABLE(main $DIR_SRCS)
第 5 和 6 行设置了两个变量 CMAKE_CXX_FLAGS_DEBUG 和 CMAKE_CXX_FLAGS_RELEASE
这两个变量是分别用于 debug 和 release 的编译选项编辑 CMakeListtxt 后需要执行 ccmake 命
令生成 Makefile 在进入项目的根目录输入 ccmake 进入一个图形化界面如下图所示
图 5 ccmake 的界面
按照界面中的提示进行操作按 c 进行 configure 这时界面中显示出了配置变量
CMAKE_BUILD_TYPE 的条目如下图所示
图 6 执行了 configure 以后 ccmake 的界面
下面我们首先生成 Debug 版的 Makefile 将变量 CMAKE_BUILD_TYPE 设置为 Debug 按 c 进
行 configure 按 g 生成 Makefile 并退出这时执行命令 find | xargs grep O0 后结果如下
清单 8 find | xargs grep O0的执行结果
CMakeFilesmaindirflagsmakeCXX_FLAGS = -O0 -Wall -g -ggdb
CMakeFilesmaindirlinktxtusrbinc++ -O0 -Wall -g -ggdb
CMakeFilesmaindirmaincppo -o main -rdynamic
CMakeListstxtSET(CMAKE_CXX_FLAGS_DEBUG $ENVCXXFLAGS -O0 -Wall -g -ggdb)
这个结果说明生成的 Makefile 中使用了变量 CMAKE_CXX_FLAGS_DEBUG 作为编译时的参数
下面我们将生成 Release 版的 Makefile 再次执行命令 ccmake 将变量 CMAKE_BUILD_TYPE
设置为 Release 生成 Makefile 并退出执行命令 find | xargs grep O0 后结果如下
清单 9 find | xargs grep O0的执行结果
CMakeListstxtSET(CMAKE_CXX_FLAGS_DEBUG $ENVCXXFLAGS -O0 -Wall -g -ggdb)
而执行命令 find | xargs grep O3 后结果如下
清单 10 find | xargs grep O3的执行结果
CMakeCachetxtCMAKE_CXX_FLAGS_RELEASESTRING=-O3 -DNDEBUG
CMakeCachetxtCMAKE_C_FLAGS_RELEASESTRING=-O3 -DNDEBUG
CMakeFilesmaindirflagsmakeCXX_FLAGS = -O3 -Wall
CMakeFilesmaindirlinktxtusrbinc++ -O3 -Wall
CMakeFilesmaindirmaincppo -o main -rdynamic
CMakeListstxtSET(CMAKE_CXX_FLAGS_RELEASE $ENVCXXFLAGS -O3 -Wall)
这两个结果说明生成的 Makefile 中使用了变量 CMAKE_CXX_FLAGS_RELEASE 作为编译时的参数
参考资料
bull 要了解 CMake 请参考其官方网站httpwwwcmakeorg
bull 维基百科中对 CMake 也有非常详细的说明具体请参考
httpzhwikipediaorgwikiCMake
bull 在 developerWorks Linux 专区 寻找为 Linux 开发人员(包括 Linux 新手入门)准备的更
多参考资料查阅我们 最受欢迎的文章和教程
bull 在 developerWorks 上查阅所有 Linux 技巧 和 Linux 教程
关于作者
王程明就读于吉林大学计算机科学与技术学网格计算与网络安全实验室主要研究领域为网络安全
- 在 linux 下使用 CMake 构建应用程序
-
CMakeListstxt 的语法比较简单由命令注释和空格组成其中命令是不区分大小写的符号后面的
内容被认为是注释命令由命令名称小括号和参数组成参数之间使用空格进行间隔例如对于清单 2 的
CMakeListstxt 文件第一行是一条命令名称是 PROJECT 参数是 main 该命令表示项目的名称是
main 第二行的命令限定了 CMake 的版本第三行使用命令 AUX_SOURCE_DIRECTORY 将当前
目录中的源文件名称赋值给变量 DIR_SRCS CMake 手册中对命令 AUX_SOURCE_DIRECTORY
的描述如下
aux_source_directory(ltdirgt ltvariablegt)
该命令会把参数 ltdirgt 中所有的源文件名称赋值给参数 ltvariablegt 第四行使用命令
ADD_EXECUTABLE 指示变量 DIR_SRCS 中的源文件需要编译 成一个名称为 main 的可执行文件
完成了文件 CMakeListstxt 的编写后需要使用 cmake 或 ccmake 命令生成 Makefile ccmake
与命令 cmake 的不同之处在于 ccmake 提供了一个图形化的操作界面cmake 命令的执行方式如下
cmake [options] ltpath-to-sourcegt
这里我们进入了 maincpp 所在的目录后执行 ldquocmake rdquo 后就可以得到 Makefile 并使用 make 进
行编译如下图所示
图 1 camke 的运行结果
处理多源文件目录的方法
CMake 处理源代码分布在不同目录中的情况也十分简单现假设我们的源代码分布情况如下
图 2 源代码分布情况
其中 src 目录下的文件要编译成一个链接库
第一步项目主目录中的 CMakeListstxt 在目录 step2 中创建文件 CMakeListstxt 文件内容如下
清单 3 目录 step2 中的 CMakeListstxt
1 PROJECT(main)
2 CMAKE_MINIMUM_REQUIRED(VERSION 26)
3 ADD_SUBDIRECTORY( src )
4 AUX_SOURCE_DIRECTORY( DIR_SRCS)
5 ADD_EXECUTABLE(main $DIR_SRCS )
6 TARGET_LINK_LIBRARIES( main Test )
相对于清单 2该文件添加了下面的内容 第三行使用命令 ADD_SUBDIRECTORY 指明本项目包含
一个子目录 src 第六行使用命令 TARGET_LINK_LIBRARIES 指明可执行文件 main 需要连接一
个名为 Test 的链接库
第二步子目录中的 CmakeListstxt 在子目录 src 中创建 CmakeListstxt文件内容如下
清单 4 目录 src 中的 CmakeListstxt
1 AUX_SOURCE_DIRECTORY( DIR_TEST1_SRCS)
2 ADD_LIBRARY ( Test $DIR_TEST1_SRCS)
在该文件中使用命令 ADD_LIBRARY 将 src 目录中的源文件编译为共享库
第三步执行 cmake
至此我们完成了项目中所有 CMakeListstxt 文件的编写进入目录 step2 中依次执行命令 ldquocmake rdquo
和 ldquomakerdquo 得到结果如下
图 3 处理多源文件目录时 cmake 的执行结果
在执行 cmake 的过程中首先解析目录 step2 中的 CMakeListstxt 当程序执行命令
ADD_SUBDIRECTORY( src ) 时进入目录 src 对其中的 CMakeListstxt 进行解析
在工程中查找并使用其他程序库的方法
在开发软件的时候我们会用到一些函数库这些函数库在不同的系统中安装的位置可能不同编译的时候需
要首先找到这些软件包的头文件以及链接库所在的目录以便生成编译选项例如一个需要使用博克利数据
库项目需要头文件 db_cxxh 和链接库 libdb_cxxso 现在该项目中有一个源代码文件 maincpp
放在项目的根目录中
第一步程序库说明文件
在项目的根目录中创建目录 cmakemodules 在 cmakemodules 下创建文件
Findlibdb_cxxcmake 内容如下
清单 5 文件 Findlibdb_cxxcmake
01 MESSAGE(STATUS Using bundled Findlibdbcmake)
02
03 FIND_PATH(
04 LIBDB_CXX_INCLUDE_DIR
05 db_cxxh
06 usrinclude
07 usrlocalinclude
08 )
09
10 FIND_LIBRARY(
11 LIBDB_CXX_LIBRARIES NAMES db_cxx
12 PATHS usrlib usrlocallib
13 )
文件 Findlibdb_cxxcmake 的命名要符合规范 FindlibNAMEcmake 其中 NAME 是函数库的名称
Findlibdb_cxxcmake 的语法与 CMakeListstxt 相同这里使用了三个命令 MESSAGE
FIND_PATH 和 FIND_LIBRARY
bull 命令 MESSAGE 会将参数的内容输出到终端
bull 命令 FIND_PATH 指明头文件查找的路径原型如下
find_path(ltVARgt name1 [path1 path2 ]) 该命令在参数 path 指示的目录中查找文件 name1
并将查找到的路径保存在变量 VAR 中清单 5第 3-8行的意思是在 usrinclude 和
usrlocalinclude 中查找文件 db_cxxh 并将 db_cxxh 所在的路径保存在
LIBDB_CXX_INCLUDE_DIR 中
bull 命令 FIND_LIBRARY 同 FIND_PATH 类似用于查找链接库并将结果保存在变量中清单 5第 10-13行
的意思是在目录 usrlib 和 usrlocallib 中寻找名称为 db_cxx 的链接库并将结果保存在
LIBDB_CXX_LIBRARIES
第二步 项目的根目录中的 CmakeListtxt 在项目的根目录中创建 CmakeListtxt
清单 6 可以查找链接库的 CMakeListtxt
01 PROJECT(main)
02 CMAKE_MINIMUM_REQUIRED(VERSION 26)
03 SET(CMAKE_SOURCE_DIR )
04 SET(CMAKE_MODULE_PATH $CMAKE_ROOTModules $CMAKE_SOURCE_DIRcmakemodules)
05 AUX_SOURCE_DIRECTORY( DIR_SRCS)
06 ADD_EXECUTABLE(main $DIR_SRCS)
07
08 FIND_PACKAGE( libdb_cxx REQUIRED)
09 MARK_AS_ADVANCED(
10 LIBDB_CXX_INCLUDE_DIR
11 LIBDB_CXX_LIBRARIES
12 )
13 IF (LIBDB_CXX_INCLUDE_DIR AND LIBDB_CXX_LIBRARIES)
14 MESSAGE(STATUS Found libdb libraries)
15 INCLUDE_DIRECTORIES($LIBDB_CXX_INCLUDE_DIR)
16 MESSAGE( $LIBDB_CXX_LIBRARIES )
17 TARGET_LINK_LIBRARIES(main $LIBDB_CXX_LIBRARIES
18 )
19 ENDIF (LIBDB_CXX_INCLUDE_DIR AND LIBDB_CXX_LIBRARIES)
在该文件中第 4 行表示到目录 cmakemodules 中查找 Findlibdb_cxxcmake 8-19 行表示查找
链接库和头文件的过程第 8 行使用命令 FIND_PACKAGE 进行查找这条命令执行后 CMake 会到变
量 CMAKE_MODULE_PATH 指示的目录中查找文件 Findlibdb_cxxcmake 并执行第 13-19 行是
条件判断语句表示如果 LIBDB_CXX_INCLUDE_DIR 和 LIBDB_CXX_LIBRARIES 都已经被赋值
则设置编译时到 LIBDB_CXX_INCLUDE_DIR 寻找头文件并且设置可执行文件 main 需要与链接库
LIBDB_CXX_LIBRARIES 进行连接
第三步执行 cmake
完成 Findlibdb_cxxcmake 和 CMakeListtxt 的编写后在项目的根目录依次执行 ldquocmake rdquo 和
ldquomake rdquo 可以进行编译结果如下图所示
图 4 使用其他程序库时 cmake 的执行结果
使用 cmake 生成 debug 版和 release 版的程序
在 Visual Studio 中我们可以生成 debug 版和 release 版的程序使用 CMake 我们也可以达到上述
效果debug 版的项目生成的可执行文件需要有调试信息并且不需要进行优化而 release 版的不需要调
试信息但需要优化这些特性在 gccg++ 中是通过编译时的参数来决定的如果将优化程度调到最高需
要设置参数-O3最低是 -O0 即不做优化添加调试信息的参数是 -g -ggdb 如果不添加这个参数调试
信息就不会被包含在生成的二进制文件中
CMake 中有一个变量 CMAKE_BUILD_TYPE 可以的取值是 Debug Release RelWithDebInfo 和
MinSizeRel当这个变量值为 Debug 的时候CMake 会使用变量 CMAKE_CXX_FLAGS_DEBUG 和
CMAKE_C_FLAGS_DEBUG 中的字符串作为编译选项生成 Makefile 当这个变量值为 Release 的时
候工程会使用变量 CMAKE_CXX_FLAGS_RELEASE 和 CMAKE_C_FLAGS_RELEASE 选项生成
Makefile
现假设项目中只有一个文件 maincpp 下面是一个可以选择生成 debug 版和 release 版的程序的
CMakeListtxt
清单 7
1 PROJECT(main)
2 CMAKE_MINIMUM_REQUIRED(VERSION 26)
3 SET(CMAKE_SOURCE_DIR )
4
5 SET(CMAKE_CXX_FLAGS_DEBUG $ENVCXXFLAGS -O0 -Wall -g -ggdb)
6 SET(CMAKE_CXX_FLAGS_RELEASE $ENVCXXFLAGS -O3 -Wall)
7
8 AUX_SOURCE_DIRECTORY( DIR_SRCS)
9 ADD_EXECUTABLE(main $DIR_SRCS)
第 5 和 6 行设置了两个变量 CMAKE_CXX_FLAGS_DEBUG 和 CMAKE_CXX_FLAGS_RELEASE
这两个变量是分别用于 debug 和 release 的编译选项编辑 CMakeListtxt 后需要执行 ccmake 命
令生成 Makefile 在进入项目的根目录输入 ccmake 进入一个图形化界面如下图所示
图 5 ccmake 的界面
按照界面中的提示进行操作按 c 进行 configure 这时界面中显示出了配置变量
CMAKE_BUILD_TYPE 的条目如下图所示
图 6 执行了 configure 以后 ccmake 的界面
下面我们首先生成 Debug 版的 Makefile 将变量 CMAKE_BUILD_TYPE 设置为 Debug 按 c 进
行 configure 按 g 生成 Makefile 并退出这时执行命令 find | xargs grep O0 后结果如下
清单 8 find | xargs grep O0的执行结果
CMakeFilesmaindirflagsmakeCXX_FLAGS = -O0 -Wall -g -ggdb
CMakeFilesmaindirlinktxtusrbinc++ -O0 -Wall -g -ggdb
CMakeFilesmaindirmaincppo -o main -rdynamic
CMakeListstxtSET(CMAKE_CXX_FLAGS_DEBUG $ENVCXXFLAGS -O0 -Wall -g -ggdb)
这个结果说明生成的 Makefile 中使用了变量 CMAKE_CXX_FLAGS_DEBUG 作为编译时的参数
下面我们将生成 Release 版的 Makefile 再次执行命令 ccmake 将变量 CMAKE_BUILD_TYPE
设置为 Release 生成 Makefile 并退出执行命令 find | xargs grep O0 后结果如下
清单 9 find | xargs grep O0的执行结果
CMakeListstxtSET(CMAKE_CXX_FLAGS_DEBUG $ENVCXXFLAGS -O0 -Wall -g -ggdb)
而执行命令 find | xargs grep O3 后结果如下
清单 10 find | xargs grep O3的执行结果
CMakeCachetxtCMAKE_CXX_FLAGS_RELEASESTRING=-O3 -DNDEBUG
CMakeCachetxtCMAKE_C_FLAGS_RELEASESTRING=-O3 -DNDEBUG
CMakeFilesmaindirflagsmakeCXX_FLAGS = -O3 -Wall
CMakeFilesmaindirlinktxtusrbinc++ -O3 -Wall
CMakeFilesmaindirmaincppo -o main -rdynamic
CMakeListstxtSET(CMAKE_CXX_FLAGS_RELEASE $ENVCXXFLAGS -O3 -Wall)
这两个结果说明生成的 Makefile 中使用了变量 CMAKE_CXX_FLAGS_RELEASE 作为编译时的参数
参考资料
bull 要了解 CMake 请参考其官方网站httpwwwcmakeorg
bull 维基百科中对 CMake 也有非常详细的说明具体请参考
httpzhwikipediaorgwikiCMake
bull 在 developerWorks Linux 专区 寻找为 Linux 开发人员(包括 Linux 新手入门)准备的更
多参考资料查阅我们 最受欢迎的文章和教程
bull 在 developerWorks 上查阅所有 Linux 技巧 和 Linux 教程
关于作者
王程明就读于吉林大学计算机科学与技术学网格计算与网络安全实验室主要研究领域为网络安全
- 在 linux 下使用 CMake 构建应用程序
-
图 2 源代码分布情况
其中 src 目录下的文件要编译成一个链接库
第一步项目主目录中的 CMakeListstxt 在目录 step2 中创建文件 CMakeListstxt 文件内容如下
清单 3 目录 step2 中的 CMakeListstxt
1 PROJECT(main)
2 CMAKE_MINIMUM_REQUIRED(VERSION 26)
3 ADD_SUBDIRECTORY( src )
4 AUX_SOURCE_DIRECTORY( DIR_SRCS)
5 ADD_EXECUTABLE(main $DIR_SRCS )
6 TARGET_LINK_LIBRARIES( main Test )
相对于清单 2该文件添加了下面的内容 第三行使用命令 ADD_SUBDIRECTORY 指明本项目包含
一个子目录 src 第六行使用命令 TARGET_LINK_LIBRARIES 指明可执行文件 main 需要连接一
个名为 Test 的链接库
第二步子目录中的 CmakeListstxt 在子目录 src 中创建 CmakeListstxt文件内容如下
清单 4 目录 src 中的 CmakeListstxt
1 AUX_SOURCE_DIRECTORY( DIR_TEST1_SRCS)
2 ADD_LIBRARY ( Test $DIR_TEST1_SRCS)
在该文件中使用命令 ADD_LIBRARY 将 src 目录中的源文件编译为共享库
第三步执行 cmake
至此我们完成了项目中所有 CMakeListstxt 文件的编写进入目录 step2 中依次执行命令 ldquocmake rdquo
和 ldquomakerdquo 得到结果如下
图 3 处理多源文件目录时 cmake 的执行结果
在执行 cmake 的过程中首先解析目录 step2 中的 CMakeListstxt 当程序执行命令
ADD_SUBDIRECTORY( src ) 时进入目录 src 对其中的 CMakeListstxt 进行解析
在工程中查找并使用其他程序库的方法
在开发软件的时候我们会用到一些函数库这些函数库在不同的系统中安装的位置可能不同编译的时候需
要首先找到这些软件包的头文件以及链接库所在的目录以便生成编译选项例如一个需要使用博克利数据
库项目需要头文件 db_cxxh 和链接库 libdb_cxxso 现在该项目中有一个源代码文件 maincpp
放在项目的根目录中
第一步程序库说明文件
在项目的根目录中创建目录 cmakemodules 在 cmakemodules 下创建文件
Findlibdb_cxxcmake 内容如下
清单 5 文件 Findlibdb_cxxcmake
01 MESSAGE(STATUS Using bundled Findlibdbcmake)
02
03 FIND_PATH(
04 LIBDB_CXX_INCLUDE_DIR
05 db_cxxh
06 usrinclude
07 usrlocalinclude
08 )
09
10 FIND_LIBRARY(
11 LIBDB_CXX_LIBRARIES NAMES db_cxx
12 PATHS usrlib usrlocallib
13 )
文件 Findlibdb_cxxcmake 的命名要符合规范 FindlibNAMEcmake 其中 NAME 是函数库的名称
Findlibdb_cxxcmake 的语法与 CMakeListstxt 相同这里使用了三个命令 MESSAGE
FIND_PATH 和 FIND_LIBRARY
bull 命令 MESSAGE 会将参数的内容输出到终端
bull 命令 FIND_PATH 指明头文件查找的路径原型如下
find_path(ltVARgt name1 [path1 path2 ]) 该命令在参数 path 指示的目录中查找文件 name1
并将查找到的路径保存在变量 VAR 中清单 5第 3-8行的意思是在 usrinclude 和
usrlocalinclude 中查找文件 db_cxxh 并将 db_cxxh 所在的路径保存在
LIBDB_CXX_INCLUDE_DIR 中
bull 命令 FIND_LIBRARY 同 FIND_PATH 类似用于查找链接库并将结果保存在变量中清单 5第 10-13行
的意思是在目录 usrlib 和 usrlocallib 中寻找名称为 db_cxx 的链接库并将结果保存在
LIBDB_CXX_LIBRARIES
第二步 项目的根目录中的 CmakeListtxt 在项目的根目录中创建 CmakeListtxt
清单 6 可以查找链接库的 CMakeListtxt
01 PROJECT(main)
02 CMAKE_MINIMUM_REQUIRED(VERSION 26)
03 SET(CMAKE_SOURCE_DIR )
04 SET(CMAKE_MODULE_PATH $CMAKE_ROOTModules $CMAKE_SOURCE_DIRcmakemodules)
05 AUX_SOURCE_DIRECTORY( DIR_SRCS)
06 ADD_EXECUTABLE(main $DIR_SRCS)
07
08 FIND_PACKAGE( libdb_cxx REQUIRED)
09 MARK_AS_ADVANCED(
10 LIBDB_CXX_INCLUDE_DIR
11 LIBDB_CXX_LIBRARIES
12 )
13 IF (LIBDB_CXX_INCLUDE_DIR AND LIBDB_CXX_LIBRARIES)
14 MESSAGE(STATUS Found libdb libraries)
15 INCLUDE_DIRECTORIES($LIBDB_CXX_INCLUDE_DIR)
16 MESSAGE( $LIBDB_CXX_LIBRARIES )
17 TARGET_LINK_LIBRARIES(main $LIBDB_CXX_LIBRARIES
18 )
19 ENDIF (LIBDB_CXX_INCLUDE_DIR AND LIBDB_CXX_LIBRARIES)
在该文件中第 4 行表示到目录 cmakemodules 中查找 Findlibdb_cxxcmake 8-19 行表示查找
链接库和头文件的过程第 8 行使用命令 FIND_PACKAGE 进行查找这条命令执行后 CMake 会到变
量 CMAKE_MODULE_PATH 指示的目录中查找文件 Findlibdb_cxxcmake 并执行第 13-19 行是
条件判断语句表示如果 LIBDB_CXX_INCLUDE_DIR 和 LIBDB_CXX_LIBRARIES 都已经被赋值
则设置编译时到 LIBDB_CXX_INCLUDE_DIR 寻找头文件并且设置可执行文件 main 需要与链接库
LIBDB_CXX_LIBRARIES 进行连接
第三步执行 cmake
完成 Findlibdb_cxxcmake 和 CMakeListtxt 的编写后在项目的根目录依次执行 ldquocmake rdquo 和
ldquomake rdquo 可以进行编译结果如下图所示
图 4 使用其他程序库时 cmake 的执行结果
使用 cmake 生成 debug 版和 release 版的程序
在 Visual Studio 中我们可以生成 debug 版和 release 版的程序使用 CMake 我们也可以达到上述
效果debug 版的项目生成的可执行文件需要有调试信息并且不需要进行优化而 release 版的不需要调
试信息但需要优化这些特性在 gccg++ 中是通过编译时的参数来决定的如果将优化程度调到最高需
要设置参数-O3最低是 -O0 即不做优化添加调试信息的参数是 -g -ggdb 如果不添加这个参数调试
信息就不会被包含在生成的二进制文件中
CMake 中有一个变量 CMAKE_BUILD_TYPE 可以的取值是 Debug Release RelWithDebInfo 和
MinSizeRel当这个变量值为 Debug 的时候CMake 会使用变量 CMAKE_CXX_FLAGS_DEBUG 和
CMAKE_C_FLAGS_DEBUG 中的字符串作为编译选项生成 Makefile 当这个变量值为 Release 的时
候工程会使用变量 CMAKE_CXX_FLAGS_RELEASE 和 CMAKE_C_FLAGS_RELEASE 选项生成
Makefile
现假设项目中只有一个文件 maincpp 下面是一个可以选择生成 debug 版和 release 版的程序的
CMakeListtxt
清单 7
1 PROJECT(main)
2 CMAKE_MINIMUM_REQUIRED(VERSION 26)
3 SET(CMAKE_SOURCE_DIR )
4
5 SET(CMAKE_CXX_FLAGS_DEBUG $ENVCXXFLAGS -O0 -Wall -g -ggdb)
6 SET(CMAKE_CXX_FLAGS_RELEASE $ENVCXXFLAGS -O3 -Wall)
7
8 AUX_SOURCE_DIRECTORY( DIR_SRCS)
9 ADD_EXECUTABLE(main $DIR_SRCS)
第 5 和 6 行设置了两个变量 CMAKE_CXX_FLAGS_DEBUG 和 CMAKE_CXX_FLAGS_RELEASE
这两个变量是分别用于 debug 和 release 的编译选项编辑 CMakeListtxt 后需要执行 ccmake 命
令生成 Makefile 在进入项目的根目录输入 ccmake 进入一个图形化界面如下图所示
图 5 ccmake 的界面
按照界面中的提示进行操作按 c 进行 configure 这时界面中显示出了配置变量
CMAKE_BUILD_TYPE 的条目如下图所示
图 6 执行了 configure 以后 ccmake 的界面
下面我们首先生成 Debug 版的 Makefile 将变量 CMAKE_BUILD_TYPE 设置为 Debug 按 c 进
行 configure 按 g 生成 Makefile 并退出这时执行命令 find | xargs grep O0 后结果如下
清单 8 find | xargs grep O0的执行结果
CMakeFilesmaindirflagsmakeCXX_FLAGS = -O0 -Wall -g -ggdb
CMakeFilesmaindirlinktxtusrbinc++ -O0 -Wall -g -ggdb
CMakeFilesmaindirmaincppo -o main -rdynamic
CMakeListstxtSET(CMAKE_CXX_FLAGS_DEBUG $ENVCXXFLAGS -O0 -Wall -g -ggdb)
这个结果说明生成的 Makefile 中使用了变量 CMAKE_CXX_FLAGS_DEBUG 作为编译时的参数
下面我们将生成 Release 版的 Makefile 再次执行命令 ccmake 将变量 CMAKE_BUILD_TYPE
设置为 Release 生成 Makefile 并退出执行命令 find | xargs grep O0 后结果如下
清单 9 find | xargs grep O0的执行结果
CMakeListstxtSET(CMAKE_CXX_FLAGS_DEBUG $ENVCXXFLAGS -O0 -Wall -g -ggdb)
而执行命令 find | xargs grep O3 后结果如下
清单 10 find | xargs grep O3的执行结果
CMakeCachetxtCMAKE_CXX_FLAGS_RELEASESTRING=-O3 -DNDEBUG
CMakeCachetxtCMAKE_C_FLAGS_RELEASESTRING=-O3 -DNDEBUG
CMakeFilesmaindirflagsmakeCXX_FLAGS = -O3 -Wall
CMakeFilesmaindirlinktxtusrbinc++ -O3 -Wall
CMakeFilesmaindirmaincppo -o main -rdynamic
CMakeListstxtSET(CMAKE_CXX_FLAGS_RELEASE $ENVCXXFLAGS -O3 -Wall)
这两个结果说明生成的 Makefile 中使用了变量 CMAKE_CXX_FLAGS_RELEASE 作为编译时的参数
参考资料
bull 要了解 CMake 请参考其官方网站httpwwwcmakeorg
bull 维基百科中对 CMake 也有非常详细的说明具体请参考
httpzhwikipediaorgwikiCMake
bull 在 developerWorks Linux 专区 寻找为 Linux 开发人员(包括 Linux 新手入门)准备的更
多参考资料查阅我们 最受欢迎的文章和教程
bull 在 developerWorks 上查阅所有 Linux 技巧 和 Linux 教程
关于作者
王程明就读于吉林大学计算机科学与技术学网格计算与网络安全实验室主要研究领域为网络安全
- 在 linux 下使用 CMake 构建应用程序
-
图 3 处理多源文件目录时 cmake 的执行结果
在执行 cmake 的过程中首先解析目录 step2 中的 CMakeListstxt 当程序执行命令
ADD_SUBDIRECTORY( src ) 时进入目录 src 对其中的 CMakeListstxt 进行解析
在工程中查找并使用其他程序库的方法
在开发软件的时候我们会用到一些函数库这些函数库在不同的系统中安装的位置可能不同编译的时候需
要首先找到这些软件包的头文件以及链接库所在的目录以便生成编译选项例如一个需要使用博克利数据
库项目需要头文件 db_cxxh 和链接库 libdb_cxxso 现在该项目中有一个源代码文件 maincpp
放在项目的根目录中
第一步程序库说明文件
在项目的根目录中创建目录 cmakemodules 在 cmakemodules 下创建文件
Findlibdb_cxxcmake 内容如下
清单 5 文件 Findlibdb_cxxcmake
01 MESSAGE(STATUS Using bundled Findlibdbcmake)
02
03 FIND_PATH(
04 LIBDB_CXX_INCLUDE_DIR
05 db_cxxh
06 usrinclude
07 usrlocalinclude
08 )
09
10 FIND_LIBRARY(
11 LIBDB_CXX_LIBRARIES NAMES db_cxx
12 PATHS usrlib usrlocallib
13 )
文件 Findlibdb_cxxcmake 的命名要符合规范 FindlibNAMEcmake 其中 NAME 是函数库的名称
Findlibdb_cxxcmake 的语法与 CMakeListstxt 相同这里使用了三个命令 MESSAGE
FIND_PATH 和 FIND_LIBRARY
bull 命令 MESSAGE 会将参数的内容输出到终端
bull 命令 FIND_PATH 指明头文件查找的路径原型如下
find_path(ltVARgt name1 [path1 path2 ]) 该命令在参数 path 指示的目录中查找文件 name1
并将查找到的路径保存在变量 VAR 中清单 5第 3-8行的意思是在 usrinclude 和
usrlocalinclude 中查找文件 db_cxxh 并将 db_cxxh 所在的路径保存在
LIBDB_CXX_INCLUDE_DIR 中
bull 命令 FIND_LIBRARY 同 FIND_PATH 类似用于查找链接库并将结果保存在变量中清单 5第 10-13行
的意思是在目录 usrlib 和 usrlocallib 中寻找名称为 db_cxx 的链接库并将结果保存在
LIBDB_CXX_LIBRARIES
第二步 项目的根目录中的 CmakeListtxt 在项目的根目录中创建 CmakeListtxt
清单 6 可以查找链接库的 CMakeListtxt
01 PROJECT(main)
02 CMAKE_MINIMUM_REQUIRED(VERSION 26)
03 SET(CMAKE_SOURCE_DIR )
04 SET(CMAKE_MODULE_PATH $CMAKE_ROOTModules $CMAKE_SOURCE_DIRcmakemodules)
05 AUX_SOURCE_DIRECTORY( DIR_SRCS)
06 ADD_EXECUTABLE(main $DIR_SRCS)
07
08 FIND_PACKAGE( libdb_cxx REQUIRED)
09 MARK_AS_ADVANCED(
10 LIBDB_CXX_INCLUDE_DIR
11 LIBDB_CXX_LIBRARIES
12 )
13 IF (LIBDB_CXX_INCLUDE_DIR AND LIBDB_CXX_LIBRARIES)
14 MESSAGE(STATUS Found libdb libraries)
15 INCLUDE_DIRECTORIES($LIBDB_CXX_INCLUDE_DIR)
16 MESSAGE( $LIBDB_CXX_LIBRARIES )
17 TARGET_LINK_LIBRARIES(main $LIBDB_CXX_LIBRARIES
18 )
19 ENDIF (LIBDB_CXX_INCLUDE_DIR AND LIBDB_CXX_LIBRARIES)
在该文件中第 4 行表示到目录 cmakemodules 中查找 Findlibdb_cxxcmake 8-19 行表示查找
链接库和头文件的过程第 8 行使用命令 FIND_PACKAGE 进行查找这条命令执行后 CMake 会到变
量 CMAKE_MODULE_PATH 指示的目录中查找文件 Findlibdb_cxxcmake 并执行第 13-19 行是
条件判断语句表示如果 LIBDB_CXX_INCLUDE_DIR 和 LIBDB_CXX_LIBRARIES 都已经被赋值
则设置编译时到 LIBDB_CXX_INCLUDE_DIR 寻找头文件并且设置可执行文件 main 需要与链接库
LIBDB_CXX_LIBRARIES 进行连接
第三步执行 cmake
完成 Findlibdb_cxxcmake 和 CMakeListtxt 的编写后在项目的根目录依次执行 ldquocmake rdquo 和
ldquomake rdquo 可以进行编译结果如下图所示
图 4 使用其他程序库时 cmake 的执行结果
使用 cmake 生成 debug 版和 release 版的程序
在 Visual Studio 中我们可以生成 debug 版和 release 版的程序使用 CMake 我们也可以达到上述
效果debug 版的项目生成的可执行文件需要有调试信息并且不需要进行优化而 release 版的不需要调
试信息但需要优化这些特性在 gccg++ 中是通过编译时的参数来决定的如果将优化程度调到最高需
要设置参数-O3最低是 -O0 即不做优化添加调试信息的参数是 -g -ggdb 如果不添加这个参数调试
信息就不会被包含在生成的二进制文件中
CMake 中有一个变量 CMAKE_BUILD_TYPE 可以的取值是 Debug Release RelWithDebInfo 和
MinSizeRel当这个变量值为 Debug 的时候CMake 会使用变量 CMAKE_CXX_FLAGS_DEBUG 和
CMAKE_C_FLAGS_DEBUG 中的字符串作为编译选项生成 Makefile 当这个变量值为 Release 的时
候工程会使用变量 CMAKE_CXX_FLAGS_RELEASE 和 CMAKE_C_FLAGS_RELEASE 选项生成
Makefile
现假设项目中只有一个文件 maincpp 下面是一个可以选择生成 debug 版和 release 版的程序的
CMakeListtxt
清单 7
1 PROJECT(main)
2 CMAKE_MINIMUM_REQUIRED(VERSION 26)
3 SET(CMAKE_SOURCE_DIR )
4
5 SET(CMAKE_CXX_FLAGS_DEBUG $ENVCXXFLAGS -O0 -Wall -g -ggdb)
6 SET(CMAKE_CXX_FLAGS_RELEASE $ENVCXXFLAGS -O3 -Wall)
7
8 AUX_SOURCE_DIRECTORY( DIR_SRCS)
9 ADD_EXECUTABLE(main $DIR_SRCS)
第 5 和 6 行设置了两个变量 CMAKE_CXX_FLAGS_DEBUG 和 CMAKE_CXX_FLAGS_RELEASE
这两个变量是分别用于 debug 和 release 的编译选项编辑 CMakeListtxt 后需要执行 ccmake 命
令生成 Makefile 在进入项目的根目录输入 ccmake 进入一个图形化界面如下图所示
图 5 ccmake 的界面
按照界面中的提示进行操作按 c 进行 configure 这时界面中显示出了配置变量
CMAKE_BUILD_TYPE 的条目如下图所示
图 6 执行了 configure 以后 ccmake 的界面
下面我们首先生成 Debug 版的 Makefile 将变量 CMAKE_BUILD_TYPE 设置为 Debug 按 c 进
行 configure 按 g 生成 Makefile 并退出这时执行命令 find | xargs grep O0 后结果如下
清单 8 find | xargs grep O0的执行结果
CMakeFilesmaindirflagsmakeCXX_FLAGS = -O0 -Wall -g -ggdb
CMakeFilesmaindirlinktxtusrbinc++ -O0 -Wall -g -ggdb
CMakeFilesmaindirmaincppo -o main -rdynamic
CMakeListstxtSET(CMAKE_CXX_FLAGS_DEBUG $ENVCXXFLAGS -O0 -Wall -g -ggdb)
这个结果说明生成的 Makefile 中使用了变量 CMAKE_CXX_FLAGS_DEBUG 作为编译时的参数
下面我们将生成 Release 版的 Makefile 再次执行命令 ccmake 将变量 CMAKE_BUILD_TYPE
设置为 Release 生成 Makefile 并退出执行命令 find | xargs grep O0 后结果如下
清单 9 find | xargs grep O0的执行结果
CMakeListstxtSET(CMAKE_CXX_FLAGS_DEBUG $ENVCXXFLAGS -O0 -Wall -g -ggdb)
而执行命令 find | xargs grep O3 后结果如下
清单 10 find | xargs grep O3的执行结果
CMakeCachetxtCMAKE_CXX_FLAGS_RELEASESTRING=-O3 -DNDEBUG
CMakeCachetxtCMAKE_C_FLAGS_RELEASESTRING=-O3 -DNDEBUG
CMakeFilesmaindirflagsmakeCXX_FLAGS = -O3 -Wall
CMakeFilesmaindirlinktxtusrbinc++ -O3 -Wall
CMakeFilesmaindirmaincppo -o main -rdynamic
CMakeListstxtSET(CMAKE_CXX_FLAGS_RELEASE $ENVCXXFLAGS -O3 -Wall)
这两个结果说明生成的 Makefile 中使用了变量 CMAKE_CXX_FLAGS_RELEASE 作为编译时的参数
参考资料
bull 要了解 CMake 请参考其官方网站httpwwwcmakeorg
bull 维基百科中对 CMake 也有非常详细的说明具体请参考
httpzhwikipediaorgwikiCMake
bull 在 developerWorks Linux 专区 寻找为 Linux 开发人员(包括 Linux 新手入门)准备的更
多参考资料查阅我们 最受欢迎的文章和教程
bull 在 developerWorks 上查阅所有 Linux 技巧 和 Linux 教程
关于作者
王程明就读于吉林大学计算机科学与技术学网格计算与网络安全实验室主要研究领域为网络安全
- 在 linux 下使用 CMake 构建应用程序
-
文件 Findlibdb_cxxcmake 的命名要符合规范 FindlibNAMEcmake 其中 NAME 是函数库的名称
Findlibdb_cxxcmake 的语法与 CMakeListstxt 相同这里使用了三个命令 MESSAGE
FIND_PATH 和 FIND_LIBRARY
bull 命令 MESSAGE 会将参数的内容输出到终端
bull 命令 FIND_PATH 指明头文件查找的路径原型如下
find_path(ltVARgt name1 [path1 path2 ]) 该命令在参数 path 指示的目录中查找文件 name1
并将查找到的路径保存在变量 VAR 中清单 5第 3-8行的意思是在 usrinclude 和
usrlocalinclude 中查找文件 db_cxxh 并将 db_cxxh 所在的路径保存在
LIBDB_CXX_INCLUDE_DIR 中
bull 命令 FIND_LIBRARY 同 FIND_PATH 类似用于查找链接库并将结果保存在变量中清单 5第 10-13行
的意思是在目录 usrlib 和 usrlocallib 中寻找名称为 db_cxx 的链接库并将结果保存在
LIBDB_CXX_LIBRARIES
第二步 项目的根目录中的 CmakeListtxt 在项目的根目录中创建 CmakeListtxt
清单 6 可以查找链接库的 CMakeListtxt
01 PROJECT(main)
02 CMAKE_MINIMUM_REQUIRED(VERSION 26)
03 SET(CMAKE_SOURCE_DIR )
04 SET(CMAKE_MODULE_PATH $CMAKE_ROOTModules $CMAKE_SOURCE_DIRcmakemodules)
05 AUX_SOURCE_DIRECTORY( DIR_SRCS)
06 ADD_EXECUTABLE(main $DIR_SRCS)
07
08 FIND_PACKAGE( libdb_cxx REQUIRED)
09 MARK_AS_ADVANCED(
10 LIBDB_CXX_INCLUDE_DIR
11 LIBDB_CXX_LIBRARIES
12 )
13 IF (LIBDB_CXX_INCLUDE_DIR AND LIBDB_CXX_LIBRARIES)
14 MESSAGE(STATUS Found libdb libraries)
15 INCLUDE_DIRECTORIES($LIBDB_CXX_INCLUDE_DIR)
16 MESSAGE( $LIBDB_CXX_LIBRARIES )
17 TARGET_LINK_LIBRARIES(main $LIBDB_CXX_LIBRARIES
18 )
19 ENDIF (LIBDB_CXX_INCLUDE_DIR AND LIBDB_CXX_LIBRARIES)
在该文件中第 4 行表示到目录 cmakemodules 中查找 Findlibdb_cxxcmake 8-19 行表示查找
链接库和头文件的过程第 8 行使用命令 FIND_PACKAGE 进行查找这条命令执行后 CMake 会到变
量 CMAKE_MODULE_PATH 指示的目录中查找文件 Findlibdb_cxxcmake 并执行第 13-19 行是
条件判断语句表示如果 LIBDB_CXX_INCLUDE_DIR 和 LIBDB_CXX_LIBRARIES 都已经被赋值
则设置编译时到 LIBDB_CXX_INCLUDE_DIR 寻找头文件并且设置可执行文件 main 需要与链接库
LIBDB_CXX_LIBRARIES 进行连接
第三步执行 cmake
完成 Findlibdb_cxxcmake 和 CMakeListtxt 的编写后在项目的根目录依次执行 ldquocmake rdquo 和
ldquomake rdquo 可以进行编译结果如下图所示
图 4 使用其他程序库时 cmake 的执行结果
使用 cmake 生成 debug 版和 release 版的程序
在 Visual Studio 中我们可以生成 debug 版和 release 版的程序使用 CMake 我们也可以达到上述
效果debug 版的项目生成的可执行文件需要有调试信息并且不需要进行优化而 release 版的不需要调
试信息但需要优化这些特性在 gccg++ 中是通过编译时的参数来决定的如果将优化程度调到最高需
要设置参数-O3最低是 -O0 即不做优化添加调试信息的参数是 -g -ggdb 如果不添加这个参数调试
信息就不会被包含在生成的二进制文件中
CMake 中有一个变量 CMAKE_BUILD_TYPE 可以的取值是 Debug Release RelWithDebInfo 和
MinSizeRel当这个变量值为 Debug 的时候CMake 会使用变量 CMAKE_CXX_FLAGS_DEBUG 和
CMAKE_C_FLAGS_DEBUG 中的字符串作为编译选项生成 Makefile 当这个变量值为 Release 的时
候工程会使用变量 CMAKE_CXX_FLAGS_RELEASE 和 CMAKE_C_FLAGS_RELEASE 选项生成
Makefile
现假设项目中只有一个文件 maincpp 下面是一个可以选择生成 debug 版和 release 版的程序的
CMakeListtxt
清单 7
1 PROJECT(main)
2 CMAKE_MINIMUM_REQUIRED(VERSION 26)
3 SET(CMAKE_SOURCE_DIR )
4
5 SET(CMAKE_CXX_FLAGS_DEBUG $ENVCXXFLAGS -O0 -Wall -g -ggdb)
6 SET(CMAKE_CXX_FLAGS_RELEASE $ENVCXXFLAGS -O3 -Wall)
7
8 AUX_SOURCE_DIRECTORY( DIR_SRCS)
9 ADD_EXECUTABLE(main $DIR_SRCS)
第 5 和 6 行设置了两个变量 CMAKE_CXX_FLAGS_DEBUG 和 CMAKE_CXX_FLAGS_RELEASE
这两个变量是分别用于 debug 和 release 的编译选项编辑 CMakeListtxt 后需要执行 ccmake 命
令生成 Makefile 在进入项目的根目录输入 ccmake 进入一个图形化界面如下图所示
图 5 ccmake 的界面
按照界面中的提示进行操作按 c 进行 configure 这时界面中显示出了配置变量
CMAKE_BUILD_TYPE 的条目如下图所示
图 6 执行了 configure 以后 ccmake 的界面
下面我们首先生成 Debug 版的 Makefile 将变量 CMAKE_BUILD_TYPE 设置为 Debug 按 c 进
行 configure 按 g 生成 Makefile 并退出这时执行命令 find | xargs grep O0 后结果如下
清单 8 find | xargs grep O0的执行结果
CMakeFilesmaindirflagsmakeCXX_FLAGS = -O0 -Wall -g -ggdb
CMakeFilesmaindirlinktxtusrbinc++ -O0 -Wall -g -ggdb
CMakeFilesmaindirmaincppo -o main -rdynamic
CMakeListstxtSET(CMAKE_CXX_FLAGS_DEBUG $ENVCXXFLAGS -O0 -Wall -g -ggdb)
这个结果说明生成的 Makefile 中使用了变量 CMAKE_CXX_FLAGS_DEBUG 作为编译时的参数
下面我们将生成 Release 版的 Makefile 再次执行命令 ccmake 将变量 CMAKE_BUILD_TYPE
设置为 Release 生成 Makefile 并退出执行命令 find | xargs grep O0 后结果如下
清单 9 find | xargs grep O0的执行结果
CMakeListstxtSET(CMAKE_CXX_FLAGS_DEBUG $ENVCXXFLAGS -O0 -Wall -g -ggdb)
而执行命令 find | xargs grep O3 后结果如下
清单 10 find | xargs grep O3的执行结果
CMakeCachetxtCMAKE_CXX_FLAGS_RELEASESTRING=-O3 -DNDEBUG
CMakeCachetxtCMAKE_C_FLAGS_RELEASESTRING=-O3 -DNDEBUG
CMakeFilesmaindirflagsmakeCXX_FLAGS = -O3 -Wall
CMakeFilesmaindirlinktxtusrbinc++ -O3 -Wall
CMakeFilesmaindirmaincppo -o main -rdynamic
CMakeListstxtSET(CMAKE_CXX_FLAGS_RELEASE $ENVCXXFLAGS -O3 -Wall)
这两个结果说明生成的 Makefile 中使用了变量 CMAKE_CXX_FLAGS_RELEASE 作为编译时的参数
参考资料
bull 要了解 CMake 请参考其官方网站httpwwwcmakeorg
bull 维基百科中对 CMake 也有非常详细的说明具体请参考
httpzhwikipediaorgwikiCMake
bull 在 developerWorks Linux 专区 寻找为 Linux 开发人员(包括 Linux 新手入门)准备的更
多参考资料查阅我们 最受欢迎的文章和教程
bull 在 developerWorks 上查阅所有 Linux 技巧 和 Linux 教程
关于作者
王程明就读于吉林大学计算机科学与技术学网格计算与网络安全实验室主要研究领域为网络安全
- 在 linux 下使用 CMake 构建应用程序
-
则设置编译时到 LIBDB_CXX_INCLUDE_DIR 寻找头文件并且设置可执行文件 main 需要与链接库
LIBDB_CXX_LIBRARIES 进行连接
第三步执行 cmake
完成 Findlibdb_cxxcmake 和 CMakeListtxt 的编写后在项目的根目录依次执行 ldquocmake rdquo 和
ldquomake rdquo 可以进行编译结果如下图所示
图 4 使用其他程序库时 cmake 的执行结果
使用 cmake 生成 debug 版和 release 版的程序
在 Visual Studio 中我们可以生成 debug 版和 release 版的程序使用 CMake 我们也可以达到上述
效果debug 版的项目生成的可执行文件需要有调试信息并且不需要进行优化而 release 版的不需要调
试信息但需要优化这些特性在 gccg++ 中是通过编译时的参数来决定的如果将优化程度调到最高需
要设置参数-O3最低是 -O0 即不做优化添加调试信息的参数是 -g -ggdb 如果不添加这个参数调试
信息就不会被包含在生成的二进制文件中
CMake 中有一个变量 CMAKE_BUILD_TYPE 可以的取值是 Debug Release RelWithDebInfo 和
MinSizeRel当这个变量值为 Debug 的时候CMake 会使用变量 CMAKE_CXX_FLAGS_DEBUG 和
CMAKE_C_FLAGS_DEBUG 中的字符串作为编译选项生成 Makefile 当这个变量值为 Release 的时
候工程会使用变量 CMAKE_CXX_FLAGS_RELEASE 和 CMAKE_C_FLAGS_RELEASE 选项生成
Makefile
现假设项目中只有一个文件 maincpp 下面是一个可以选择生成 debug 版和 release 版的程序的
CMakeListtxt
清单 7
1 PROJECT(main)
2 CMAKE_MINIMUM_REQUIRED(VERSION 26)
3 SET(CMAKE_SOURCE_DIR )
4
5 SET(CMAKE_CXX_FLAGS_DEBUG $ENVCXXFLAGS -O0 -Wall -g -ggdb)
6 SET(CMAKE_CXX_FLAGS_RELEASE $ENVCXXFLAGS -O3 -Wall)
7
8 AUX_SOURCE_DIRECTORY( DIR_SRCS)
9 ADD_EXECUTABLE(main $DIR_SRCS)
第 5 和 6 行设置了两个变量 CMAKE_CXX_FLAGS_DEBUG 和 CMAKE_CXX_FLAGS_RELEASE
这两个变量是分别用于 debug 和 release 的编译选项编辑 CMakeListtxt 后需要执行 ccmake 命
令生成 Makefile 在进入项目的根目录输入 ccmake 进入一个图形化界面如下图所示
图 5 ccmake 的界面
按照界面中的提示进行操作按 c 进行 configure 这时界面中显示出了配置变量
CMAKE_BUILD_TYPE 的条目如下图所示
图 6 执行了 configure 以后 ccmake 的界面
下面我们首先生成 Debug 版的 Makefile 将变量 CMAKE_BUILD_TYPE 设置为 Debug 按 c 进
行 configure 按 g 生成 Makefile 并退出这时执行命令 find | xargs grep O0 后结果如下
清单 8 find | xargs grep O0的执行结果
CMakeFilesmaindirflagsmakeCXX_FLAGS = -O0 -Wall -g -ggdb
CMakeFilesmaindirlinktxtusrbinc++ -O0 -Wall -g -ggdb
CMakeFilesmaindirmaincppo -o main -rdynamic
CMakeListstxtSET(CMAKE_CXX_FLAGS_DEBUG $ENVCXXFLAGS -O0 -Wall -g -ggdb)
这个结果说明生成的 Makefile 中使用了变量 CMAKE_CXX_FLAGS_DEBUG 作为编译时的参数
下面我们将生成 Release 版的 Makefile 再次执行命令 ccmake 将变量 CMAKE_BUILD_TYPE
设置为 Release 生成 Makefile 并退出执行命令 find | xargs grep O0 后结果如下
清单 9 find | xargs grep O0的执行结果
CMakeListstxtSET(CMAKE_CXX_FLAGS_DEBUG $ENVCXXFLAGS -O0 -Wall -g -ggdb)
而执行命令 find | xargs grep O3 后结果如下
清单 10 find | xargs grep O3的执行结果
CMakeCachetxtCMAKE_CXX_FLAGS_RELEASESTRING=-O3 -DNDEBUG
CMakeCachetxtCMAKE_C_FLAGS_RELEASESTRING=-O3 -DNDEBUG
CMakeFilesmaindirflagsmakeCXX_FLAGS = -O3 -Wall
CMakeFilesmaindirlinktxtusrbinc++ -O3 -Wall
CMakeFilesmaindirmaincppo -o main -rdynamic
CMakeListstxtSET(CMAKE_CXX_FLAGS_RELEASE $ENVCXXFLAGS -O3 -Wall)
这两个结果说明生成的 Makefile 中使用了变量 CMAKE_CXX_FLAGS_RELEASE 作为编译时的参数
参考资料
bull 要了解 CMake 请参考其官方网站httpwwwcmakeorg
bull 维基百科中对 CMake 也有非常详细的说明具体请参考
httpzhwikipediaorgwikiCMake
bull 在 developerWorks Linux 专区 寻找为 Linux 开发人员(包括 Linux 新手入门)准备的更
多参考资料查阅我们 最受欢迎的文章和教程
bull 在 developerWorks 上查阅所有 Linux 技巧 和 Linux 教程
关于作者
王程明就读于吉林大学计算机科学与技术学网格计算与网络安全实验室主要研究领域为网络安全
- 在 linux 下使用 CMake 构建应用程序
-
6 SET(CMAKE_CXX_FLAGS_RELEASE $ENVCXXFLAGS -O3 -Wall)
7
8 AUX_SOURCE_DIRECTORY( DIR_SRCS)
9 ADD_EXECUTABLE(main $DIR_SRCS)
第 5 和 6 行设置了两个变量 CMAKE_CXX_FLAGS_DEBUG 和 CMAKE_CXX_FLAGS_RELEASE
这两个变量是分别用于 debug 和 release 的编译选项编辑 CMakeListtxt 后需要执行 ccmake 命
令生成 Makefile 在进入项目的根目录输入 ccmake 进入一个图形化界面如下图所示
图 5 ccmake 的界面
按照界面中的提示进行操作按 c 进行 configure 这时界面中显示出了配置变量
CMAKE_BUILD_TYPE 的条目如下图所示
图 6 执行了 configure 以后 ccmake 的界面
下面我们首先生成 Debug 版的 Makefile 将变量 CMAKE_BUILD_TYPE 设置为 Debug 按 c 进
行 configure 按 g 生成 Makefile 并退出这时执行命令 find | xargs grep O0 后结果如下
清单 8 find | xargs grep O0的执行结果
CMakeFilesmaindirflagsmakeCXX_FLAGS = -O0 -Wall -g -ggdb
CMakeFilesmaindirlinktxtusrbinc++ -O0 -Wall -g -ggdb
CMakeFilesmaindirmaincppo -o main -rdynamic
CMakeListstxtSET(CMAKE_CXX_FLAGS_DEBUG $ENVCXXFLAGS -O0 -Wall -g -ggdb)
这个结果说明生成的 Makefile 中使用了变量 CMAKE_CXX_FLAGS_DEBUG 作为编译时的参数
下面我们将生成 Release 版的 Makefile 再次执行命令 ccmake 将变量 CMAKE_BUILD_TYPE
设置为 Release 生成 Makefile 并退出执行命令 find | xargs grep O0 后结果如下
清单 9 find | xargs grep O0的执行结果
CMakeListstxtSET(CMAKE_CXX_FLAGS_DEBUG $ENVCXXFLAGS -O0 -Wall -g -ggdb)
而执行命令 find | xargs grep O3 后结果如下
清单 10 find | xargs grep O3的执行结果
CMakeCachetxtCMAKE_CXX_FLAGS_RELEASESTRING=-O3 -DNDEBUG
CMakeCachetxtCMAKE_C_FLAGS_RELEASESTRING=-O3 -DNDEBUG
CMakeFilesmaindirflagsmakeCXX_FLAGS = -O3 -Wall
CMakeFilesmaindirlinktxtusrbinc++ -O3 -Wall
CMakeFilesmaindirmaincppo -o main -rdynamic
CMakeListstxtSET(CMAKE_CXX_FLAGS_RELEASE $ENVCXXFLAGS -O3 -Wall)
这两个结果说明生成的 Makefile 中使用了变量 CMAKE_CXX_FLAGS_RELEASE 作为编译时的参数
参考资料
bull 要了解 CMake 请参考其官方网站httpwwwcmakeorg
bull 维基百科中对 CMake 也有非常详细的说明具体请参考
httpzhwikipediaorgwikiCMake
bull 在 developerWorks Linux 专区 寻找为 Linux 开发人员(包括 Linux 新手入门)准备的更
多参考资料查阅我们 最受欢迎的文章和教程
bull 在 developerWorks 上查阅所有 Linux 技巧 和 Linux 教程
关于作者
王程明就读于吉林大学计算机科学与技术学网格计算与网络安全实验室主要研究领域为网络安全
- 在 linux 下使用 CMake 构建应用程序
-
下面我们首先生成 Debug 版的 Makefile 将变量 CMAKE_BUILD_TYPE 设置为 Debug 按 c 进
行 configure 按 g 生成 Makefile 并退出这时执行命令 find | xargs grep O0 后结果如下
清单 8 find | xargs grep O0的执行结果
CMakeFilesmaindirflagsmakeCXX_FLAGS = -O0 -Wall -g -ggdb
CMakeFilesmaindirlinktxtusrbinc++ -O0 -Wall -g -ggdb
CMakeFilesmaindirmaincppo -o main -rdynamic
CMakeListstxtSET(CMAKE_CXX_FLAGS_DEBUG $ENVCXXFLAGS -O0 -Wall -g -ggdb)
这个结果说明生成的 Makefile 中使用了变量 CMAKE_CXX_FLAGS_DEBUG 作为编译时的参数
下面我们将生成 Release 版的 Makefile 再次执行命令 ccmake 将变量 CMAKE_BUILD_TYPE
设置为 Release 生成 Makefile 并退出执行命令 find | xargs grep O0 后结果如下
清单 9 find | xargs grep O0的执行结果
CMakeListstxtSET(CMAKE_CXX_FLAGS_DEBUG $ENVCXXFLAGS -O0 -Wall -g -ggdb)
而执行命令 find | xargs grep O3 后结果如下
清单 10 find | xargs grep O3的执行结果
CMakeCachetxtCMAKE_CXX_FLAGS_RELEASESTRING=-O3 -DNDEBUG
CMakeCachetxtCMAKE_C_FLAGS_RELEASESTRING=-O3 -DNDEBUG
CMakeFilesmaindirflagsmakeCXX_FLAGS = -O3 -Wall
CMakeFilesmaindirlinktxtusrbinc++ -O3 -Wall
CMakeFilesmaindirmaincppo -o main -rdynamic
CMakeListstxtSET(CMAKE_CXX_FLAGS_RELEASE $ENVCXXFLAGS -O3 -Wall)
这两个结果说明生成的 Makefile 中使用了变量 CMAKE_CXX_FLAGS_RELEASE 作为编译时的参数
参考资料
bull 要了解 CMake 请参考其官方网站httpwwwcmakeorg
bull 维基百科中对 CMake 也有非常详细的说明具体请参考
httpzhwikipediaorgwikiCMake
bull 在 developerWorks Linux 专区 寻找为 Linux 开发人员(包括 Linux 新手入门)准备的更
多参考资料查阅我们 最受欢迎的文章和教程
bull 在 developerWorks 上查阅所有 Linux 技巧 和 Linux 教程
关于作者
王程明就读于吉林大学计算机科学与技术学网格计算与网络安全实验室主要研究领域为网络安全
- 在 linux 下使用 CMake 构建应用程序
-
王程明就读于吉林大学计算机科学与技术学网格计算与网络安全实验室主要研究领域为网络安全
- 在 linux 下使用 CMake 构建应用程序
-