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
欄位時。在 CMake 4.0 之前的版本中,請參閱策略CMP0060
以討論另一種情況。如果函式庫檔案位於 macOS framework 中,則 framework 的
Headers
目錄也將作為 使用需求 處理。這具有與將 framework 目錄作為包含目錄傳遞相同的效果。版本 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
) 被假定為 匯入的 或 別名 函式庫目標名稱,如果不存在此類目標,將導致錯誤。請參閱策略 CMP0028
。
請參閱 CMAKE_LINK_LIBRARIES_STRATEGY
變數和對應的 LINK_LIBRARIES_STRATEGY
目標屬性,以了解有關 CMake 如何在連結器命令行上對直接連結相依項進行排序的詳細資訊。
請參閱 cmake-buildsystem(7)
手冊以了解有關定義建置系統屬性的更多資訊。
處理編譯器驅動程式差異¶
版本 4.0 新增。
若要將選項傳遞給連結器工具,每個編譯器驅動程式都有其自己的語法。LINKER:
前綴和 ,
分隔符可用於以可移植的方式指定要傳遞給連結器工具的選項。LINKER:
由適當的驅動程式選項取代,而 ,
由適當的驅動程式分隔符取代。驅動程式前綴和驅動程式分隔符由 CMAKE_<LANG>_LINKER_WRAPPER_FLAG
和 CMAKE_<LANG>_LINKER_WRAPPER_FLAG_SEP
變數的值給出。
例如,"LINKER:-z,defs"
對於 Clang
變成 -Xlinker -z -Xlinker defs
,對於 GNU GCC
變成 -Wl,-z,defs
。
LINKER:
前綴作為替代語法,支援使用 SHELL:
前綴和空格作為分隔符來指定引數。然後,先前的範例變成 "LINKER:SHELL:-z defs"
。
注意
不支援在 LINKER:
前綴開頭以外的任何位置指定 SHELL:
前綴。
目標和/或其相依項的函式庫¶
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
目標屬性中,並且可以透過直接設定屬性來覆寫。
在 CMake 4.0 之前的版本中,如果 CMP0022
未設定為 NEW
,則內建可傳遞連結,但可以由 LINK_INTERFACE_LIBRARIES
屬性覆寫。對此命令的其他簽章的調用可能會設定屬性,使由此簽章獨佔連結的任何函式庫成為私有的。
目標和/或其相依項的函式庫 (舊版)¶
此簽章僅為相容性而存在。請改用 PUBLIC
或 PRIVATE
關鍵字。
target_link_libraries(<target>
<LINK_PRIVATE|LINK_PUBLIC> <lib>...
[<LINK_PRIVATE|LINK_PUBLIC> <lib>...]...)
LINK_PUBLIC
和 LINK_PRIVATE
模式可用於在一個命令中同時指定連結相依性和連結介面。
遵循 LINK_PUBLIC
的函式庫和目標會連結到,並成為 INTERFACE_LINK_LIBRARIES
的一部分。
在 CMake 4.0 之前的版本中,如果策略 CMP0022
不是 NEW
,它們也會成為 INTERFACE_LINK_LIBRARIES
的一部分。遵循 LINK_PRIVATE
的函式庫和目標會連結到,但不會成為 INTERFACE_LINK_LIBRARIES
(或 LINK_INTERFACE_LIBRARIES
) 的一部分。
僅限相依項的函式庫 (舊版)¶
此簽章僅為相容性而存在。請改用 INTERFACE
模式。
target_link_libraries(<target> LINK_INTERFACE_LIBRARIES <item>...)
LINK_INTERFACE_LIBRARIES
模式將函式庫附加到 INTERFACE_LINK_LIBRARIES
目標屬性,而不是將它們用於連結。
在 CMake 4.0 之前的版本中,如果策略 CMP0022
不是 NEW
,則此模式也會將函式庫附加到 INTERFACE_LINK_LIBRARIES
及其每個配置的等效屬性。
連結物件函式庫¶
版本 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.c
和 obj3.c
的物件檔案連結可執行檔 main3
,後跟 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.c
和 obj3.c
的物件檔案連結可執行檔 use_obj3
。
這也透過靜態函式庫傳遞地工作。由於靜態函式庫不連結,因此它不會使用以此方式引用的物件函式庫中的物件檔案。相反,物件檔案成為靜態函式庫的傳遞連結相依項。繼續上面的範例,程式碼
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
的連結相依性會傳播,包括對 $<TARGET_OBJECTS:obj3>
的 iface_obj3
引用。use_static3
可執行檔是使用來自 use_static3.c
和 obj3.c
的物件檔案建立的,並連結到函式庫 libstatic3.a
。
使用此方法時,專案有責任避免將多個相依二進制檔案連結到 iface_obj3
,因為它們都將在其連結行上取得 obj3
物件檔案。
注意
在 CMake 3.21 之前的版本中,在 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)
手冊中,以了解在為重新發布建立套件時,指定使用需求時必須格外小心的相關討論。