![](/img/trans.png)
[英]How do I compile + link C++ code in Xcode in an Objective-C project?
[英]How do I link and use LLVM libraries from an Objective-C Xcode project?
我想在我自己的 Objective-C 應用程序中使用 LLVM 項目中的幾個類。 具體來說,我想使用在BitstreamReader.h和BitstreamWriter.h中聲明的類。 不幸的是,我沒有太多鏈接 C++ 庫的經驗,所以我真的不知道從哪里開始。 我首先通過 Homebrew 使用brew install llvm@14
。 然后,在我的 Xcode 項目中,我嘗試鏈接/opt/homebrew/opt/llvm@14/lib
中的庫,並將/opt/homebrew/opt/llvm@14/include/**
添加到我的HEADER_SEARCH_PATHS
中。
現在我完全卡住了。 我在 Xcode 中有一堆構建錯誤,例如:
任何幫助都將不勝感激。 謝謝!
在 C++ 世界中,有很多方法可以將依賴項合並到您的項目中,我將概述其中的一些,但會嘗試詳細描述我認為最適合您的場景的一種:
這是最經典的方法,當您為特定平台預編譯和預安裝庫時,它們可以在默認庫搜索路徑下使用。 類似於 iOS 中系統框架的使用方式——你只在項目中添加 linker 命令,而框架(庫)獨立存在(或不存在,導致 linker 錯誤)。 這種方法的問題是,您不能真正將庫用於受限系統,其中“默認”庫是不可更改的(iOS、tvOS、iPadOS)
另一種方法是將您需要的所有庫預編譯到所有平台的檔案庫中,這些庫應該被使用,然后只將其中一個所需的庫版本嵌入到您的最終應用程序二進制文件中。 這種方法有些麻煩且不可移植,因為每次需要更改庫的某些部分或支持新平台時,它都需要您手動編譯庫並重新嵌入它。
xcframework
這種方法與前一種方法非常相似,有一些好處,您可以將所有平台的二進制文件打包在一個 package 下,甚至可以在 SPM 中發布。
C++ 中的許多項目(LLVM 也不例外)都是使用所謂的 CMake 工具制作的。 它被廣泛采用的多平台構建系統,您可以使用的好處之一是您可以輕松地將任何其他項目作為您自己的一部分。 同時 CMake 在移動開發領域並不普遍,因此您可能很難找到這些平台的相關信息。
這是我想更詳細地描述的解決方案。 簡而言之,該方法包括 6 個步驟:
這種方法的好處是它提供了最一致的體驗(生成項目后,所有部分都可以從 Xcode 進行配置)、管理源代碼的自由(LLVM 項目文件可以根據需要進行更改),以及內置的豪華 -在依賴圖中(構建目標所需的所有庫都在 Xcode 設置下給出)。
您可以從此處克隆該項目。 請注意,這必須位於您未來工作區所在的同一文件夾中,因此您最好提前做好准備:
% mkdir MyWorkspace && cd MyWorkspace
% git clone git@github.com:llvm/llvm-project.git
首先,確保您已安裝 CMake(它不是隨 macOS 開箱即用的)。 您可以使用brew
或從官方網站下載應用程序。 之后,在llvm-project
repo 文件夾旁邊為未來的 Xcode 項目創建一個新文件夾,並在 LLVM 工具包項目上運行cmake
:
% mkdir LLVM && cd LLVM
% cmake -GXCode ../llvm-project/llvm
這里沒什么特別的,只需打開 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構建設置並在目標依賴項部分檢查它依賴於什么:
現在也將這些依賴項添加到您的項目中。 最終您的框架和庫部分應該如下所示:
Debug
/ Release
/ MinSizeRel
/ RelWithDebInfo
)。 為了讓您自己的項目的目標找到使用給定配置構建的庫,您必須調整 LLVM 項目/目標設置,我不推薦這樣做,因為它需要大量手動工作,或者只需將自定義庫搜索路徑添加到你的項目。 對於后者 go 在上一步中添加依賴項的目標的構建設置,找到Library Search Path項並添加$(SRCROOT)/../LLVM/$(CONFIGURATION)/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.