网上关于 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, 这点请注意 。