Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/cmake/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使“target\u link\u libraries”依赖项从cmake中的对象库传递?_Cmake - Fatal编程技术网

如何使“target\u link\u libraries”依赖项从cmake中的对象库传递?

如何使“target\u link\u libraries”依赖项从cmake中的对象库传递?,cmake,Cmake,如果在CMake中指定对象库的依赖关系链,则在目标可执行文件中仅使用最后一个库的目标链接库依赖关系 最简单的例子: main取决于objB,后者取决于objA。 objA和objB都是CMake中的OBJECT库 我希望main与这两个对象文件链接。没有 cmake_minimum_required(VERSION 3.13) project(transitive-object-library-link-issue VERSION 1.0.0 LANGUAGES C) add_library(

如果在CMake中指定
对象
库的依赖关系链,则在目标可执行文件中仅使用最后一个库的
目标链接库
依赖关系

最简单的例子:

main
取决于
objB
,后者取决于
objA

objA
objB
都是CMake中的
OBJECT

我希望
main
与这两个对象文件链接。没有

cmake_minimum_required(VERSION 3.13)
project(transitive-object-library-link-issue VERSION 1.0.0 LANGUAGES C)

add_library(objA OBJECT a.c)

add_library(objB OBJECT b.c)
target_link_libraries(objB PUBLIC objA)

# Should link with 'a.o', since 'objA' is "linked" by 'objB'
add_executable(main main.c)
target_link_libraries(main objB)
注意:一组工作文件可在

如果我将
objA
更改为非
对象
库,则通过消除
对象
库依赖项链,可以消除该问题。换言之,更改行

add_library(objA OBJECT a.c)
将是:

add_library(objA a.c)
因此,它是特定于
对象
库的。我应该如何指定使
main
链接到
objA
?(无需在每个使用
objB
的可执行目标中指定
objA

目标不是真正的库,它们只是对象的集合,但在用于构建真正的目标(如可执行库或共享/静态库)之前,它们不会真正链接在一起。引用链接文件:

add_library(<name> OBJECT <src>...)
add_库(对象…)
创建一个对象库。对象库编译源文件,但不将其对象文件归档或链接到库中

尽管如此,还是使用
target\u link\u library()
命令将其链接到对象库,但只指定其源对其他库的依赖关系。链接文档解释了您的问题:

对象库的使用要求以传递方式传播[…],但其对象文件不是

对象库可以“链接”到其他对象库以获得使用要求,但由于它们没有链接步骤,因此无法对其对象文件执行任何操作


因此,传递传播只影响编译其他真实库的定义和依赖项,而不影响对象本身。

这源于
对象
库的另一个问题:对象代码的复制。作为布拉德·金:

我们需要小心地消除[示例项的]对象文件的重复使用

如果默认为传递传播,则可能会意外导致链接器尝试链接同一代码的多个副本,从而使您的项目不可由CMake编译

这是一个不允许
对象
库的可传递依赖项的充分理由。这很棘手,所以最好避免。如此之多,以至于在他的优秀著作“”中提到这是一个良好的实践:

如果目标使用某个库中的内容,它应该始终直接链接到该库。即使 库已经是一个链接依赖于其他目标链接,不要依赖于间接链接 目标直接使用的内容的链接依赖关系

他还补充说:

对象库的可传递性与常规库不同。手册上的文字是这样的:

这些其他目标的链接(或归档)步骤将使用直接链接的对象库中的对象文件

其中的关键部分是“直接链接”。在您的示例中,
main
b
获取对象,因为它直接链接到
b
,但因为它不直接链接到
a
,所以它不会获取
a
的对象,即使
b
链接到
a
。 其原因与深瞬变性可能导致多次添加对象文件的问题有关,这将导致错误。这一特定方面在问题跟踪程序中出现过几次,但我手头没有问题编号(您可能可以搜索它们并跟踪各种讨论)

因此,解决方案似乎是避免依赖
对象
库的
目标链接库
。有两种方法:第一种是不使用
对象
库。第二个是明确指定要在层次结构中链接的对象,如Hiroshi Miura所述:

add_library(a OBJECT a.c)
add_library(b OBJECT b.c)
target_sources(b PUBLIC $<TARGET_OBJECTS:a>)

add_executable(main main.c)
target_sources(main PRIVATE $<TARGET_OBJECTS:b>)
add_库(对象a.c)
添加库(b对象b.c)
目标资源(b公共美元)
添加可执行文件(main.c)
目标资源(主要私有$)
这是明确的,但甚至不能解决我的问题!我怀疑由于菱形图案,这也可能会遇到重复问题,但我还没有测试过


也许在接下来的几个月里,我会根据
objA
的LINK\u LIBRARIES属性,使用生成器表达式找到一个更好的解决方案。但是,不确定如何做到这一点。

一个解决方案是为每个对象库定义一个接口库。接口库的依赖关系是可传递的

# Defines an object library named ${T}_obj,
# interface library named ${T} linked to it,
# and sets ${varname} to ${T}_obj.
macro(add_object varname T)
  add_library(${T}_obj OBJECT ${ARGN})
  add_library(${T} INTERFACE)
  target_link_libraries(${T} INTERFACE ${T}_obj $<TARGET_OBJECTS:${T}_obj>)
  set(${varname} ${T}_obj)
endmacro(add_object)

objA
objA
都是CMake中的对象库。你是说
objA
objB
都是CMake中的对象库吗。@ManthanTilva修复了。谢谢。我本以为
target\u link\u library
也是一个“对象库的使用要求”,因此是“可传递的传播”。我同意,至少说起来很尴尬。鉴于此CMake对象库功能似乎取代了libtool便利库,它也应该提供这种便利。
add_object(T a a.c) 

add_object(T b b.c) # sets T to b_obj
target_link_libraries(${T} a)