Skip to content

Commit a272801

Browse files
committed
Update documentation now that we build and release LLVM as xcframework
1 parent 1434cec commit a272801

2 files changed

Lines changed: 18 additions & 63 deletions

File tree

HeaderSearchPaths.png

-99.8 KB
Binary file not shown.

README.md

Lines changed: 18 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,18 @@ llvm::raw_ostream &errorOutputStream
2424
to `clangInterpret` and replace all `llvm::errs()` with `errorOutputStream` so we can capture the compilation output and pass it back to the app front-end to display to the user.
2525

2626
4. **For real iOS device**: The implementation of [`llvm::sys::getProcessTriple()`](https://github.com/llvm/llvm-project/blob/master/llvm/lib/Support/Host.cpp) is currently bogus according to the implementation of [`JITTargetMachineBuilder::detectHost()`](https://github.com/llvm/llvm-project/blob/master/llvm/lib/ExecutionEngine/Orc/JITTargetMachineBuilder.cpp).
27-
So we need to add the appropriate conditional compilation directive `#if TARGET_OS_SIMULATOR ... #else ... #endif` to give it the correct triple. (The platform macro is documented at `<TargetConditionals.h>`.)
27+
So we need to add the appropriate conditional compilation directive `#ifdef __aarch64__ ... #else ... #endif` to give it the correct triple.
2828

2929
In the latest version, you should be able to edit the program, interpret it and see the output in the app UI.
3030

3131
### Preparations
3232

3333
Before building the project, you need to either
34-
1. compile LLVM (see instructions down) and copy the LLVM installation directory to Sample project; or
35-
2. download a prebuilt binary package from our [releases](https://github.com/light-tech/LLVM-On-iOS/releases),
36-
`cd` to the `Sample` project folder and do
34+
1. compile LLVM (see instructions down below) and copy the `LLVM.xcframework` to Sample project; or
35+
2. download our prebuilt XCFramework (the file named `LLVM.xcframework.tar.xz`) from our [releases](https://github.com/light-tech/LLVM-On-iOS/releases),
36+
then `cd` to the `Sample` project folder and do
3737
```shell
38-
tar -xzf PATH_TO_DOWNLOADED_TAR_XZ # e.g. ~/Downloads/LLVM-iOS.tar.xz
38+
tar -xzf PATH_TO_DOWNLOADED_TAR_XZ # e.g. ~/Downloads/LLVM.xcframework.tar.xz
3939
```
4040

4141
![Edit the program screenshot](Screenshot1.png)
@@ -45,7 +45,7 @@ tar -xzf PATH_TO_DOWNLOADED_TAR_XZ # e.g. ~/Downloads/LLVM-iOS.tar.xz
4545

4646
For simulator, can only build **Debug** version only!
4747

48-
Do NOT expect the app to work on real iPhone due to iOS security preventing [Just-In-Time (JIT) Execution](https://saagarjha.com/blog/2020/02/23/jailed-just-in-time-compilation-on-ios/) that the interpreter example was doing.
48+
You can run the app on the Mac (thank to Mac Catalyst) and iOS simulator. Do NOT expect the app to work on real iPhone due to iOS security preventing [Just-In-Time (JIT) Execution](https://saagarjha.com/blog/2020/02/23/jailed-just-in-time-compilation-on-ios/) that the interpreter example was doing.
4949
By pulling out the device crash logs, the reason turns out to be the fact the [code generated in-memory by LLVM/Clang wasn't signed](http://iphonedevwiki.net/index.php/Code_Signing) and so the app was terminated with SIGTERM CODESIGN.
5050

5151
If there is compilation error, the error message was printed out instead of crashing as expected:
@@ -58,14 +58,14 @@ If there is compilation error, the error message was printed out instead of cras
5858
To make the app work on real iPhone _untethered from Xcode_, one possibility is to use compilation into binary, somehow sign it and use [system()](https://stackoverflow.com/questions/32439095/how-to-execute-a-command-line-in-iphone).
5959
Another possibility would be to use the slower LLVM bytecode interpreter instead of ORC JIT that the example was doing, as many [existing terminal apps](https://opensource.com/article/20/9/run-linux-ios) illustrated.
6060

61-
Build LLVM for iOS (physical device and simulator)
62-
--------------------------------------------------
61+
Build LLVM for iOS
62+
------------------
6363

6464
### The tools we needs
6565

6666
* [Xcode](https://developer.apple.com/xcode/): Download from app store.
67-
* [CMake](https://cmake.org/download/): See [installation instruction](https://tudat.tudelft.nl/installation/setupDevMacOs.html) to add to PATH.
68-
* [Ninja](https://github.com/ninja-build/ninja/releases): Download and extract the ninja executable to `~/Downloads` folder.
67+
* [CMake](https://cmake.org/download/): See [installation instruction](https://tudat.tudelft.nl/installation/setupDevMacOs.html) to add to `$PATH`.
68+
* [Ninja](https://github.com/ninja-build/ninja/releases): Download and extract the ninja executable to this repo root.
6969
* The GNU tools `autoconf`, `automake` and `libtool` are needed to build libffi, install them with homebrew from the terminal
7070
```shell
7171
brew install autoconf automake libtool
@@ -83,53 +83,18 @@ Simply execute [build-libffi.sh](build-libffi.sh) in the repo root.
8383
./build-libffi.sh macOS # Build for macOS
8484
```
8585

86-
To package and release (for building LLVM with Azure DevOps):
87-
```shell
88-
tar -cJf libffi.tar.xz libffi/Release-iphoneos libffi/Release-maccatalyst
89-
```
90-
9186
### Build LLVM and co.
9287

93-
Our script [build-llvm.sh](buildllvm-iOS.sh) builds LLVM + Clang for multiple Apple platforms.
94-
We disable various stuffs such as `terminfo` since there is no terminal in iOS; otherwise, there will be problem when linking in Xcode.
95-
Feel free to adjust to suit your need according to [the official instructions](https://llvm.org/docs/GettingStarted.html).
88+
Apple has introduced [XCFramework](https://developer.apple.com/videos/play/wwdc2019/416/) to allow packaging a library for multiple-platforms (iOS, Simulator, watchOS, macOS) and CPU architectures (x86_64, arm64) that could be easily added to a project.
9689

97-
We can now build the library on [Azure DevOps](https://lightech.visualstudio.com/LLVM/_build) pipeline.
90+
Our script [build-llvm-framework.sh](build-llvm-framework.sh) builds LLVM for several iOS platforms and packages it as an XCFramework so we do not have to switch out the libraries when we build the app for different targets (e.g. testing the app on real iPhone arm64 vs simulator x86_64).
9891

9992
At this repo root:
10093
```shell
101-
git clone --single-branch --branch release/11.x https://github.com/llvm/llvm-project.git
102-
./build-llvm.sh iOS # Build for running on real iPhones
103-
./build-llvm.sh iOS-Sim # Build for iOS simulator
104-
./build-llvm.sh macOS # Build for macOS
105-
```
106-
107-
Grab a coffee as it will take roughly 30 mins to complete.
108-
109-
Once the build process is completed, the library and include headers should be installed at `LLVM-iOS`, `LLVM-iOS-Sim` or `LLVM-macOS` in the root repo.
110-
(We will subsequently refer to these directories as the _LLVM installation dir_.)
111-
112-
### Post compilation and installation
113-
114-
Before being able to use in Xcode, in the built folder, we first need to move the `lib/cmake` and `lib/*.dylib` out of `lib/`:
115-
```shell
116-
cd LLVM-iOS
117-
mkdir lib2
118-
mv lib/cmake lib2/
119-
mv lib/*.dylib lib2/
120-
mv lib/libc++* lib2/
121-
#rm -rf lib2
94+
./build-llvm-framework.sh
12295
```
123-
Otherwise, iOS will crash when loading dynamic libraries.
124-
Optionally, you could move the `liblld*` to `lib2` as well and the `bin` since it's unlikely you need binary linkage and the `clang` command line program in iOS app.
12596

126-
Running our script [prepare-llvm.sh](prepare-llvm.sh) in the LLVM installation dir will perform the necessary set-up.
127-
We also combine all static libraries `*.a` into a single `llvm.a` for ease of use.
128-
129-
The ready-to-use archive on our release page was created with
130-
```shell
131-
tar -cJf LLVM-11.0.1-iOS.tar.xz LLVM-iOS/
132-
```
97+
We can now build the library on an [Azure DevOps](https://lightech.visualstudio.com/LLVM/_build) pipeline.
13398

13499
Behind the Scene
135100
----------------
@@ -167,21 +132,11 @@ is fairly useful in helping us write the Objective-C bridging class `LLVMBridge`
167132

168133
### Configure iOS App Xcode Project
169134

170-
1. Create a new iOS app project in Xcode and copy an LLVM installation to the project folder.
171-
Unfortunately, LLVM cannot build fat binary for iOS at the moment so we have to manually switch between the two LLVM installations when we switch testing between real iOS device (ARM) or iOS simulator (x86_64).
172-
A good approach is to copy both folders `~/Download/LLVM-iOS` or `~/Download/LLVM-iOS-Simulator` to the project folder and rename one of them to `LLVM` depending on our build target.
173-
174-
2. Add the LLVM static libraries to your project by right click on the Sample project, choose **Add files to "YOUR PROJECT NAME"** and select the **LLVM/lib** folder.
175-
Enable **Create groups** but not **Copy items if needed**.
176-
177-
3. Next, we add `LLVM/include` to header search path so that our C++/Objective-C++ code can `#include` the LLVM's headers.
178-
Go to **Build settings** your project, click on **All** and search for `header`.
179-
You should find **Header Search Paths** under **Search Paths**.
180-
Add a new item `$(PROJECT_DIR)/LLVM/include`.
135+
1. Create a new iOS app project in Xcode and copy `LLVM.xcframework` to the project folder.
181136

182-
![Header Search Paths Setting](HeaderSearchPaths.png)
137+
2. In Xcode, add `LLVM.xcframework` to the project's Framework and Libraries. Choose **Do not embed** so that the static library is linked into the app and the entire framework is NOT copied to the app bundle.
183138

184-
4. To create the Objective-C bridge between Swift and C++ mentioned at the beginning, add to your project a new header file, say `LLVMBridge.h` and an implementation file, say `LLVMBridge.mm` (here, we use the `.mm` extension for Objective-C++ since we do need C++ to implement our `LLVMBridge` class) and then change the Objective-C bridging header setting in the project file to tell Xcode that the Objective-C class defined in `LLVMBridge.h` should be exposed to Swift.
139+
3. To create the Objective-C bridge between Swift and C++ mentioned at the beginning, add to your project a new header file, say `LLVMBridge.h` and an implementation file, say `LLVMBridge.mm` (here, we use the `.mm` extension for Objective-C++ since we do need C++ to implement our `LLVMBridge` class) and then change the Objective-C bridging header setting in the project file to tell Xcode that the Objective-C class defined in `LLVMBridge.h` should be exposed to Swift.
185140
Again, go to **Build settings** your project and search for `bridg` and you should find **Objective-C Bridging Header** under **Swift Compiler - General**.
186141
Set it to `PROJECT_NAME/LLVMBridge.h` or if you are using more than just LLVM, a header file of your choice (but that header should include `LLVMBridge.h`).
187142

@@ -192,7 +147,7 @@ Set it to `PROJECT_NAME/LLVMBridge.h` or if you are using more than just LLVM, a
192147
At this point, we should be able to run the project on iOS simulator.
193148
**To build the app for real iOS devices, an extra step is needed.**
194149

195-
5. Since we are using a bunch of precompiled static libraries (and not the actual C++ source code in our app), we need to disable bitcode. Search for `bitcod` and set **Enable Bitcode** setting to `No`.
150+
4. Since we are using a bunch of precompiled static libraries (and not the actual C++ source code in our app), we need to disable bitcode. Search for `bitcod` and set **Enable Bitcode** setting to `No`.
196151

197152
![Bitcode Setting](DisableBitcode.png)
198153

0 commit comments

Comments
 (0)