微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用cmake从复杂项目中仅安装一个目标(及其依赖项)(打开更好的解决方案)

假设我有一个由几个子项目A,B,C,D组成的项目……
所有子项目都依赖于A,而A的变化相当频繁.
另外,可能还有一些依赖项:
在这个例子中,D取决于B.

现在:很多人正在研究这些项目.主CMakeLists.txt文件应包含所有目录,以便构建all构建所有目录.但人们也希望能够只在其中一个项目上工作,而不必每次都构建/安装所有项目.

如果我正在研究D,我可以通过调用轻松构建“仅”D

cmake --build . --target D -- -j7

要么

ninja -j7 D

如果他们的某些东西发生了变化,这也将构建A和B.完善.

但是如何在不触发构建全部的情况下仅为D调用安装?
如果我打电话,我想这样:

ninja -j7 D install

它只构建D(和依赖项),然后只安装D及其依赖项(A和B).
相反,它构建目标all并安装所有.

我想保持目标都在继续建立一切.所以EXCLUDE_FROM_ALL不是一个选项.但是朝着那个方向走,我找不到任何解决方案.

所以我在考虑以下策略:

>除子项目A外,所有其他目标都设置为EXCLUDE_FROM_ALL,安装时可选.
>我添加一个额外的子项目,它只依赖于所有其他子项目(也许我通过使用PARENT_ScopE中设置的一些变量使每个目标发布其名称),人们将不得不在他们想要构建和安装所有内容调用它.

它会起作用吗?有没有更好的解决方案?

我们希望避免每个人都必须编辑主CMakeLists.txt文件以排除他不感兴趣的项目.解决方案应该可以移植到不同的操作系统.

编辑:

我尝试了我提出的策略,但它没有用:在我的情况下,为目标设置一个install语句(即使指定为OPTIONAL)也会使EXCLUDE_FROM_ALL无效.在documentation中读得更好我发现:

Installing a target with EXCLUDE_FROM_ALL set to true has undefined behavior.

我也收到这个警告:

Target <targetname> has EXCLUDE_FROM_ALL set and will not be built by default but an install rule has been provided for it.  CMake does not define behavior for this case.

编辑2:

我尝试将EXCLUDE_FROM_ALL作为add_subdirectory的选项(而不是add_library / add_executable),但是那些子目录中的所有安装语句似乎都被忽略:只安装非排除所有子目录中的安装语句.

编辑3:

即使我激活CMAKE_SKIP_INSTALL_ALL_DEPENDENCY

set(CMAKE_SKIP_INSTALL_ALL_DEPENDENCY true)

在主CMakeLists.txt文件中,我省略了所有EXCLUDE_FROM_ALL,安装了我想要的多个目标可选(在我的情况下,除了A之外),如果在安装之前构建特定目标,那么命令:

ninja -j7 D && ninja install

由于某种原因会失败,说明C(其安装设置为OPTIONAL)不存在(它没有创建,因为D仅依赖于A和B)…

file INSTALL cannot find "<name of dll file for C>"

编辑4:

它看起来像是一个cmake bug. (我在Windows下使用2.8.11,也测试了2.8.10)
这个INSTALL命令

install(TARGETS ${targetname} RUNTIME DESTINATION . LIBRARY DESTINATION . OPTIONAL)

在cmake_install.cmake中转换为:

06009

FILE(INSTALL DESTINATION “${CMAKE_INSTALL_PREFIX}/.” TYPE SHARED_LIBRARY FILES *path_to_dll*)

IF(EXISTS “$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/./” AND NOT IS_SYMLINK “$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/./*dll_name*”)

060010

命令FILE缺少OPTIONAL!如果我手动添加OPTIONAL,它可以工作!
(注意:我在这里编辑了* dll_name *和* path_to_dll *占位符)

编辑5:

我确认这是cmake的错误,或者至少是错误的文档.我会报告这个.
这种情况解决了要么更简单

install(TARGETS ${targetname} DESTINATION . OPTIONAL)

(但在我的情况下,这也将安装我不想要的.lib.a文件)

或者在可选标志前面移动:

install(TARGETS ${targetname} OPTIONAL RUNTIME DESTINATION . LIBRARY DESTINATION .)

cmake documentation可以理解的是,OPTIONAL应该作为最后的选择.

什么有效:

> Remove dependency of “install” target to “all” target(一次,在主CMakeLists.txt中):

设置(CMAKE_SKIP_INSTALL_ALL_DEPENDENCY为true)
>设置为您不希望始终构建的所有目标的可选安装:

安装(TARGETS<< targetname>> DESTINATION.可选)
>构建要安装的目标

ninja -j7<<目标列表>>,或更一般地说:

<< your builder>> <<您的选项>> <<目标列表>>

这将构建列出的所有目标及其依赖项
>致电安装人员
忍者安装.这将安装您构建的所有库,您明确提到的库以及它们所依赖的库.这解决了安装特定目标及其依赖项的问题!
>要在Unix和Windows上连接命令,您可以使用

ninja -j7<<目标列表>> &安培;&安培;忍者安装
>请注意,至少对于忍者来说,你不能简单地将“安装”添加到目标列表中,因为目标“安装”不再依赖于任何目标,并且在你正在构建你的工作时,并行化工作的忍者会运行安装目标.替换旧的忍者-j7安装是

忍者-j7&&忍者安装.

目标“all”仍然可用(它仍然是认目标).
>如果需要创建要一起构建的目标列表,可以定义custom target

add_custom_target(<<< collective target name>> DEPENDS<<目标列表>>)

这不会包含在目标中.添加一个COMMAND还允许为我们想要的目标创建一个安装目标,例如ninja -j7 install_D,但我认为现在我们超出了这个问题的范围.

进一步考虑:

>(注意,2018年7月:这可能已经过时)如果您使用RUNTIME DESTINATION,LIBRARY DESTINATION等,很可能是因为CMake错误,OPTIONAL关键字应该准确放在下面指出的位置:

安装(TARGETS<< targetname>> OPTIONAL RUNTIME DESTINATION<< some dir>> LIBRARY DESTINATION<< some(other)dir>>)

这与documentation中的内容相矛盾,我将继续将其作为一个错误报告给CMake开发人员.
>将EXCLUDE_FROM_ALL与INSTALL OPTIONAL结合使用是a bad idea

Installing a target with EXCLUDE_FROM_ALL set to true has undefined behavior.

(并且cmake会在解析代码时尝试警告你)

原文地址:https://www.jb51.cc/javaschema/282004.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐