如何在安装语句中使用cmake文件(GET_RUNTIME_DEPENDENCIES? [英] How to use cmake file( GET_RUNTIME_DEPENDENCIES in an install statement?

查看:76
本文介绍了如何在安装语句中使用cmake文件(GET_RUNTIME_DEPENDENCIES?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

您如何使用文件(GET_RUNTIME_DEPENDENCIES ...)在cmake install脚本语句中?我在网上找不到这种用法的示例,并且文档和使用[[]]嵌入式自定义脚本的错误消息中的声明对我来说还不清楚.

How do you use file(GET_RUNTIME_DEPENDENCIES...) in a cmake install scripted statement? I can't find an example of this usage online, and the statement in the documentation and errors messages of using [[ ]] embedded custom scripting is not clear to me.

给我的印象是,在安装时,它可以用来定位cmake目标的文件依赖关系,并有可能通过安装操作将其移过来,从而使其以独立形式使用.

The impression I get is that at install time, this can be used to locate file dependencies of your cmake target and potentially bring them over with your install action, making it usable in standalone form.

例如,我的应用程序取决于QT,并且期望如果配置正确,此应用程序所需的QT dll将被复制到bin中.(我只是想确保我在这种情况下也不会误解它的功能).它可能不会直接复制文件,但我认为提供了要复制的文件列表,然后安装将对其进行处理(全部在安装时完成).

For example, my application depends on QT and the expectation is that if this is configured correctly, the QT dlls needed for this application will be copied over to the bin. (I just want to be sure I don't have a misunderstanding of it's function in this context as well). It may not directly copy the files but I assume provides a list of files to copy that install will then process (all done at install time).

我天真地向它扔东西的尝试是:

My naive attempt to just throw something at it to start is:

set(TARGET_NAME "myapp")

#  installation settings
install(TARGETS ${TARGET_NAME}
    [[
    file(GET_RUNTIME_DEPENDENCIES
        RESOLVED_DEPENDENCIES_VAR RES
        UNRESOLVED_DEPENDENCIES_VAR UNRES
        CONFLICTING_DEPENDENCIES_PREFIX CONFLICTING_DEPENDENCIES
        EXECUTABLES ${TARGET_NAME}
    )]]

    RUNTIME DESTINATION "${INSTALL_X_BIN}" COMPONENT libraries
    LIBRARY DESTINATION "${INSTALL_X_LIB}" COMPONENT libraries
)

但是,这当然给了我

CMake Error at applications/CMakeLists.txt:117 (install):
install TARGETS given target " file(GET_RUNTIME_DEPENDENCIES

      RESOLVED_DEPENDENCIES_VAR RES
      UNRESOLVED_DEPENDENCIES_VAR UNRES
      CONFLICTING_DEPENDENCIES_PREFIX CONFLICTING_DEPENDENCIES
      EXECUTABLES ${TARGET_NAME}
  )" which does not exist.


-- Configuring incomplete, errors occurred!

对此我感到很愚蠢,就像我错过了一些基本的东西.

I feel silly about this like I'm missing something pretty basic.

推荐答案

首先,警告

您提到了Qt.不管您在这里做什么,该方法都不太可能完全适用于Qt,因为无法仅使用程序/库的运行时依赖项来发现任何Qt 插件或您的安装可能还需要的其他组件.Qt的依赖关系不仅仅是库.

First, a caveat

You mentioned Qt. No matter what you do here, this method is unlikely to work for Qt all by itself, because there's no way using only the runtime dependencies of a program/library that you can discover any Qt plugins or other components that your installation may also require. Qt's dependencies are more complex than just libraries.

(我的在此处回答演示了如何使用 QCocoaIntegrationPlugin获取用于捆绑目的Qt插件信息以macOS上的code> QPA为例,在最近的发行版中,所有Qt插件均由其自己的 IMPORTED CMake目标表示,因此通常可以编写 install(CODE ...)脚本,该脚本使用生成器表达式以类似于以下代码的方式拾取这些目标.)

(My answer here demonstrates how to obtain Qt plugin information for bundling purposes, using the QCocoaIntegrationPlugin QPA on macOS as an example. All of Qt's plugins are represented by their own IMPORTED CMake targets, in recent releases, so it's typically possible to write install(CODE ...) scripting which picks up those targets using generator expressions in a similar manner to the following code.)

正如Tsyvarev在评论中指出的那样, GET_RUNTIME_DEPENDENCIES 旨在用于安装阶段,而不是配置阶段.因此,需要将其放置在 install(CODE ...) install(SCRIPT ...)语句中,这将导致代码评估延迟直到构建完成之后.(实际上, install(CODE ...)会将给定的代码直接插入当前目录的 cmake_install.cmake 脚本中.您可以通过查看该文件来检查结果,甚至无需运行安装.)

As Tsyvarev noted in comments, GET_RUNTIME_DEPENDENCIES is intended to be used in the install stage, not the configure stage. As such, it needs to be placed in an install(CODE ...) or install(SCRIPT ...) statement, which will cause the code evaluation to be delayed until after the build is complete. (In fact, install(CODE ...) inserts the given code right into the current directory's cmake_install.cmake script. You can examine the results just by looking at that file, without even having to run the install.)

延迟评估还带有一些皱纹.主要是:代码不了解目标.目标在安装阶段不再存在.因此,要包含任何目标信息,您必须使用生成器表达式来插入正确的值.

The delayed evaluation also comes with a few wrinkles. Primarily: The code doesn't understand targets. The targets no longer exist at the install stage. So, to include any target info, you have to use generator expressions to insert the correct values.

虽然CMake文档指示未在括号参数内评估变量引用和转义符,但生成器表达式 .因此,您可以编写包裹在 [[[ ]] 中的 CODE ,以避免遗漏所有内容.

While the CMake documentation indicates that variable references and escapes aren't evaluated inside bracket arguments, generator expressions are. So, you can compose the CODE wrapped in [[ ]] to avoid escaping everything.

您仍然必须注意变量扩展/转义.大多数变量(包括您创建的变量)在安装上下文中不可用-只有少数变量,例如 CMAKE_INSTALL_PREFIX .您必须扩展或设置其他任何内容.

You still have to be careful about variable expansion / escaping. Most variables (including any you create) aren't available in the install context — only a few are, like CMAKE_INSTALL_PREFIX. You have to either expand or set any others.

AFAICT没有生成器表达式来访问任意变量.有一些特定的变量/值,但是您不能说类似 $< LIST:MY_LIST_VAR> $< VALUE:MY_STRING_VAR> 之类的变量和变量组合方括号参数.

There are, AFAICT, no generator expressions to access arbitrary variables. There are some for specific variables/values, but you can't say something like $<LIST:MY_LIST_VAR> or $<VALUE:MY_STRING_VAR> to combine variables and bracket arguments.

因此,如果您想在 CODE 中使用 configure 上下文中的变量,并在 install 时对它们进行评估,最简单的方法是转移"通过 set()- CODE 中的变量将它们导入安装脚本.

So, if you want to use variables from the configure context in the CODE, where they'll be evaluated at install time, the easiest thing to do is to "transfer" them into the install script by set()-ing a variable in the CODE.

要安装共享库依赖项,如果您构建共享库目标,则可以使用与CMake本身在 cmake_install.cmake 中使用的相同的 file(INSTALL)命令.它使用 TYPE SHARED_LIBRARY 选项添加一些额外的处理. FOLLOW_SYMLINK_CHAIN 选项也特别方便.它们一起使 file(INSTALL)都解析源文件中的符号链接,在目标路径中自动重新创建它们.

To install shared library dependencies, you can use the same file(INSTALL) command that CMake itself uses in cmake_install.cmake if you build a shared library target. It uses the TYPE SHARED_LIBRARY option to add some extra processing. The FOLLOW_SYMLINK_CHAIN option is also especially handy. Together they'll make file(INSTALL) both resolve symbolic links in the source files, and automatically recreate them in the destination path.

总而言之,您想要执行以下操作:

So all in all, you'd want to do something like this:

set(MY_DEPENDENCY_PATHS /path/one /path/two)

# Transfer the value of ${MY_DEPENDENCY_PATHS} into the install script
install(CODE "set(MY_DEPENDENCY_PATHS \"${MY_DEPENDENCY_PATHS}\")")

install(CODE [[
  file(GET_RUNTIME_DEPENDENCIES
    LIBRARIES $<TARGET_FILE:mylibtarget>
    EXECUTABLES $<TARGET_FILE:myprogtarget>
    RESOLVED_DEPENDENCIES_VAR _r_deps
    UNRESOLVED_DEPENDENCIES_VAR _u_deps
    DIRECTORIES ${MY_DEPENDENCY_PATHS}
  )
  foreach(_file ${_r_deps})
    file(INSTALL
      DESTINATION "${CMAKE_INSTALL_PREFIX}/lib"
      TYPE SHARED_LIBRARY
      FOLLLOW_SYMLINK_CHAIN
      FILES "${_file}"
    )
  endforeach()
  list(LENGTH _u_deps _u_length)
  if("${_u_length}" GREATER 0)
    message(WARNING "Unresolved dependencies detected!")
  endif()
]])

* –(请注意,在非Windows系统上使用 DIRECTORIES 参数将导致CMake发出警告,因为应该仅在当前环境下才能解决文件的依赖关系.)

* – (Note that using the DIRECTORIES argument on a non-Windows system will cause CMake to emit a warning, as files' dependencies are supposed to be resolvable using only the current environment.)

如果代码过于复杂,则始终可以选择在 $ {CMAKE_CURRENT_SOURCE_DIR} 中创建单独的脚本文件 copy_deps.cmake 并使用 install(脚本copy_deps.cmake).(此答案的先前版本建议使用 file(GENERATE ...)来构建脚本-该脚本不起作用,因为只有在处理 CMakeLists之后才写入文件.txt .)

If the code gets too complex, there's always the option to create a separate script file copy_deps.cmake in the ${CMAKE_CURRENT_SOURCE_DIR} and use install(SCRIPT copy_deps.cmake). (A previous version of this answer suggested using file(GENERATE...) to build the script — that won't work, as the file isn't written until after processing the CMakeLists.txt.)

这篇关于如何在安装语句中使用cmake文件(GET_RUNTIME_DEPENDENCIES?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆