gpt4 book ai didi

c++ - CMake - 如何链接到项目中打包的外部库?

转载 作者:太空宇宙 更新时间:2023-11-04 13:17:13 25 4
gpt4 key购买 nike

如何链接到项目中打包的外部库?

我的项目是这样设置的:

我有一个名为 App 的文件夹,这是我的 main.cpp 所在的位置。

C:\Raph\src\App

main.cpp

我还有一个名为“ExternalLibrary”的文件夹,我在其中捆绑了我需要在我的项目中使用的 Qt 库:

C:\Raph\src\ExternalLibrary\Platform\Windows\Qt5.6\VS2013_64bit

它包含 3 个文件夹:

**bin**
moc.exe
rcc.exe
uic.exe
......
bunch of Qt dll files

**include**
bunch of Qt header files

**lib**
bunch of Qt lib files

我需要设置 Cmake 来做三件事:

  1. 动态链接到我打包在“ExternalLibrary”中的 Qt 库。

  2. 每次在项目中添加Qt类或资源时自动执行moc.exe、uic.exe、rcc.exe。我也不需要任何生成的 moc_myClassname.cpp 显示在项目中。

  3. 我希望所有 Qt dll 都位于可执行文件所在的 bin 文件夹中。例如:

    C:\Raph\build\Raph\Windows\x64\Debug\bin

    Raph.exe + 所有必要的 Qt Dll

最佳答案

(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 还支持 AUTOUICAUTORCC。我还没有尝试过它们,但它们的工作原理可能相似。

(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_DLLSDEBUG_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)

检索到该信息后,您可以通过以下方式创建自定义目标。假设您的所有 dll 路径都在列表 RELEASE_DLLSDEBUG_DLLS 中,并且您的可执行文件名称作为列表在 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...")

关于c++ - CMake - 如何链接到项目中打包的外部库?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36812904/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com