問題描述
假設(shè)動態(tài)庫B依賴動態(tài)庫A驻债,可執(zhí)行程序C依賴動態(tài)庫B逗宁。 如下圖:
C[程序C] -->|依賴| B(動態(tài)庫B) --> |依賴|A(動態(tài)庫A)
在linux平臺下,按照正常來說奸晴,在編譯C時贱枣,只需要鏈接B就好了监署。
但是使用Cmake編譯時,會報(bào)找不到libA.so的錯誤纽哥。
通過cmake生成的gcc命令看到钠乏,編譯命令確實(shí)將A也鏈接了進(jìn)來。
那么問題來了春塌,為什么cmake會將B的依賴加到我C的頭上晓避?
答案
原因在于 target_link_libraries()
命令。
熟悉cmake的朋友都知道這是設(shè)置鏈接庫的命令只壳。
但其實(shí)它的原型是:
target_link_libraries(<target>
<PRIVATE|PUBLIC|INTERFACE> <lib> ...
[<PRIVATE|PUBLIC|INTERFACE> <lib> ... ] ...])
可以通過PRIVATE | PUBLIC | INTERFACE 設(shè)置依賴的傳遞性.
摘抄一下官方文檔的描述:
The PUBLIC, PRIVATE and INTERFACE keywords can be used to specify both the link dependencies and the link interface in one command. Libraries and targets following PUBLIC are linked to, and are made part of the link interface. Libraries and targets following PRIVATE are linked to, but are not made part of the link interface. Libraries following INTERFACE are appended to the link interface and are not used for linking <target>.
參考:
https://cmake.org/cmake/help/v3.0/command/target_link_libraries.html
其實(shí)大白話就是:
- 如果B的頭文件中包含了A的頭文件(源文件間接包含)俏拱,那么這里應(yīng)該用PUBLIC,依賴關(guān)系會傳遞下去吕世。
- 如果B僅源文件中包含了A的頭文件彰触,那么這里應(yīng)該用PRIVATE,依賴關(guān)系不會傳遞命辖。
- 如果B的頭文件包含A况毅,但源文件未包含,那么這里應(yīng)該用INTERFACE尔艇,依賴關(guān)系不會傳遞尔许。
好了,大家以后再使用target_link_libraries()
的時候就可以加上PRIVATE
關(guān)鍵字终娃,這樣C就不會鏈接A了味廊。
需要注意:
根據(jù)CMP0023描述:
加關(guān)鍵字和不加關(guān)鍵字的用法不可以混合使用,如下面一起使用就會報(bào)錯棠耕。
target_link_libraries(mylib A)
target_link_libraries(mylib PRIVATE B)
參考:
https://cmake.org/cmake/help/v3.0/policy/CMP0023.html