maplibre-rs/docs/book/print.html

4471 lines
232 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE HTML>
<html lang="en" class="sidebar-visible no-js light">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>MapLibre Rust Documentation</title>
<meta name="robots" content="noindex" />
<!-- Custom HTML head -->
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff" />
<link rel="icon" href="favicon.svg">
<link rel="shortcut icon" href="favicon.png">
<link rel="stylesheet" href="css/variables.css">
<link rel="stylesheet" href="css/general.css">
<link rel="stylesheet" href="css/chrome.css">
<link rel="stylesheet" href="css/print.css" media="print">
<!-- Fonts -->
<link rel="stylesheet" href="FontAwesome/css/font-awesome.css">
<link rel="stylesheet" href="fonts/fonts.css">
<!-- Highlight.js Stylesheets -->
<link rel="stylesheet" href="highlight.css">
<link rel="stylesheet" href="tomorrow-night.css">
<link rel="stylesheet" href="ayu-highlight.css">
<!-- Custom theme stylesheets -->
<link rel="stylesheet" href="diff.css">
</head>
<body>
<!-- Provide site root to javascript -->
<script type="text/javascript">
var path_to_root = "";
var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "navy" : "light";
</script>
<!-- Work around some values being stored in localStorage wrapped in quotes -->
<script type="text/javascript">
try {
var theme = localStorage.getItem('mdbook-theme');
var sidebar = localStorage.getItem('mdbook-sidebar');
if (theme.startsWith('"') && theme.endsWith('"')) {
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
}
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
}
} catch (e) { }
</script>
<!-- Set the theme before any content is loaded, prevents flash -->
<script type="text/javascript">
var theme;
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
if (theme === null || theme === undefined) { theme = default_theme; }
var html = document.querySelector('html');
html.classList.remove('no-js')
html.classList.remove('light')
html.classList.add(theme);
html.classList.add('js');
</script>
<!-- Hide / unhide sidebar before it is displayed -->
<script type="text/javascript">
var html = document.querySelector('html');
var sidebar = 'hidden';
if (document.body.clientWidth >= 1080) {
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
sidebar = sidebar || 'visible';
}
html.classList.remove('sidebar-visible');
html.classList.add("sidebar-" + sidebar);
</script>
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
<div class="sidebar-scrollbox">
<ol class="chapter"><li class="chapter-item expanded affix "><a href="introduction.html">Introduction</a></li><li class="chapter-item expanded affix "><a href="supported-platforms.html">Supported Platforms</a></li><li class="chapter-item expanded affix "><a href="developer-log.html">Developer Log</a></li><li class="chapter-item expanded "><a href="user-guide/index.html"><strong aria-hidden="true">1.</strong> User Guide</a></li><li class="chapter-item expanded "><a href="development-guide/index.html"><strong aria-hidden="true">2.</strong> Development Guide</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="development-guide/how-to-run.html"><strong aria-hidden="true">2.1.</strong> How to Run Demos</a></li><li class="chapter-item expanded "><a href="development-guide/building-libraries.html"><strong aria-hidden="true">2.2.</strong> Building Libraries</a></li><li class="chapter-item expanded "><a href="development-guide/debugging.html"><strong aria-hidden="true">2.3.</strong> Debugging</a></li></ol></li><li class="chapter-item expanded "><a href="development-documents/index.html"><strong aria-hidden="true">3.</strong> Development Documents</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="development-documents/architecture.html"><strong aria-hidden="true">3.1.</strong> Architecture</a></li><li class="chapter-item expanded "><a href="development-documents/design.html"><strong aria-hidden="true">3.2.</strong> Design</a></li><li class="chapter-item expanded "><a href="development-documents/caching.html"><strong aria-hidden="true">3.3.</strong> Caching</a></li><li class="chapter-item expanded "><a href="development-documents/stencil-masking.html"><strong aria-hidden="true">3.4.</strong> Stencil Masking</a></li><li class="chapter-item expanded "><a href="development-documents/font-rendering.html"><strong aria-hidden="true">3.5.</strong> Font Rendering</a></li><li class="chapter-item expanded "><a href="development-documents/library-packaging.html"><strong aria-hidden="true">3.6.</strong> Library Packaging</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="development-documents/library-packaging/apple.html"><strong aria-hidden="true">3.6.1.</strong> Apple</a></li><li class="chapter-item expanded "><a href="development-documents/library-packaging/android.html"><strong aria-hidden="true">3.6.2.</strong> Android</a></li><li class="chapter-item expanded "><a href="development-documents/library-packaging/web.html"><strong aria-hidden="true">3.6.3.</strong> Web</a></li></ol></li></ol></li><li class="chapter-item expanded "><a href="appendix/index.html"><strong aria-hidden="true">4.</strong> Appendix</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="appendix/link-collection.html"><strong aria-hidden="true">4.1.</strong> Link Collection</a></li></ol></li></ol>
</div>
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
</nav>
<div id="page-wrapper" class="page-wrapper">
<div class="page">
<div id="menu-bar-hover-placeholder"></div>
<div id="menu-bar" class="menu-bar sticky bordered">
<div class="left-buttons">
<button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
<i class="fa fa-bars"></i>
</button>
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
<i class="fa fa-paint-brush"></i>
</button>
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
<li role="none"><button role="menuitem" class="theme" id="light">Light (default)</button></li>
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
</ul>
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
<i class="fa fa-search"></i>
</button>
</div>
<h1 class="menu-title">MapLibre Rust Documentation</h1>
<div class="right-buttons">
<a href="print.html" title="Print this book" aria-label="Print this book">
<i id="print-button" class="fa fa-print"></i>
</a>
</div>
</div>
<div id="search-wrapper" class="hidden">
<form id="searchbar-outer" class="searchbar-outer">
<input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
</form>
<div id="searchresults-outer" class="searchresults-outer hidden">
<div id="searchresults-header" class="searchresults-header"></div>
<ul id="searchresults">
</ul>
</div>
</div>
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
<script type="text/javascript">
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
});
</script>
<div id="content" class="content">
<main>
<p><img src="./logo/maplibre-rs-with-text.svg" alt="" /></p>
<h1 id="introduction"><a class="header" href="#introduction">Introduction</a></h1>
<p>maplibre-rs is a portable and performant vector maps renderer. </p>
<h2 id="name"><a class="header" href="#name">Name</a></h2>
<p>The name of the library is &quot;maplibre-rs&quot;. The camel-case version of it is &quot;MapLibreRs&quot;.</p>
<div style="break-before: page; page-break-before: always;"></div><h1 id="supported-platforms"><a class="header" href="#supported-platforms">Supported Platforms</a></h1>
<p>For development the following platforms are recommended:</p>
<ul>
<li>Linux X11/Wayland</li>
<li>MacOS</li>
<li>Latest Firefox Nightly/Chrome Canary with WebGPU (Because WebGPU is a living spec, sometimes a bleeding-edge browser
release is required)</li>
</ul>
<h2 id="short-term-obstacles"><a class="header" href="#short-term-obstacles">Short-term Obstacles</a></h2>
<table><thead><tr><th>Platform</th><th>Obstacles</th></tr></thead><tbody>
<tr><td>Linux X11</td><td></td></tr>
<tr><td>Linux Wayland</td><td></td></tr>
<tr><td>Windows</td><td></td></tr>
<tr><td>MacOS</td><td></td></tr>
<tr><td>Android</td><td>* Unable to get window size before resume</td></tr>
<tr><td>iOS</td><td>* Touches are crashing the app on real devices <br/> * Instanced indices drawing is not supported <br/> * Drawing zero-length indices is prohibited<br/></td></tr>
<tr><td>Firefox</td><td>* Shared Memory is currently not working because it a parallel web worker corrupts memory</td></tr>
<tr><td>Chrome</td><td></td></tr>
<tr><td>Safari</td><td></td></tr>
<tr><td>Mobile Firefox</td><td></td></tr>
<tr><td>Mobile Chrome</td><td></td></tr>
<tr><td>Mobile Safari</td><td></td></tr>
</tbody></table>
<h2 id="long-term-goals"><a class="header" href="#long-term-goals">Long-term Goals</a></h2>
<p><a href="https://caniuse.com/webgpu">WebGPU</a> is not enabled by default for all platforms.</p>
<p>WebGPU Status:</p>
<ul>
<li><a href="https://github.com/gpuweb/gpuweb/wiki/Implementation-Status#firefox-and-servo">Firefox</a></li>
<li><a href="https://chromestatus.com/feature/6213121689518080">Chrome</a></li>
<li><a href="https://webkit.org/status/#specification-webgpu">WebKit</a></li>
</ul>
<table><thead><tr><th>Platform</th><th>Linux &amp; Android</th><th>Graphics API</th><th>Note</th></tr></thead><tbody>
<tr><td>Linux X11</td><td></td><td>Vulkan</td><td></td></tr>
<tr><td>Linux Wayland</td><td></td><td>Vulkan</td><td></td></tr>
<tr><td>Windows</td><td></td><td></td><td></td></tr>
<tr><td>MacOS</td><td></td><td></td><td></td></tr>
<tr><td>Android</td><td></td><td>Vulkan/OpenGL ES/Angle</td><td>Not tested, but should work on all devices if <a href="https://github.com/gfx-rs/wgpu/blob/master/README.md#supported-platforms">Angle</a> is used. <a href="https://developer.android.com/about/dashboards">Vulkan</a> is not yet supported widely.</td></tr>
<tr><td>iOS</td><td></td><td>Metal</td><td>Not tested.</td></tr>
<tr><td>Firefox</td><td></td><td>WebGL/WebGPU</td><td></td></tr>
<tr><td>Chrome</td><td></td><td>WebGL/WebGPU</td><td>WebGPU is significantly faster because WASM output is smaller.</td></tr>
<tr><td>Safari</td><td>🛠️</td><td>WebGL/WebGPU</td><td>Safari does not yet support <a href="https://caniuse.com/sharedarraybuffer">Shared Array Buffer</a></td></tr>
<tr><td>Mobile Firefox</td><td>🆗</td><td>WebGL/WebGPU</td><td></td></tr>
<tr><td>Mobile Chrome</td><td>🆗</td><td>WebGL</td><td><a href="https://caniuse.com/webgpu">WebGPU</a> is not implemented.</td></tr>
<tr><td>Mobile Safari</td><td>🛠️</td><td>WebGL</td><td><a href="https://caniuse.com/webgpu">WebGPU</a> is not implemented. Safari does not yet support <a href="https://caniuse.com/sharedarraybuffer">Shared Array Buffer</a></td></tr>
</tbody></table>
<p>✅ = First Class Support — 🆗= Best Effort Support — 🛠️ = Unsupported, but support
in progress</p>
<div style="break-before: page; page-break-before: always;"></div><h1 id="developer-log"><a class="header" href="#developer-log">Developer Log</a></h1>
<p>I'm regularly releasing blog posts <a href="https://maxammann.org/categories/maplibre/">on my blog</a>.</p>
<div style="break-before: page; page-break-before: always;"></div><h1 id="user-guide"><a class="header" href="#user-guide">User Guide</a></h1>
<div style="break-before: page; page-break-before: always;"></div><h1 id="development-guide"><a class="header" href="#development-guide">Development Guide</a></h1>
<div style="break-before: page; page-break-before: always;"></div><h1 id="running-maplibre-rs-demos-on-various-platforms"><a class="header" href="#running-maplibre-rs-demos-on-various-platforms">Running maplibre-rs demos on various platforms</a></h1>
<p>During development, you will want to run the maplibre demos on your local machine to test out your changes.
There are multiple demos of maplibre-rs for different targets. Some targets have prerequisites
depending on your operating system.</p>
<ul>
<li><strong>maplibre-demo</strong> - targets Windows, MacOS and Linux, it is built directly with cargo.</li>
<li><strong>apple</strong> - targets iOS and MacOS and relies on the xcode IDE.</li>
<li><strong>android</strong> - targets Android devices and builds in Android Studio.</li>
<li><strong>web</strong> - targets the web using a WASM binary.</li>
<li><strong>maplibre-headless</strong> - <em>TBD</em></li>
</ul>
<p>All the targets below require you to install <a href="https://rustup.rs/">rustup</a> to manage your Rust toolchain.</p>
<blockquote>
<p><strong>Note</strong>: Make sure you have selected the right toolchain target within rustup. You can use <code>rustup show</code> to see your
active toolchain. If you want to change the target of the build manually, use the cargo <code>--target</code> parameter.</p>
</blockquote>
<h2 id="maplibre-demo"><a class="header" href="#maplibre-demo">Maplibre-demo</a></h2>
<h3 id="linuxmacos"><a class="header" href="#linuxmacos">Linux/MacOS</a></h3>
<p>The build for desktop is very simple, you just have to run the following command from the root of the
maplibre-rs project:</p>
<pre><code class="language-bash">cargo run -p maplibre-demo
</code></pre>
<h3 id="windows"><a class="header" href="#windows">Windows</a></h3>
<p>Windows has two additional prerequisites to be able to run. You will need CMake, Visual Studio C++ build tools and the
sqlite3 library.</p>
<p>Install <a href="https://cmake.org/download/">CMake</a> and add it to your path environment variables.</p>
<p>For the C++ build tools, download the <a href="https://visualstudio.microsoft.com/downloads/">Visual Studio 2022 Build tools</a>
from the Microsoft website. After the download, while installing the Build tools, make sure that you select the
<em>C++ build tools</em>.</p>
<p>To install sqlite3 you need to build the sqlite3.lib manually with the following
<a href="https://gist.github.com/zeljic/d8b542788b225b1bcb5fce169ee28c55">steps</a>. This will generate a .lib file that
you will have to add to the SQLITE3_LIB_DIR environment variable.</p>
<p>Restart your shell to make sure you are using up-to-date environment variables.</p>
<p>Finally, the command below should execute successfully:</p>
<pre><code class="language-bash">cargo run -p maplibre-demo
</code></pre>
<h2 id="android"><a class="header" href="#android">Android</a></h2>
<p>Start by installing the
<a href="https://developer.android.com/studio?gclid=CjwKCAjwj42UBhAAEiwACIhADmF7uHXnEHGnmOgFnjp0Z6n-TnBvutC5faGA89lwouMIXiR6OXK4hBoCq78QAvD_BwE&amp;gclsrc=aw.ds">Android Studio IDE</a>.</p>
<p>Make sure the NDK is installed. The Native Development Kit (NDK) is a set of tools that allows
you to use C and C++ code with Android. You have to install manually the version that is used in
<code>./android/gradle/lib/build.gradle</code>.</p>
<pre><code>ANDROID STUDIO -&gt; tools -&gt; SDK manager -&gt; SDK tools -&gt; tick show package details -&gt; ndk (side by side)
</code></pre>
<p>Open the project within <code>./android/gradle</code> and create a new virtual device with the device manager. Minimum SDK version
should be 21. This was tested on a x86_64 emulator. Finally, run the demo configuration. It should open your virtual device and
run the maplibre-rs Android demo on it. Alternatively you can also run it on your own Android device.</p>
<blockquote>
<p>Note: If you are building for a x86 Android device, you probably need to install the following target using<br />
rustup with the following command <code>rustup target add i686-linux-android</code>.</p>
</blockquote>
<blockquote>
<p>Note: Android is configured to support OpenGL ES 3.1 (This API specification is supported by Android 5.0 (API level 21) and higher).
Your Android device is required to support OpenGL ES 3.1 at least. There are some issues
<a href="https://stackoverflow.com/questions/40797975/android-emulator-and-opengl-es3-egl-bad-config">here</a> and
<a href="https://www.reddit.com/r/Arcore/comments/8squbo/opengl_es_31_is_required_for_android_emulator_to/">here</a> that
discuss configuration of Android Studio for OpenGL ES 3.1 support in emulators.</p>
</blockquote>
<h2 id="apple"><a class="header" href="#apple">Apple</a></h2>
<p>Apple builds rely on the <a href="https://apps.apple.com/us/app/xcode/id497799835?ls=1&amp;mt=12">XCode IDE</a>.
Start by installing XCode and open the project within <code>./apple/xcode</code>.</p>
<blockquote>
<p>Cargo is used in to build the maplibre library in the build phases of the XCode project configuration.</p>
</blockquote>
<h3 id="ios"><a class="header" href="#ios">iOS</a></h3>
<p>You can use XCode to run on a iOS Simulator or a real device. Install a simulator in XCode.
Version 9 is the minimum version supported theoretically.</p>
<p>Select the scheme called <em>example (iOS)</em> and click on run. This will start the iOS application.</p>
<h3 id="macos"><a class="header" href="#macos">MacOS</a></h3>
<p>As you might have seen in the maplibre-demo section, you can build Unix executables directly with Cargo.
In order to build a proper MacOS application (in OSX terminology) you have to use the <code>./apple/xcode</code> project.</p>
<p>Open the project from the folder <code>./apple/xcode</code> with XCode. Select the scheme called <em>example (macOS)</em> and
click on run. This will start the MacOS application. </p>
<blockquote>
<p>The minimum target OSX version for the MacOS build is defined inside <em>Build settings -&gt; Deployment -&gt; MacOS deployment target</em>.
If you are using a lower version of OSX, you will not be able to run the application on your computer.</p>
</blockquote>
<h2 id="web-webgl-webgpu"><a class="header" href="#web-webgl-webgpu">Web (WebGL, WebGPU)</a></h2>
<p>If you have a browser which already supports a recent version of the WebGPU specification then you can start a
development server using the following commands.</p>
<pre><code class="language-bash">cd web
npm run start
</code></pre>
<p>If you want to run maplibre-rs with WebGL which is supported on every major browser, then you have to use the following
command.</p>
<pre><code class="language-bash">just web-lib esbuild
just web-demo start
</code></pre>
<div style="break-before: page; page-break-before: always;"></div><h1 id="building-libraries"><a class="header" href="#building-libraries">Building Libraries</a></h1>
<p>TODO</p>
<div style="break-before: page; page-break-before: always;"></div><h1 id="debugging"><a class="header" href="#debugging">Debugging</a></h1>
<ul>
<li>log crate</li>
</ul>
<h2 id="gpu-debugging"><a class="header" href="#gpu-debugging">GPU Debugging</a></h2>
<ul>
<li>For WebGL there is SpectorJS is enabled by default right now. For debugging on a desktop environment you can use
<a href="https://renderdoc.org/">RenderDoc</a>.</li>
</ul>
<h2 id="frame-profiling"><a class="header" href="#frame-profiling">Frame Profiling</a></h2>
<ul>
<li>tracing crate</li>
</ul>
<div style="break-before: page; page-break-before: always;"></div><h1 id="development-documents"><a class="header" href="#development-documents">Development Documents</a></h1>
<div style="break-before: page; page-break-before: always;"></div><h1 id="architecture"><a class="header" href="#architecture">Architecture</a></h1>
<h2 id="rendering-architecture"><a class="header" href="#rendering-architecture">Rendering Architecture</a></h2>
<p>The big picture of wgpu is as follows:</p>
<p><img src="https://raw.githubusercontent.com/gfx-rs/wgpu/8f02b73655aff641361822a8ac0347fc47622b49/etc/big-picture.png" alt="" /></p>
<p>A simplified version is shown below:</p>
<p><img src="development-documents/./figures/render-stack.drawio.svg" alt="" /></p>
<p>Notes:</p>
<ul>
<li>wgpu is able to create an interface through which we can reach any device with a GPU.</li>
</ul>
<p>Notes:</p>
<ul>
<li>The ability to use shared memory or the atomic instruction set of WASM comes by enabling compilation features.</li>
<li><code>threads</code> support here does not introduce threads like we know them from Linux. It introduces </li>
<li><a href="https://github.com/WebAssembly/threads/blob/main/proposals/threads/Overview.md">support for atomics</a> like
specified in a working draft to WebAssembly. Threads are simulated using WebWorkers by the browser.</li>
</ul>
<div style="break-before: page; page-break-before: always;"></div><h1 id="design"><a class="header" href="#design">Design</a></h1>
<script src="https://unpkg.com/@panzoom/panzoom@4.5.0/dist/panzoom.min.js"></script>
<h2 id="domain-model"><a class="header" href="#domain-model">Domain Model</a></h2>
<div style="overflow: hidden; border-style: solid; width: 110%">
<img src="development-documents/./figures/domain-model.drawio.svg" class="diagram" />
</div>
<h2 id="data-model"><a class="header" href="#data-model">Data Model</a></h2>
<div style="overflow: hidden; border-style: solid; width: 110%">
<img src="development-documents/./figures/data-model.drawio.svg" class="diagram" />
</div>
<h2 id="crate-and-project-structure"><a class="header" href="#crate-and-project-structure">Crate and Project Structure</a></h2>
<div style="overflow: hidden; border-style: solid; width: 110%">
<img src="development-documents/./figures/crate-and-projects-structure.drawio.svg" class="diagram" />
</div>
<script>
Array.from(document.getElementsByClassName('diagram')).forEach(e => {
panzoom = Panzoom(e, {});
e.parentElement.addEventListener('wheel', panzoom.zoomWithWheel)
})
</script>
<div style="break-before: page; page-break-before: always;"></div><h1 id="caching"><a class="header" href="#caching">Caching</a></h1>
<p>The caching for maplibre-rs is handled on the networking layer. This means that data which is fetched over slow IO is cached in
the format of the network requests. The maplibre-rs library is not introducing a separate serialization format for caching.</p>
<p>Instead, caching functionality of HTTP client libraries of the web platform are used. This has the advantage that we can
honor HTTP headers which configure caching. This is very important for fetched tiles, as they can have an expiry date.</p>
<ul>
<li>On the web the browser is automatically caching raw tiles.</li>
<li>On Linux, MacOs, iOS and Android we are
utilizing <a href="https://crates.io/crates/reqwest-middleware-cache/">reqwest-middleware-cache</a>, which writes raw network
requests to disk.</li>
</ul>
<div style="break-before: page; page-break-before: always;"></div><h1 id="stencil-masking"><a class="header" href="#stencil-masking">Stencil Masking</a></h1>
<p>The following diagram shows a method which has been used in the beginning of maplibre-rs. It is not used currently.</p>
<p><img src="development-documents/figures/stencil_buffer.drawio.svg" alt="" /></p>
<div style="break-before: page; page-break-before: always;"></div><h1 id="font-rendering"><a class="header" href="#font-rendering">Font Rendering</a></h1>
<p>There exists no universally perfect solution to font rendering. Depending on the runtime environment a method needs to
be chosen. <a href="https://stackoverflow.com/a/5278471">This StackOverflow post</a> outlines some state-of-the-art methods. Some
more approaches are described <a href="https://aras-p.info/blog/2017/02/15/Font-Rendering-is-Getting-Interesting/">here</a>.</p>
<p>From my perspective the following approaches could work potentially:</p>
<ol>
<li>Tessellate Fonts</li>
<li>SDF Font Rendering</li>
<li>GPU Text Rendering directly from Bezier Curves</li>
<li>Draw text using a Web Canvas and load them to GPU</li>
</ol>
<p>There is a thesis which summarizes some methods <a href="https://lup.lub.lu.se/luur/download?func=downloadFile&amp;recordOId=9024910&amp;fileOId=9024911">here</a>.
A link collection about font related projects can be viewed <a href="development-documents/../appendix/link-collection.html#font-rendering">here</a>.</p>
<h2 id="approaches"><a class="header" href="#approaches">Approaches</a></h2>
<h3 id="tessellate-fonts"><a class="header" href="#tessellate-fonts">Tessellate Fonts</a></h3>
<p>There is <a href="https://github.com/fetisov/ttf2mesh">ttf2mesh</a> which generates meshes. I was already able to generate about 1k
glyphs with ~40FPS.</p>
<h3 id="sdf-font-rendering"><a class="header" href="#sdf-font-rendering">SDF Font Rendering</a></h3>
<p>There is a blogpost by Mapbox <a href="https://blog.mapbox.com/drawing-text-with-signed-distance-fields-in-mapbox-gl-b0933af6f817">here</a>.
Some more implementation documents are available <a href="https://github.com/mapbox/mapbox-gl-native/wiki/Text-Rendering">here</a>.
A good foundation for SDF fonts was created by Chlumsky with <a href="https://github.com/Chlumsky/msdfgen">msdfgen</a>.</p>
<h3 id="gpu-text-rendering-from-bezier-curves"><a class="header" href="#gpu-text-rendering-from-bezier-curves">GPU Text Rendering from Bezier Curves</a></h3>
<p>The solutions exist:</p>
<ul>
<li><a href="https://wdobbie.com/post/gpu-text-rendering-with-vector-textures/">By Will Dobbie</a> with an
implementation <a href="https://github.com/azsn/gllabel">here</a></li>
<li><a href="http://sluglibrary.com/">Slug Library</a> which is patented and probably therefore not usable</li>
</ul>
<p><a href="https://jcgt.org/published/0006/02/02/paper.pdf">Here</a> is the whitepaper of the Slug library. There is also
a <a href="http://sluglibrary.com/slug_algorithm.pdf">poster</a> about it. There also exists
an <a href="https://github.com/mightycow/Sluggish">open implementation</a>.</p>
<h3 id="draw-text-using-a-web-canvas"><a class="header" href="#draw-text-using-a-web-canvas">Draw text using a Web Canvas</a></h3>
<p>This approach has the downside that we can not dynamically scale rendered fonts according to the current zoom level.</p>
<h2 id="other-approaches"><a class="header" href="#other-approaches">Other Approaches</a></h2>
<ul>
<li><a href="https://superluminal.eu/16x-aa-font-rendering-using-coverage-masks-part-iii/">16x AA font rendering using coverage masks</a></li>
</ul>
<div style="break-before: page; page-break-before: always;"></div><h1 id="library-packaging"><a class="header" href="#library-packaging">Library Packaging</a></h1>
<div style="break-before: page; page-break-before: always;"></div><h1 id="apple-1"><a class="header" href="#apple-1">Apple</a></h1>
<p>On Apple maplibre-rs is packaged as:</p>
<ul>
<li>Multiple .xcarchive packages which include a framework. Each for a different architecture and platform.</li>
<li>A single .xcframework package which contains multiple frameworks of different architectures and platforms.</li>
<li>A swift package which just references the .xcframework package and makes distributing easier.</li>
</ul>
<p>The following diffs are extracted from <a href="development-documents/library-packaging/../../../../apple/framework.diff">this diff</a>. They should serve as documentation
for the XCode project. This is required because XCode is a mess.</p>
<h2 id="xcode-project-description"><a class="header" href="#xcode-project-description">XCode Project description</a></h2>
<h3 id="library-entry"><a class="header" href="#library-entry">Library Entry</a></h3>
<div id="d2h-374920" class="d2h-file-wrapper" data-lang="swift">
<div class="d2h-file-header">
<span class="d2h-file-name-wrapper">
<svg aria-hidden="true" class="d2h-icon" height="16" version="1.1" viewBox="0 0 12 16" width="12">
<path d="M6 5H2v-1h4v1zM2 8h7v-1H2v1z m0 2h7v-1H2v1z m0 2h7v-1H2v1z m10-7.5v9.5c0 0.55-0.45 1-1 1H1c-0.55 0-1-0.45-1-1V2c0-0.55 0.45-1 1-1h7.5l3.5 3.5z m-1 0.5L8 2H1v12h10V5z"></path>
</svg> <span class="d2h-file-name">xcode/maplibre-rs/maplibre.swift</span>
<span class="d2h-tag d2h-added d2h-added-tag">ADDED</span></span>
<label class="d2h-file-collapse">
<input class="d2h-file-collapse-input" type="checkbox" name="viewed" value="viewed">
Viewed
</label>
</div>
<div class="d2h-file-diff">
<div class="d2h-code-wrapper">
<table class="d2h-diff-table">
<tbody class="d2h-diff-tbody">
<tr>
<td class="d2h-code-linenumber d2h-info"></td>
<td class="d2h-info">
<div class="d2h-code-line">@@ -0,0 +1,5 @@</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">1</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn">public class MapLibre {</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">2</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> public static func start() {</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">3</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> maplibre_apple_main();</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">4</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> }</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">5</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn">}</span>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<p>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.</p>
<h3 id="framework"><a class="header" href="#framework">Framework</a></h3>
<div class="d2h-file-wrapper" data-lang="pbxproj">
<div class="d2h-file-header">
<span class="d2h-file-name-wrapper">
<svg aria-hidden="true" class="d2h-icon" height="16" version="1.1" viewBox="0 0 12 16" width="12">
<path d="M6 5H2v-1h4v1zM2 8h7v-1H2v1z m0 2h7v-1H2v1z m0 2h7v-1H2v1z m10-7.5v9.5c0 0.55-0.45 1-1 1H1c-0.55 0-1-0.45-1-1V2c0-0.55 0.45-1 1-1h7.5l3.5 3.5z m-1 0.5L8 2H1v12h10V5z"></path>
</svg> <span class="d2h-file-name">{diff/maplibre-rs → xcode}/maplibre-rs.xcodeproj/project.pbxproj</span>
<span class="d2h-tag d2h-moved d2h-moved-tag">RENAMED</span></span>
<label class="d2h-file-collapse">
<input class="d2h-file-collapse-input" type="checkbox" name="viewed" value="viewed">
Viewed
</label>
</div>
<div class="d2h-file-diff">
<div class="d2h-code-wrapper">
<table class="d2h-diff-table">
<tbody class="d2h-diff-tbody">
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">29</div>
<div class="line-num2">33</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"><br></span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">30</div>
<div class="line-num2">34</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn">/* Begin PBXFrameworksBuildPhase section */</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-del d2h-change">
<div class="line-num1">31</div>
<div class="line-num2"></div>
</td>
<td class="d2h-del d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">-</span>
<span class="d2h-code-line-ctn"> <del>0BE452E128132EA6003BD2A5</del> /* Frameworks */ = {</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins d2h-change">
<div class="line-num1"></div>
<div class="line-num2">35</div>
</td>
<td class="d2h-ins d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> <ins>0B85D5682812903700906D21</ins> /* Frameworks */ = {</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">32</div>
<div class="line-num2">36</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> isa = PBXFrameworksBuildPhase;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">33</div>
<div class="line-num2">37</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> buildActionMask = 2147483647;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">34</div>
<div class="line-num2">38</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> files = (</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">39</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> 0B85D5A42812991100906D21 /* libmaplibre_apple.a in Frameworks */,</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">35</div>
<div class="line-num2">40</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> );</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">36</div>
<div class="line-num2">41</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> runOnlyForDeploymentPostprocessing = 0;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">37</div>
<div class="line-num2">42</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> };</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-del d2h-change">
<div class="line-num1">38</div>
<div class="line-num2"></div>
</td>
<td class="d2h-del d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">-</span>
<span class="d2h-code-line-ctn"> <del>0BE452F128132EB5003BD2A5</del> /* Frameworks */ = {</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins d2h-change">
<div class="line-num1"></div>
<div class="line-num2">43</div>
</td>
<td class="d2h-ins d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> <ins>0B85D57B281290F800906D21</ins> /* Frameworks */ = {</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">39</div>
<div class="line-num2">44</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> isa = PBXFrameworksBuildPhase;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">40</div>
<div class="line-num2">45</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> buildActionMask = 2147483647;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">41</div>
<div class="line-num2">46</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> files = (</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">47</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> 0B85D596281291A400906D21 /* maplibre_rs.framework in Frameworks */,</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">42</div>
<div class="line-num2">48</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> );</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">43</div>
<div class="line-num2">49</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> runOnlyForDeploymentPostprocessing = 0;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">44</div>
<div class="line-num2">50</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> };</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-del d2h-change">
<div class="line-num1">45</div>
<div class="line-num2"></div>
</td>
<td class="d2h-del d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">-</span>
<span class="d2h-code-line-ctn"> <del>0BE452F628132EB5003BD2A5</del> /* Frameworks */ = {</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins d2h-change">
<div class="line-num1"></div>
<div class="line-num2">51</div>
</td>
<td class="d2h-ins d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> <ins>0B85D580281290F800906D21</ins> /* Frameworks */ = {</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">46</div>
<div class="line-num2">52</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> isa = PBXFrameworksBuildPhase;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">47</div>
<div class="line-num2">53</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> buildActionMask = 2147483647;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">48</div>
<div class="line-num2">54</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> files = (</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">55</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> 0B85D599281291A700906D21 /* maplibre_rs.framework in Frameworks */,</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">49</div>
<div class="line-num2">56</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> );</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">50</div>
<div class="line-num2">57</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> runOnlyForDeploymentPostprocessing = 0;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">51</div>
<div class="line-num2">58</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> };</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1"></div>
<div class="line-num2">59</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn">/* End PBXFrameworksBuildPhase section */</span>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<p>The framework needs to link against the static library <code>libmaplibre_apple.a</code>, which has been generated by Cargo.
In order to allow XCode to dynamically select the library based on the <code>Library Search Path</code> (Build Settings) one needs
to add a relative file to XCode. The entry in the <code>project.pbxproj</code> should look like that:</p>
<pre><code class="language-js">B085D5A32812987B00906D21 /* libmaplibre_apple.a */ = {
isa = PBXFileReference;
lastKnownFileType = archive.ar;
path = libmaplibre_apple.a;
sourceTree = SOURCE_ROOT;
};
</code></pre>
<p>Note the <code>path = libmaplibre_apple.a</code>. This path does not link to a concrete file, but to a file which can be found
during building.</p>
<p>A file can be added to the frameworks and library link phase in XCode.</p>
<h3 id="cargo-build-phase"><a class="header" href="#cargo-build-phase">Cargo Build Phase</a></h3>
<div class="d2h-file-wrapper" data-lang="pbxproj">
<div class="d2h-file-header">
<span class="d2h-file-name-wrapper">
<svg aria-hidden="true" class="d2h-icon" height="16" version="1.1" viewBox="0 0 12 16" width="12">
<path d="M6 5H2v-1h4v1zM2 8h7v-1H2v1z m0 2h7v-1H2v1z m0 2h7v-1H2v1z m10-7.5v9.5c0 0.55-0.45 1-1 1H1c-0.55 0-1-0.45-1-1V2c0-0.55 0.45-1 1-1h7.5l3.5 3.5z m-1 0.5L8 2H1v12h10V5z"></path>
</svg> <span class="d2h-file-name">{diff/maplibre-rs → xcode}/maplibre-rs.xcodeproj/project.pbxproj</span>
<span class="d2h-tag d2h-moved d2h-moved-tag">RENAMED</span></span>
<label class="d2h-file-collapse">
<input class="d2h-file-collapse-input" type="checkbox" name="viewed" value="viewed">
Viewed
</label>
</div>
<div class="d2h-file-diff">
<div class="d2h-code-wrapper">
<table class="d2h-diff-table">
<tbody class="d2h-diff-tbody">
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">114</div>
<div class="line-num2">131</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn">/* Begin PBXNativeTarget section */</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-del d2h-change">
<div class="line-num1">115</div>
<div class="line-num2"></div>
</td>
<td class="d2h-del d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">-</span>
<span class="d2h-code-line-ctn"> <del>0BE452E328132EA6003BD2A5</del> /* maplibre-rs */ = {</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins d2h-change">
<div class="line-num1"></div>
<div class="line-num2">132</div>
</td>
<td class="d2h-ins d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> <ins>0B85D56A2812903700906D21</ins> /* maplibre-rs */ = {</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">116</div>
<div class="line-num2">133</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> isa = PBXNativeTarget;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-del d2h-change">
<div class="line-num1">117</div>
<div class="line-num2"></div>
</td>
<td class="d2h-del d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">-</span>
<span class="d2h-code-line-ctn"> buildConfigurationList = <del>0BE452E928132EA6003BD2A5</del> /* Build configuration list for PBXNativeTarget "maplibre-rs" */;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins d2h-change">
<div class="line-num1"></div>
<div class="line-num2">134</div>
</td>
<td class="d2h-ins d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> buildConfigurationList = <ins>0B85D5702812903700906D21</ins> /* Build configuration list for PBXNativeTarget "maplibre-rs" */;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">118</div>
<div class="line-num2">135</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> buildPhases = (</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-del d2h-change">
<div class="line-num1">119</div>
<div class="line-num2"></div>
</td>
<td class="d2h-del d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">-</span>
<span class="d2h-code-line-ctn"> <del>0BE452DF28132EA6003BD2A5</del> /* Headers */,</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-del d2h-change">
<div class="line-num1">120</div>
<div class="line-num2"></div>
</td>
<td class="d2h-del d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">-</span>
<span class="d2h-code-line-ctn"> <del>0BE452E028132EA6003BD2A5</del> /* Sources */,</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-del d2h-change">
<div class="line-num1">121</div>
<div class="line-num2"></div>
</td>
<td class="d2h-del d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">-</span>
<span class="d2h-code-line-ctn"> <del>0BE452E128132EA6003BD2A5</del> /* Frameworks */,</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-del d2h-change">
<div class="line-num1">122</div>
<div class="line-num2"></div>
</td>
<td class="d2h-del d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">-</span>
<span class="d2h-code-line-ctn"> <del>0BE452E228132EA6003BD2A5</del> /* Resources */,</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins d2h-change">
<div class="line-num1"></div>
<div class="line-num2">136</div>
</td>
<td class="d2h-ins d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> <ins>0B85D5662812903700906D21</ins> /* Headers */,</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins d2h-change">
<div class="line-num1"></div>
<div class="line-num2">137</div>
</td>
<td class="d2h-ins d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> <ins>0B85D5672812903700906D21</ins> /* Sources */,</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins d2h-change">
<div class="line-num1"></div>
<div class="line-num2">138</div>
</td>
<td class="d2h-ins d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> <ins>0B85D5682812903700906D21</ins> /* Frameworks */,</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins d2h-change">
<div class="line-num1"></div>
<div class="line-num2">139</div>
</td>
<td class="d2h-ins d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> <ins>0B85D5692812903700906D21</ins> /* Resources */,</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">140</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> 0BE452D72812EFC1003BD2A5 /* Cargo Build */,</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">229</div>
<div class="line-num2">248</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> );</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">230</div>
<div class="line-num2">249</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> runOnlyForDeploymentPostprocessing = 0;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">231</div>
<div class="line-num2">250</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> };</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">232</div>
<div class="line-num2">251</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn">/* End PBXResourcesBuildPhase section */</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">233</div>
<div class="line-num2">252</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"><br></span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">253</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn">/* Begin PBXShellScriptBuildPhase section */</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">254</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> 0BE452D72812EFC1003BD2A5 /* Cargo Build */ = {</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">255</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> isa = PBXShellScriptBuildPhase;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">256</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> buildActionMask = 2147483647;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">257</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> files = (</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">258</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> );</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">259</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> inputFileListPaths = (</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">260</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> );</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">261</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> inputPaths = (</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">262</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> );</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">263</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> name = "Cargo Build";</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">264</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> outputFileListPaths = (</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">265</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> );</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">266</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> outputPaths = (</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">267</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> );</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">268</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> runOnlyForDeploymentPostprocessing = 0;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">269</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> shellPath = /bin/bash;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">270</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> shellScript = ". \"$HOME/.cargo/env\"\n\narch=\"unknown\"\nvendor=\"apple\"\nos_type=\"unknown\"\nenvironment_type=\"\"\n\nmode=\"\"\n\necho \"ARCH: $ARCHS\"\n\nif [[ $CONFIGURATION == \"Release\" ]]\nthen\n mode=\"--release\"\nfi\n\nif [[ $ARCHS == \"x86_64\" ]]\nthen\n arch=\"x86_64\"\nelif [[ $ARCHS == \"arm64\" ]]\nthen\n arch=\"aarch64\"\nfi\n\nif [[ $SDK_NAME == *\"iphoneos\"* ]]\nthen\n os_type=\"ios\"\nelif [[ $SDK_NAME == *\"macos\"* ]]\nthen\n os_type=\"darwin\"\nelif [[ $SDK_NAME == *\"iphonesimulator\"* ]]\nthen\n os_type=\"ios\"\n environment_type=\"sim\"\nfi\n\n\ntriplet=\"$arch-$vendor-$os_type\"\n\nif [ -n \"$environment_type\" ]\nthen\n triplet=\"$triplet-$environment_type\"\nfi\n\necho \"$mode\"\necho \"$triplet\"\n\nenv -i zsh -c \"cargo build -p maplibre-apple $mode --target $triplet --lib\"\n\n";</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">271</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> };</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">272</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn">/* End PBXShellScriptBuildPhase section */</span>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<p>In order to trigger Cargo builds when starting a XCode build we include a <code>Cargo Build</code> script. This build script needs
to run before the linking phase (drag and drop it to the top).</p>
<p>The following build script builds based on XCode environment variables the correct static library. We depend on
the <code>$ARCHS</code>
environment variable, as the others seem unreliable. Note that this can include multiple architectures, unless the build
setting <code>ONLY_ACTIVE_ARCH</code> is set to <code>YES</code>.</p>
<pre><code class="language-bash">arch=&quot;unknown&quot;
vendor=&quot;apple&quot;
os_type=&quot;unknown&quot;
environment_type=&quot;&quot;
mode=&quot;&quot;
echo &quot;ARCH: $ARCHS&quot;
if [[ $CONFIGURATION == &quot;Release&quot; ]]
then
mode=&quot;--release&quot;
fi
if [[ $ARCHS == &quot;x86_64&quot; ]]
then
arch=&quot;x86_64&quot;
elif [[ $ARCHS == &quot;arm64&quot; ]]
then
arch=&quot;aarch64&quot;
fi
if [[ $SDK_NAME == *&quot;iphoneos&quot;* ]]
then
os_type=&quot;ios&quot;
elif [[ $SDK_NAME == *&quot;macos&quot;* ]]
then
os_type=&quot;darwin&quot;
elif [[ $SDK_NAME == *&quot;iphonesimulator&quot;* ]]
then
os_type=&quot;ios&quot;
if [[ $ARCHS == &quot;arm64&quot; ]]
then
environment_type=&quot;sim&quot;
fi
fi
triplet=&quot;$arch-$vendor-$os_type&quot;
if [ -n &quot;$environment_type&quot; ]
then
triplet=&quot;$triplet-$environment_type&quot;
fi
echo &quot;Mode: $mode&quot;
echo &quot;Triplet: $triplet&quot;
echo &quot;Shell: $SHELL&quot;
cmd=&quot;export HOME=$HOME &amp;&amp; . $HOME/.cargo/env &amp;&amp; cargo build -p apple $mode --target $triplet --lib&quot;
echo &quot;Command: $cmd&quot;
env -i /bin/bash -c &quot;$cmd&quot;
</code></pre>
<h3 id="build-settings"><a class="header" href="#build-settings">Build Settings</a></h3>
<div class="d2h-file-wrapper" data-lang="pbxproj">
<div class="d2h-file-header">
<span class="d2h-file-name-wrapper">
<svg aria-hidden="true" class="d2h-icon" height="16" version="1.1" viewBox="0 0 12 16" width="12">
<path d="M6 5H2v-1h4v1zM2 8h7v-1H2v1z m0 2h7v-1H2v1z m0 2h7v-1H2v1z m10-7.5v9.5c0 0.55-0.45 1-1 1H1c-0.55 0-1-0.45-1-1V2c0-0.55 0.45-1 1-1h7.5l3.5 3.5z m-1 0.5L8 2H1v12h10V5z"></path>
</svg> <span class="d2h-file-name">{diff/maplibre-rs → xcode}/maplibre-rs.xcodeproj/project.pbxproj</span>
<span class="d2h-tag d2h-moved d2h-moved-tag">RENAMED</span></span>
<label class="d2h-file-collapse">
<input class="d2h-file-collapse-input" type="checkbox" name="viewed" value="viewed">
Viewed
</label>
</div>
<div class="d2h-file-diff">
<div class="d2h-code-wrapper">
<table class="d2h-diff-table">
<tbody class="d2h-diff-tbody">
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">260</div>
<div class="line-num2">299</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn">/* End PBXSourcesBuildPhase section */</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-del d2h-change">
<div class="line-num1">275</div>
<div class="line-num2"></div>
</td>
<td class="d2h-del d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">-</span>
<span class="d2h-code-line-ctn"> <del>0BE452EA28132EA6003BD2A5</del> /* Debug */ = {</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins d2h-change">
<div class="line-num1"></div>
<div class="line-num2">314</div>
</td>
<td class="d2h-ins d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> <ins>0B85D5712812903700906D21</ins> /* Debug */ = {</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">276</div>
<div class="line-num2">315</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> isa = XCBuildConfiguration;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">277</div>
<div class="line-num2">316</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> buildSettings = {</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">317</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> ALLOW_TARGET_PLATFORM_SPECIALIZATION = YES;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">278</div>
<div class="line-num2">318</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> ALWAYS_SEARCH_USER_PATHS = NO;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">319</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> BUILD_LIBRARY_FOR_DISTRIBUTION = YES;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">279</div>
<div class="line-num2">320</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> CLANG_ANALYZER_NONNULL = YES;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">280</div>
<div class="line-num2">321</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">281</div>
<div class="line-num2">322</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-info"></td>
<td class="d2h-info">
<div class="d2h-code-line">@@ -304,11 +345,13 @@</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">304</div>
<div class="line-num2">345</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">305</div>
<div class="line-num2">346</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> CLANG_WARN_UNREACHABLE_CODE = YES;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">306</div>
<div class="line-num2">347</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-del d2h-change">
<div class="line-num1">307</div>
<div class="line-num2"></div>
</td>
<td class="d2h-del d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">-</span>
<span class="d2h-code-line-ctn"> <del>CODE_SIGN_STYLE</del> = <del>Automatic</del>;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins d2h-change">
<div class="line-num1"></div>
<div class="line-num2">348</div>
</td>
<td class="d2h-ins d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> <ins>CODE_SIGN_IDENTITY</ins> = <ins>"Apple Development"</ins>;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">349</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> CODE_SIGN_STYLE = Manual;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">308</div>
<div class="line-num2">350</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> COPY_PHASE_STRIP = NO;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">309</div>
<div class="line-num2">351</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> CURRENT_PROJECT_VERSION = 1;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">310</div>
<div class="line-num2">352</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> DEBUG_INFORMATION_FORMAT = dwarf;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">311</div>
<div class="line-num2">353</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> DEFINES_MODULE = YES;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">354</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> DEVELOPMENT_TEAM = "";</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">312</div>
<div class="line-num2">355</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> DYLIB_COMPATIBILITY_VERSION = 1;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">313</div>
<div class="line-num2">356</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> DYLIB_CURRENT_VERSION = 1;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">314</div>
<div class="line-num2">357</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> DYLIB_INSTALL_NAME_BASE = "@rpath";</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-info"></td>
<td class="d2h-info">
<div class="d2h-code-line">@@ -337,14 +380,28 @@</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">337</div>
<div class="line-num2">380</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> "@executable_path/Frameworks",</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">338</div>
<div class="line-num2">381</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> "@loader_path/Frameworks",</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">339</div>
<div class="line-num2">382</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> );</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">383</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> LIBRARY_SEARCH_PATHS = (</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">384</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> "$(inherited)",</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">385</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> "$(PROJECT_DIR)",</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">386</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> );</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">387</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> "LIBRARY_SEARCH_PATHS[sdk=iphoneos*][arch=arm64]" = "$(PROJECT_DIR)/libs/aarch64-apple-ios/debug";</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">388</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> "LIBRARY_SEARCH_PATHS[sdk=iphoneos*][arch=x86_64]" = "$(PROJECT_DIR)/libs/x86_64-apple-ios/debug";</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">389</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> "LIBRARY_SEARCH_PATHS[sdk=iphonesimulator*][arch=arm64]" = "$(PROJECT_DIR)/libs/aarch64-apple-ios-sim/debug";</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">390</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> "LIBRARY_SEARCH_PATHS[sdk=macosx*][arch=arm64]" = "$(PROJECT_DIR)/libs/aarch64-apple-darwin/debug";</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">391</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> "LIBRARY_SEARCH_PATHS[sdk=macosx*][arch=x86_64]" = "$(PROJECT_DIR)/libs/x86_64-apple-darwin/debug";</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">392</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> MACH_O_TYPE = staticlib;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">340</div>
<div class="line-num2">393</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> MARKETING_VERSION = 1.0;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">341</div>
<div class="line-num2">394</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">342</div>
<div class="line-num2">395</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> MTL_FAST_MATH = YES;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">343</div>
<div class="line-num2">396</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> ONLY_ACTIVE_ARCH = YES;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">344</div>
<div class="line-num2">397</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> PRODUCT_BUNDLE_IDENTIFIER = "org.maplibre.maplibre-rs";</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">345</div>
<div class="line-num2">398</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">399</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> PROVISIONING_PROFILE_SPECIFIER = "";</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">400</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> "PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = "";</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">346</div>
<div class="line-num2">401</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> SDKROOT = iphoneos;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-del d2h-change">
<div class="line-num1">347</div>
<div class="line-num2"></div>
</td>
<td class="d2h-del d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">-</span>
<span class="d2h-code-line-ctn"> SKIP_INSTALL = <del>YES</del>;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins d2h-change">
<div class="line-num1"></div>
<div class="line-num2">402</div>
</td>
<td class="d2h-ins d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> SKIP_INSTALL = <ins>NO</ins>;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">403</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> SUPPORTED_PLATFORMS = "watchsimulator watchos macosx iphonesimulator iphoneos driverkit appletvsimulator appletvos";</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">404</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> SUPPORTS_MACCATALYST = YES;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">348</div>
<div class="line-num2">405</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">349</div>
<div class="line-num2">406</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> SWIFT_EMIT_LOC_STRINGS = YES;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">350</div>
<div class="line-num2">407</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> SWIFT_OPTIMIZATION_LEVEL = "-Onone";</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-info"></td>
<td class="d2h-info">
<div class="d2h-code-line">@@ -355,10 +412,12 @@</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">355</div>
<div class="line-num2">412</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> };</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">356</div>
<div class="line-num2">413</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> name = Debug;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">357</div>
<div class="line-num2">414</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> };</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-del d2h-change">
<div class="line-num1">358</div>
<div class="line-num2"></div>
</td>
<td class="d2h-del d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">-</span>
<span class="d2h-code-line-ctn"> <del>0BE452EB28132EA6003BD2A5</del> /* Release */ = {</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins d2h-change">
<div class="line-num1"></div>
<div class="line-num2">415</div>
</td>
<td class="d2h-ins d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> <ins>0B85D5722812903700906D21</ins> /* Release */ = {</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">359</div>
<div class="line-num2">416</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> isa = XCBuildConfiguration;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">360</div>
<div class="line-num2">417</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> buildSettings = {</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">418</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> ALLOW_TARGET_PLATFORM_SPECIALIZATION = YES;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">361</div>
<div class="line-num2">419</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> ALWAYS_SEARCH_USER_PATHS = NO;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">420</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> BUILD_LIBRARY_FOR_DISTRIBUTION = YES;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">362</div>
<div class="line-num2">421</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> CLANG_ANALYZER_NONNULL = YES;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">363</div>
<div class="line-num2">422</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">364</div>
<div class="line-num2">423</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-info"></td>
<td class="d2h-info">
<div class="d2h-code-line">@@ -387,11 +446,13 @@</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">387</div>
<div class="line-num2">446</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">388</div>
<div class="line-num2">447</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> CLANG_WARN_UNREACHABLE_CODE = YES;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">389</div>
<div class="line-num2">448</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-del d2h-change">
<div class="line-num1">390</div>
<div class="line-num2"></div>
</td>
<td class="d2h-del d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">-</span>
<span class="d2h-code-line-ctn"> <del>CODE_SIGN_STYLE</del> = <del>Automatic</del>;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins d2h-change">
<div class="line-num1"></div>
<div class="line-num2">449</div>
</td>
<td class="d2h-ins d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> <ins>CODE_SIGN_IDENTITY</ins> = <ins>"Apple Development"</ins>;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">450</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> CODE_SIGN_STYLE = Manual;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">391</div>
<div class="line-num2">451</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> COPY_PHASE_STRIP = NO;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">392</div>
<div class="line-num2">452</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> CURRENT_PROJECT_VERSION = 1;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">393</div>
<div class="line-num2">453</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">394</div>
<div class="line-num2">454</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> DEFINES_MODULE = YES;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">455</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> DEVELOPMENT_TEAM = "";</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">395</div>
<div class="line-num2">456</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> DYLIB_COMPATIBILITY_VERSION = 1;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">396</div>
<div class="line-num2">457</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> DYLIB_CURRENT_VERSION = 1;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">397</div>
<div class="line-num2">458</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> DYLIB_INSTALL_NAME_BASE = "@rpath";</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-info"></td>
<td class="d2h-info">
<div class="d2h-code-line">@@ -414,13 +475,28 @@</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">414</div>
<div class="line-num2">475</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> "@executable_path/Frameworks",</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">415</div>
<div class="line-num2">476</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> "@loader_path/Frameworks",</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">416</div>
<div class="line-num2">477</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> );</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">478</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> LIBRARY_SEARCH_PATHS = (</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">479</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> "$(inherited)",</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">480</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> "$(PROJECT_DIR)",</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">481</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> );</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">482</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> "LIBRARY_SEARCH_PATHS[sdk=iphoneos*][arch=arm64]" = "$(PROJECT_DIR)/libs/aarch64-apple-ios/release";</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">483</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> "LIBRARY_SEARCH_PATHS[sdk=iphoneos*][arch=x86_64]" = "$(PROJECT_DIR)/libs/x86_64-apple-ios/release";</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">484</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> "LIBRARY_SEARCH_PATHS[sdk=iphonesimulator*][arch=arm64]" = "$(PROJECT_DIR)/libs/aarch64-apple-ios-sim/release";</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">485</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> "LIBRARY_SEARCH_PATHS[sdk=macosx*][arch=arm64]" = "$(PROJECT_DIR)/libs/aarch64-apple-darwin/release";</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">486</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> "LIBRARY_SEARCH_PATHS[sdk=macosx*][arch=x86_64]" = "$(PROJECT_DIR)/libs/x86_64-apple-darwin/release";</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">487</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> MACH_O_TYPE = staticlib;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">417</div>
<div class="line-num2">488</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> MARKETING_VERSION = 1.0;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">418</div>
<div class="line-num2">489</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> MTL_ENABLE_DEBUG_INFO = NO;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">419</div>
<div class="line-num2">490</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> MTL_FAST_MATH = YES;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">491</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> ONLY_ACTIVE_ARCH = YES;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">420</div>
<div class="line-num2">492</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> PRODUCT_BUNDLE_IDENTIFIER = "org.maplibre.maplibre-rs";</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">421</div>
<div class="line-num2">493</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">494</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> PROVISIONING_PROFILE_SPECIFIER = "";</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">495</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> "PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = "";</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">422</div>
<div class="line-num2">496</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> SDKROOT = iphoneos;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-del d2h-change">
<div class="line-num1">423</div>
<div class="line-num2"></div>
</td>
<td class="d2h-del d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">-</span>
<span class="d2h-code-line-ctn"> SKIP_INSTALL = <del>YES</del>;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins d2h-change">
<div class="line-num1"></div>
<div class="line-num2">497</div>
</td>
<td class="d2h-ins d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> SKIP_INSTALL = <ins>NO</ins>;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">498</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> SUPPORTED_PLATFORMS = "watchsimulator watchos macosx iphonesimulator iphoneos driverkit appletvsimulator appletvos";</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">499</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> SUPPORTS_MACCATALYST = YES;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">424</div>
<div class="line-num2">500</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> SWIFT_COMPILATION_MODE = wholemodule;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">425</div>
<div class="line-num2">501</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> SWIFT_EMIT_LOC_STRINGS = YES;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">426</div>
<div class="line-num2">502</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> SWIFT_OPTIMIZATION_LEVEL = "-O";</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-info"></td>
<td class="d2h-info">
<div class="d2h-code-line">@@ -432,7 +508,7 @@</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">432</div>
<div class="line-num2">508</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> };</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">433</div>
<div class="line-num2">509</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> name = Release;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1"></div>
<div class="line-num2">510</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> };</span>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<p>Explanations for the settings:</p>
<ul>
<li><code>BUILD_LIBRARY_FOR_DISTRIBUTION</code>: Define that this is a library (effect unknown to me)</li>
<li><code>CODE_SIGN_STYLE</code>: The framework is not signed</li>
<li><code>DEVELOPMENT_TEAM</code>: No development team is set</li>
<li><code>LIBRARY_SEARCH_PATHS[sdk=x][arch=y]</code>: We set the path for the <code>libmaplibre_apple.a</code> lies</li>
<li><code>MACH_O_TYPE</code> / <code>SKIP_INSTALL</code>: If this is not set to <code>staticlib</code> and <code>NO</code>, then the <code>libmaplibre_apple.a</code> binary is not included in the final framework xcarchive.</li>
<li><code>SUPPORTED_PLATFORMS</code>: Explicitly says that this library works on any platform. </li>
<li><code>SUPPORTS_MACCATALYST</code>: Explicitly says that this library works on Mac Catalyst.</li>
</ul>
<p>The same settings are done for Release and Debug.</p>
<h2 id="xcframework-packaging"><a class="header" href="#xcframework-packaging">xcframework packaging</a></h2>
<p>Creating a xcframework is usually quite straight forward. Just execute the following:</p>
<pre><code class="language-bash">xargs xcodebuild -create-xcframework -framework ./a -framework ./b -output out.xcframework
</code></pre>
<p>Unfortunately, it is not possible to bundle some frameworks together like:</p>
<ul>
<li>macOS-arm64 and macOS-x86_64</li>
</ul>
<p>In order to package these architectures and platforms together a fat binary needs to be created using the <code>lipo</code> tool.
This means from two frameworks we create a unified framework with a fat binary.
There are two important steps:</p>
<ol>
<li>Create a fat binary using <code>lipo -create binA binB -output binfat</code></li>
<li>Copy for example the arm64 framework and add the <code>.swiftmodule</code> definitions from the x86_64 framework</li>
</ol>
<h2 id="single-uiapplication"><a class="header" href="#single-uiapplication">Single UIApplication</a></h2>
<p>Right now <code>winit</code> only allows the usage of a <code>UIApplication</code>. This means the application needs to run in fullscreen.
<a href="https://github.com/maplibre/maplibre-rs/issues/28">Tracking Issue</a></p>
<h2 id="example-app"><a class="header" href="#example-app">Example App</a></h2>
<p>The following settings are important for the example application within the XCode project.</p>
<h3 id="info-plist-for-applications"><a class="header" href="#info-plist-for-applications">Info Plist for Applications</a></h3>
<div class="d2h-file-wrapper" data-lang="pbxproj">
<div class="d2h-file-header">
<span class="d2h-file-name-wrapper">
<svg aria-hidden="true" class="d2h-icon" height="16" version="1.1" viewBox="0 0 12 16" width="12">
<path d="M6 5H2v-1h4v1zM2 8h7v-1H2v1z m0 2h7v-1H2v1z m0 2h7v-1H2v1z m10-7.5v9.5c0 0.55-0.45 1-1 1H1c-0.55 0-1-0.45-1-1V2c0-0.55 0.45-1 1-1h7.5l3.5 3.5z m-1 0.5L8 2H1v12h10V5z"></path>
</svg> <span class="d2h-file-name">{diff/maplibre-rs → xcode}/maplibre-rs.xcodeproj/project.pbxproj</span>
<span class="d2h-tag d2h-moved d2h-moved-tag">RENAMED</span></span>
<label class="d2h-file-collapse">
<input class="d2h-file-collapse-input" type="checkbox" name="viewed" value="viewed">
Viewed
</label>
</div>
<div class="d2h-file-diff">
<div class="d2h-code-wrapper">
<table class="d2h-diff-table">
<tbody class="d2h-diff-tbody">
<tr>
<td class="d2h-code-linenumber d2h-del d2h-change">
<div class="line-num1">435</div>
<div class="line-num2"></div>
</td>
<td class="d2h-del d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">-</span>
<span class="d2h-code-line-ctn"> <del>0BE4530328132EB5003BD2A5</del> /* Debug */ = {</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins d2h-change">
<div class="line-num1"></div>
<div class="line-num2">511</div>
</td>
<td class="d2h-ins d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> <ins>0B85D58D281290F800906D21</ins> /* Debug */ = {</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">436</div>
<div class="line-num2">512</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> isa = XCBuildConfiguration;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">437</div>
<div class="line-num2">513</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> buildSettings = {</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">438</div>
<div class="line-num2">514</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> ALWAYS_SEARCH_USER_PATHS = NO;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-info"></td>
<td class="d2h-info">
<div class="d2h-code-line">@@ -489,7 +565,7 @@</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">489</div>
<div class="line-num2">565</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> GCC_WARN_UNUSED_FUNCTION = YES;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">490</div>
<div class="line-num2">566</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> GCC_WARN_UNUSED_VARIABLE = YES;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">491</div>
<div class="line-num2">567</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> GENERATE_INFOPLIST_FILE = YES;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-del d2h-change">
<div class="line-num1">492</div>
<div class="line-num2"></div>
</td>
<td class="d2h-del d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">-</span>
<span class="d2h-code-line-ctn"> <del>INFOPLIST_KEY_UIApplicationSceneManifest_Generation</del> = <del>YES</del>;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins d2h-change">
<div class="line-num1"></div>
<div class="line-num2">568</div>
</td>
<td class="d2h-ins d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> <ins>INFOPLIST_FILE</ins> = <ins>"example--iOS--Info.plist"</ins>;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">493</div>
<div class="line-num2">569</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">494</div>
<div class="line-num2">570</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> INFOPLIST_KEY_UILaunchScreen_Generation = YES;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">495</div>
<div class="line-num2">571</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-info"></td>
<td class="d2h-info">
<div class="d2h-code-line">@@ -514,7 +590,7 @@</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">514</div>
<div class="line-num2">590</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> };</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">515</div>
<div class="line-num2">591</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> name = Debug;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">516</div>
<div class="line-num2">592</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> };</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-del d2h-change">
<div class="line-num1">517</div>
<div class="line-num2"></div>
</td>
<td class="d2h-del d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">-</span>
<span class="d2h-code-line-ctn"> <del>0BE4530428132EB5003BD2A5</del> /* Release */ = {</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins d2h-change">
<div class="line-num1"></div>
<div class="line-num2">593</div>
</td>
<td class="d2h-ins d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> <ins>0B85D58E281290F800906D21</ins> /* Release */ = {</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">518</div>
<div class="line-num2">594</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> isa = XCBuildConfiguration;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">519</div>
<div class="line-num2">595</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> buildSettings = {</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">520</div>
<div class="line-num2">596</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> ALWAYS_SEARCH_USER_PATHS = NO;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-info"></td>
<td class="d2h-info">
<div class="d2h-code-line">@@ -565,7 +641,7 @@</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">565</div>
<div class="line-num2">641</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> GCC_WARN_UNUSED_FUNCTION = YES;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">566</div>
<div class="line-num2">642</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> GCC_WARN_UNUSED_VARIABLE = YES;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">567</div>
<div class="line-num2">643</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> GENERATE_INFOPLIST_FILE = YES;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-del d2h-change">
<div class="line-num1">568</div>
<div class="line-num2"></div>
</td>
<td class="d2h-del d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">-</span>
<span class="d2h-code-line-ctn"> <del>INFOPLIST_KEY_UIApplicationSceneManifest_Generation</del> = <del>YES</del>;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins d2h-change">
<div class="line-num1"></div>
<div class="line-num2">644</div>
</td>
<td class="d2h-ins d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> <ins>INFOPLIST_FILE</ins> = <ins>"example--iOS--Info.plist"</ins>;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">569</div>
<div class="line-num2">645</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">570</div>
<div class="line-num2">646</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> INFOPLIST_KEY_UILaunchScreen_Generation = YES;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">571</div>
<div class="line-num2">647</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-info"></td>
<td class="d2h-info">
<div class="d2h-code-line">@@ -590,7 +666,7 @@</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<ul>
<li>The <code>INFOPLIST_KEY_UIApplicationSceneManifest_Generation</code> needs to be unset. Else the application screen is just black.</li>
</ul>
<h3 id="files--assets"><a class="header" href="#files--assets">Files &amp; Assets</a></h3>
<div class="d2h-file-wrapper" data-lang="pbxproj">
<div class="d2h-file-header">
<span class="d2h-file-name-wrapper">
<svg aria-hidden="true" class="d2h-icon" height="16" version="1.1" viewBox="0 0 12 16" width="12">
<path d="M6 5H2v-1h4v1zM2 8h7v-1H2v1z m0 2h7v-1H2v1z m0 2h7v-1H2v1z m10-7.5v9.5c0 0.55-0.45 1-1 1H1c-0.55 0-1-0.45-1-1V2c0-0.55 0.45-1 1-1h7.5l3.5 3.5z m-1 0.5L8 2H1v12h10V5z"></path>
</svg> <span class="d2h-file-name">{diff/maplibre-rs → xcode}/maplibre-rs.xcodeproj/project.pbxproj</span>
<span class="d2h-tag d2h-moved d2h-moved-tag">RENAMED</span></span>
<label class="d2h-file-collapse">
<input class="d2h-file-collapse-input" type="checkbox" name="viewed" value="viewed">
Viewed
</label>
</div>
<div class="d2h-file-diff">
<div class="d2h-code-wrapper">
<table class="d2h-diff-table">
<tbody class="d2h-diff-tbody">
<tr>
<td class="d2h-code-linenumber d2h-info"></td>
<td class="d2h-info">
<div class="d2h-code-line">@@ -7,93 +7,110 @@</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">7</div>
<div class="line-num2">7</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"> objects = {</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">8</div>
<div class="line-num2">8</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"><br></span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">9</div>
<div class="line-num2">9</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn">/* Begin PBXBuildFile section */</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-del d2h-change">
<div class="line-num1">10</div>
<div class="line-num2"></div>
</td>
<td class="d2h-del d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">-</span>
<span class="d2h-code-line-ctn"> <del>0BE452E828132EA6003BD2A5</del> /* maplibre_rs.h in Headers */ = {isa = PBXBuildFile; fileRef = <del>0BE452E728132EA6003BD2A5</del> /* maplibre_rs.h */; settings = {ATTRIBUTES = (Public, ); }; };</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-del d2h-change">
<div class="line-num1">11</div>
<div class="line-num2"></div>
</td>
<td class="d2h-del d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">-</span>
<span class="d2h-code-line-ctn"> <del>0BE452FC28132EB5003BD2A5</del> /* exampleApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = <del>0BE452ED28132EB5003BD2A5</del> /* exampleApp.swift */; };</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-del d2h-change">
<div class="line-num1">12</div>
<div class="line-num2"></div>
</td>
<td class="d2h-del d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">-</span>
<span class="d2h-code-line-ctn"> <del>0BE452FD28132EB5003BD2A5</del> /* exampleApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = <del>0BE452ED28132EB5003BD2A5</del> /* exampleApp.swift */; };</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-del d2h-change">
<div class="line-num1">13</div>
<div class="line-num2"></div>
</td>
<td class="d2h-del d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">-</span>
<span class="d2h-code-line-ctn"> <del>0BE452FE28132EB5003BD2A5</del> /* <del>ContentView</del>.<del>swift</del> in <del>Sources</del> */ = {isa = PBXBuildFile; fileRef = <del>0BE452EE28132EB5003BD2A5</del> /* <del>ContentView</del>.<del>swift</del> */; };</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-del d2h-change">
<div class="line-num1">14</div>
<div class="line-num2"></div>
</td>
<td class="d2h-del d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">-</span>
<span class="d2h-code-line-ctn"> <del>0BE452FF28132EB5003BD2A5</del> /* <del>ContentView</del>.<del>swift</del> in <del>Sources</del> */ = {isa = PBXBuildFile; fileRef = <del>0BE452EE28132EB5003BD2A5</del> /* <del>ContentView</del>.<del>swift</del> */; };</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-del d2h-change">
<div class="line-num1">15</div>
<div class="line-num2"></div>
</td>
<td class="d2h-del d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">-</span>
<span class="d2h-code-line-ctn"> <del>0BE4530028132EB5003BD2A5</del> /* <del>Assets</del>.<del>xcassets</del> in <del>Resources</del> */ = {isa = PBXBuildFile; fileRef = <del>0BE452EF28132EB5003BD2A5</del> /* <del>Assets</del>.<del>xcassets</del> */; };</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-del d2h-change">
<div class="line-num1">16</div>
<div class="line-num2"></div>
</td>
<td class="d2h-del d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">-</span>
<span class="d2h-code-line-ctn"> <del>0BE4530128132EB5003BD2A5</del> /* <del>Assets</del>.<del>xcassets</del> in <del>Resources</del> */ = {isa = PBXBuildFile; fileRef = <del>0BE452EF28132EB5003BD2A5</del> /* <del>Assets</del>.<del>xcassets</del> */; };</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins d2h-change">
<div class="line-num1"></div>
<div class="line-num2">10</div>
</td>
<td class="d2h-ins d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> <ins>0B85D56F2812903700906D21</ins> /* maplibre_rs.h in Headers */ = {isa = PBXBuildFile; fileRef = <ins>0B85D56E2812903700906D21</ins> /* maplibre_rs.h */; settings = {ATTRIBUTES = (Public, ); }; };</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins d2h-change">
<div class="line-num1"></div>
<div class="line-num2">11</div>
</td>
<td class="d2h-ins d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> <ins>0B85D586281290F800906D21</ins> /* exampleApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = <ins>0B85D577281290F800906D21</ins> /* exampleApp.swift */; };</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins d2h-change">
<div class="line-num1"></div>
<div class="line-num2">12</div>
</td>
<td class="d2h-ins d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> <ins>0B85D587281290F800906D21</ins> /* exampleApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = <ins>0B85D577281290F800906D21</ins> /* exampleApp.swift */; };</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins d2h-change">
<div class="line-num1"></div>
<div class="line-num2">13</div>
</td>
<td class="d2h-ins d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> <ins>0B85D58A281290F800906D21</ins> /* <ins>Assets</ins>.<ins>xcassets</ins> in <ins>Resources</ins> */ = {isa = PBXBuildFile; fileRef = <ins>0B85D579281290F800906D21</ins> /* <ins>Assets</ins>.<ins>xcassets</ins> */; };</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins d2h-change">
<div class="line-num1"></div>
<div class="line-num2">14</div>
</td>
<td class="d2h-ins d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> <ins>0B85D58B281290F800906D21</ins> /* <ins>Assets</ins>.<ins>xcassets</ins> in <ins>Resources</ins> */ = {isa = PBXBuildFile; fileRef = <ins>0B85D579281290F800906D21</ins> /* <ins>Assets</ins>.<ins>xcassets</ins> */; };</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins d2h-change">
<div class="line-num1"></div>
<div class="line-num2">15</div>
</td>
<td class="d2h-ins d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> <ins>0B85D5952812913700906D21</ins> /* <ins>maplibre</ins>.<ins>swift</ins> in <ins>Sources</ins> */ = {isa = PBXBuildFile; fileRef = <ins>0B85D5942812913700906D21</ins> /* <ins>maplibre</ins>.<ins>swift</ins> */; };</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins d2h-change">
<div class="line-num1"></div>
<div class="line-num2">16</div>
</td>
<td class="d2h-ins d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> <ins>0B85D596281291A400906D21</ins> /* <ins>maplibre_rs</ins>.<ins>framework</ins> in <ins>Frameworks</ins> */ = {isa = PBXBuildFile; fileRef = <ins>0B85D56B2812903700906D21</ins> /* <ins>maplibre_rs</ins>.<ins>framework</ins> */; };</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">17</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> 0B85D599281291A700906D21 /* maplibre_rs.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0B85D56B2812903700906D21 /* maplibre_rs.framework */; };</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">18</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> 0B85D5A42812991100906D21 /* libmaplibre_apple.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0B85D5A32812987B00906D21 /* libmaplibre_apple.a */; };</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">17</div>
<div class="line-num2">19</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn">/* End PBXBuildFile section */</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">18</div>
<div class="line-num2">20</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn"><br></span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx">
<div class="line-num1">19</div>
<div class="line-num2">21</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn">/* Begin PBXFileReference section */</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-del d2h-change">
<div class="line-num1">20</div>
<div class="line-num2"></div>
</td>
<td class="d2h-del d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">-</span>
<span class="d2h-code-line-ctn"> <del>0BE452E428132EA6003BD2A5</del> /* maplibre_rs.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = maplibre_rs.framework; sourceTree = BUILT_PRODUCTS_DIR; };</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-del d2h-change">
<div class="line-num1">21</div>
<div class="line-num2"></div>
</td>
<td class="d2h-del d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">-</span>
<span class="d2h-code-line-ctn"> <del>0BE452E728132EA6003BD2A5</del> /* maplibre_rs.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = maplibre_rs.h; sourceTree = "&lt;group&gt;"; };</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-del d2h-change">
<div class="line-num1">22</div>
<div class="line-num2"></div>
</td>
<td class="d2h-del d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">-</span>
<span class="d2h-code-line-ctn"> <del>0BE452ED28132EB5003BD2A5</del> /* exampleApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = exampleApp.swift; sourceTree = "&lt;group&gt;"; };</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-del d2h-change">
<div class="line-num1">23</div>
<div class="line-num2"></div>
</td>
<td class="d2h-del d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">-</span>
<span class="d2h-code-line-ctn"> <del>0BE452EE28132EB5003BD2A5</del> /* <del>ContentView</del>.<del>swift</del> */ = {isa = PBXFileReference; lastKnownFileType = <del>sourcecode</del>.<del>swift</del>; path = <del>ContentView</del>.<del>swift</del>; sourceTree = "&lt;group&gt;"; };</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-del d2h-change">
<div class="line-num1">24</div>
<div class="line-num2"></div>
</td>
<td class="d2h-del d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">-</span>
<span class="d2h-code-line-ctn"> <del>0BE452EF28132EB5003BD2A5</del> /* <del>Assets</del>.<del>xcassets</del> */ = {isa = PBXFileReference; <del>lastKnownFileType</del> = <del>folder</del>.<del>assetcatalog</del>; path = <del>Assets</del>.<del>xcassets</del>; sourceTree = <del>"&lt;group&gt;"</del>; };</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-del d2h-change">
<div class="line-num1">25</div>
<div class="line-num2"></div>
</td>
<td class="d2h-del d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">-</span>
<span class="d2h-code-line-ctn"> <del>0BE452F428132EB5003BD2A5</del> /* example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = example.app; sourceTree = BUILT_PRODUCTS_DIR; };</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-del d2h-change">
<div class="line-num1">26</div>
<div class="line-num2"></div>
</td>
<td class="d2h-del d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">-</span>
<span class="d2h-code-line-ctn"> <del>0BE452F928132EB5003BD2A5</del> /* <del>example</del>.<del>app</del> */ = {isa = PBXFileReference; <del>explicitFileType</del> = <del>wrapper</del>.<del>application</del>; <del>includeInIndex = 0; </del>path = <del>example</del>.<del>app</del>; sourceTree = <del>BUILT_PRODUCTS_DIR</del>; };</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-del d2h-change">
<div class="line-num1">27</div>
<div class="line-num2"></div>
</td>
<td class="d2h-del d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">-</span>
<span class="d2h-code-line-ctn"> <del>0BE452FB28132EB5003BD2A5</del> /* <del>macOS</del>.<del>entitlements</del> */ = {isa = PBXFileReference; lastKnownFileType = <del>text</del>.<del>plist.entitlements</del>; path = <del>macOS</del>.<del>entitlements</del>; sourceTree = "&lt;group&gt;"; };</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins d2h-change">
<div class="line-num1"></div>
<div class="line-num2">22</div>
</td>
<td class="d2h-ins d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> <ins>0B85D56B2812903700906D21</ins> /* maplibre_rs.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = maplibre_rs.framework; sourceTree = BUILT_PRODUCTS_DIR; };</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins d2h-change">
<div class="line-num1"></div>
<div class="line-num2">23</div>
</td>
<td class="d2h-ins d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> <ins>0B85D56E2812903700906D21</ins> /* maplibre_rs.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = maplibre_rs.h; sourceTree = "&lt;group&gt;"; };</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins d2h-change">
<div class="line-num1"></div>
<div class="line-num2">24</div>
</td>
<td class="d2h-ins d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> <ins>0B85D577281290F800906D21</ins> /* exampleApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = exampleApp.swift; sourceTree = "&lt;group&gt;"; };</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins d2h-change">
<div class="line-num1"></div>
<div class="line-num2">25</div>
</td>
<td class="d2h-ins d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> <ins>0B85D579281290F800906D21</ins> /* <ins>Assets</ins>.<ins>xcassets</ins> */ = {isa = PBXFileReference; lastKnownFileType = <ins>folder</ins>.<ins>assetcatalog</ins>; path = <ins>Assets</ins>.<ins>xcassets</ins>; sourceTree = "&lt;group&gt;"; };</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins d2h-change">
<div class="line-num1"></div>
<div class="line-num2">26</div>
</td>
<td class="d2h-ins d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> <ins>0B85D57E281290F800906D21</ins> /* <ins>example</ins>.<ins>app</ins> */ = {isa = PBXFileReference; <ins>explicitFileType</ins> = <ins>wrapper</ins>.<ins>application</ins>; <ins>includeInIndex = 0; </ins>path = <ins>example</ins>.<ins>app</ins>; sourceTree = <ins>BUILT_PRODUCTS_DIR</ins>; };</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins d2h-change">
<div class="line-num1"></div>
<div class="line-num2">27</div>
</td>
<td class="d2h-ins d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> <ins>0B85D583281290F800906D21</ins> /* example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = example.app; sourceTree = BUILT_PRODUCTS_DIR; };</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins d2h-change">
<div class="line-num1"></div>
<div class="line-num2">28</div>
</td>
<td class="d2h-ins d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> <ins>0B85D585281290F800906D21</ins> /* <ins>macOS</ins>.<ins>entitlements</ins> */ = {isa = PBXFileReference; <ins>lastKnownFileType</ins> = <ins>text</ins>.<ins>plist.entitlements</ins>; path = <ins>macOS</ins>.<ins>entitlements</ins>; sourceTree = <ins>"&lt;group&gt;"</ins>; };</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins d2h-change">
<div class="line-num1"></div>
<div class="line-num2">29</div>
</td>
<td class="d2h-ins d2h-change">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> <ins>0B85D5942812913700906D21</ins> /* <ins>maplibre</ins>.<ins>swift</ins> */ = {isa = PBXFileReference; lastKnownFileType = <ins>sourcecode</ins>.<ins>swift</ins>; path = <ins>maplibre</ins>.<ins>swift</ins>; sourceTree = "&lt;group&gt;"; };</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">30</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> 0B85D5A32812987B00906D21 /* libmaplibre_apple.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libmaplibre_apple.a; sourceTree = SOURCE_ROOT; };</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">31</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> 0BE452D62812EEA8003BD2A5 /* example--iOS--Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = "example--iOS--Info.plist"; sourceTree = "&lt;group&gt;"; };</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-cntx d2h-info">
<div class="line-num1"></div>
<div class="line-num2">32</div>
</td>
<td class="d2h-cntx">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">&nbsp;</span>
<span class="d2h-code-line-ctn">/* End PBXFileReference section */</span>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<ul>
<li>The example/demo application within the XCode project references the <code>maplibre_rs.framework</code>. Some default files have
been removed.</li>
</ul>
<h3 id="macos-entitlements"><a class="header" href="#macos-entitlements">MacOS Entitlements</a></h3>
<div id="d2h-648583" class="d2h-file-wrapper" data-lang="entitlements">
<div class="d2h-file-header">
<span class="d2h-file-name-wrapper">
<svg aria-hidden="true" class="d2h-icon" height="16" version="1.1" viewBox="0 0 12 16" width="12">
<path d="M6 5H2v-1h4v1zM2 8h7v-1H2v1z m0 2h7v-1H2v1z m0 2h7v-1H2v1z m10-7.5v9.5c0 0.55-0.45 1-1 1H1c-0.55 0-1-0.45-1-1V2c0-0.55 0.45-1 1-1h7.5l3.5 3.5z m-1 0.5L8 2H1v12h10V5z"></path>
</svg> <span class="d2h-file-name">xcode/macOS/macOS.entitlements</span>
<span class="d2h-tag d2h-added d2h-added-tag">ADDED</span></span>
<label class="d2h-file-collapse">
<input class="d2h-file-collapse-input" type="checkbox" name="viewed" value="viewed">
Viewed
</label>
</div>
<div class="d2h-file-diff">
<div class="d2h-code-wrapper">
<table class="d2h-diff-table">
<tbody class="d2h-diff-tbody">
<tr>
<td class="d2h-code-linenumber d2h-info"></td>
<td class="d2h-info">
<div class="d2h-code-line">@@ -0,0 +1,12 @@</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">1</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn">&lt;?xml version="1.0" encoding="UTF-8"?&gt;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">2</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn">&lt;!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"&gt;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">3</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn">&lt;plist version="1.0"&gt;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">4</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn">&lt;dict&gt;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">5</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> &lt;key&gt;com.apple.security.app-sandbox&lt;/key&gt;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">6</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> &lt;true/&gt;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">7</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> &lt;key&gt;com.apple.security.files.user-selected.read-only&lt;/key&gt;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">8</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> &lt;true/&gt;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">9</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> &lt;key&gt;com.apple.security.network.client&lt;/key&gt;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">10</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn"> &lt;true/&gt;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">11</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn">&lt;/dict&gt;</span>
</div>
</td>
</tr>
<tr>
<td class="d2h-code-linenumber d2h-ins">
<div class="line-num1"></div>
<div class="line-num2">12</div>
</td>
<td class="d2h-ins">
<div class="d2h-code-line">
<span class="d2h-code-line-prefix">+</span>
<span class="d2h-code-line-ctn">&lt;/plist&gt;</span>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<ul>
<li>On macOS one needs to allow network access via <code>com.apple.security.network.client</code></li>
</ul>
<div style="break-before: page; page-break-before: always;"></div><h1 id="android-1"><a class="header" href="#android-1">Android</a></h1>
<h2 id="gradle-project-setup"><a class="header" href="#gradle-project-setup">Gradle Project Setup</a></h2>
<p>In order to package an Android <code>.aar</code> archive we use
the <a href="https://github.com/mozilla/rust-android-gradle">rust-android-gradle</a>.
Except some customisations for the latest NDK toolchain release everything worked flawlessly.</p>
<h2 id="jni"><a class="header" href="#jni">JNI</a></h2>
<p>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.</p>
<h2 id="single-nativeactivity"><a class="header" href="#single-nativeactivity">Single NativeActivity</a></h2>
<p>Right now <code>winit</code> only allows the usage of a <code>NativeActivity</code>. 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.
<a href="https://github.com/maplibre/maplibre-rs/issues/28">Tracking Issue</a></p>
<div style="break-before: page; page-break-before: always;"></div><h1 id="web"><a class="header" href="#web">Web</a></h1>
<p>This document describes issues and challenges when packaging maplibre-rs as a npm package.</p>
<h2 id="required-formats"><a class="header" href="#required-formats">Required Formats</a></h2>
<h3 id="esm"><a class="header" href="#esm">ESM</a></h3>
<p>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:</p>
<pre><code class="language-ts">new Worker(new URL(&quot;./pool.worker.ts&quot;, import.meta.url), {
type: 'module'
});
</code></pre>
<p>Similarly, the following works:</p>
<pre><code class="language-ts">new URL('index_bg.wasm', import.meta.url);
</code></pre>
<h3 id="iife-immediately-invoked-function-expression"><a class="header" href="#iife-immediately-invoked-function-expression">IIFE (immediately-invoked function expression)</a></h3>
<blockquote>
<p>This format is used when including maplibre-rs in a <code>&lt;script&gt;</code> tag. The library is &quot;written&quot; onto the window/global
object. This allows quick prototyping/playgrounds/experiments using maplibre-rs.</p>
</blockquote>
<p>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. Users of
these libraries have to specify where WASM or non-inlined WebWorkers are located.</p>
<p>Both assets could be inlined theoretically. This is common for WebWorkers, but not for WASM files.</p>
<h3 id="umd"><a class="header" href="#umd">UMD</a></h3>
<blockquote>
<p>UMD modules are needed when creating a library which should run in Node as well as browsers. This is not a usecase
for maplibre-rs. If we support node, then we probably would ship a separate package called &quot;maplibre-rs-node&quot; which
bundles to CJS directly.</p>
</blockquote>
<h3 id="cjscommonjs"><a class="header" href="#cjscommonjs">CJS/CommonJS</a></h3>
<blockquote>
<p>Not needed for the browser build of maplibre-rs, possibly needed when supporting Node</p>
</blockquote>
<p>With a CommonJS module its is not possible for bundlers to dynamically resolve WebWorkers or WASM files.</p>
<p>The <code>import.meta.url</code> token can not exist in a CommonJS module. Therefore, bundlers which encounter a CommonJS module
have to use a different mechanism of resolving files.</p>
<p>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.</p>
<h2 id="wasm-pack-output"><a class="header" href="#wasm-pack-output">wasm-pack output</a></h2>
<p>wasm-pack can output <a href="https://rustwasm.github.io/docs/wasm-pack/commands/build.html#target">multiple formats</a>. The <code>web</code>
and <code>bundler</code> outputs offer the most modular modules.
Unfortunately, the
function <a href="https://docs.rs/wasm-bindgen/0.2.80/src/wasm_bindgen/lib.rs.html#1208-1217">wasm_bindgen::module()</a>
is only supported in <code>web</code> and <code>no-modules</code>. We currently are using this in order to send loaded instances
of <code>WebAssembly.Module</code> to WebWorkers. <code>nodejs</code> should not be used because MapLibre does not target Node.
Therefore, we should stick to the <code>web</code> output format.</p>
<h2 id="required-features"><a class="header" href="#required-features">Required Features</a></h2>
<ul>
<li>WASM Bundling: Make the WASM binary available to users of the maplibre-rs library</li>
<li>WebWorker Bundling: Make the WebWorker available to users of the maplibre-rs library. This could also be achived by inlining.</li>
<li>WebWorker Inlining: Inline the WebWorker bundle in the library bundle as a string.</li>
<li>Predictable Paths: Without predictable paths, it's difficult for users to reference the wasm file directly from the <code>node_modules</code> directory if requried.</li>
</ul>
<h2 id="bundler-feature-comparison"><a class="header" href="#bundler-feature-comparison">Bundler Feature Comparison</a></h2>
<table><thead><tr><th>Bundler</th><th><em>ESM</em></th><th><em>IIFE</em></th><th>CJS</th><th>UMD</th><th><em>WebWorker Inlining</em></th><th>Web Worker Bundling</th><th><em>WASM Bundling</em></th><th><em>Predictable Paths</em></th><th>Inlining Environment Variables</th></tr></thead><tbody>
<tr><td>Babel 1)</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>TypeScript 1)</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>Webpack</td><td>❌ 4)</td><td></td><td></td><td></td><td>❌ 2)</td><td></td><td></td><td></td><td></td></tr>
<tr><td>Parcel</td><td></td><td></td><td></td><td></td><td>🛠️ 3)</td><td></td><td></td><td>❌ 5)</td><td></td></tr>
<tr><td>ESBuild</td><td></td><td></td><td></td><td></td><td>✅ 6)</td><td></td><td>✅ 6)</td><td></td><td></td></tr>
<tr><td>Rollup</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
</tbody></table>
<p>Features in <em><strong>italic</strong></em>s are required for maplibre-rs.</p>
<blockquote>
<ol>
<li>Technically not a bundler but can be used to emit ES modules</li>
<li>Was Supported in Webpack 4, but currently is not supported</li>
<li>https://github.com/parcel-bundler/parcel/issues/8004</li>
<li>As of the time of writing Webpack can not output ESM libraries</li>
<li>Plugins exist, but they don't work reliably</li>
<li>Plugins exist, and work reliably</li>
</ol>
</blockquote>
<h3 id="esbuild"><a class="header" href="#esbuild">ESBuild</a></h3>
<p>ESBuild supports CJS, ESM and IIFI modules equally well. Plugins exist for WebWorker inlining and resolving assets
through <code>import.meta.url</code>. The plugin quality seems to be superior compared to Parcel. It is also very fast compared to
all other bundlers.</p>
<ul>
<li>IIFI: The esbuild bundler translates to <code>new URL('index_bg.wasm', import.meta.url);</code> to
<pre><code class="language-js">var __currentScriptUrl__ = document.currentScript &amp;&amp; document.currentScript.src || document.baseURI;
new URL(&quot;./assets/index_bg.wasm?emit=file&quot;, __currentScriptUrl__);
</code></pre>
</li>
</ul>
<p>See config in <code>web/lib/build.mjs</code> for an example usage.</p>
<h3 id="babel--typescript"><a class="header" href="#babel--typescript">Babel &amp; TypeScript</a></h3>
<p>Babel and TypeScript both can produce ESM modules, but they <strong>fail with transforming references within the source code</strong>
like <code>new URL(&quot;./pool.worker.ts&quot;, import.meta.url)</code>. There exist some Babel plugins, but none of them is stable.
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.</p>
<h3 id="webpack"><a class="header" href="#webpack">WebPack</a></h3>
<p>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.</p>
<ul>
<li>CJS: Webpack translates <code>new URL('index_bg.wasm', import.meta.url);</code> to something that is equivalent to <code>'./index_bg.wasm'</code>
. It just expects that assets are resolvable from the current file.</li>
</ul>
<p>Example scripts for <code>package.json</code>:</p>
<pre><code class="language-json">{
&quot;scripts&quot;: {
&quot;webpack&quot;: &quot;webpack --mode=development&quot;,
&quot;webpack-webgl&quot;: &quot;npm run build -- --env webgl&quot;,
&quot;webpack-production&quot;: &quot;webpack --mode=production&quot;,
&quot;webpack-webgl-production&quot;: &quot;npm run production-build -- --env webgl&quot;
}
}
</code></pre>
<p>Example config:</p>
<pre><code class="language-js">const path = require(&quot;path&quot;);
const webpack = require(&quot;webpack&quot;);
const WasmPackPlugin = require(&quot;@wasm-tool/wasm-pack-plugin&quot;);
let dist = path.join(__dirname, 'dist/maplibre-rs');
module.exports = (env) =&gt; ({
mode: &quot;development&quot;,
entry: &quot;./src/index.ts&quot;,
experiments: {
syncWebAssembly: true,
},
performance: {
maxEntrypointSize: 400000,
maxAssetSize: 400000000,
},
output: {
path: dist,
filename: &quot;maplibre-rs.js&quot;,
library: {
name: 'maplibre_rs',
type: 'umd',
},
},
module: {
rules: [
{
test: /\.ts$/,
exclude: /node_modules/,
use: [
{
loader: 'ts-loader',
options: {}
}
]
},
],
},
resolve: {
extensions: ['.ts', '.js'],
},
plugins: [
new webpack.DefinePlugin({
'process.env.WEBGL': !!env.webgl
}),
new WasmPackPlugin({
crateDirectory: path.resolve(__dirname, '../'),
// Check https://rustwasm.github.io/wasm-pack/book/commands/build.html for
// the available set of arguments.
//
// Optional space delimited arguments to appear before the wasm-pack
// command. Default arguments are `--verbose`.
//args: '--log-level warn',
// Default arguments are `--typescript --target browser --mode normal`.
extraArgs: ` --target web -- . -Z build-std=std,panic_abort ${env.webgl ? '--features web-webgl' : ''} ${env.tracing ? '--features trace' : ''}`,
// Optional array of absolute paths to directories, changes to which
// will trigger the build.
// watchDirectories: [
// path.resolve(__dirname, &quot;another-crate/src&quot;)
// ],
// The same as the `--out-dir` option for `wasm-pack`
outDir: path.resolve(__dirname, 'src/wasm-pack'),
// The same as the `--out-name` option for `wasm-pack`
// outName: &quot;index&quot;,
// If defined, `forceWatch` will force activate/deactivate watch mode for
// `.rs` files.
//
// The default (not set) aligns watch mode for `.rs` files to Webpack's
// watch mode.
// forceWatch: true,
// If defined, `forceMode` will force the compilation mode for `wasm-pack`
//
// Possible values are `development` and `production`.
//
// the mode `development` makes `wasm-pack` build in `debug` mode.
// the mode `production` makes `wasm-pack` build in `release` mode.
// forceMode: &quot;production&quot;,
// Controls plugin output verbosity, either 'info' or 'error'.
// Defaults to 'info'.
// pluginLogLevel: 'info'
}),
]
});
</code></pre>
<h3 id="parcel"><a class="header" href="#parcel">Parcel</a></h3>
<p>Parcel supports CommonJS and ESM modules equally good. The documentation about <code>import.meta.url</code> is very good. In other
bundlers documentations around this feature is missing. In the latest Parcel version inlining WebWorkers is not working.</p>
<ul>
<li>CJS: The Parcel bundler translates to <code>new URL('index_bg.wasm', import.meta.url);</code>
to <code>new URL(&quot;index_bg.wasm&quot;, &quot;file:&quot; + __filename);</code>
While depending on <code>file:</code> and <code>filename</code> works for NodeJS, it is unsupported in the browser.</li>
</ul>
<p>Example scripts for <code>package.json</code>:</p>
<pre><code class="language-json">{
&quot;scripts&quot;: {
&quot;parcel&quot;: &quot;npm run clean &amp;&amp; npm run wasm-pack &amp;&amp; WEBGL=false parcel build --no-cache src/index.ts&quot;,
&quot;parcel-webgl&quot;: &quot;npm run clean &amp;&amp; FEATURES=web-webgl npm run wasm-pack &amp;&amp; WEBGL=true parcel build --no-cache src/index.ts&quot;
}
}
</code></pre>
<p>Example config in `package.json:</p>
<pre><code class="language-json">{
&quot;module&quot;: &quot;dist/parcel-esm/module.js&quot;,
&quot;main&quot;: &quot;dist/parcel-cjs/main.js&quot;,
&quot;types&quot;: &quot;dist/parcel/types.d.ts&quot;,
&quot;targets&quot;: {
&quot;main&quot;: {
&quot;distDir&quot;: &quot;./dist/parcel-cjs&quot;,
&quot;context&quot;: &quot;browser&quot;,
&quot;outputFormat&quot;: &quot;commonjs&quot;
},
&quot;module&quot;: {
&quot;distDir&quot;: &quot;./dist/parcel-esm&quot;,
&quot;context&quot;: &quot;browser&quot;,
&quot;outputFormat&quot;: &quot;esmodule&quot;
}
},
&quot;@parcel/transformer-js&quot;: {
&quot;inlineFS&quot;: false,
&quot;inlineEnvironment&quot;: [
&quot;WEBGL&quot;
]
}
}
</code></pre>
<h3 id="rollup"><a class="header" href="#rollup">Rollup</a></h3>
<p>Not yet evaluated</p>
<div style="break-before: page; page-break-before: always;"></div><h1 id="appendix"><a class="header" href="#appendix">Appendix</a></h1>
<h2 id="goals"><a class="header" href="#goals">Goals</a></h2>
<h3 id="next-major-goals"><a class="header" href="#next-major-goals">Next Major Goals</a></h3>
<ul>
<li><del>Improve buffer_pool eviction rules</del></li>
<li><del>Use MPI: https://doc.rust-lang.org/book/ch16-02-message-passing.html</del></li>
<li>Input-handling via events and functional pipelines</li>
<li><del>Show old tiles until new tile is ready / Show mixed tiles, based on availability</del></li>
<li>Use a simple style definition
<ul>
<li>type: background/fill/line</li>
<li>minzoom/maxzoom</li>
<li>source</li>
<li>source-layer</li>
<li>paint (fill-color)</li>
</ul>
</li>
<li>Map feeling:
<ul>
<li>Wrap world around in x direction</li>
<li>Limit panning in y direction</li>
<li>Nicer default map style</li>
</ul>
</li>
</ul>
<h3 id="intermediate-goals"><a class="header" href="#intermediate-goals">Intermediate Goals</a></h3>
<ul>
<li>Support multiple projections? PoC such that we are sure the renderer is acceptable</li>
</ul>
<h3 id="future-goals"><a class="header" href="#future-goals">Future Goals</a></h3>
<ul>
<li>Very simple text rendering</li>
<li>Cache tessellation results
<ul>
<li>We have three &quot;caches&quot;: downloaded tiles, tessellated tiles, gpu tiles</li>
</ul>
</li>
<li>Handle missing tiles</li>
<li>Support different tile raster addressing</li>
</ul>
<h2 id="future-ideas"><a class="header" href="#future-ideas">Future Ideas</a></h2>
<ul>
<li>Use <a href="https://github.com/EmbarkStudios/rust-gpu">rust-gpu</a> as shading language</li>
<li>Focus on accessibility of maps: https://www.w3.org/WAI/RD/wiki/Accessible_Maps</li>
<li>Display in AR: https://developer.apple.com/documentation/arkit/displaying_an_ar_experience_with_metal</li>
<li>Use tracing framework: <a href="https://docs.rs/tracing/0.1.31/tracing">tracing</a></li>
</ul>
<h2 id="challenges"><a class="header" href="#challenges">Challenges:</a></h2>
<ul>
<li>Accuracy of floating point numbers is very bad for big world view
coordinates (<a href="https://en.wikipedia.org/wiki/IEEE_754#/media/File:IEEE754.svg">Plot</a>)</li>
<li><a href="https://paroj.github.io/gltut/Positioning/Tut07%20The%20Perils%20of%20World%20Space.html">Perils of World Space</a></li>
</ul>
<h3 id="create-paths-for-tessellating-streets"><a class="header" href="#create-paths-for-tessellating-streets">Create paths for tessellating streets</a></h3>
<p>Streets can have unusual shaped like shown <a href="https://www.google.de/maps/@48.1353883,11.5717232,19z">here</a> in Munich. OSM
does not offer such data and therefore just renders an ordinary street contour like
shown <a href="https://www.openstreetmap.org/query?lat=48.13533&amp;lon=11.57143">here</a>.
Because the data is probably not available this is a very hard challenge.</p>
<div style="break-before: page; page-break-before: always;"></div><h1 id="related-resources"><a class="header" href="#related-resources">Related Resources</a></h1>
<h2 id="talks"><a class="header" href="#talks">Talks</a></h2>
<ul>
<li><a href="https://docs.google.com/presentation/d/e/2PACX-1vRsi-sGsqwUXEIQDClaZF4BH2RgjufQQ-yxFDWeOGrm0EbIf4H4lFY3U4at4cAIlxSTWi4XyF2LKjRu/pub">2022-04-13-World-in-Vectors</a></li>
</ul>
<h2 id="related-projects"><a class="header" href="#related-projects">Related Projects</a></h2>
<ul>
<li><a href="https://github.com/tangrams/tangram/">Tangram Renderer</a></li>
<li><a href="https://www.nextzen.org/">Tilezen/Nextzen</a></li>
<li><a href="https://protomaps.com/">Protomaps: New Maps Stack</a></li>
<li><a href="https://www.harp.gl/">Harp GL</a></li>
</ul>
<h2 id="gis"><a class="header" href="#gis">GIS</a></h2>
<ul>
<li><a href="https://www.maptiler.com/google-maps-coordinates-tile-bounds-projection">Google Maps Projection</a></li>
<li><a href="https://gist.github.com/maptiler/fddb5ce33ba995d5523de9afdf8ef118">Grid Calculation Examples</a></li>
<li><a href="https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames">Slippy map tilenames</a> (also known as XYZ) </li>
<li><a href="https://wiki.osgeo.org/wiki/Tile_Map_Service_Specification#TileMap_Diagram">TMS</a></li>
<li><a href="https://www.mapbox.com/blog/adaptive-projections">Mapbox Adaptive Projections</a></li>
<li><a href="https://docs.microsoft.com/en-us/bingmaps/articles/bing-maps-tile-system">Bing Map Tile System</a></li>
<li><a href="https://docs.microsoft.com/en-us/bingmaps/articles/understanding-scale-and-resolution">Bing: Understanding Scale and Resolution</a></li>
</ul>
<h2 id="webassembly-and-webworkers"><a class="header" href="#webassembly-and-webworkers">WebAssembly and WebWorkers</a></h2>
<p>Specs:</p>
<ul>
<li><a href="https://webassembly.github.io/threads/core/bikeshed/#atomic-memory-instructions%E2%91%A2">Thread/Atomics Proposal for WASM</a></li>
</ul>
<p>Projects:</p>
<ul>
<li><a href="https://github.com/Ciantic/rust-shared-wasm-experiments">Experiment with shared memory</a> and <a href="https://github.com/rustwasm/wasm-bindgen/issues/2225">the idea behind it</a></li>
<li><a href="https://github.com/wasm-rs/shared-channel">Shared channel</a></li>
<li><a href="https://docs.rs/async_executors/latest/async_executors/">Bridge for async executors</a></li>
<li><a href="https://github.com/GoogleChromeLabs/wasm-bindgen-rayon">Rayon for WebAssembly</a></li>
<li><a href="https://github.com/w3reality/wasm-mt">wasm-mt: postMessage message passing</a></li>
<li></li>
</ul>
<p>Articles:</p>
<ul>
<li><a href="https://web.dev/webassembly-threads/">WebAssembly Threads (official)</a></li>
<li><a href="https://rustwasm.github.io/2018/10/24/multithreading-rust-and-wasm.html">Multithreading Rust and Wasm 2018</a></li>
<li><a href="https://surma.dev/things/is-postmessage-slow/">postMessage Performance</a></li>
<li><a href="https://radu-matei.com/blog/practical-guide-to-wasm-memory/">A practical guide to WebAssembly memory</a></li>
</ul>
<p>Examples:</p>
<ul>
<li><a href="https://rustwasm.github.io/wasm-bindgen/examples/wasm-in-web-worker.html">WASM in a WebWorker</a></li>
<li><a href="https://github.com/rustwasm/wasm-bindgen/blob/main/examples/raytrace-parallel/build.sh">Building for Shared Memory</a></li>
<li><a href="https://rustwasm.github.io/docs/wasm-bindgen/examples/raytrace.html">Parallel Raytracing</a></li>
</ul>
<h2 id="rendering"><a class="header" href="#rendering">Rendering</a></h2>
<p>Specs:</p>
<ul>
<li><a href="https://gpuweb.github.io/gpuweb/">WebGPU Spec</a></li>
<li><a href="https://gpuweb.github.io/gpuweb/wgsl/">WGSL Spec</a></li>
<li><a href="https://gpuweb.github.io/gpuweb/wgsl/#alignment-and-size">WGSL Struct Alignment</a></li>
<li><a href="https://github.com/gpuweb/gpuweb/blob/main/design/Pipelines.md#depth-stencil-state">Mismatches Stencil Test</a></li>
</ul>
<p>Articles:</p>
<ul>
<li><a href="https://github.com/maplibre/maplibre-gl-js/blob/main/docs/life-of-a-tile.md">Life of a Tile (MapLibre)</a></li>
</ul>
<p>Tutorials:</p>
<ul>
<li><a href="https://learnopengl.com/Advanced-OpenGL/Stencil-testing">Stencil Testing</a></li>
<li><a href="https://learnopengl.com/Getting-started/Camera">Camera</a></li>
<li><a href="https://zeux.io/2020/02/27/writing-an-efficient-vulkan-renderer/">Writing an efficient Vulkan renderer</a></li>
</ul>
<p>Examples:</p>
<ul>
<li><a href="https://github.com/ruffle-rs/ruffle/blob/master/render/wgpu/src/pipelines.rs#L330">Stencil Mask Example</a></li>
<li><a href="https://github.com/gfx-rs/wgpu/blob/ad0c8d4f781aaf9907b5f3a90bc7d00a13c51153/wgpu/examples/README.md">WGPU Examples</a></li>
</ul>
<h2 id="maths"><a class="header" href="#maths">Maths</a></h2>
<p>Articles:</p>
<ul>
<li><a href="https://ncase.me/matrix/">Magnificent Matrix</a></li>
</ul>
<p>Examples:</p>
<ul>
<li><a href="https://github.com/h3r2tic/dolly">Dolly Camera</a></li>
</ul>
<h2 id="font-rendering-1"><a class="header" href="#font-rendering-1">Font Rendering</a></h2>
<p>Specs:</p>
<ul>
<li><a href="https://github.com/mapbox/node-fontnik/blob/master/proto/glyphs.proto">MapBox Glyphs Spec</a></li>
</ul>
<p>Articles:</p>
<ul>
<li><a href="https://en.wikipedia.org/wiki/Signed_distance_function">Signed distance function</a></li>
</ul>
<p>Projects:</p>
<ul>
<li><a href="https://github.com/mapbox/node-fontnik/">Mapbox fontnik</a></li>
<li><a href="https://github.com/mapbox/tiny-sdf">TinySDK (JS)</a></li>
<li><a href="https://github.com/redox-os/rusttype">RustType</a></li>
<li><a href="https://docs.rs/sdf_glyph_renderer/latest/sdf_glyph_renderer/">SDF Render</a></li>
<li><a href="https://github.com/stadiamaps/pbf_font_tools">pbf_font_tools</a></li>
<li><a href="https://github.com/Chlumsky/msdfgen">Multi-channel signed distance field generator</a>
<ul>
<li><a href="https://github.com/Chlumsky/msdf-atlas-gen">MSDF font atlas generator </a></li>
</ul>
</li>
</ul>
<h2 id="tessellation"><a class="header" href="#tessellation">Tessellation</a></h2>
<p>Projects:</p>
<ul>
<li><a href="https://github.com/donbright/earcutr">earcutr</a></li>
<li><a href="https://github.com/maplibre/maplibre-gl-js/blob/main/src/data/bucket/line_bucket.ts">Line Tessellation in MapLibre</a></li>
</ul>
<h2 id="specifications"><a class="header" href="#specifications">Specifications</a></h2>
<ul>
<li><a href="https://github.com/mapbox/tilejson-spec">TileJSON</a></li>
</ul>
<h2 id="render-graphs"><a class="header" href="#render-graphs">Render Graphs</a></h2>
<ul>
<li>https://github.com/metal-by-example/simple-instancing/blob/master/MetalSimpleInstancing/Renderer.swift</li>
<li>https://github.com/troughton/Substrate</li>
<li>https://de.slideshare.net/DICEStudio/framegraph-extensible-rendering-architecture-in-frostbite</li>
<li>http://themaister.net/blog/2017/08/15/render-graphs-and-vulkan-a-deep-dive/</li>
<li>http://themaister.net/blog/2017/08/15/render-graphs-and-vulkan-a-deep-dive/</li>
</ul>
<h2 id="animation"><a class="header" href="#animation">Animation</a></h2>
<ul>
<li>https://crates.io/crates/pareen</li>
<li>https://crates.io/crates/keyframe</li>
</ul>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<div style="clear: both"></div>
</nav>
</div>
</div>
<nav class="nav-wide-wrapper" aria-label="Page navigation">
</nav>
</div>
<script type="text/javascript">
window.playground_copyable = true;
</script>
<script src="elasticlunr.min.js" type="text/javascript" charset="utf-8"></script>
<script src="mark.min.js" type="text/javascript" charset="utf-8"></script>
<script src="searcher.js" type="text/javascript" charset="utf-8"></script>
<script src="clipboard.min.js" type="text/javascript" charset="utf-8"></script>
<script src="highlight.js" type="text/javascript" charset="utf-8"></script>
<script src="book.js" type="text/javascript" charset="utf-8"></script>
<!-- Custom JS scripts -->
<script type="text/javascript">
window.addEventListener('load', function() {
window.setTimeout(window.print, 100);
});
</script>
</body>
</html>