Cmake学习小结

日期:2015年2月13日 10:02 星期五 农历 甲午 马年 十二月廿五
修改记录:
2015-02-26 补充10-12条
2015-03-31 补充第13条


正文:
想学Cmake有很长一段时间了,但是一直没有找到好的学习契机。根据以往的经验,在实际项目中去学习一个东西往往是最快的,在实际项目中通过问题与触发学习一个东西往往是印象最深刻的。最近发现了BullseyeCoverage这个可以在VC下就看代码覆盖率的小工具,但是打开这个工具就会产生"compiler out of heap"的告警,逼得我不得不修改编译器的Zm参数,经过多次尝试,无论是用Replace替换还是直接用set指定,抑或是直接在执行cmake命令的时候指定,都没有达到我想要的效果,几经折腾,终于发现cmake还有cache这个东西存在,最终攻克了这个问题。经过这次折腾,我觉得我对cmake已经有了一定的了解,该是对它做一个系统的学习的时候了,于是便有了这篇总结。在写的同时,我希望能自己独立完成一个工程的cmake编写,这样才是真正入门了。


1. 指定cmake的最低版本,这个是必须的,否则cmake将无法执行
cmake_minimum_required(VERSION 2.8)


2. 创建一个空的工程
Project(Gtest)


3. 指定这个工程应该包含哪些头文件,把工程所依赖的所有的头文件全都添加进来即可。
INCLUDE_DIRECTORIES(
"${CMAKE_CURRENT_SOURCE_DIR}/3th/include"
"${CMAKE_CURRENT_SOURCE_DIR}/code/include"
"${CMAKE_CURRENT_SOURCE_DIR}/code/include/base"
)


4. 指定工程所包含的源文件
这个步骤可以有两种方法,一种是通过set命令把源文件列表都放到一个变量中去
set(all_files 
"${CMAKE_CURRENT_SOURCE_DIR}/code/src/Library.cpp" 
"${CMAKE_CURRENT_SOURCE_DIR}/test/LibraryTest.cpp" 
"${CMAKE_CURRENT_SOURCE_DIR}/test/main.cpp"
)
还有一种方法,比这个稍微简单一点点,就是利用FILE方法递归获取所有的文件
FILE(GLOB_RECURSE all_files 
code/*.cpp
test/*.cpp
)
如果仅仅是生成最简工程,只添加cpp或者c文件就已经足够了,但是很多工程在指定源文件的时候也把各种头文件添加进去了,因为如果你不添加进去,头文件不会显示在工程的list中,如果要查看,只能在External Dependencies中查看,不是很方便。
FILE(GLOB_RECURSE all_files 
code/*.cpp
code/*.h
test/*.cpp
test/*.h
3th/*.h
)
把头文件加上以后,所有的头文件就自动添加到"Header Files"中了


5. 指定工程生成的可执行程序的名称以及指定可执行程序依赖的源文件
add_executable(Gtest ${all_files})


====================================================================================================
===================== 通过以上几步,已经可以生成一个最简单的工程了 =================================
====================================================================================================


6. 如果程序依赖其它的外部库的话,还需要指定库的位置,并把库加入链接
link_directories("${CMAKE_CURRENT_SOURCE_DIR}/3th/lib")  #这个操作必须放到第5步之前,否则链接的时候会提示找不到库
target_link_libraries(Gtest gtest-vc10)      #这个操作必须放在第5步之后,因为它的第一个参数就是第5步产生的


7. 第4步中生成的源文件与头文件都是平铺开放在工程中的,没有按实际的目录结构放置。如果想按目录结构还放置应该怎么办呢?
cmake提供了一个SOURCE_GROUP命令来把文件按照路径归类,别人提供了一个宏,我摘录于此。
MACRO(source_group_by_dir source_files)
    SET(sgbd_cur_dir ${CMAKE_CURRENT_SOURCE_DIR})
    FOREACH(sgbd_file ${${source_files}})
        STRING(REGEX REPLACE ${sgbd_cur_dir}/\(.*\) \\1 sgbd_fpath ${sgbd_file})
        STRING(REGEX REPLACE "\(.*\)/.*" \\1 sgbd_group_name ${sgbd_fpath})
        STRING(COMPARE EQUAL ${sgbd_fpath} ${sgbd_group_name} sgbd_nogroup)
        IF(MSVC)
            string(REPLACE "/" "\\" sgbd_group_name ${sgbd_group_name})
        ENDIF(MSVC)
        IF(sgbd_nogroup)
            SET(sgbd_group_name "\\")
        ENDIF(sgbd_nogroup)
        SOURCE_GROUP(${sgbd_group_name} FILES ${sgbd_file})
    ENDFOREACH(sgbd_file)
ENDMACRO(source_group_by_dir)


在add_executable之前调用这个宏进行分组即可。
source_group_by_dir(all_files)


8. cmake是支持跨平台的,对于windows与linux需要区别对待的地方应该怎么做呢?通常这种情况,我们需要在makefile中定义一些预编译宏来解决这个问题,cmake同样是支持的,首先,它内部有一些预编译宏,例如:
if(WIN32)
    link_directories("C:\\Program Files\\Microsoft SDKs\\Windows\\v7.0A\\Lib\\")
else()
    link_directories(${CMAKE_SOURCE_DIR}/third_party/gcov)
endif()
自己也可以定义一些预编译宏,例如:
add_definitions(-D_SCL_SECURE_NO_WARNINGS)
add_definitions(-DWIN32_LEAN_AND_MEAN)
add_definitions(-D_XGW_CSS_SIMU_VC)
add_definitions(-D_XGW_CSS_SIMU_GNU)
add_definitions(-D_SIMU_VC)
add_definitions(-D_HSGW_SIMU_VC)
add_definitions(-D_PHY_BOARD=_BT_PC)
add_definitions(-D_SVR_NAME=_SN_PSCTRL)
这些自定义的预编译宏在代码中就可以直接使用了,因为他们最终会传递到makefile中去


9. cmake对变量的赋值与对变量的引用
cmake通过set命令对变量进行赋值,例如:
set(all_files 
"${CMAKE_CURRENT_SOURCE_DIR}/code/src/Library.cpp" 
"${CMAKE_CURRENT_SOURCE_DIR}/test/LibraryTest.cpp" 
"${CMAKE_CURRENT_SOURCE_DIR}/test/main.cpp"
)
后面的参数都用空格或者回车隔开,最终的值放在第一个参数中,是一个list
对变量的引用用$符号,例如上例中的${CMAKE_CURRENT_SOURCE_DIR},但是如果变量用在if条件中,直接使用变量名即可


10. cmake提供了一些内置变量,这些内部变量大多以CMAKE_或者PROJECT_开头,可以通过set命令修改这些变量的默认值,例如
CMAKE_CURRENT_SOURCE_DIR:表示当前的CmakeList.txt所在的目录
CMAKE_SOURCE_DIR与PROJECT_SOURCE_DIR表示工程顶层目录
CMAKE_C_FLAGS与CMAKE_CXX_FLAGS分别表示C与C++编译时的编译选项


11. cmake可以通过message命令打印字符串或者参数的值,例如:
message(STATUS "CMake project files for xgwFT")
message(STATUS "CMake C compile: ${CMAKE_C_COMPILER}")


12. cmake存在一个cache机制,因为这种机制的存在,导致cmake的set命令有一些陷阱,通过cmake的帮助文件可以看出,一般情况下,用户只能对cache中不存在的变量进行set操作,如果对cache中存在的命令进行set操作是不生效的,因为cmake会直接从cache中取这个变量的值。例如说CMAKE_C_FLAGS与CMAKE_CXX_FLAGS等一些cmake的内置变量,它们在cache肯定是存在的,所以直接对它们进行set是不会生效的,需要强制写入cache才会生效。我曾经在这个上面吃了亏,修改编译选项总是修改不成功,折腾了两天才发现这个东东,还是没仔细读帮忙文件啊!看来无论用什么工具,都要学会阅读自带的帮助文件。例如:
set(CMAKE_C_FLAGS " /DWIN32 /D_WINDOWS /W0 /Zm100 /Gm") ----不生效
set(CMAKE_C_FLAGS " /DWIN32 /D_WINDOWS /W0 /Zm100 /Gm" CACHE FORCE "") ----生效


13. 如果想在cmake中调用外部命令,可以通过add_custom_command命令来实现。
add_custom_command(OUTPUT output1 [output2 ...]
                 COMMAND command1 [ARGS] [args1...]
                 [COMMAND command2 [ARGS] [args2...] ...]
                 [MAIN_DEPENDENCY depend]
                 [DEPENDS [depends...]]
                 [IMPLICIT_DEPENDS <lang1> depend1 ...]
                 [WORKING_DIRECTORY dir]
                 [COMMENT comment] [VERBATIM] [APPEND])


add_custom_command(TARGET target
                 PRE_BUILD | PRE_LINK | POST_BUILD
                 COMMAND command1 [ARGS] [args1...]
                 [COMMAND command2 [ARGS] [args2...] ...]
                 [WORKING_DIRECTORY dir]
                 [COMMENT comment] [VERBATIM])
它的详细用法如上,第一种是根据已有文件生成另外一个文件,在构建时就会调用。第二中是在编译前后可以增加一下外部命令的调用,当使用这种方式时,TARGET一定要填对,一般是ProjectName. 之所以如此,是因为cmake提供的命令,有一些是在执行cmakelist文件的时候执行的,另外有些命令是用于执行makefile的时候执行的,这样它就既能控制makefile的生成,又能控制makefile的执行。













  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: "master cmake pdf" 这句话翻译成中文是“掌握 CMake PDF”。以下是关于这个话题的300字中文回答: CMake是一个跨平台的构建工具,用于管理和生成项目的构建过程。掌握CMake对于软件开发者来说非常重要,能够帮助他们更高效地组织自己的代码和构建过程。不仅如此,掌握CMake还可以使开发者更容易地在不同的操作系统和编译器之间进行移植。 PDF是一种用于呈现和共享电子文档的文件格式。CMake可以与各种工具集成,包括可以将项目文档导出为PDF格式的工具。通过掌握CMake的相关命令和选项,开发者可以自定义文档生成的方式,并将其导出为PDF文件,以便与团队成员共享或者进行版本控制。 要掌握CMake,可以从学习CMake的基本概念和工作原理开始。可以通过阅读CMake的官方文档或者参考书籍来获得更详细的了解。在学习过程中,需要熟悉CMake的语法和常用命令,例如添加源文件、链接库和设置编译选项等。通过实际的项目实践,开发者可以更深入地理解CMake的使用和调试技巧。 在掌握CMake之后,开发者可以将项目的构建过程更加模块化和可维护,使项目的代码更易读和易于扩展。此外,CMake还可以与其他工具集成,如静态分析工具、测试框架和持续集成系统,以进一步提高开发效率和代码质量。 总而言之,掌握CMake和PDF生成是软件开发过程中的重要技能,可以帮助开发者更好地管理和构建项目,提高开发效率和代码质量。 ### 回答2: cmake是一种跨平台的构建工具,它可以自动生成各种不同平台下的构建脚本。使用cmake可以方便地管理项目的构建过程,使得整个项目的构建过程更加简洁、可维护。 PDF(Portable Document Format)是一种通用的文档格式,它可以在不同平台和操作系统之间进行文档的交流和共享。PDF具有格式统一、跨平台可用的特点,使得用户可以在不同的设备上保持文档的一致性,方便地进行阅读和打印。 "master cmake pdf" 这个短语可以理解为掌握cmake构建工具和PDF文档格式的含义。 要掌握cmake,首先需要学习cmake的基本语法和命令。可以通过阅读cmake的官方文档、参考书籍或者在线教程来学习。掌握cmake后,我们就可以使用cmake来管理项目的构建过程,从而实现项目的自动化构建。 要掌握PDF,可以了解PDF的格式规范和特点。可以学习PDF的标准化组织Adobe的相关文档,对PDF的结构、元数据和样式进行了解。同时,还可以学习使用Adobe Acrobat等专业软件创建和编辑PDF文档,以及使用其他工具将不同格式的文档转换为PDF格式。 掌握cmake和PDF后,我们可以将这两者结合起来,通过使用cmake来管理生成PDF文档的过程。例如,可以通过编写cmake脚本来自动化生成PDF文档,包括将文本、图片等内容转换为PDF格式,并指定样式和布局。通过将cmake和PDF结合使用,可以提高项目的构建效率和文档生成的一致性。 总结来说,掌握cmake和PDF可以提高项目的构建效率和文档生成的一致性。学习cmake和PDF的基本知识和技能,可以通过自动化构建和标准化文档格式来简化项目管理和交流。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值