target_link_libraries¶
指定連結給定目標和/或其相依項時要使用的函式庫或旗標。使用需求將從連結的函式庫目標傳播。目標相依項的使用需求會影響其自身來源的編譯。
概述¶
此命令有多種簽名,如下面的子章節所述。它們都具有以下一般形式
target_link_libraries(<target> ... <item>... ...)
指定的 <target>
必須是由 add_executable()
或 add_library()
等命令建立的,而且不能是 別名目標。如果政策 CMP0079
未設定為 NEW
,則目標必須是在目前目錄中建立的。針對相同的 <target>
重複呼叫會依呼叫順序附加項目。
在 3.13 版本中新增: <target>
不必與 target_link_libraries
呼叫定義在相同的目錄中。
每個 <item>
可以是
函式庫目標名稱:產生的連結行將具有與目標關聯的可連結函式庫檔案的完整路徑。如果函式庫檔案發生變更,建置系統將具有重新連結
<target>
的相依性。指定的目標必須由專案內的
add_library()
或作為 匯入的函式庫建立。如果在專案中建立,則會在建置系統中自動新增順序相依性,以確保指定的函式庫目標在<target>
連結之前是最新的。如果匯入的函式庫設定了
IMPORTED_NO_SONAME
目標屬性,CMake 可能會要求連結器搜尋函式庫,而不是使用完整路徑(例如,/usr/lib/libfoo.so
變成-lfoo
)。目標成品檔案的完整路徑將會自動加上引號/逸出,以供 Shell 使用。
函式庫檔案的完整路徑:產生的連結行通常會保留檔案的完整路徑。如果函式庫檔案發生變更,建置系統將具有重新連結
<target>
的相依性。在某些情況下,CMake 可能會要求連結器搜尋函式庫(例如,
/usr/lib/libfoo.so
變成-lfoo
),例如,當偵測到共享函式庫沒有SONAME
欄位時。請參閱政策CMP0060
以瞭解其他情況的討論。如果函式庫檔案位於 macOS 框架中,則框架的
Headers
目錄也會被處理為 使用需求。這與將框架目錄作為包含目錄傳遞的效果相同。在 3.28 版本中新增: 函式庫檔案可能會指向 Apple 平台上的
.xcframework
資料夾。如果是這樣,目標將會獲得所選函式庫的Headers
目錄作為使用需求。在 3.8 版本中新增: 在適用於 VS 2010 及更高版本的 Visual Studio 產生器上,結尾為
.targets
的函式庫檔案將被視為 MSBuild 目標檔案,並匯入到產生的專案檔案中。其他產生器不支援此功能。函式庫檔案的完整路徑將會自動加上引號/逸出,以供 Shell 使用。
純函式庫名稱:產生的連結行將要求連結器搜尋函式庫(例如,
foo
變成-lfoo
或foo.lib
)。函式庫名稱/旗標會被視為命令列字串片段,使用時不會有額外的引號或逸出。
連結旗標:開頭為
-
但不是-l
或-framework
的項目名稱會被視為連結器旗標。請注意,為了傳遞相依性的目的,這些旗標會被視為任何其他函式庫連結項目,因此它們通常只能安全地指定為不會傳播到相依項的私有連結項目。此處指定的連結旗標會插入到連結命令中,與連結函式庫的位置相同。根據連結器的不同,這可能不正確。請使用
LINK_OPTIONS
目標屬性或target_link_options()
命令來明確新增連結旗標。然後,這些旗標將會放置在連結命令中工具鏈定義的旗標位置。在 3.13 版本中新增:
LINK_OPTIONS
目標屬性和target_link_options()
命令。對於較早版本的 CMake,請改用LINK_FLAGS
屬性。連結旗標會被視為命令列字串片段,使用時不會有額外的引號或逸出。
產生器運算式:
$<...>
產生器運算式
可以評估為上述任何項目,或評估為它們的 以分號分隔的清單。如果...
包含任何;
字元,例如在評估${list}
變數之後,請務必使用明確加引號的引數"$<...>"
,以便此命令將其接收為單一的<item>
。此外,產生器運算式可以用作上述任何項目的片段,例如
foo$<1:_d>
。緊接在另一個
<item>
後面的debug
、optimized
或general
關鍵字。此類關鍵字後面的項目只會用於對應的建置組態。debug
關鍵字對應於Debug
組態(或如果已設定DEBUG_CONFIGURATIONS
全域屬性,則對應於在其中命名的組態)。optimized
關鍵字對應於所有其他組態。general
關鍵字對應於所有組態,而且是完全可選的。透過建立並連結到 匯入的函式庫目標,可以實現每個組態規則的更高細微度。這些關鍵字會立即被此命令解譯,因此當由產生器運算式產生時,它們沒有特殊含義。
包含 ::
的項目,例如 Foo::Bar
,會被視為 IMPORTED 或 ALIAS 函式庫目標名稱,如果沒有此類目標存在,將會導致錯誤。請參閱政策 CMP0028
。
請參閱 CMAKE_LINK_LIBRARIES_STRATEGY
變數和對應的 LINK_LIBRARIES_STRATEGY
目標屬性,以了解 CMake 如何在連結器命令行上對直接連結的相依性進行排序的詳細資訊。
請參閱 cmake-buildsystem(7)
手冊,以了解更多關於定義建置系統屬性的資訊。
目標和/或其相依項的函式庫¶
target_link_libraries(<target>
<PRIVATE|PUBLIC|INTERFACE> <item>...
[<PRIVATE|PUBLIC|INTERFACE> <item>...]...)
PUBLIC
、PRIVATE
和 INTERFACE
範圍 關鍵字可用於在一個命令中指定連結相依性和連結介面。
在 PUBLIC
後面的函式庫和目標會被連結到,並成為連結介面的一部分。在 PRIVATE
後面的函式庫和目標會被連結到,但不會成為連結介面的一部分。在 INTERFACE
後面的函式庫會被附加到連結介面,並且不會用於連結 <target>
。
目標及其相依項的函式庫¶
target_link_libraries(<target> <item>...)
依預設,此簽章的函式庫相依性是遞移的。當此目標被連結到另一個目標時,連結到此目標的函式庫也會出現在另一個目標的連結行上。這種遞移的「連結介面」儲存在 INTERFACE_LINK_LIBRARIES
目標屬性中,並且可以透過直接設定該屬性來覆寫。當 CMP0022
未設定為 NEW
時,遞移連結是內建的,但可以透過 LINK_INTERFACE_LIBRARIES
屬性來覆寫。呼叫此命令的其他簽章可能會設定該屬性,使此簽章專門連結的任何函式庫成為私有的。
目標和/或其相依項的函式庫 (舊版)¶
target_link_libraries(<target>
<LINK_PRIVATE|LINK_PUBLIC> <lib>...
[<LINK_PRIVATE|LINK_PUBLIC> <lib>...]...)
LINK_PUBLIC
和 LINK_PRIVATE
模式可用於在一個命令中指定連結相依性和連結介面。
此簽章僅用於相容性。請改用 PUBLIC
或 PRIVATE
關鍵字。
在 LINK_PUBLIC
後面的函式庫和目標會被連結到,並成為 INTERFACE_LINK_LIBRARIES
的一部分。如果政策 CMP0022
不是 NEW
,它們也會成為 LINK_INTERFACE_LIBRARIES
的一部分。在 LINK_PRIVATE
後面的函式庫和目標會被連結到,但不會成為 INTERFACE_LINK_LIBRARIES
(或 LINK_INTERFACE_LIBRARIES
) 的一部分。
僅供相依項使用的函式庫 (舊版)¶
target_link_libraries(<target> LINK_INTERFACE_LIBRARIES <item>...)
LINK_INTERFACE_LIBRARIES
模式會將函式庫附加到 INTERFACE_LINK_LIBRARIES
目標屬性,而不是用於連結。如果政策 CMP0022
不是 NEW
,則此模式也會將函式庫附加到 LINK_INTERFACE_LIBRARIES
及其每個組態的對等屬性。
此簽章僅用於相容性。請改用 INTERFACE
模式。
指定為 debug
的函式庫會包裝在產生器表達式中,以對應於偵錯組建。如果政策 CMP0022
不是 NEW
,則函式庫也會附加到 LINK_INTERFACE_LIBRARIES_DEBUG
屬性 (或附加到 DEBUG_CONFIGURATIONS
全域屬性中列出的組態所對應的屬性,如果已設定)。指定為 optimized
的函式庫會附加到 INTERFACE_LINK_LIBRARIES
屬性。如果政策 CMP0022
不是 NEW
,它們也會附加到 LINK_INTERFACE_LIBRARIES
屬性。指定為 general
(或沒有任何關鍵字) 的函式庫會被視為同時為 debug
和 optimized
指定。
連結物件函式庫¶
在版本 3.12 中新增。
物件函式庫 可用作 target_link_libraries
的 <target>
(第一個) 引數,以指定其來源對其他函式庫的相依性。例如,程式碼
add_library(A SHARED a.c)
target_compile_definitions(A PUBLIC A)
add_library(obj OBJECT obj.c)
target_compile_definitions(obj PUBLIC OBJ)
target_link_libraries(obj PUBLIC A)
會使用 -DA -DOBJ
編譯 obj.c
,並為 obj
建立使用需求,這些需求會傳遞到其相依項。
一般函式庫和可執行檔可以連結到 物件函式庫,以取得其物件和使用需求。繼續上面的範例,程式碼
add_library(B SHARED b.c)
target_link_libraries(B PUBLIC obj)
會使用 -DA -DOBJ
編譯 b.c
,使用 b.c
和 obj.c
的物件檔案建立共享函式庫 B
,並將 B
連結到 A
。此外,程式碼
add_executable(main main.c)
target_link_libraries(main B)
使用 -DA -DOBJ
編譯 main.c
,並將可執行檔 main
連結到 B
和 A
。物件函式庫的使用需求會透過 B
傳遞,但其物件檔案則不會。
物件函式庫 可以「連結」到其他物件函式庫以取得使用需求,但由於它們沒有連結步驟,因此不會處理其物件檔案。延續上面的範例,以下程式碼
add_library(obj2 OBJECT obj2.c)
target_link_libraries(obj2 PUBLIC obj)
add_executable(main2 main2.c)
target_link_libraries(main2 obj2)
使用 -DA -DOBJ
編譯 obj2.c
,使用來自 main2.c
和 obj2.c
的物件檔案建立可執行檔 main2
,並將 main2
連結到 A
。
換句話說,當 物件函式庫 出現在目標的 INTERFACE_LINK_LIBRARIES
屬性中時,它們會被視為 介面函式庫,但當它們出現在目標的 LINK_LIBRARIES
屬性中時,它們的物件檔案也會包含在連結中。
透過 $<TARGET_OBJECTS>
連結物件函式庫¶
於 3.21 版本新增。
與物件函式庫關聯的物件檔案可以使用 $<TARGET_OBJECTS>
產生器表達式來引用。此類物件檔案會放置在連結行的所有函式庫之前,無論它們的相對順序如何。此外,將在建置系統中新增排序相依性,以確保在相依目標連結之前,物件函式庫是最新的。例如,以下程式碼
add_library(obj3 OBJECT obj3.c)
target_compile_definitions(obj3 PUBLIC OBJ3)
add_executable(main3 main3.c)
target_link_libraries(main3 PRIVATE a3 $<TARGET_OBJECTS:obj3> b3)
將可執行檔 main3
與來自 main3.c
和 obj3.c
的物件檔案連結,後面接著 a3
和 b3
函式庫。main3.c
不會使用來自 obj3
的使用需求進行編譯,例如 -DOBJ3
。
這種方法可用於在連結行中實現物件檔案的傳遞式包含,作為使用需求。繼續上面的範例,以下程式碼
add_library(iface_obj3 INTERFACE)
target_link_libraries(iface_obj3 INTERFACE obj3 $<TARGET_OBJECTS:obj3>)
建立一個介面函式庫 iface_obj3
,它會轉發 obj3
的使用需求,並將 obj3
的物件檔案新增至相依目標的連結行。以下程式碼
add_executable(use_obj3 use_obj3.c)
target_link_libraries(use_obj3 PRIVATE iface_obj3)
使用 -DOBJ3
編譯 use_obj3.c
,並將可執行檔 use_obj3
與來自 use_obj3.c
和 obj3.c
的物件檔案連結。
這也適用於透過靜態函式庫進行傳遞。由於靜態函式庫不進行連結,因此它不會使用以這種方式引用的物件函式庫中的物件檔案。相反,物件檔案會成為靜態函式庫的傳遞式連結相依性。繼續上面的範例,以下程式碼
add_library(static3 STATIC static3.c)
target_link_libraries(static3 PRIVATE iface_obj3)
add_executable(use_static3 use_static3.c)
target_link_libraries(use_static3 PRIVATE static3)
使用 -DOBJ3
編譯 static3.c
,並僅使用它自己的物件檔案建立 libstatic3.a
。use_static3.c
的編譯沒有 -DOBJ3
,因為使用需求不會透過 static3
的私有相依性傳遞。但是,會傳遞 static3
的連結相依性,包括 iface_obj3
對 $<TARGET_OBJECTS:obj3>
的引用。建立 use_static3
可執行檔時,會使用來自 use_static3.c
和 obj3.c
的物件檔案,並連結到函式庫 libstatic3.a
。
使用這種方法時,專案有責任避免將多個相依二進位檔連結到 iface_obj3
,因為它們的連結行都會取得 obj3
的物件檔案。
注意
在 3.21 之前的 CMake 版本中,在某些情況下,在 target_link_libraries
呼叫中引用 $<TARGET_OBJECTS>
是可以運作的,但並未完全支援
它不會將物件檔案放置在連結行上的函式庫之前。
它不會在物件函式庫上新增排序相依性。
它在 Xcode 中使用多個架構時無法運作。
靜態函式庫的循環相依性¶
函式庫相依性圖表通常是非循環的 (DAG),但在互相相依的 STATIC
函式庫的情況下,CMake 允許圖表包含循環 (強連通元件)。當另一個目標連結到其中一個函式庫時,CMake 會重複整個連通元件。例如,以下程式碼
add_library(A STATIC a.c)
add_library(B STATIC b.c)
target_link_libraries(A B)
target_link_libraries(B A)
add_executable(main main.c)
target_link_libraries(main A)
將 main
連結到 A B A B
。雖然一次重複通常就足夠,但病態的物件檔案和符號排列可能需要更多次。您可以使用 LINK_INTERFACE_MULTIPLICITY
目標屬性,或在最後一次 target_link_libraries
呼叫中手動重複元件,來處理這種情況。但是,如果兩個封存檔真的如此相互依賴,它們應該合併到單一封存檔中,或許可以使用 物件函式庫。
建立可重新定位的套件¶
請注意,不建議使用相依性的絕對路徑來填入目標的 INTERFACE_LINK_LIBRARIES
。這會將相依性的函式庫檔案路徑硬式編碼到已安裝的套件中,如同在建立套件的機器上找到的一樣。
請參閱 cmake-packages(7)
手冊的 建立可重新定位的套件 章節,以討論在為重新發佈建立套件時指定使用需求時必須格外注意的事項。