以前习惯了在windows下写代码时直接用MSVC新建项目,后来要在Linux下开发,以前写的代码不能直接使用,还要仔细地写makefile,实在是费事费力;再后来又在Mac中使用Xcode,除了对自己编写的代码本身的可移植性有很高的要求外,还会遇到使用QT、VTK、ITK、OpenCV等其他开源库的情况,这时安装好这些库后要在自己的项目文件中使用,包含文件、依赖库的配置也比较费事。
直到尝试了用Cmake来生成项目文件,上面的这些问题才得到很好的解决。CMake是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装(编译过程),能够输出各种各样的makefile或者project文件,能测试编译器所支持的C++特性,类似UNIX下的automake。Cmake虽然使项目的创建和管理变得简单,然而熟练地掌握其用法也非易事。快速入门的方法可以参见:http://sewm.pku.edu.cn/src/paradise/reference/CMake%20Practice.pdf
以下是一个基于ITK和QT的项目的例子,该项目用来开发一个三维图像处理的小工具,源文件分成了几个子文件夹,例如view2D, controller等。为了防止在单个Cmakelist.txt中出现过多的内容,使用了subdirectory的方式。其原理是将view2D与controller文件夹下的内容分别编译成库文件,然后再与项目中的可执行文件进行连接。
项目文件夹下的 CMakeList.txt 的内容为:
# 版本要求
cmake_minimum_required(VERSION 2.8)
# 项目名称
PROJECT(SegTool)
# 使用QT
find_package ( Qt4 COMPONENTS QtGui QtOpenGL REQUIRED )
set (QT_USE_QTOPENGL TRUE)
INCLUDE(${QT_USE_FILE})
message("Libs: ${QT_LIBRARIES}")
add_definitions(${QT_DEFINITIONS})
include_directories( ${QT_QTOPENGL_INCLUDE_DIR} ${OPENGL_INCLUDE_DIR} )
# 使用了QT的头文件,这些文件要先生成相应的moc_*.cxx才能使用QT中的信号和槽的机制。
set (FOO_MOC_HEADERS
main/mainwindow.h)
# 所有的.h文件
set (HEADER_FILES
main/mainwindow.h
main/GlobalDefinition.h)
# 所有的.cpp文件
set (SOURCES_FILES
main/main.cpp
main/mainwindow.cpp
main/GlobalDefinition.cpp
${HEADER_FILES})
# QT的处理,将*.ui界面文件转换成相应的ui_*.h文件,由使用了QT特性的头文件生成moc_*.cxx文件。
QT4_WRAP_UI(UISrcs main/mainwindow.ui)
QT4_WRAP_CPP(MOCSrcs ${FOO_MOC_HEADERS})
#使用ITK
find_package(ITK REQUIRED)
include(${ITK_USE_FILE})
if (ITKVtkGlue_LOADED)
find_package(VTK REQUIRED)
include(${VTK_USE_FILE})
else()
find_package(ItkVtkGlue REQUIRED)
include(${ItkVtkGlue_USE_FILE})
set(Glue ItkVtkGlue)
endif()
# 添加子文件夹,每一个文件夹下面分别包含一个CMakeList.txt,各生成一个库文件
add_subdirectory(model)
add_subdirectory(view2d)
add_subdirectory(view3d)
add_subdirectory(interaction)
add_subdirectory(controller)
add_subdirectory(algorithm)
include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
# 生成可执行文件
ADD_EXECUTABLE(SegTool ${SOURCES_FILES} ${MOCSrcs} ${UISrcs})
# 连接所需要的库
TARGET_LINK_LIBRARIES(SegTool ${QT_LIBRARIES} ${Glue} ${VTK_LIBRARIES} ${ITK_LIBRARIES} model view2d view3d interaction controller algorithm)
子文件夹下,以view2D为例,CMakeList.txt的内容为:
# 得到所有的头文件和源文件
FILE(GLOB VIEW2D_MOC_HEADERS *.h)
FILE(GLOB VIEW2D_SOURCES_FILES *.cpp *.h)
# 生成moc_*.cxx文件
QT4_WRAP_CPP(VIEW2D_MOCSrcs ${VIEW2D_MOC_HEADERS})
include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
# 生成库文件
ADD_LIBRARY(view2d ${VIEW2D_MOCSrcs} ${VIEW2D_SOURCES_FILES} ../GLSL/GLSLShader.cpp)
# 对源文件进行分组,方便在IDE中查看和管理
source_group(ImageWidget\\Headers FILES gl2dwidget.h
TextureLoadingWidget.h
axialglwidget.h
sagittalglwidget.h
coronalglwidget.h
CentralWidget.h
view2dwidget.h
viewassemblewidget.h)
source_group(ImageWidget\\Sources FILES gl2dwidget.cpp
TextureLoadingWidget.cpp
axialglwidget.cpp
sagittalglwidget.cpp
coronalglwidget.cpp
CentralWidget.cpp
view2dwidget.cpp
viewassemblewidget.cpp)
source_group(PanelWidget\\Headers FILES gcpanelwidget.h
ThresholdSegPanelWidget.h
SettingPanelWidget.h
PanelWidget.h )
source_group(PanelWidget\\Sources FILES gcpanelwidget.cpp
ThresholdSegPanelWidget.cpp
SettingPanelWidget.cpp
PanelWidget.cpp )
Enjoy!