CMake练习
在昨天我学了CMake之后,于是我就打算把我之前写的一个小demo配上CMakeLists,毕竟那个项目只能在我电脑上运行,我还不知道怎么让别人的电脑跑那个项目
而且我之前没有学vcpkg,所有的第三方库都是我自己手动编译成.lib文件的,所以配这个CMakeLists中也非常麻烦
我首先是把CMakeLists的框架搭好了,大概就是规定了cmake的版本,规定了生成项目的名字和语言,之后让QT查找对应的MOD,qrc,ui,坚持QT的版本和各个模块是否能用
把源码(.cpp|.h|.ui)收集起来,生成可执行文件,然后把第三方的.lib链接库收集起来,且对应的.h文件也收集起来,大概就是这样,然而在我编译的时候却出问题了
问题一:因为这些都是我自己手动编译的第三方库,之前在vs中改改路径就能用,可是到了cmake中会缺少一些东西,比如说QXlsx,你不止要包含QXlsx的.lib,链接库时还要包含Qt${QT_VERSION_MAJOR}::GuiPrivate,除此之外,libcurl这个库也是,还要在链接库的时候加上ws2_32,wldap32,crypt32,normaliz,还要加上设置libcurl的静态库,还有jsoncpp,之前在vs中编译没问题,但是在cmake中又会提示你版本不对应,总之就是有非常非常多的问题,以后真的还是用vcpkg吧
点击查看代码
cmake_minimum_required(VERSION 3.10)
project(MedicalEngineering VERSION 1.0 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
#让Qt工具查找生成的头文件/资源文件(避免UI/MOC路径错误)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
#检查Qt5,6,各个模块是否能用
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core Network Quick Widgets Sql)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Network Quick Widgets Sql)
#收集源码
file(GLOB_RECURSE SOURCES
main.cpp
src/*.cpp
)
#收集头文件
file(GLOB_RECURSE HEADERS
src/*.h
)
#收集ui文件
file(GLOB_RECURSE UI_FILES
${CMAKE_CURRENT_SOURCE_DIR}/ui/*.ui
)
#设置所有的文件
set(SRC
${SOURCES}
${HEADERS}
${UI_FILES}
image.qrc
MedicalEngineeringProject.qrc
)
#设置可执行文件
add_executable(MedicalEngineering ${SRC})
#收集.lib库文件
file(GLOB_RECURSE THIRD_PARTY_LIBS
${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/*/lib/*/*.lib
${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/*/lib/*.lib
)
#配置头文件包含(除了aip-cpp-sdk-4.16.7,其他都包含到上级.h目录)
target_include_directories(MedicalEngineering
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src
#第三方库目录
${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/aip-cpp-sdk-4.16.7
${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/jsoncpp/include
${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/libcurl/include
${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/OpenSSL-Win64/include
${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/QXlsx
)
#链接库
target_link_libraries(MedicalEngineering
PRIVATE
Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Network
Qt${QT_VERSION_MAJOR}::Quick
Qt${QT_VERSION_MAJOR}::Widgets
Qt${QT_VERSION_MAJOR}::Sql
Qt${QT_VERSION_MAJOR}::GuiPrivate
${THIRD_PARTY_LIBS}
ws2_32
wldap32
crypt32
normaliz
)
install(TARGETS MedicalEngineering
RUNTIME DESTINATION bin
)

为了解决这个问题我们首先要把它们都用UTF-8 BOM保存下来

然后打开Qt,依次设置,最后在文本编译器中把UTF-8改为UTF-8 BOM,然后在CMakelists中加入这样一段代码(在可执行文件设置之前),保存,然后关掉Qt,删除对应的build,重新cmake一下就行
点击查看代码
if(MSVC)
# 只添加 /utf-8,不要加其他编码参数
add_compile_options(
"$<$<C_COMPILER_ID:MSVC>:/utf-8>"
"$<$<CXX_COMPILER_ID:MSVC>:/utf-8>"
)
endif()

问题三:
文件的包含路径问题,这个问题其实在我们编码的过程中就能避免,但是我当初做这个项目的时候还没有把不同类型文件分文件夹的习惯,所以出了这个错误
比如我们的ui文件都会编译成ui_…….h文件,而我们把ui文件都放在了ui文件夹中,所有的头文件又都放在了src文件夹中,所以当我们引用#include "ui/ui_ExtraLargeImageWidget.h"使需要在ui文件中找,而且需要再CMakeLists中加上这样一段代码
点击查看代码
#防止系统找ui文件去别的文件夹找而不是ui文件夹
set(CMAKE_AUTOUIC_SEARCH_PATHS ${CMAKE_CURRENT_SOURCE_DIR}/ui)
总结:
这个CMakeLists真的难配,以后最好还是直接用vcpkg,它能把相关的版本,库,或者其他的东西都加进来,不用手动编译库了,真的巨麻烦,还有编码的问题,这是mscv的通病,按照我的方法改就行,昨天改这玩意真的废了我一天,真麻烦
这是cmakelists源码
点击查看代码
cmake_minimum_required(VERSION 3.10)
project(MedicalEngineering VERSION 1.0 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
#让Qt工具查找生成的头文件/资源文件(避免UI/MOC路径错误)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
#防止系统找ui文件去别的文件夹找而不是ui文件夹
set(CMAKE_AUTOUIC_SEARCH_PATHS ${CMAKE_CURRENT_SOURCE_DIR}/ui)
#检查Qt5,6,各个模块是否能用
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core Network Quick Widgets Sql)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Network Quick Widgets Sql)
if(MSVC)
# 只添加 /utf-8,不要加其他编码参数
add_compile_options(
"$<$<C_COMPILER_ID:MSVC>:/utf-8>"
"$<$<CXX_COMPILER_ID:MSVC>:/utf-8>"
)
endif()
#收集源码
file(GLOB_RECURSE SOURCES
main.cpp
src/*.cpp
)
#收集头文件
file(GLOB_RECURSE HEADERS
src/*.h
)
#收集ui文件
file(GLOB_RECURSE UI_FILES
${CMAKE_CURRENT_SOURCE_DIR}/ui/*.ui
)
#设置所有的文件
set(SRC
${SOURCES}
${HEADERS}
${UI_FILES}
image.qrc
MedicalEngineeringProject.qrc
)
#设置可执行文件
add_executable(MedicalEngineering ${SRC})
target_compile_definitions(MedicalEngineering PRIVATE
CURL_STATICLIB # 告诉 libcurl 头文件使用静态库方式
)
#收集.lib库文件
file(GLOB_RECURSE THIRD_PARTY_LIBS
${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/*/lib/*/*.lib
${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/*/lib/*.lib
)
#配置头文件包含(除了aip-cpp-sdk-4.16.7,其他都包含到上级.h目录)
target_include_directories(MedicalEngineering
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src
#第三方库目录
${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/aip-cpp-sdk-4.16.7
${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/jsoncpp/include
${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/libcurl/include
${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/OpenSSL-Win64/include
${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/QXlsx
)
#链接库
target_link_libraries(MedicalEngineering
PRIVATE
Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Network
Qt${QT_VERSION_MAJOR}::Quick
Qt${QT_VERSION_MAJOR}::Widgets
Qt${QT_VERSION_MAJOR}::Sql
Qt${QT_VERSION_MAJOR}::GuiPrivate
${THIRD_PARTY_LIBS}
ws2_32
wldap32
crypt32
normaliz
)
#收集.dll文件
file(GLOB_RECURSE ALL_DLLS ${CMAKE_CURRENT_SOURCE_DIR}/*.dll)
# 编译后自动复制到程序输出目录(和exe同目录)
foreach(DLL_FILE ${ALL_DLLS})
add_custom_command(TARGET MedicalEngineering POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
${DLL_FILE}
$<TARGET_FILE_DIR:MedicalEngineering> # exe所在目录
)
endforeach()
# 4.Qt的DLL自动复制
if(WIN32)
add_custom_command(TARGET MedicalEngineering POST_BUILD
COMMAND ${CMAKE_COMMAND} -E env "PATH=${Qt${QT_VERSION_MAJOR}_DIR}/../../../bin"
$<TARGET_FILE_DIR:MedicalEngineering>/windeployqt.exe
--verbose 0
$<TARGET_FILE:MedicalEngineering>
)
endif()
install(TARGETS MedicalEngineering
RUNTIME DESTINATION bin
)
浙公网安备 33010602011771号