这似乎是一个很简单的问题,因为用 qmake 的时候确实很简单,但是对于一个刚刚开始接触CMake的用户的来说,太困难了,耗了整整一天的时间来查资料,不过还好,总算找到一个可以工作的方案。废话少说,看问题 问题的引入这是一个很简单的程序,不是么? //main.cpp #include <QtGui/QApplication> #include <QtGui/QWidget> class Widget:public QWidget { Q_OBJECT public: Widget(QWidget * parent=0):QWidget(parent){} }; int main(int argc, char** argv) { QApplication app(argc, argv); Widget w; w.show(); return app.exec(); } #include "main.moc" 这个例子确实很简单,当我们用 qmake 是,我们只需要编写下面的 .pro 文件即可: TEMPLATE = app SOURCES += main.cpp 然后 qmake, make, 万事大吉。可是, CMakeLists.txt 怎么写先写个框出来, PROJECT(mytest) CMAKE_MINIMUM_REQUIRED(VERSION 2.6) FIND_PACKAGE(Qt4 COMPONENTS QtCore QtGui REQUIRED) INCLUDE(${QT_USE_FILE}) SET(pro_SOURCES main.cpp) #QT4_WRAP_CPP(Generated_MOC_SRCS main.cpp) #SET_SOURCE_FILES_PROPERTIES(${Generated_MOC_SRCS} PROPERTIES HEADER_FILE_ONLY true) #QT4_AUTOMOC(${pro_SOURCES}) #QT4_GENERATE_MOC(main.cpp ${CMAKE_CURRENT_BINARY_DIR}/main.moc) #SET_SOURCE_FILES_PROPERTIES(main.cpp PROPERTIES OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/main.moc) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) ADD_DEFINITIONS(${QT_DEFINITIONS}) ADD_EXECUTABLE(mytest ${pro_SOURCES} #${CMAKE_CURRENT_BINARY_DIR}/main.moc #${Generated_MOC_SRCS} ) TARGET_LINK_LIBRARIES(mytest ${QT_LIBRARIES}) QT4_WRAP_CPP我们尝试一下,用 QT4_WRAP_CPP 能解决问题吗? 首先,我们启用 QT4_WRAP_CPP(Generated_MOC_SRCS main.cpp)
只需要将程序内的 #include "main.moc"改为#include "moc_main.cxx"即可
好吧,我们将其生成的文件加入 ADD_EXECUTABLE 中(即去掉#${Generated_MOC_SRCS} 前面的注释)。
为什么? 因为 moc_main.cxx 被加入到了依赖中:一方面他被包含进了我们的 main.cpp 文件,另一方面,cmake还会尝试去单独编译它。 或许你说不就是重复了嘛,把 main.cpp 中的 #include 去掉不就行了么。但不幸,这么做不工作,moc_main.cxx 无法编译通过 无法通过的原因:moc对 xxx.h 和 xxx.cpp 处理时采取的方式不同: 对头文件,生成的文件内中将包含自动包含xxx.h;后者则不会自动包含xxx.cpp!!于是这样的文件的无法单独编译的。
SET_SOURCE_FILES_PROPERTIES(${Generated_MOC_SRCS} PROPERTIES HEADER_FILE_ONLY true)
QT4_AUTOMOCQT4_WRAP_CPP 不理想,用 QT4_WRAP_CPP 能解决问题吗? 我们来看看 说明:cmake的手册中提到,该宏还处于试验阶段,不如QT4_WRAP_CPP成熟,我们不考虑这个,先看起能不能用 首先,启用automoc QT4_AUTOMOC(${pro_SOURCES})
其工作方式是这样的,首先扫描pro_SOURCES文件,如果发现其中#include "xxx.moc",它将尝试生成 xxx.moc。 怎么生成xxx.moc呢?它将查找 xxx.hpp 和 xxx.h 文件,找到后将moc该头文件来生成 xxx.moc 发现问题了吧,它处理的是头文件,而不是我们的main.cpp文件。
IF(EXISTS ${_abs_PATH}/${_basename}.hpp) SET(_header ${_abs_PATH}/${_basename}.hpp) ELSE(EXISTS ${_abs_PATH}/${_basename}.hpp) if(EXISTS ${_abs_PATH}/${_basename}.h) # we add this line SET(_header ${_abs_PATH}/${_basename}.h) else(EXISTS ${_abs_PATH}/${_basename}.h) #we add this line SET(_header ${_abs_PATH}/${_basename}.cpp) #we add this line endif(EXISTS ${_abs_PATH}/${_basename}.h) #we add this line ENDIF(EXISTS ${_abs_PATH}/${_basename}.hpp)
QT4_GENERATE_MOCQT4_AUTOMOC 不解决问题,接续探索答案,于是注意到 QT4_GENERATE_MOC 从 cmake的模块findqt4.cmake 中看到这个宏的时候,我眼睛一亮,认定答案就是它了: QT4_GENERATE_MOC(main.cpp ${CMAKE_CURRENT_BINARY_DIR}/main.moc)
可是我怎么让他执行呢?肯定要添加依赖关系了,翻啊翻cmake手册,终于发现一个靠谱的 SET_SOURCE_FILES_PROPERTIES(main.cpp PROPERTIES OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/main.moc)
太高兴了,这个可以工作了。 经高人指点,可以不用上面的 SET_SOURCE_FILES_PROPERTIES 语句,将文件加入 ADD_EXECUTABLE 即可。 ${CMAKE_CURRENT_BINARY_DIR}/main.moc
现在它终于比较好的工作了. 完整的CMakeList.txtPROJECT(mytest) CMAKE_MINIMUM_REQUIRED(VERSION 2.6) FIND_PACKAGE(Qt4 COMPONENTS QtCore QtGui REQUIRED) INCLUDE(${QT_USE_FILE}) SET(pro_SOURCES main.cpp) QT4_GENERATE_MOC(main.cpp ${CMAKE_CURRENT_BINARY_DIR}/main.moc) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) ADD_DEFINITIONS(${QT_DEFINITIONS}) ADD_EXECUTABLE(mytest ${pro_SOURCES} ${CMAKE_CURRENT_BINARY_DIR}/main.moc ) TARGET_LINK_LIBRARIES(mytest ${QT_LIBRARIES}) 小记
|
Qt4的xxx.cpp文件内包含Q_OBJECT时CMakeLists.txt的编写
最新推荐文章于 2022-06-28 12:24:52 发布