(1) 您可以通过以下方式找到 Qt 库:
find_package(Qt5Core [...] 5.6 REQUIRED)
add_executable(someExe file1.cpp)
target_link_libraries(someExe Qt5::Core)
请注意,您应该保留 Qt 的原始目录结构,还包含 Qt cmake 脚本,例如lib/cmake/Qt5/Qt5Config.cmake
如果您希望在搜索 Qt 时包含特定目录,您可以这样做(在搜索 Qt 之前):
set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} "./your/path")
例如,这可以是您提供的目录。
(2) 您可以使用 cmake 的 automoc 功能。只需添加
set(CMAKE_AUTOMOC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
在您的 cmake 脚本的开头。 CMake 还支持AUTOUIC 和AUTORCC。我还没有尝试过,但可能工作类似。
(3) 例如,您可以将自定义目标添加到您的项目中,以复制 dll。构建该目标时,将复制所有 dll。您可以从 Qt 查找脚本定义的目标(如 Qt5::Core)中获取 dll 的路径。
get_target_property(LOC_R Qt5::Core LOCATION_RELEASE)
get_target_property(LOC_D Qt5::Core LOCATION_DEBUG)
但是,您还应该扫描这些目标的依赖项(它们依赖的其他 dll)。您可以编写一个宏来扫描整个目标列表以查找对应的 dll 并将它们添加到列表中,我们将它们称为 RELEASE_DLLS 和 DEBUG_DLLS:
macro(copydlls RELEASE_DLLS DEBUG_DLLS MODULELIST)
foreach(ELEMENT ${${MODULELIST}})
get_target_property(LOC_R ${ELEMENT} LOCATION_RELEASE)
get_target_property(LOC_D ${ELEMENT} LOCATION_DEBUG)
list(APPEND ${RELEASE_DLLS} ${LOC_R})
list(APPEND ${DEBUG_DLLS} ${LOC_D})
get_target_property(DEPENDENCIES_RELEASE ${ELEMENT} IMPORTED_LINK_DEPENDENT_LIBRARIES_RELEASE)
foreach(DEPENDENCY ${DEPENDENCIES_RELEASE})
if(TARGET ${DEPENDENCY})
get_target_property(LOC_R ${DEPENDENCY} LOCATION_RELEASE)
if(${LOC_R} MATCHES ".dll$")
list(APPEND ${RELEASE_DLLS} ${LOC_R})
endif()
endif()
endforeach()
get_target_property(DEPENDENCIES_DEBUG ${ELEMENT} IMPORTED_LINK_DEPENDENT_LIBRARIES_DEBUG)
foreach(DEPENDENCY ${DEPENDENCIES_DEBUG})
if(TARGET ${DEPENDENCY})
get_target_property(LOC_D ${DEPENDENCY} LOCATION_DEBUG)
if(${LOC_D} MATCHES ".dll$")
list(APPEND ${DEBUG_DLLS} ${LOC_D})
endif()
endif()
endforeach()
get_target_property(DEPENDENCIES_RELEASE ${ELEMENT} IMPORTED_LINK_INTERFACE_LIBRARIES_RELEASE)
foreach(DEPENDENCY ${DEPENDENCIES_RELEASE})
if(TARGET ${DEPENDENCY})
get_target_property(LOC_R ${DEPENDENCY} LOCATION_RELEASE)
if(${LOC_R} MATCHES ".dll$")
list(APPEND ${RELEASE_DLLS} ${LOC_R})
endif()
endif()
endforeach()
get_target_property(DEPENDENCIES_DEBUG ${ELEMENT} IMPORTED_LINK_INTERFACE_LIBRARIES_DEBUG)
foreach(DEPENDENCY ${DEPENDENCIES_DEBUG})
if(TARGET ${DEPENDENCY})
get_target_property(LOC_D ${DEPENDENCY} LOCATION_DEBUG)
if(${LOC_D} MATCHES ".dll$")
list(APPEND ${DEBUG_DLLS} ${LOC_D})
endif()
endif()
endforeach()
endforeach()
endmacro()
然后你可以通过调用这个宏来获得一个列表中的所有 Qt dll:
IF(MSVC)
set(QT_MODULES "Qt5::Core" "Qt5::Gui" "Qt5::Widgets")
set(RELEASE_DLLS)
set(DEBUG_DLLS)
copydlls(RELEASE_DLLS DEBUG_DLLS QT_MODULES)
ENDIF(MSVC)
检索到该信息后,您可以通过以下方式创建自定义目标。假设您在RELEASE_DLLS 和DEBUG_DLLS 列表中拥有所有的dll 路径,在TARGETS 中拥有您的可执行文件名称作为列表。然后你可以这样做:
if(MSVC)
set(COPY_COMMAND_RELEASE "-E copy_if_different ")
set(COPY_COMMAND_DEBUG "-E copy_if_different ")
list(REMOVE_DUPLICATES RELEASE_DLLS)
list(REMOVE_DUPLICATES DEBUG_DLLS)
foreach(DLL ${RELEASE_DLLS})
string(CONCAT COPY_COMMAND_RELEASE "${COPY_COMMAND_RELEASE} \"${DLL}\" ")
endforeach()
foreach(DLL ${DEBUG_DLLS})
string(CONCAT COPY_COMMAND_DEBUG "${COPY_COMMAND_DEBUG} \"${DLL}\" ")
endforeach()
string(CONCAT COPY_COMMAND_RELEASE ${COPY_COMMAND_RELEASE} "\"${CMAKE_CURRENT_BINARY_DIR}/Release\" ")
string(CONCAT COPY_COMMAND_DEBUG ${COPY_COMMAND_DEBUG} "\"${CMAKE_CURRENT_BINARY_DIR}/Debug\" ")
add_custom_target(COPY_DLLS)
foreach(EXECUTABLE ${TARGETS})
add_custom_command(TARGET COPY_DLLS PRE_BUILD COMMAND ${CMAKE_COMMAND} ${COPY_COMMAND_RELEASE} COMMENT "Copying dlls to executable directory...")
add_custom_command(TARGET COPY_DLLS PRE_BUILD COMMAND ${CMAKE_COMMAND} ${COPY_COMMAND_DEBUG} COMMENT "Copying dlls to executable directory...")
endforeach()
endif()
如果您希望每次构建其他目标之一时都执行此目标,您可以这样做:
foreach(EXECUTABLE ${TARGETS})
add_dependencies(${EXECUTABLE} COPY_DLLS)
endforeach()
不要忘记您还必须将 platforms 目录从 plugins 复制到可执行文件夹,例如将其添加到复制 dll 目标:
add_custom_command(TARGET COPY_DLLS PRE_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory ${PATH_QT_ROOT}/plugins/platforms ${CMAKE_CURRENT_BINARY_DIR}/Debug/platforms
COMMAND ${CMAKE_COMMAND} -E copy_directory ${PATH_QT_ROOT}/plugins/platforms ${CMAKE_CURRENT_BINARY_DIR}/Release/platforms
COMMENT "Copying Qt platforms to executable directory...")