簡體   English   中英

如何鏈接和使用 Objective-C Xcode 項目中的 LLVM 庫?

[英]How do I link and use LLVM libraries from an Objective-C Xcode project?

我想在我自己的 Objective-C 應用程序中使用 LLVM 項目中的幾個類。 具體來說,我想使用在BitstreamReader.hBitstreamWriter.h中聲明的類。 不幸的是,我沒有太多鏈接 C++ 庫的經驗,所以我真的不知道從哪里開始。 我首先通過 Homebrew 使用brew install llvm@14 然后,在我的 Xcode 項目中,我嘗試鏈接/opt/homebrew/opt/llvm@14/lib中的庫,並將/opt/homebrew/opt/llvm@14/include/**添加到我的HEADER_SEARCH_PATHS中。

現在我完全卡住了。 我在 Xcode 中有一堆構建錯誤,例如:

  • “參考未解決的使用聲明”
  • “全局命名空間中沒有名為‘ldiv’的成員”
  • “使用未聲明的標識符‘wcspbrk’”
  • ...

任何幫助都將不勝感激。 謝謝!

在 C++ 世界中,有很多方法可以將依賴項合並到您的項目中,我將概述其中的一些,但會嘗試詳細描述我認為最適合您的場景的一種:

1. 在系統/用戶范圍內安裝庫

這是最經典的方法,當您為特定平台預編譯和預安裝庫時,它們可以在默認庫搜索路徑下使用。 類似於 iOS 中系統框架的使用方式——你只在項目中添加 linker 命令,而框架(庫)獨立存在(或不存在,導致 linker 錯誤)。 這種方法的問題是,您不能真正將庫用於受限系統,其中“默認”庫是不可更改的(iOS、tvOS、iPadOS)

2.嵌入static庫

另一種方法是將您需要的所有庫預編譯到所有平台的檔案庫中,這些庫應該被使用,然后只將其中一個所需的庫版本嵌入到您的最終應用程序二進制文件中。 這種方法有些麻煩且不可移植,因為每次需要更改庫的某些部分或支持新平台時,它都需要您手動編譯庫並重新嵌入它。

3.嵌入一個xcframework

這種方法與前一種方法非常相似,有一些好處,您可以將所有平台的二進制文件打包在一個 package 下,甚至可以在 SPM 中發布。

4.使用CMake構建系統

C++ 中的許多項目(LLVM 也不例外)都是使用所謂的 CMake 工具制作的。 它被廣泛采用的多平台構建系統,您可以使用的好處之一是您可以輕松地將任何其他項目作為您自己的一部分。 同時 CMake 在移動開發領域並不普遍,因此您可能很難找到這些平台的相關信息。

5.使用Xcode個工作空間

這是我想更詳細地描述的解決方案。 簡而言之,該方法包括 6 個步驟:

  • 下載 LLVM 項目倉庫;
  • 使用 CMake 為所需的 LLVM 庫生成 Xcode 項目;
  • 制作一個 Xcode 工作空間,將新生成的項目添加到其中;
  • 將您自己的項目添加到同一工作區;
  • 將 LLVM 項目所需的依賴項添加到您自己的項目中;
  • 調整項目設置以使其與依賴項兼容。

這種方法的好處是它提供了最一致的體驗(生成項目后,所有部分都可以從 Xcode 進行配置)、管理源代碼的自由(LLVM 項目文件可以根據需要進行更改),以及內置的豪華 -在依賴圖中(構建目標所需的所有庫都在 Xcode 設置下給出)。


下載 LLVM 項目

您可以從此處克隆該項目。 請注意,這必須位於您未來工作區所在的同一文件夾中,因此您最好提前做好准備:

% mkdir MyWorkspace && cd MyWorkspace
% git clone git@github.com:llvm/llvm-project.git

生成 LLVM Xcode 項目

首先,確保您已安裝 CMake(它不是隨 macOS 開箱即用的)。 您可以使用brew或從官方網站下載應用程序。 之后,在llvm-project repo 文件夾旁邊為未來的 Xcode 項目創建一個新文件夾,並在 LLVM 工具包項目上運行cmake

% mkdir LLVM && cd LLVM
% cmake -GXCode ../llvm-project/llvm

創建 Xcode 工作區

這里沒什么特別的,只需打開 Xcode 並導航到File/New/Workspace菜單( Ctrl+Cmd+N快捷鍵)。 確保您的工作區是在MyWorkspace文件夾中創建的。 你可以從 Xcode 開始: 在此處輸入圖像描述

然后,添加在上一步中創建的 LLVM 項目。 打開File/Add Files to "MyWorkspace"...菜單( Option+Cmd+A )和 select Xcode 項目文件: 在此處輸入圖像描述

如果 Xcode 建議自動創建方案,我建議您接受此建議,這樣您以后就不必自己處理了。

添加自己的項目

此步驟模仿前一個步驟,但您將自己的項目添加到工作區。 我沒有現有的項目,所以我只是在工作區目錄中創建了一個新項目(在我的例子中是 macOS 命令行應用程序)。 如果您這樣做,請確保項目已添加到“MyWorkspace”並且文件夾正確: 在此處輸入圖像描述

最終你的工作區“Project Navigator”應該看起來像這樣: 在此處輸入圖像描述

簡而言之,目錄樹如下所示:

% tree -L 2
.
|-- LLVM
|   |-- $(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
|   |-- CMakeCache.txt
|   |-- CMakeFiles
|   |-- CMakeScripts
|   |-- CPackConfig.cmake
|   |-- CPackSourceConfig.cmake
|   |-- Debug
|   |-- LLVM.xcodeproj
|   |-- MinSizeRel
|   |-- RelWithDebInfo
|   |-- Release
|   |-- benchmarks
|   |-- build
|   |-- cmake
|   |-- cmake_install.cmake
|   |-- docs
|   |-- examples
|   |-- include
|   |-- lib
|   |-- llvm.spec
|   |-- projects
|   |-- runtimes
|   |-- test
|   |-- third-party
|   |-- tools
|   |-- unittests
|   `-- utils
|-- MyProject
|   |-- MyProject
|   `-- MyProject.xcodeproj
|-- MyWorkspace.xcworkspace
|   |-- contents.xcworkspacedata
|   |-- xcshareddata
|   `-- xcuserdata
`-- llvm-project
    |-- CONTRIBUTING.md
    |-- LICENSE.TXT
    |-- README.md
    |-- SECURITY.md
    |-- bolt
    |-- clang
    |-- clang-tools-extra
    |-- cmake
    |-- compiler-rt
    |-- cross-project-tests
    |-- flang
    |-- libc
    |-- libclc
    |-- libcxx
    |-- libcxxabi
    |-- libunwind
    |-- lld
    |-- lldb
    |-- llvm
    |-- llvm-libgcc
    |-- mlir
    |-- openmp
    |-- polly
    |-- pstl
    |-- runtimes
    |-- third-party
    `-- utils

將依賴項添加到您的項目

從現在開始,您只需輸入 Xcode 即可完成這項工作。 首先,讓我們將您需要的庫鏈接到項目並從Bitstream存檔開始。 打開項目的目標“常規”選項卡設置,然后在“框架”和“庫”下單擊+號,這會將您帶到包含當前可用的所有本地依賴項的屏幕。 LLVM 項目 + 本機 Apple 庫中的工具列表相當長,因此您可能希望根據需要對其進行過濾以找到所需的 position:

在此處輸入圖像描述

現在是棘手的部分。 您可能實際上不需要這樣做,但如果LLVMBitstreamReader目標本身依賴於其他庫的符號(並通過顯式使用庫符號公開這種依賴性)項目鏈接將失敗,所以為了安全起見 go 到LLVMBitstreamReader構建設置並在目標依賴項部分檢查它依賴於什么:

在此處輸入圖像描述

現在也將這些依賴項添加到您的項目中。 最終您的框架和庫部分應該如下所示:

在此處輸入圖像描述

調整項目設置

  • CMake 生成 Xcode 項目具有特殊性。 在我們的例子中,LLVM 項目目標的構建文件夾位於項目目錄下,名稱與所選配置匹配( Debug / Release / MinSizeRel / RelWithDebInfo )。 為了讓您自己的項目的目標找到使用給定配置構建的庫,您必須調整 LLVM 項目/目標設置,我不推薦這樣做,因為它需要大量手動工作,或者只需將自定義庫搜索路徑添加到你的項目。 對於后者 go 在上一步中添加依賴項的目標的構建設置,找到Library Search Path項並添加$(SRCROOT)/../LLVM/$(CONFIGURATION)/lib作為新項:

在此處輸入圖像描述

  • 另一個棘手的部分是,如果依賴項的目標具有不兼容的構建設置,則依賴目標將不會生成依賴項來構建。 不兼容在這里是一個模糊的術語,但通常意味着匹配架構部分。 幸運的是,在我們的例子中,它僅意味着進行發布配置以僅構建活動架構(調試根本不需要任何更改):

在此處輸入圖像描述

  • 最后但並非最不重要的一點是庫的標題。 生成 LLVM Xcode 項目后,它提供的標頭並未(完全)隨項目一起提供,實際上位於存儲庫文件夾中。 您可以直接將標頭復制到您自己的項目中,但我建議在系統標頭搜索路徑中添加 repo 目錄以與 LLVM Xcode 項目設置保持一致(您可以自己檢查標頭搜索路徑在LLVMBitstreamReader Build 下的位置設置)。 與lib搜索路徑類似,我建議使用設置變量的幫助並靈活地添加此路徑:
$(SRCROOT)/../llvm-project/llvm/include
$(SRCROOT)/../LLVM/include

在此處輸入圖像描述

壓軸

此時,您應該可以很好地使用 LLVMBitstreamReader 庫和其中定義的類。 我將main.m重命名為main.mm ,因此 clang 知道我將在我的代碼中使用 C++,這是我的示例代碼:

//
//  main.mm
//  MyProject
//
//  Created by Aleksandr Medvedev on 14.12.2022.
//

#import <Foundation/Foundation.h>
#import <llvm/Bitstream/BitstreamReader.h>
#import <iostream>

int main(int argc, const char * argv[]) {
    llvm::BitstreamBlockInfo::BlockInfo info;
    info.Name = "Hello, LLVM!";
    std::cout << info.Name << std::endl;
    
    @autoreleasepool {
        // insert code here...
        NSLog(@"Hello, World!");
    }
    return 0;
}

如果一切正常,現在應該可以正常編譯了。


PS我多次關注特定目錄層次結構是有原因的 - 當通過 CMake 生成 XCode 項目時,它通常使用絕對路徑,而不是相對路徑,如果將項目移動到另一個目錄,則必須調整構建中的路徑所需目標/項目的設置或重復生成 LLVM Xcode 項目的步驟。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM