CMake - 如何链接到我的项目打包的外部库?
Posted
技术标签:
【中文标题】CMake - 如何链接到我的项目打包的外部库?【英文标题】:CMake - How Can I link to an external library that I have packed with my project? 【发布时间】:2016-04-23 15:45:06 【问题描述】:如何链接到我的项目打包的外部库?
这是我的项目的设置方式:
我有一个名为 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 来做三件事:
链接到我动态打包到“ExternalLibrary”中的 Qt 库。
每次在项目中添加 Qt 类或资源时自动执行 moc.exe、uic.exe、rcc.exe。我也不需要任何 生成的 moc_myClassname.cpp 将显示在项目中。
我希望所有 Qt dll 最终都放在可执行文件所在的 bin 文件夹中。例如:
C:\Raph\build\Raph\Windows\x64\Debug\bin
Raph.exe + 所有必要的 Qt Dlls
【问题讨论】:
太宽泛:几个不相关的问题。简而言之:1.谷歌find_package + QT
。 2. 自动显示新的源文件不是 CMake 的特性。通常每次添加/删除源时都需要修改CMakeLists.txt
。 3. 只需创建将文件复制到目标目录的规则。尝试专注于单个问题并在询问之前对其进行基本搜索。
【参考方案1】:
(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...")
【讨论】:
以上是关于CMake - 如何链接到我的项目打包的外部库?的主要内容,如果未能解决你的问题,请参考以下文章