创建时间:2023-02-18 17:58:04
项目文件较多,全部放在一个目录下就像依托答辩。
希望能将头文件放入include
,ui文件放入ui
,源文件放入src
。
为了将Qt代码和一般非Qt代码分离开,进一步地:
qt_src
,普通源文件放入src
qt_include
,普通头文件放入include
ui
。并且使用set(CMAKE_AUTOUIC ON)
、set(CMAKE_AUTOMOC ON)
来让它自己处理。
过程中还是遇到一些问题,通过看官方文档和其他人的提问得以解决,在这里分享一下。
简化问题,就暂时只搞了顶层一个CMakeLists.txt
。
(这里只添加了必须的,如果你使用Qt Creator,最好将头文件、ui文件什么的都加进去,不然它里面看不到)
cmake_minimum_required(VERSION 3.1)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_PREFIX_PATH /opt/Qt/6.3.2/gcc_64 /opt/paddlepaddle)
set(EXE main)
project(${EXE})
aux_source_directory(qt_src SRC)
aux_source_directory(src SRC)
aux_source_directory(qt_src SRC)
FILE(GLOB QT_INC "qt_include/*.h")
list(APPEND CMAKE_AUTOUIC_SEARCH_PATHS "ui")
add_executable(${EXE} ${SRC} ${QT_INC})
find_package(Qt6 REQUIRED COMPONENTS Widgets)
find_package(OpenCV 4 REQUIRED)
find_package(FastDeploy REQUIRED)
target_include_directories(${EXE} PUBLIC
${FASTDEPLOY_INCS} include qt_include)
target_link_directories(${EXE} PUBLIC /usr/lib/seetaface6)
target_link_libraries(
${EXE}
PUBLIC Qt6::Widgets
${OpenCV_LIBS}
${FASTDEPLOY_LIBS}
SeetaAgePredictor600
SeetaAuthorize
SeetaEyeStateDetector200
SeetaFaceAntiSpoofingX600
SeetaFaceDetector600
SeetaFaceLandmarker600
SeetaFaceRecognizer610
SeetaFaceTracking600
SeetaGenderPredictor600
SeetaPoseEstimation600
SeetaQualityAssessor300
tennis_haswell
tennis_pentium
tennis_sandy_bridge
tennis)
主要看一下根目录,设想里面已经说了我的放置策略。
## 项目根目录
$ ls
build CMakeLists.txt include qt_include qt_src src ui
下面是目录详细内容,不过不是我们的重点。
## 普通源文件目录
$ ls src
app.cpp FaceAction_demo.cpp PPMatting_StaticLib_cpu.cpp video.cpp
emotion.cpp handler.cpp step.cpp
FaceAction.cpp model.cpp to.cpp
## 普通头文件目录
$ ls include
app.h FaceAction.h model.h step.h video.h
emotion.h handler.h PPMatting_StaticLib_cpu.h to.h
## Qt代码源文件目录
$ ls qt_src
cv2seetaimage.cpp main.cpp register_widget.cpp user_info.cpp
faceinfo.cpp mainfunction.cpp seetafacetools.cpp
facelogin.cpp mainwindow.cpp settingmodel.cpp
login_widget.cpp register_info.cpp trans.cpp
## Qt头文件目录
$ ls qt_include
cv2seetaimage.h login_widget.h register_info.h settingmodel.h
faceinfo.h mainfunction.h register_widget.h trans.h
facelogin.h mainwindow.h seetafacetools.h user_info.h
## ui文件目录
$ ls ui
facelogin.ui mainfunction.ui register_info.ui user_info.ui
login_widget.ui mainwindow.ui register_widget.ui
笨方法是手动,把文件一个一个加进去,这样不够方便。
对于源文件,我们都知道可以用aux_source_directory()
来添加,但是它只会添加源文件,不会添加目录下的.h
文件和.ui
文件。
解决方法:
FILE(GLOB UI "ui/*.ui")
FILE(GLOB INC "include/*.h")
提一句,有看到说FILE GLOB邪恶的,也许有什么缺点,暂且没有过度关注。
由于采用set(CMAKE_AUTOUIC ON)
的方式处理ui文件,编译时会报错找不到ui文件。
需要将ui文件夹加入AUTOUIC
的搜索目录,这样AUTOUIC
处理时才能找到ui文件。
解决方法:
list(APPEND CMAKE_AUTOUIC_SEARCH_PATHS "ui")
注意:是
CMAKE_AUTOUIC_SEARCH_PATHS
,而不是AUTOUIC_SEARCH_PATHS
。这个把我坑惨了。
接下来可能会继续报错找不到生成的对应的ui_XXX.h
头文件,可以尝试以下选项之一:
set(CMAKE_INCLUDE_CURRENT_DIR ON)# 其实只要这一条就够了,后面两条似乎也可以。
include_directories(${CMAKE_BINARY_PATH})
include_directories(${CMAKE_CURRENT_BINRAY_PATH})
因为自动生成的ui_XXX.h
头文件是在构建目录下的,添加它即可。
undefined to 'vtable for XXX'
)这个是最让我头疼的,cmake官网也没有说怎么解决。(这部分还专门翻译了一下,见我的另一篇博客:cmake-qt AUTOMOC)
看到网上的解释,意思是如果你不在add_executable()
中添加使用了Qt元系统的头文件,那么AUTOMOC
就不会处理这些头文件。
所以我们把Qt的头文件加入到add_executable()
即可,这也是我为什么将普通头文件和Qt头文件分离开的原因之一(因为普通头文件不需要,虽然加上也没错)。
add_executable(${EXE} ${SRC} ${INC})
我想后面如果要添加资源文件,那么可能会有类似的问题,遇到了再回来补充。
2023.5.7更新:
资源文件,也就是CMAKE_AUTORCC
的篇幅较多,不宜在这里展开,见另一篇博客:
探索qrc,rcc和CMAKE_AUTORCC