CMAKE_LINK_LIBRARY_USING_<FEATURE>¶
於 3.24 版本新增。
當使用 LINK_LIBRARY
產生器表達式時,此變數定義如何連結指定 <FEATURE>
的函式庫或框架。必須滿足以下兩個條件,此變數才會生效:
相關聯的
CMAKE_LINK_LIBRARY_USING_<FEATURE>_SUPPORTED
變數必須設定為 true。對於相同的
<FEATURE>
,沒有語言特定的定義。這表示對於評估LINK_LIBRARY
產生器表達式的目標所使用的連結語言,CMAKE_<LANG>_LINK_LIBRARY_USING_<FEATURE>_SUPPORTED
不能為 true。
功能名稱區分大小寫,且只能包含字母、數字和底線。以全部大寫字母定義的功能名稱保留給 CMake 內建功能使用 (請參閱下方的 預先定義的功能)。
功能行為的某些方面可以由 CMAKE_<LANG>_LINK_LIBRARY_<FEATURE>_ATTRIBUTES
和 CMAKE_LINK_LIBRARY_<FEATURE>_ATTRIBUTES
變數定義。
功能定義¶
函式庫功能定義是一個包含一或三個元素的清單
[<PREFIX>] <LIBRARY_EXPRESSION> [<SUFFIX>]
當指定 <PREFIX>
和 <SUFFIX>
時,它們分別位於 LINK_LIBRARY
表達式中指定的整個函式庫清單之前和之後,而不是每個函式庫項目。但不能保證指定函式庫的清單會保持分組在一起,因此如果 CMake 重新組織函式庫清單以滿足其他限制,則 <PREFIX>
和 <SUFFIX>
可能會出現多次。這表示不能以這種方式使用 GNU ld
連結器支援的 --start-group
和 --end-group
等建構。應該改用 LINK_GROUP
產生器表達式來處理此類建構。
<LIBRARY_EXPRESSION>
用於指定建構每個函式庫連結器命令列上對應片段的模式。可以在表達式中使用以下預留位置:
<LIBRARY>
展開為 CMake 目標的函式庫完整路徑,或基於其他項目的平台特定值 (與 Windows 上的<LINK_ITEM>
相同,或其他平台上的函式庫基本名稱)。<LINK_ITEM>
展開為函式庫在連結器命令列上通常的連結方式。<LIB_ITEM>
展開為 CMake 目標的函式庫完整路徑,或與<LIBRARY_EXPRESSION>
中指定的項目完全相同的項目。
除了上述內容外,還可以針對路徑 (使用檔案路徑指定的 CMake 目標和外部函式庫) 使用一種模式,而針對僅按名稱指定的其他項目使用另一種模式。可以使用 PATH{}
和 NAME{}
包裝器分別提供這兩種情況的展開。當使用包裝器時,兩者都必須存在。例如:
set(CMAKE_LINK_LIBRARY_USING_weak_library
"PATH{-weak_library <LIBRARY>}NAME{LINKER:-weak-l<LIB_ITEM>}"
)
對於此變數的三個元素 (<PREFIX>
、<LIBRARY_EXPRESSION>
和 <SUFFIX>
),可以使用 LINKER:
前置詞。
為了將選項傳遞至連結器工具,每個編譯器驅動程式都有其自己的語法。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:
前置詞和空格作為分隔符號的替代語法來指定引數。先前的範例因此會變成 "LINKER:SHELL:-z defs"
。
注意
不支援在 LINKER:
前置詞的開頭以外的任何位置指定 SHELL:
前置詞。
範例¶
載入整個靜態函式庫¶
一個常見的需求是防止連結器捨棄靜態函式庫中的任何符號。不同的連結器使用不同的語法來實現此目的。以下範例說明如何為某些連結器實作此功能。請注意,這僅供說明之用。專案應改用內建的 WHOLE_ARCHIVE
功能 (請參閱 預先定義的功能),它提供了更完整且更穩健的此功能實作。
set(CMAKE_C_LINK_LIBRARY_USING_load_archive_SUPPORTED TRUE)
if(CMAKE_C_COMPILER_ID STREQUAL "AppleClang")
set(CMAKE_C_LINK_LIBRARY_USING_load_archive "-force_load <LIB_ITEM>")
elseif(CMAKE_C_COMPILER_ID STREQUAL "GNU" AND CMAKE_SYSTEM_NAME STREQUAL "Linux")
set(CMAKE_C_LINK_LIBRARY_USING_load_archive
"LINKER:--push-state,--whole-archive"
"<LINK_ITEM>"
"LINKER:--pop-state"
)
elseif(CMAKE_C_COMPILER_ID STREQUAL "MSVC")
set(CMAKE_C_LINK_LIBRARY_USING_load_archive "/WHOLEARCHIVE:<LIBRARY>")
else()
# feature not yet supported for the other environments
set(CMAKE_C_LINK_LIBRARY_USING_load_archive_SUPPORTED FALSE)
endif()
add_library(lib1 STATIC ...)
add_library(lib2 SHARED ...)
if(CMAKE_C_LINK_LIBRARY_USING_load_archive_SUPPORTED)
# The -force_load Apple linker option requires a file name
set(external_lib
"$<IF:$<LINK_LANG_AND_ID:C,AppleClang>,libexternal.a,external>"
)
target_link_libraries(lib2 PRIVATE
"$<LINK_LIBRARY:load_archive,lib1,${external_lib}>"
)
else()
target_link_libraries(lib2 PRIVATE lib1 external)
endif()
CMake 將產生以下連結表達式:
AppleClang
:-force_load /path/to/lib1.a -force_load libexternal.a
GNU
:-Wl,--push-state,--whole-archive /path/to/lib1.a -lexternal -Wl,--pop-state
MSVC
:/WHOLEARCHIVE:/path/to/lib1.lib /WHOLEARCHIVE:external.lib
以弱模式連結函式庫¶
在 macOS 上,可以以弱模式連結函式庫 (函式庫和所有參考都標記為弱匯入)。對於依檔案路徑指定的函式庫,必須使用不同的旗標,而不是依名稱指定的函式庫。可以使用 PATH{}
和 NAME{}
包裝器來解決此限制。再次強調,以下範例說明如何為某些連結器實作此功能,但僅供說明之用。專案應改用內建的 WEAK_FRAMEWORK
或 WEAK_LIBRARY
功能 (請參閱 預先定義的功能),它們提供了更完整且更穩健的此功能實作。
if (CMAKE_C_COMPILER_ID STREQUAL "AppleClang")
set(CMAKE_LINK_LIBRARY_USING_weak_library
"PATH{-weak_library <LIBRARY>}NAME{LINKER:-weak-l<LIB_ITEM>}"
)
set(CMAKE_LINK_LIBRARY_USING_weak_library_SUPPORTED TRUE)
endif()
add_library(lib SHARED ...)
add_executable(main ...)
if(CMAKE_LINK_LIBRARY_USING_weak_library_SUPPORTED)
target_link_libraries(main PRIVATE "$<LINK_LIBRARY:weak_library,lib,external>")
else()
target_link_libraries(main PRIVATE lib external)
endif()
當使用 AppleClang
工具鏈連結 main
時,CMake 將產生以下連結器命令列片段:
-weak_library /path/to/lib -Xlinker -weak-lexternal
.
預先定義的功能¶
CMake 預先定義了以下內建函式庫功能:
DEFAULT
此功能對應於標準連結,基本上等同於完全不使用任何功能。它通常只會與
LINK_LIBRARY_OVERRIDE
和LINK_LIBRARY_OVERRIDE_<LIBRARY>
目標屬性搭配使用。WHOLE_ARCHIVE
強制包含靜態函式庫的所有成員。此功能僅支援以下平台,並註明限制:
Linux。
所有 BSD 變體。
SunOS。
所有 Apple 變體。此函式庫必須指定為 CMake 目標名稱、函式庫檔案名稱(例如
libfoo.a
),或函式庫檔案路徑(例如/path/to/libfoo.a
)。由於 Apple 連接器的限制,它不能指定為像foo
這樣的純函式庫名稱,其中foo
不是 CMake 目標。Windows。當使用 MSVC 或類似 MSVC 的工具鏈時,MSVC 版本必須大於 1900。
Cygwin。
MSYS。
FRAMEWORK
此選項會告知連接器使用
-framework
連接器選項搜尋指定的框架。它只能在 Apple 平台上使用,且只能與理解所用選項的連接器一起使用(即 Xcode 提供的連接器,或與其相容的連接器)。框架可以指定為 CMake 框架目標、裸框架名稱或檔案路徑。如果給定目標,則該目標必須將
FRAMEWORK
目標屬性設定為 true。對於檔案路徑,如果它包含目錄部分,則該目錄將被新增為框架搜尋路徑。add_library(lib SHARED ...) target_link_libraries(lib PRIVATE "$<LINK_LIBRARY:FRAMEWORK,/path/to/my_framework>") # The constructed linker command line will contain: # -F/path/to -framework my_framework
檔案路徑必須符合以下模式之一(
*
是萬用字元,可選部分顯示為[...]
)[/path/to/]FwName[.framework]
[/path/to/]FwName.framework/FwName[suffix]
[/path/to/]FwName.framework/Versions/*/FwName[suffix]
請注意,CMake 會識別並自動處理框架目標,即使不使用
$<LINK_LIBRARY:FRAMEWORK,...>
表達式。如果專案希望明確說明,仍然可以將產生器表達式與 CMake 目標一起使用,但並非必須如此。使用或不使用產生器表達式可能會在連接器命令列上有一些差異,但最終結果應該是相同的。另一方面,如果給定檔案路徑,CMake 會自動識別某些路徑,但並非所有情況。專案可能希望針對檔案路徑使用$<LINK_LIBRARY:FRAMEWORK,...>
,以使預期行為明確。在 3.25 版本中新增:
FRAMEWORK_MULTI_CONFIG_POSTFIX_<CONFIG>
目標屬性以及框架函式庫名稱的suffix
現在受到FRAMEWORK
功能的支援。NEEDED_FRAMEWORK
這與
FRAMEWORK
功能類似,但它會強制連接器與框架連結,即使沒有使用其中的任何符號。它使用-needed_framework
選項,並且具有與FRAMEWORK
相同的連接器約束。REEXPORT_FRAMEWORK
這與
FRAMEWORK
功能類似,但它會告知連接器,框架應該可供連結到正在建立的函式庫的用戶端使用。它使用-reexport_framework
選項,並且具有與FRAMEWORK
相同的連接器約束。WEAK_FRAMEWORK
這與
FRAMEWORK
功能類似,但它會強制連接器將框架及其所有參考標記為弱匯入。它使用-weak_framework
選項,並且具有與FRAMEWORK
相同的連接器約束。NEEDED_LIBRARY
這與
NEEDED_FRAMEWORK
功能類似,但它是用於非框架目標或函式庫(僅限 Apple 平台)。它會適當地使用-needed_library
或-needed-l
選項,並且具有與NEEDED_FRAMEWORK
相同的連接器約束。REEXPORT_LIBRARY
這與
REEXPORT_FRAMEWORK
功能類似,但它是用於非框架目標或函式庫(僅限 Apple 平台)。它會適當地使用-reexport_library
或-reexport-l
選項,並且具有與REEXPORT_FRAMEWORK
相同的連接器約束。WEAK_LIBRARY
這與
WEAK_FRAMEWORK
功能類似,但它是用於非框架目標或函式庫(僅限 Apple 平台)。它會適當地使用-weak_library
或-weak-l
選項,並且具有與WEAK_FRAMEWORK
相同的連接器約束。