问题描述
我必须在编译时在解决方案中复制dll,因此我正在使用add_custom_command,如下所示:
I have to copy dll's in my solution at the compile time , so i am using add_custom_command for that as follows:
function(dll_dependencies TEST_CASE )
foreach(depencency ${ARGN})
add_custom_command(TARGET ${TEST_CASE} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
$<DLL_FILE_NAME:${depencency}>)
endforeach()
endfunction()
在cmakelist.txt中,我将上述函数称为:
and in the cmakelist.txt i am calling the above function as:
dll_dependencies(performance QT5::Core QT5::FileSystem)
但是我遇到了错误:
Error evaluating generator expression:
$<DLL_FILE_NAME:QT5::Core>
Error evaluating generator expression:
$<DLL_FILE_NAME:QT5::FileSystem>
所以,我没有得到它无法到达与qt相关的东西所在的位置的信息已安装,还是在add_custom_command生成器表达式中做错了?
我希望函数是如此通用,以至于我要在解决方案中获取的任何dll都在编译期间放置在目标内部。
So, i am not getting wether its not able to reach to the location of where qt related stuff is installed or am i doing mistake in the add_custom_command generator expression?I want the function to be so generic that whatever dll i want to get in the solution is placed inside the target during compilation.
推荐答案
您将无法以通用的方式管理所有依赖项,因为这不是通用的问题,我认为尝试使用它甚至不是一个好主意。
You're not going to be able to manage all dependencies in a generic way, because it's not a generic problem, and I'll contend that it's not even a good idea to try.
以Qt为例(这是问题中提到的唯一依赖项)。在Windows上,复制Qt dll依赖项的正确方法是运行 windeployqt.exe
。您要做的不只是复制dll来运行Qt应用程序,还需要在二进制目录中精确地镜像 的目录结构/依赖项。 windeployqt
为您完成所有这些工作。以其他任何方式管理Qt dll依赖项都是 Bad Idea 。
Take Qt for example (which are the only dependencies mentioned in your question). On windows, the right way to copy Qt dll dependencies is to run windeployqt.exe
. You need to do more than just copy dll's to get Qt apps to run, there are directory structures/dependencies that have to be mirrored exactly in your binary directory. windeployqt
does all that for you. Managing the Qt dll dependencies any other way is a Bad Idea. There is no reason to fight the tool or reinvent the wheel.
这是我自定义构建步骤,用于运行 windeployqt
:
Here's my custom build step for running windeployqt
:
# Windows specific build steps
if(WIN32)
# Run winddeployqt if it can be found
find_program(WINDEPLOYQT_EXECUTABLE NAMES windeployqt HINTS ${QTDIR} ENV QTDIR PATH_SUFFIXES bin)
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD
COMMAND ${WINDEPLOYQT_EXECUTABLE} $<TARGET_FILE:${TARGET_NAME}>)
endif()
找到它,然后将其作为构建后的步骤运行。简单。
It finds it, then runs it as a post-build step. Simple.
它假定:
- 您的Qt根路径在
QTDIR
cmake或环境变量。 - 您的可执行目标名称存储在变量
TARGET_NAME
$中b $ b
- Your Qt root path is set in the
QTDIR
cmake or environment variable. - your executable target name is stored in the variable
TARGET_NAME
对于非qt dll(在本例中为qwt),我有这样一个步骤:
For non-qt dll's (in this case qwt), I have a step like this:
# on windows, to copy, we need to replace the pesky forward slashes with back slashes
STRING(REGEX REPLACE "/" "\\\\" copySource \"${QWT_DIR}/lib/*.dll\")
STRING(REGEX REPLACE "/" "\\\\" copyDest \"${CMAKE_CURRENT_BINARY_DIR}/$<CONFIGURATION>\")
# Copy
ADD_CUSTOM_COMMAND( TARGET ${TARGET_NAME}
POST_BUILD
COMMAND COMMAND copy ${copySource} ${copyDest}
COMMENT "Copying Qwt dll's...\n"
)
通常可行,但也可能ly复制了很多垃圾。请注意,您仍然需要知道在哪里可以找到Dll(在 $ {QWT_DIR}
中指定)。环境变量可能是您的朋友
Usually that works, but it also probably copies a lot of garbage. Notice, you still need to know where to find the Dll's (specified in ${QWT_DIR}
). Environment variables could be your friend,
如果您愿意,也可以使用 $ {CMAKE_COMMAND} -E复制
或将其打开
You can probably also use ${CMAKE_COMMAND} -E copy
if you like, or turn it into a function that takes in the dll lib location.
@Florian提供了一些帮助有关使共享库复制步骤跨平台的建议。使用 file(TO_NATIVE_PATH)
替换正则表达式,使用cmake变量的后缀以及使用cmake命令替换 copy
命令-行复制,您将得到:
@Florian made some very helpful suggestions for making the shared-library copy step cross-platform. Replacing the regexs with file(TO_NATIVE_PATH)
, the suffixes with cmake variables, and the copy
command with the cmake command-line copy, you get:
file(TO_NATIVE_PATH "${QWT_DIR}/lib/*.${CMAKE_SHARED_LIBRARY_SUFFIX}" copy_source)
set(copy_dest "$<TARGET_FILE_DIR:${TARGET_NAME}>")
# perform copy
ADD_CUSTOM_COMMAND(TARGET ${TARGET_NAME}
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${copySource} ${copyDest}
)
在注释中,直到3.5版之前,在cmake -E复制中使用通配符(*)无效。对于较旧的版本,可以使用包含特定于平台的复制命令的变量。
As mentioned in the comments, using wildcard(*) in cmake -E copy was not working until version 3.5. For older versions, a variable containing the platform-specific copy command could be used.
这篇关于如何使用add_custom_command使用生成器表达式复制dll?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!