cmake target_link_libraries 中的PRIVATE, PUBLIC, INTERFACE 详解

  • Post author:
  • Post category:其他


网上关于 target_link_libraries 中的 PRIVATE, PUBLIC , INTERFACE  的解释大部分是错的,而且不是一般的错,是胡说。 因为这三个属性在不同的命令中使用时意义不同,有很多是从target_include_libraries中抄来的。

以下的解释主要场景是linux中,windows不存在这种关系,无需考虑。

我们来解释下,假设我们有一个程序 A  , A调用库B, B调用库C.

A -> B -> C

A link B时不管是private还是public都没关系,毕竟A不需要导出符号,也没有人以API方式调用它。

现在主要问题就是B这个库用private还是public.  C是动态库。

如果B是动态或静态库,C是动态库,这个问题就会有影响。同样,如果B、C同为静态库时也会有问题。

B用private link C,  此时A link B,但是不知道B->C这层关系,可以正常link B. 运行时,A->B->C 时,B找不到C中的函数。linux下没有直接依赖关系,所有的B/C的依赖都会转到到A下,可以用LDD命令验证,此时A只依赖于B, 不见C, 当B中的函数调用C中的函数时,因为没有加载C, 所以报找不到符号错误。解决的办法就是在A link B时,同样也写上C. 但是因为private的原因,A是不知道C中的符号这事,只能强制 link C到A才能解决。

如果B link C时用public 指示, 当编译A时,就会检查到C中的符号没有实现,此时你就会知道要把C link到A来解决这个问题了。

其实private/public 解决的是指示问题,本质上可以使用public 来解决, 可以减少坑。

下面是target_link_libraries中的解释,不想看英文的,直接拉到最后。

Link Inheritance

Similarly, for any

target

, in the linking stage, we would need to decide, given the

item

to be linked, whether we have to put the

item

in the link dependencies, or the link interface, or both, in the compiled

target

. Here the link dependencies means the

item

has some implementations that the

target

would use, and it is linked to the

item

, so that whenever we call the functions or methods corresponding to those implementations it will always be mapped correctly to the implementations in

item

via the link, whereas the link interface means the

target

becomes an interface for linking the

item

for other targets which have dependencies on the

target

, and the

target

does not have to use

item

at all.

Link Type Description
PUBLIC All the objects following PUBLIC will be used for linking to the current target and providing the interface to the other targets that have dependencies on the current target.
PRIVATE All the objects following PRIVATE will only be used for linking to the current target.
INTERFACE All the objects following INTERFACE will only be used for providing the interface to the other targets that have dependencies on the current target.

For example, if the

fruit

library has the implementation of functions, such as

size

and

color

, and the

apple

library has a function

apple_size

which called the

size

from the

fruit

library and was

PRIVATE

linked with the

fruit

library. We could create an executable

eat_apple

that calls

apple_size

by

PUBLIC

or

PRIVATE

linking with the

apple

library. However, if we want to create an executable

eat_apple

that calls the

size

and

color

from the

fruit

library, only linking with the

apple

library will cause building error, since the

fruit

library was not part of the interface in the

apple

library, and is thus inaccessible to

eat_apple

. To make the

apple

library to inherit the

size

and

color

from the

fruit

library, we have to make the linking of the

apple

library to the the

fruit

library

PUBLIC

instead of

PRIVATE

.

下面用人话(汉语)翻译下:


PUBLIC    在public后面的库会被Link到你的target中,并且里面的符号也会被导出,提供给第三方使用。


PRIVATE  在private后面的库仅被link到你的target中,并且终结掉,第三方不能感知你调了啥库


INTERFACE   在interface后面引入的库不会被链接到你的target中,只会导出符号。


—- 更新———-


​​​​​​​target_link_libraries 会在目标程序中生成rpath, 这点请注意 。



版权声明:本文为znsoft原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。