8wDlpd.png
8wDFp9.png
8wDEOx.png
8wDMfH.png
8wDKte.png

如何使用 CMake 将 DLL 文件复制到与可执行文件相同的文件夹中?

anthony sottile 2月前

128 0

我们使用 CMake 在 SVN 中生成源代码的 Visual Studio 文件。现在我的工具需要一些 DLL 文件与可执行文件位于同一文件夹中。DLL 文件位于旁边的文件夹中...

我们使用 CMake 在 SVN 中生成源代码的 Visual Studio 文件。现在我的工具需要一些 DLL 文件与可执行文件位于同一文件夹中。DLL 文件位于源代码旁边的文件夹中。

我怎样才能更改 CMakeLists.txt 以使生成的 Visual Studio 项目已经在发布/调试文件夹中拥有特定的 DLL 文件或者在编译时复制它们?

帖子版权声明 1、本帖标题:如何使用 CMake 将 DLL 文件复制到与可执行文件相同的文件夹中?
    本站网址:http://xjnalaquan.com/
2、本网站的资源部分来源于网络,如有侵权,请联系站长进行删除处理。
3、会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。
4、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
5、站长邮箱:yeweds@126.com 除非注明,本帖由anthony sottile在本站《visual-studio》版块原创发布, 转载请注明出处!
最新回复 (0)
  • 1. 最正确的方式: install(TARGET_RUNTIME_DLLS) (CMake >= 3.21)

    install(FILES $<TARGET_RUNTIME_DLLS:your_exe_here> TYPE BIN)
    

    为了实现这一点,依赖项的 CMake 模块必须编写良好。换句话说,它们使用 CMake 3 目标,并且所有目标属性均已正确设置。如果它们正确设置了所有内容,则会自动收集所有 DLL 并将其与 exe 一起安装。CMake 将自动匹配哪种类型的 DLL(例如发布版还是调试版)以匹配目标 exe。

    这是 CMake 未来的发展方向,如果您可以选择的话,这是您应该选择的方式。

    您应该更喜欢 install() 直接将文件复制到其中, $CMAKE_RUNTIME_OUTPUT_DIRECTORY 因为 install() is the official CMake-sanctioned way to put things in $CMAKE_RUNTIME_OUTPUT_DIRECTORY . install() 之所以命名如此奇怪,是因为 CMake 不仅仅是一个构建工具。它也是一个安装程序生成工具。此安装程序生成功能称为 CPack。在 CMake 看来, $CMAKE_RUNTIME_OUTPUT_DIRECTORY 只是 CPack 的保存区域。 When you install() a file, you tell CMake that it should be considered a program file, to be copied around wherever the exe goes. If you don't go through install() , CMake will see it as a random unrecognized file.

    2. 第二正确的方法: install(RUNTIME_DEPENDENCIES) (CMake >= 3.21)

    install(TARGETS your_exe_here
        RUNTIME ARCHIVE LIBRARY RUNTIME FRAMEWORK BUNDLE PUBLIC_HEADER RESOURCE)
    install(TARGETS your_exe_here
        COMPONENT your_exe_here
        RUNTIME_DEPENDENCIES
        PRE_EXCLUDE_REGEXES "api-ms-" "ext-ms-"
        POST_EXCLUDE_REGEXES ".*system32/.*\\.dll"
        DIRECTORIES $<TARGET_FILE_DIR:your_exe_here>)
    

    关键在于 RUNTIME_DEPENDENCIES .

    在内部, RUNTIME_DEPENDENCIES 文件 file(GET_RUNTIME_DEPENDENCIES) ,尽力准确复制实际依赖项解析的样子,并记下在此过程中提到的所有 DLL。这些被传回到 install() .

    这意味着,这并不依赖于您的依赖项的 CMake 模块是否正确设置了其目标属性。您的实际可执行二进制文件将被扫描。所有内容都将被拾取。

    3. 第三个最正确的方法: file(GET_RUNTIME_DEPENDENCIES) (CMake >= 3.16)

    file(GET_RUNTIME_DEPENDENCIES) install(RUNTIME_DEPENDENCIES) 底层调用的,但 file(GET_RUNTIME_DEPENDENCIES) 在较早的 CMake 版本中可用 install(RUNTIME_DEPENDENCIES) 。我们仍然可以在较旧的 CMake 版本中执行相同的操作,只是需要更多样板。

    棘手的部分是 file(GET_RUNTIME_DEPENDENCIES) 只能在安装时调用。这意味着我们需要使用 install(CODE) 来运行一个脚本,该脚本反过来调用 file(GET_RUNTIME_DEPENDENCIES) 。有关实现, 请参阅此处 .

    4. 最后的手段: install(DIRECTORY)

    install(
      DIRECTORY "${DIR_CONTAINING_YOUR_DLLS}"
      TYPE BIN
      FILES_MATCHING REGEX "[^\\\\/.]\\.[dD][lL][lL]$"
    )
    

    要使用,请将适合您的构建的 DLL 放入 $DIR_CONTAINING_YOUR_DLLS .

    这里的技巧是,unlike install(FILES) , install(DIRECTORY) 在安装之前并不关心目录中有哪些特定文件。这意味着现在我们拥有所有的配置时间和编译时间,可以获取 DLL 列表并将它们填充进去 $DIR_CONTAINING_YOUR_DLLS 。只要 DLL 文件 $DIR_CONTAINING_YOUR_DLLS 在安装时存在, install(DIRECTORY) unlike 就会拾取它们。

    如果您选择此方法,则您有责任将 DLL 与构建配置进行匹配。 (考虑:静态与动态、调试与发布、导入库版本与 DLL 版本、具有可选多线程的库、忘记删除不再需要的 DLL。)

    如果选择此方法,则可能需要使用类似 vcpkg applocal.ps1。 (假设,应该可以 vcpkg 使用 重新实现纯 CMake 中 的功能 applocal.ps1 install(CODE) 但我还没有准备好发布的实现。)


    提示 vcpkg

    如果您使用 vpckg 启用 VCPKG_APPLOCAL_DEPS 的, vcpkg 它将为您找到并将您的 DLL 复制到您的 $CMAKE_RUNTIME_OUTPUT_DIRECTORY 目录中,但无需经过 install() 。您需要使用 install(DIRECTORY) 技巧让 CMake 拾取它们。

    (在内部, vcpkg 使用 dumpbin , llvm-objdump objdump 扫描您的可执行二进制文件以获取这些文件名。)

返回
作者最近主题: