mirror of
https://github.com/maplibre/maplibre-rs.git
synced 2025-12-08 19:05:57 +00:00
Add packaging Documentation (#52)
* Add apple documentation * Fix web documentation * Update android docs * Add script for serving the book * Update web docs
This commit is contained in:
parent
4f2a5da25a
commit
187cf9f5a9
17
.idea/runConfigurations/Serve_Book.xml
generated
Normal file
17
.idea/runConfigurations/Serve_Book.xml
generated
Normal file
@ -0,0 +1,17 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="Serve Book" type="ShConfigurationType">
|
||||
<option name="SCRIPT_TEXT" value="" />
|
||||
<option name="INDEPENDENT_SCRIPT_PATH" value="true" />
|
||||
<option name="SCRIPT_PATH" value="$PROJECT_DIR$/justfile" />
|
||||
<option name="SCRIPT_OPTIONS" value="book-serve" />
|
||||
<option name="INDEPENDENT_SCRIPT_WORKING_DIRECTORY" value="true" />
|
||||
<option name="SCRIPT_WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
||||
<option name="INDEPENDENT_INTERPRETER_PATH" value="true" />
|
||||
<option name="INTERPRETER_PATH" value="/bin/env" />
|
||||
<option name="INTERPRETER_OPTIONS" value="just --justfile" />
|
||||
<option name="EXECUTE_IN_TERMINAL" value="false" />
|
||||
<option name="EXECUTE_SCRIPT_FILE" value="true" />
|
||||
<envs />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
||||
@ -1,6 +1,18 @@
|
||||
# Android
|
||||
|
||||
## Gradle Project Setup
|
||||
|
||||
## Gradle Project setup
|
||||
In order to package an Android `.aar` archive we use
|
||||
the [rust-android-gradle](https://github.com/mozilla/rust-android-gradle).
|
||||
Except some customisations for the latest NDK toolchain release everything worked flawlessly.
|
||||
|
||||
## NativeActivity
|
||||
## JNI
|
||||
|
||||
There is no way right now to automatically generate JNI stubs for Rust. A manual example is available in the android
|
||||
crate of maplibre-rs.
|
||||
|
||||
## Single NativeActivity
|
||||
|
||||
Right now `winit` only allows the usage of a `NativeActivity`. This means the application needs to run in fullscreen.
|
||||
This native activity is referenced in the ´AndroidManifest.xml` by defining the name of the shared library.
|
||||
[Tracking Issue](https://github.com/maplibre/maplibre-rs/issues/28)
|
||||
|
||||
@ -1,26 +1,166 @@
|
||||
# Apple
|
||||
|
||||
{{#include figures/diff-macOS-entitlements.html}}
|
||||
On Apple maplibre-rs is packaged as:
|
||||
* Multiple .xcarchive packages which include a framework. Each for a different architecture and platform.
|
||||
* A single .xcframework package which contains multiple frameworks of different architectures and platforms.
|
||||
* A swift package which just references the .xcframework package and makes distributing easier.
|
||||
|
||||
## Library Entry
|
||||
The following diffs are extracted from [this diff](../../../../apple/framework.diff). They should serve as documentation
|
||||
for the XCode project. This is required because XCode is a mess.
|
||||
|
||||
## XCode Project description
|
||||
|
||||
### Library Entry
|
||||
|
||||
{{#include figures/diff-maplibre-swift.html}}
|
||||
|
||||
## Files & Assets
|
||||
The swift code above is the main entry for the Swift API. From this entry file we can expose more API of maplibre-rs.
|
||||
Any C functions which are referenced in the XCode framework's header are available automatically in Swift.
|
||||
|
||||
{{#include figures/diff-xcode-project-assets.html}}
|
||||
|
||||
## Framework
|
||||
### Framework
|
||||
|
||||
{{#include figures/diff-xcode-project-framework.html}}
|
||||
|
||||
## Cargo Build Phase
|
||||
The framework needs to link against the static library `libmaplibre_apple.a`, which has been generated by Cargo.
|
||||
In order to allow XCode to dynamically select the library based on the `Library Search Path` (Build Settings) one needs
|
||||
to add a relative file to XCode. The entry in the `project.pbxproj` should look like that:
|
||||
|
||||
```js
|
||||
B085D5A32812987B00906D21 /* libmaplibre_apple.a */ = {
|
||||
isa = PBXFileReference;
|
||||
lastKnownFileType = archive.ar;
|
||||
path = libmaplibre_apple.a;
|
||||
sourceTree = SOURCE_ROOT;
|
||||
};
|
||||
```
|
||||
|
||||
Note the `path = libmaplibre_apple.a`. This path does not link to a concrete file, but to a file which can be found
|
||||
during building.
|
||||
|
||||
A file can be added to the frameworks and library link phase in XCode.
|
||||
|
||||
### Cargo Build Phase
|
||||
|
||||
{{#include figures/diff-xcode-project-build-cargo.html}}
|
||||
|
||||
## Build Settings
|
||||
In order to trigger Cargo builds when starting a XCode build we include a `Cargo Build` script. This build script needs
|
||||
to run before the linking phase (drag and drop it to the top).
|
||||
|
||||
The following build script builds based on XCode environment variables the correct static library. We depend on
|
||||
the `$ARCHS`
|
||||
environment variable, as the others seem unreliable. Note that this can include multiple architectures, unless the build
|
||||
setting `ONLY_ACTIVE_ARCH` is set to `YES`.
|
||||
|
||||
```bash
|
||||
. "$HOME/.cargo/env"
|
||||
|
||||
arch="unknown"
|
||||
vendor="apple"
|
||||
os_type="unknown"
|
||||
environment_type=""
|
||||
|
||||
mode=""
|
||||
|
||||
echo "ARCH: $ARCHS"
|
||||
|
||||
if [[ $CONFIGURATION == "Release" ]]
|
||||
then
|
||||
mode="--release"
|
||||
fi
|
||||
|
||||
if [[ $ARCHS == "x86_64" ]]
|
||||
then
|
||||
arch="x86_64"
|
||||
elif [[ $ARCHS == "arm64" ]]
|
||||
then
|
||||
arch="aarch64"
|
||||
fi
|
||||
|
||||
if [[ $SDK_NAME == *"iphoneos"* ]]
|
||||
then
|
||||
os_type="ios"
|
||||
elif [[ $SDK_NAME == *"macos"* ]]
|
||||
then
|
||||
os_type="darwin"
|
||||
elif [[ $SDK_NAME == *"iphonesimulator"* ]]
|
||||
then
|
||||
os_type="ios"
|
||||
environment_type="sim"
|
||||
fi
|
||||
|
||||
|
||||
triplet="$arch-$vendor-$os_type"
|
||||
|
||||
if [ -n "$environment_type" ]
|
||||
then
|
||||
triplet="$triplet-$environment_type"
|
||||
fi
|
||||
|
||||
echo "$mode"
|
||||
echo "$triplet"
|
||||
|
||||
env -i zsh -c "cargo build -p maplibre-apple $mode --target $triplet --lib"
|
||||
```
|
||||
|
||||
### Build Settings
|
||||
|
||||
{{#include figures/diff-xcode-project-build-settings.html}}
|
||||
|
||||
## Info Plist for Applications
|
||||
Explanations for the settings:
|
||||
|
||||
{{#include figures/diff-xcode-project-info-plist.html}}
|
||||
* `BUILD_LIBRARY_FOR_DISTRIBUTION`: Define that this is a library (effect unknown to me)
|
||||
* `CODE_SIGN_STYLE`: The framework is not signed
|
||||
* `DEVELOPMENT_TEAM`: No development team is set
|
||||
* `LIBRARY_SEARCH_PATHS[sdk=x][arch=y]`: We set the path for the `libmaplibre_apple.a` lies
|
||||
* `MACH_O_TYPE` / `SKIP_INSTALL`: If this is not set to `staticlib` and `NO`, then the `libmaplibre_apple.a` binary is not included in the final framework xcarchive.
|
||||
* `SUPPORTED_PLATFORMS`: Explicitly says that this library works on any platform.
|
||||
* `SUPPORTS_MACCATALYST`: Explicitly says that this library works on Mac Catalyst.
|
||||
|
||||
The same settings are done for Release and Debug.
|
||||
|
||||
## xcframework packaging
|
||||
|
||||
Creating a xcframework is usually quite straight forward. Just execute the following:
|
||||
|
||||
```bash
|
||||
xargs xcodebuild -create-xcframework -framework ./a -framework ./b -output out.xcframework
|
||||
```
|
||||
|
||||
Unfortunately, it is not possible to bundle some frameworks together like:
|
||||
|
||||
* macOS-arm64 and macOS-x86_64
|
||||
|
||||
In order to package these architectures and platforms together a fat binary needs to be created using the `lipo` tool.
|
||||
This means from two frameworks we create a unified framework with a fat binary.
|
||||
There are two important steps:
|
||||
|
||||
1. Create a fat binary using `lipo -create binA binB -output binfat`
|
||||
2. Copy for example the arm64 framework and add the `.swiftmodule` definitions from the x86_64 framework
|
||||
|
||||
## Single UIApplication
|
||||
|
||||
Right now `winit` only allows the usage of a `UIApplication`. This means the application needs to run in fullscreen.
|
||||
[Tracking Issue](https://github.com/maplibre/maplibre-rs/issues/28)
|
||||
|
||||
## Example App
|
||||
|
||||
The following settings are important for the example application within the XCode project.
|
||||
|
||||
### Info Plist for Applications
|
||||
|
||||
{{#include figures/diff-xcode-project-info-plist.html}}
|
||||
|
||||
* The `INFOPLIST_KEY_UIApplicationSceneManifest_Generation` needs to be unset. Else the application screen is just black.
|
||||
|
||||
### Files & Assets
|
||||
|
||||
{{#include figures/diff-xcode-project-assets.html}}
|
||||
|
||||
* The example/demo application within the XCode project references the `maplibre_rs.framework`. Some default files have
|
||||
been removed.
|
||||
|
||||
### MacOS Entitlements
|
||||
|
||||
{{#include figures/diff-macOS-entitlements.html}}
|
||||
|
||||
* On macOS one needs to allow network access via `com.apple.security.network.client`
|
||||
@ -6,7 +6,7 @@ This document describes issues and challenges when packaging maplibre-rs as a np
|
||||
|
||||
### ESM
|
||||
|
||||
The ESM module format is the standard nowadays which should be followed. If a bundler like webpack encounters an ESM
|
||||
The ESM module format is the standard nowadays which should be followed. If a JS bundler encounters an ESM
|
||||
module it can resolve WebAssembly files or WebWorkers dynamically.
|
||||
The following syntax is used to resolve referenced WebWorkers:
|
||||
|
||||
@ -28,7 +28,8 @@ new URL('index_bg.wasm', import.meta.url);
|
||||
> object. This allows quick prototyping/playgrounds/experiments using maplibre-rs.
|
||||
|
||||
In order to support this we need to create a bundle which works on any modern browser. Additionally, a WASM file and
|
||||
WebWorker needs to be deployed at a predictable path, because there is no bundler active which manages assets.
|
||||
WebWorker needs to be deployed at a predictable path, because there is no bundler active which manages assets. Users of
|
||||
these libraries have to specify where WASM or non-inlined WebWorkers are located.
|
||||
|
||||
Both assets could be inlined theoretically. This is common for WebWorkers, but not for WASM files.
|
||||
|
||||
@ -42,18 +43,14 @@ Both assets could be inlined theoretically. This is common for WebWorkers, but n
|
||||
|
||||
> Not needed for the browser build of maplibre-rs, possibly needed when supporting Node
|
||||
|
||||
With a CommonJS module its is not possible for bundlers to dynamically resolve WebWorkers or WASM files. Users of these
|
||||
libraries have
|
||||
to specify where WASM or non-inlined WebWorkers are hosted.
|
||||
With a CommonJS module its is not possible for bundlers to dynamically resolve WebWorkers or WASM files.
|
||||
|
||||
The `import.meta.url` token can not exist in a CommonJS module. Therefore, bundlers which encounter a CommonJS module
|
||||
have to use a different mechanism of resolving files.
|
||||
|
||||
* The Parcel bundler translates to `new URL('index_bg.wasm', import.meta.url);`
|
||||
to `new URL("index_bg.wasm", "file:" + __filename);`
|
||||
While depending on `file:` and `filename` works for NodeJS, it is unsupported in the browser
|
||||
* Webpack translates `new URL('index_bg.wasm', import.meta.url);` to something that is equivalent to `'./index_bg.wasm'`
|
||||
. It just expects that assets are resolvable from the current file.
|
||||
Generally, we do not need to support CommonJS, because we are not targeting Node with maplibre-rs. It's properly good to
|
||||
support it as a fallback though, for bundlers which can not deal with ESM modules yet.
|
||||
This is for example true for test runners like Jest which require that dependencies are available as CJS module.
|
||||
|
||||
## wasm-pack output
|
||||
|
||||
@ -67,25 +64,22 @@ Therefore, we should stick to the `web` output format.
|
||||
|
||||
## Required Features
|
||||
|
||||
* WASM Bundling
|
||||
> Make the WASM binary available to users of the maplibre-rs library
|
||||
* WebWorker Bundling
|
||||
> Make the WebWorker available to users of the maplibre-rs library. This could also be achived by inlining.
|
||||
* WebWorker Inlining
|
||||
> Inline the WebWorker bundle in the library bundle as a string.
|
||||
* Predictable paths for CJS
|
||||
> TODO
|
||||
* WASM Bundling: Make the WASM binary available to users of the maplibre-rs library
|
||||
* WebWorker Bundling: Make the WebWorker available to users of the maplibre-rs library. This could also be achived by inlining.
|
||||
* WebWorker Inlining: Inline the WebWorker bundle in the library bundle as a string.
|
||||
* Predictable Paths: Without predictable paths, it's difficult for users to reference the wasm file directly from the `node_modules` directory if requried.
|
||||
|
||||
|
||||
## Bundler Feature Comparison
|
||||
|
||||
| Bundler | *ESM* | *IIFE* | CJS | UMD | *WebWorker Inlining* | Web Worker Bundling | *WASM Bundling* | *Predictable Paths* |
|
||||
|---------------|-------|--------|-----|-----|----------------------|---------------------|-----------------|---------------------|
|
||||
| Babel 1) | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ |
|
||||
| TypeScript 1) | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ |
|
||||
| Webpack | ❌ 4) | ❓ | ❌ | ❓ | ❌ 2) | ✅ | ✅ | ❓ |
|
||||
| Parcel | ✅ | ❌ | ✅ | ❌ | 🛠️ 3) | ✅ | ✅ | ❌ 5) |
|
||||
| ESBuild | ✅ | ✅ | ✅ | ❌ | ✅ 6) | ❓ | ✅ 6) | ✅ |
|
||||
| Rollup | ❓ | ❓ | ❓ | ❓ | ❓ | ❓ | ❓ | ❓ |
|
||||
| Bundler | *ESM* | *IIFE* | CJS | UMD | *WebWorker Inlining* | Web Worker Bundling | *WASM Bundling* | *Predictable Paths* | Inlining Environment Variables |
|
||||
|---------------|-------|--------|-----|-----|----------------------|---------------------|-----------------|---------------------|--------------------------------|
|
||||
| Babel 1) | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ |
|
||||
| TypeScript 1) | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ |
|
||||
| Webpack | ❌ 4) | ❓ | ❌ | ❓ | ❌ 2) | ✅ | ✅ | ❓ | ✅ |
|
||||
| Parcel | ✅ | ❌ | ✅ | ❌ | 🛠️ 3) | ✅ | ✅ | ❌ 5) | ✅ |
|
||||
| ESBuild | ✅ | ✅ | ✅ | ❌ | ✅ 6) | ❓ | ✅ 6) | ✅ | ✅ |
|
||||
| Rollup | ❓ | ❓ | ❓ | ❓ | ❓ | ❓ | ❓ | ❓ | ✅ |
|
||||
|
||||
Features in ***italic***s are required for maplibre-rs.
|
||||
|
||||
@ -96,6 +90,20 @@ Features in ***italic***s are required for maplibre-rs.
|
||||
> 5) Plugins exist, but they don't work reliably
|
||||
> 6) Plugins exist, and work reliably
|
||||
|
||||
### ESBuild
|
||||
|
||||
ESBuild supports CJS, ESM and IIFI modules equally well. Plugins exist for WebWorker inlining and resolving assets
|
||||
through `import.meta.url`. The plugin quality seems to be superior compared to Parcel. It is also very fast compared to
|
||||
all other bundlers.
|
||||
|
||||
* IIFI: The esbuild bundler translates to `new URL('index_bg.wasm', import.meta.url);` to
|
||||
```js
|
||||
var __currentScriptUrl__ = document.currentScript && document.currentScript.src || document.baseURI;
|
||||
new URL("./assets/index_bg.wasm?emit=file", __currentScriptUrl__);
|
||||
```
|
||||
|
||||
See config in `web/lib/build.mjs` for an example usage.
|
||||
|
||||
### Babel & TypeScript
|
||||
|
||||
Babel and TypeScript both can produce ESM modules, but they **fail with transforming references within the source code**
|
||||
@ -103,13 +111,16 @@ like `new URL("./pool.worker.ts", import.meta.url)`. There exist some Babel plug
|
||||
Therefore, we actually need a proper bundler which supports outputting ESM modules.
|
||||
The only stable solution to this is Parcel. Parcel also has good documentation around the bundling of WebWorkers.
|
||||
|
||||
|
||||
### WebPack
|
||||
|
||||
TODO
|
||||
WebPack supports older module formats like CommonJS or UMD very well. It falls short when bundling the format ESM
|
||||
format which is not yet stable. It also does not support inlining WebWorkers in version 5. The wasm-pack plugin
|
||||
for WebPack makes including Cargo projects easy.
|
||||
|
||||
* CJS: Webpack translates `new URL('index_bg.wasm', import.meta.url);` to something that is equivalent to `'./index_bg.wasm'`
|
||||
. It just expects that assets are resolvable from the current file.
|
||||
|
||||
Example scripts:
|
||||
Example scripts for `package.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
@ -156,8 +167,7 @@ module.exports = (env) => ({
|
||||
use: [
|
||||
{
|
||||
loader: 'ts-loader',
|
||||
options: {
|
||||
}
|
||||
options: {}
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -219,9 +229,14 @@ module.exports = (env) => ({
|
||||
|
||||
### Parcel
|
||||
|
||||
TODO
|
||||
Parcel supports CommonJS and ESM modules equally good. The documentation about `import.meta.url` is very good. In other
|
||||
bundlers documentations around this feature is missing. In the latest Parcel version inlining WebWorkers is not working.
|
||||
|
||||
Example scripts:
|
||||
* CJS: The Parcel bundler translates to `new URL('index_bg.wasm', import.meta.url);`
|
||||
to `new URL("index_bg.wasm", "file:" + __filename);`
|
||||
While depending on `file:` and `filename` works for NodeJS, it is unsupported in the browser.
|
||||
|
||||
Example scripts for `package.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
@ -260,13 +275,6 @@ Example config in `package.json:
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### ESBuild
|
||||
|
||||
TODO
|
||||
|
||||
See config in `web/lib/build.mjs`.
|
||||
|
||||
### Rollup
|
||||
|
||||
Not yet evaluated
|
||||
Loading…
x
Reference in New Issue
Block a user