以前习惯了在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 )