最近一直在研究cmake构建项目,之前接触cmake的时候就感觉不太喜欢cmake,觉得它太乱了,产生了太多的中间文件,产生的项目文件也不是特别友好,在windows下,生成的项目文件经常需要修改,而在linux和常规的makefile风格也打不一致,文件太多,不方便学习研究。
不够经过这段时间系统的研究,觉得cmake还是非常强大的,吃透之后它的确非常方便,比手工写makefile要简单的多,因此在linux使用cmake我觉得是非常合适的,不过在windows则相对要差一些。cmake的主要优势在于自动生成项目文件,如果熟练掌握,对于自动构架项目还是有很大帮助的。
本文主要讲下在windows下使用cmake给项目添加预编译头文件功能,做过windows项目的同学都知道,windows下使用预编译头文件非常普遍,能加快编译速度,一些头文件交叉引用问题也能使用它来解决,但是cmake对这块支持不是很完善,资料也很少,我在网上查询了很久,才找到一个合适的方案,下面就详细讲下这个方案。
为了复用预编译这个功能,我们把预编译相关的cmake功能编写成一个文件,比如叫msvcpch.cmake。
#msvcpch.cmake
#声明一个宏,参数如下
#USE_MSVC_PCH :宏名字
#PCH_TARGET :项目名称
#PCH_HEADER_FILE :预编译头文件名称(stdafx.h)
#PCH_SOURCE_FILE :预编译源文件名称(stdafx.cpp)
MACRO(USE_MSVC_PCH PCH_TARGET PCH_HEADER_FILE PCH_SOURCE_FILE)
IF(MSVC)
# 获取预编译头文件的文件名,通常是stdafx
GET_FILENAME_COMPONENT(PCH_NAME ${PCH_HEADER_FILE} NAME_WE)
# 生成预编译文件的路径
IF(CMAKE_CONFIGURATION_TYPES)
# 如果有配置选项(Debug/Release),路径添加以及配置选项
SET(PCH_DIR "${CMAKE_CURRENT_BINARY_DIR}/PCH/${CMAKE_CFG_INTDIR}")
ELSE(CMAKE_CONFIGURATION_TYPES)
SET(PCH_DIR "${CMAKE_CURRENT_BINARY_DIR}/PCH")
ENDIF(CMAKE_CONFIGURATION_TYPES)
# 创建预编译文件的路径
FILE(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/PCH)
# 设置项目属性,使用预编译头文件
SET_TARGET_PROPERTIES(${PCH_TARGET} PROPERTIES COMPILE_FLAGS
"/Yu${PCH_HEADER_FILE} /FI${PCH_HEADER_FILE} /Fp${PCH_DIR}/${PCH_NAME}.pch")
# 预编译源文件(stdafx.cpp)设置属性,创建预编译文件
SET_SOURCE_FILES_PROPERTIES(${PCH_SOURCE_FILE} PROPERTIES COMPILE_FLAGS
"/Yc${PCH_HEADER_FILE}")
# 把预编译文件寄到清除列表
SET_DIRECTORY_PROPERTIES(PROPERTIES
ADDITIONAL_MAKE_CLEAN_FILES ${PCH_DIR}/${PCH_NAME}.pch)
ENDIF(MSVC)
ENDMACRO(USE_MSVC_PCH)
需要注意的是,PCH_HEADER_FILE (stdafx.h)不需要路径,只传文件名即可,而PCH_SOURCE_FILE(stdafx.cpp)则需要传完整路径,即在VS项目文件(.vcxproj)中能访问的正确路径,可以是相对路径,也可以绝对路径。
编写好这个文件之后,我们以后写cmake文件的时候可以可以直接引用它了。如下则是使用的示例:
if (CMAKE_SYSTEM_NAME MATCHES "Windows")
# msvcpch.cmake的路径
set(MSVCCMAKE_PCH ${CMAKE_SOURCE_DIR}/build/)
# 预编译头文件和源文件的路径
set(STDAFX_PCH_H ${CMAKE_SOURCE_DIR}/Protocol/stdafx.h)
set(STDAFX_PCH_C ${CMAKE_SOURCE_DIR}/Protocol/stdafx.cpp)
# 添加预编译cmake的路径
LIST(APPEND CMAKE_MODULE_PATH ${MSVCCMAKE_PCH})
# 包含msvcpch.cmake
INCLUDE(msvcpch)
endif ()
if (CMAKE_SYSTEM_NAME MATCHES "Windows")
# 添加源文件,生成可执行文件
add_executable(Proxy ${proxy_src} ${STDAFX_PCH_C})
# 添加链接库
target_link_libraries(Proxy Comm)
# 此处是关键,添加我们在msvcpch.cmake定义的宏
USE_MSVC_PCH(Proxy stdafx.h ${STDAFX_PCH_C})
endif ()
好了,使用上面的方法就可以给vs的工程添加预编译头文件的支持了。