Repository: redbadger/crux (language: rust)

Issue:
[iOS] building to device issues - Library not loaded
I'm getting an error when building to the device. The build is successful but on boot, I get this error. 

error message:
```text
dyld[669]: Library not loaded: /Users/romerorickyio/Developer/crux/apps/crux-submodule-app/target/aarch64-apple-ios/debug/deps/libshared.dylib
  Referenced from: <_ID_> /private/var/containers/Bundle/Application/_ID_/iOS.app/iOS
  Reason: tried: '/usr/lib/system/introspection/libshared.dylib' (errno=2, not in dyld cache), '/Users/romerorickyio/Developer/crux/apps/crux-submodule-app/target/aarch64-apple-ios/debug/deps/libshared.dylib' (errno=2), '/private/preboot/Cryptexes/OS/Users/romerorickyio/Developer/crux/apps/crux-submodule-app/target/aarch64-apple-ios/debug/deps/libshared.dylib' (errno=2), '/Users/romerorickyio/Developer/crux/apps/crux-submodule-app/target/aarch64-apple-ios/debug/deps/libshared.dylib' (errno=2), '/usr/local/lib/libshared.dylib' (errno=2), '/usr/lib/libshared.dylib' (errno=2, not in dyld cache)
Library not loaded: /Users/romerorickyio/Developer/crux/apps/crux-submodule-app/target/aarch64-apple-ios/debug/deps/libshared.dylib
  Referenced from: <_ID_> /private/var/containers/Bundle/Application/_ID_/iOS.app/iOS
  Reason: tried: '/usr/lib/system/introspection/libshared.dylib' (errno=2, not in dyld cache), '/Users/romerorickyio/Developer/crux/apps/crux-submodule-app/target/aarch64-apple-ios/debug/deps/libshared.dylib' (errno=2), '/private/preboot/Cryptexes/OS/Users/romerorickyio/Developer/crux/apps/crux-submodule-app/target/aarch64-apple-ios/debug/deps/libshared.dylib' (errno=2), '/Users/romerorickyio/Developer/crux/apps/crux-submodule-app/target/aarch64-apple-ios/debug/deps/libshared.dylib' (errno=2), '/usr/local/lib/libshared.dylib' (errno=2), '/usr/lib/libshared.dylib' (errno=2, not in dyld cache)
dyld config: DYLD_LIBRARY_PATH=/usr/lib/system/introspection DYLD_INSERT_LIBRARIES=/usr/lib/libBacktraceRecording.dylib:/usr/lib/libMainThreadChecker.dylib:/usr/lib/libRPAC.dylib:/Developer/Library/PrivateFrameworks/DTDDISupport.framework/libViewDebuggerSupport.dylib
``` 

I have the `LIBRARY_SEARCH_PATHS` setup.
```
"LIBRARY_SEARCH_PATHS[sdk=iphoneos*][arch=arm64]" = "$(PROJECT_DIR)/../target/aarch64-apple-ios/debug";
```
![Screenshot 2023-03-23 at 2 32 13 PM](https://user-images.githubusercontent.com/13227774/227369099-8a80336d-e99d-40e4-bfac-10076b090321.png)

Both `target/aarch64-apple-ios/debug/deps/libshared.dylib'` & `target/aarch64-apple-ios/debug/libshared.dylib'`files are in the target folder..

![Screenshot 2023-03-23 at 2 32 42 PM](https://user-images.githubusercontent.com/13227774/227369375-74abc3cd-1762-47cf-9642-ac570d58f53a.png)

I don't get an error when building to the sim. 


Discussion / hints:
Hey @romerorickyio, thank you for raising this, and apologies for the slow response. 
For iOS we need to link in a static binary (`libshared.a`), which needs to be compiled for the right target (`aarch64-apple-ios`). There are more details here https://redbadger.github.io/crux/getting_started/ios.html.
Also, I will try to deploy one of the examples to my phone and let you know how I get on, updating docs as I go.
Ahh actually, I'm getting the same issue! I'll investigate.

Fix patch:
diff --git a/docs/src/getting_started/ios.md b/docs/src/getting_started/ios.md
index 98b28076..b2484ee6 100644
--- a/docs/src/getting_started/ios.md
+++ b/docs/src/getting_started/ios.md
@@ -14,17 +14,17 @@ We want to make setting up Xcode to work with Crux really easy. As time progress
 
 The first thing we need to do is create a new iOS app in Xcode.
 
-Let's call the app "iOS" and select "SwiftUI" for the interface and "Swift" for the language. If you choose to create the app in the root folder then your repo's directory structure might now look something like this (some files elided):
+Let's call the app "CounterApp" and select "SwiftUI" for the interface and "Swift" for the language. If you choose to create the app in the root folder of your monorepo, then you might want to rename the folder it creates to "iOS". Your repo's directory structure might now look something like this (some files elided):
 
 ```txt
 .
 ├── Cargo.lock
 ├── Cargo.toml
 ├── iOS
-│  ├── iOS
+│  ├── CounterApp
 │  │  ├── ContentView.swift
-│  │  └── iOSApp.swift
-│  └── iOS.xcodeproj
+│  │  └── CounterAppApp.swift
+│  └── CounterApp.xcodeproj
 │     └── project.pbxproj
 ├── shared
 │  ├── build.rs
@@ -79,7 +79,7 @@ $(PROJECT_DIR)/generated/$(INPUT_FILE_BASE).swift
 $(PROJECT_DIR)/generated/$(INPUT_FILE_BASE)FFI.h
 ```
 
-Now go to "Build Phases" => "Compile Sources", and add `/shared/src/shared.udl` using the "add other" button, selecting "Copy items if needed" and "Create folder references".
+Now go to "Build Phases" => "Compile Sources", and add `/shared/src/shared.udl` using the "add other" button, selecting "Create folder references".
 
 Build the project (cmd-B), which will fail, but the above script should run successfully and the "generated" folder should contain the generated Swift types and C header files:
 
@@ -88,70 +88,43 @@ $ ls iOS/generated
 shared.swift  sharedFFI.h  sharedFFI.modulemap
 ```
 
+### Add the bridging header
+
+In "Build Settings", search for "bridging header", and add `generated/sharedFFI.h`, for any architecture/SDK, i.e. in both Debug and Release.
+If there isn't already a setting for "bridging header" you can add one (and then delete it) as per [this StackOverflow question](https://stackoverflow.com/questions/41787935/how-to-use-objective-c-bridging-header-in-a-swift-project/41788055#41788055)
+
+
 ## Compile our Rust shared library
 
-When we build our iOS app, we also want to build the Rust core as a static library so that it can be linked into the binary that we're going to ship. We do this with Cargo, specifying the relevant target.
+When we build our iOS app, we also want to build the Rust core as a static library so that it can be linked into the binary that we're going to ship.
 
-Create a group called `bin` in your Xcode project and add a shell script (called something like `rust_build.sh`) to it (don't forget to tick the box to ensure it targets our iOS app), with the following contents:
+```admonish
+We will use [`cargo-xcode`](https://crates.io/crates/cargo-xcode) to generate an Xcode project for our shared library, which we can add as a sub-project in Xcode.
 
-```bash
-{{#include ../../../scripts/ios_build.sh}}
+If you don't have this already, you can install it with `cargo install cargo-xcode`.
 ```
 
-Then create a new "Build Phase" of type "Run Script" (called something like `Build Rust library` — you can rename by double-clicking) to call the script something like this:
+Let's generate the sub-project:
 
 ```bash
-cd "$PROJECT_DIR/../shared"
-bash "$PROJECT_DIR/bin/rust_build.sh" shared
+cargo xcode
 ```
 
-Uncheck "Based on dependency analysis".
-
-You can drag this build phase up a bit (e.g. before "Compile Sources"), and test that it compiles the Rust library when you build your project.
-
-## Link the Rust shared library into our iOS binary
-
-Now that we have successfully compiled the share Rust library, we need to link it into the iOS binary. We need to tell Xcode where to find the relevant static library based on which build configuration we have built for (`Debug` or `Release`).
-
-This is a little convoluted, but this may be the easiest way to do this:
+This generates an Xcode project for each crate in the workspace, but we're only interested in the one it creates in the `shared` directory. Don't open this generated project yet.
 
-1.  In "Build Settings", search for "library search paths" and add a dummy string "XXXX" for debug and release (this will update the project file so you can search in it for `XXXX` in the next step).
+Using Finder, drag the `shared/shared.xcodeproj` folder under the Xcode project root.
 
-1.  Open the project configuration file (`*.pbxproj`) in a code editor and search for "XXXX" (you should find 2 occurrences), and replace it with the following:
+Then, in "Build Phases", add the static library to the "Link Binary with Libraries" section (you should be able to navigate to it under `Workspace -> shared -> libshared_static.a`)
 
-    1.  In the "Debug" section
-
-    ```txt
-    "LIBRARY_SEARCH_PATHS[sdk=iphoneos*][arch=arm64]" = "$(PROJECT_DIR)/../target/aarch64-apple-ios/debug";
-    "LIBRARY_SEARCH_PATHS[sdk=iphonesimulator*][arch=arm64]" = "$(PROJECT_DIR)/../target/aarch64-apple-ios-sim/debug";
-    "LIBRARY_SEARCH_PATHS[sdk=iphonesimulator*][arch=x86_64]" = "$(PROJECT_DIR)/../target/x86_64-apple-ios/debug";
-    ```
-
-    1.  In the "Release"" section
-
-    ```txt
-    "LIBRARY_SEARCH_PATHS[sdk=iphoneos*][arch=arm64]" = "$(PROJECT_DIR)/../target/aarch64-apple-ios/release";
-    "LIBRARY_SEARCH_PATHS[sdk=iphonesimulator*][arch=arm64]" = "$(PROJECT_DIR)/../target/aarch64-apple-ios-sim/release";
-    "LIBRARY_SEARCH_PATHS[sdk=iphonesimulator*][arch=x86_64]" = "$(PROJECT_DIR)/../target/x86_64-apple-ios/release";
-    ```
+## Add the Shared Types
 
-1.  In "Build Phases", add `/target/debug/libshared.a` to the "Link Binary with Libraries" section (this is the wrong target, but the library search paths, which we set above, should resolve this.
-    For more info see the blog post linked above ([this post](https://blog.mozilla.org/data/2022/01/31/this-week-in-glean-building-and-deploying-a-rust-library-on-ios/)))
+In `File -> Add Files to "CounterApp"`, add `/shared_types/generated/swift/shared_types.swift`.
 
 ## Add the `Serde` package
 
 In order to serialize data across the "bridge" we need to add the [`Serde` package](https://github.com/starcoin-sdk/Serde.swift) to our project. You can do this with `File -> Add Packages` and search for "https://github.com/starcoin-sdk/Serde.swift".
 
-## Add the bridging header
-
-In "Build Settings", search for "bridging header", and add `generated/sharedFFI.h`, for any architecture/SDK, i.e. in both Debug and Release.
-If there isn't already a setting for "bridging header" you can add one (and then delete it) as per [this StackOverflow question](https://stackoverflow.com/questions/41787935/how-to-use-objective-c-bridging-header-in-a-swift-project/41788055#41788055)
-
-## Add the Shared Types
-
-In `File -> Add Files to iOS`, add `/shared_types/generated/swift/shared_types.swift`.
-
-## Create some UI and run in the Simulator
+## Create some UI and run in the Simulator, or on an iPhone
 
 ### Hello World counter example
 
@@ -267,7 +240,7 @@ struct iOSApp: App {
 ```
 
 ```admonish success
-You should then be able to run the app in the simulator, and it should look like this:
+You should then be able to run the app in the simulator or on an iPhone, and it should look like this:
 
 <p align="center"><img alt="hello world app" src="./hello_world_ios.webp"  width="300"></p>
 ```
diff --git a/examples/cat_facts/iOS/.gitignore b/examples/cat_facts/iOS/.gitignore
deleted file mode 100644
index c5451120..00000000
--- a/examples/cat_facts/iOS/.gitignore
+++ /dev/null
@@ -1,1 +0,0 @@
-xcuserdata/
diff --git a/examples/cat_facts/iOS/CatFacts.xcodeproj/project.pbxproj b/examples/cat_facts/iOS/CatFacts.xcodeproj/project.pbxproj
new file mode 100644
index 00000000..e69979fd
--- /dev/null
+++ b/examples/cat_facts/iOS/CatFacts.xcodeproj/project.pbxproj
@@ -0,0 +1,476 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 56;
+	objects = {
+
+/* Begin PBXBuildFile section */
+		CC0F616E29D59F62008DAC80 /* libshared_static.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CC0F616829D59F4B008DAC80 /* libshared_static.a */; };
+		CC0F617129D59F95008DAC80 /* Serde in Frameworks */ = {isa = PBXBuildFile; productRef = CC0F617029D59F95008DAC80 /* Serde */; };
+		CC0F617429D5A0AB008DAC80 /* shared.udl in Sources */ = {isa = PBXBuildFile; fileRef = CC0F617329D5A0AB008DAC80 /* shared.udl */; };
+		CC0F617529D5A1BA008DAC80 /* shared_types.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC0F617229D59FC6008DAC80 /* shared_types.swift */; };
+		CC67B94329D59EDC008C6144 /* CatFactsApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC67B94229D59EDC008C6144 /* CatFactsApp.swift */; };
+		CC67B94529D59EDC008C6144 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC67B94429D59EDC008C6144 /* ContentView.swift */; };
+		CC67B94729D59EDD008C6144 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CC67B94629D59EDD008C6144 /* Assets.xcassets */; };
+		CC67B94A29D59EDD008C6144 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CC67B94929D59EDD008C6144 /* Preview Assets.xcassets */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXBuildRule section */
+		CC0F616029D59F10008DAC80 /* PBXBuildRule */ = {
+			isa = PBXBuildRule;
+			compilerSpec = com.apple.compilers.proxy.script;
+			filePatterns = "*.udl";
+			fileType = pattern.proxy;
+			inputFiles = (
+			);
+			isEditable = 1;
+			outputFiles = (
+				"$(PROJECT_DIR)/generated/$(INPUT_FILE_BASE).swift",
+				"$(PROJECT_DIR)/generated/$(INPUT_FILE_BASE)FFI.h",
+			);
+			runOncePerArchitecture = 0;
+			script = "# Skip during indexing phase in XCode 13+\nif [ $ACTION == \"indexbuild\" ]; then\n   echo \"Not building *.udl files during indexing.\"\n   exit 0\nfi\n\n# Skip for preview builds\nif [ \"${ENABLE_PREVIEWS}\" = \"YES\" ]; then\n   echo \"Not building *.udl files during preview builds.\"\n   exit 0\nfi\n\n# note, for now, run a cargo build manually to ensure the binary exists for this step\ncd \"$INPUT_FILE_DIR\"/.. && \"$PROJECT_DIR/../target/debug/uniffi-bindgen\" generate src/\"$INPUT_FILE_NAME\" --language swift --out-dir \"$PROJECT_DIR/generated\"\n";
+		};
+/* End PBXBuildRule section */
+
+/* Begin PBXContainerItemProxy section */
+		CC0F616729D59F4B008DAC80 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = CC0F616129D59F4B008DAC80 /* shared.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = CA60431E8A50FB09138082B7;
+			remoteInfo = "shared-staticlib";
+		};
+		CC0F616929D59F4B008DAC80 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = CC0F616129D59F4B008DAC80 /* shared.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = CA6027CBEBE510F7F7FCAC5B;
+			remoteInfo = "shared-cdylib";
+		};
+		CC0F616B29D59F4B008DAC80 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = CC0F616129D59F4B008DAC80 /* shared.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = CA605677FFD78109328FB0D5;
+			remoteInfo = "uniffi-bindgen-bin";
+		};
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXFileReference section */
+		CC0F616129D59F4B008DAC80 /* shared.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = shared.xcodeproj; path = ../shared/shared.xcodeproj; sourceTree = "<group>"; };
+		CC0F617229D59FC6008DAC80 /* shared_types.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = shared_types.swift; path = ../shared_types/generated/swift/shared_types.swift; sourceTree = "<group>"; };
+		CC0F617329D5A0AB008DAC80 /* shared.udl */ = {isa = PBXFileReference; lastKnownFileType = text; name = shared.udl; path = ../shared/src/shared.udl; sourceTree = "<group>"; };
+		CC67B93F29D59EDC008C6144 /* CatFacts.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CatFacts.app; sourceTree = BUILT_PRODUCTS_DIR; };
+		CC67B94229D59EDC008C6144 /* CatFactsApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CatFactsApp.swift; sourceTree = "<group>"; };
+		CC67B94429D59EDC008C6144 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
+		CC67B94629D59EDD008C6144 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
+		CC67B94929D59EDD008C6144 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		CC67B93C29D59EDC008C6144 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				CC0F617129D59F95008DAC80 /* Serde in Frameworks */,
+				CC0F616E29D59F62008DAC80 /* libshared_static.a in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		CC0F616229D59F4B008DAC80 /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				CC0F616829D59F4B008DAC80 /* libshared_static.a */,
+				CC0F616A29D59F4B008DAC80 /* shared.dylib */,
+				CC0F616C29D59F4B008DAC80 /* uniffi-bindgen */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		CC0F616D29D59F62008DAC80 /* Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+			);
+			name = Frameworks;
+			sourceTree = "<group>";
+		};
+		CC67B93629D59EDC008C6144 = {
+			isa = PBXGroup;
+			children = (
+				CC0F617329D5A0AB008DAC80 /* shared.udl */,
+				CC0F617229D59FC6008DAC80 /* shared_types.swift */,
+				CC0F616129D59F4B008DAC80 /* shared.xcodeproj */,
+				CC67B94129D59EDC008C6144 /* CatFacts */,
+				CC67B94029D59EDC008C6144 /* Products */,
+				CC0F616D29D59F62008DAC80 /* Frameworks */,
+			);
+			sourceTree = "<group>";
+		};
+		CC67B94029D59EDC008C6144 /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				CC67B93F29D59EDC008C6144 /* CatFacts.app */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		CC67B94129D59EDC008C6144 /* CatFacts */ = {
+			isa = PBXGroup;
+			children = (
+				CC67B94229D59EDC008C6144 /* CatFactsApp.swift */,
+				CC67B94429D59EDC008C6144 /* ContentView.swift */,
+				CC67B94629D59EDD008C6144 /* Assets.xcassets */,
+				CC67B94829D59EDD008C6144 /* Preview Content */,
+			);
+			path = CatFacts;
+			sourceTree = "<group>";
+		};
+		CC67B94829D59EDD008C6144 /* Preview Content */ = {
+			isa = PBXGroup;
+			children = (
+				CC67B94929D59EDD008C6144 /* Preview Assets.xcassets */,
+			);
+			path = "Preview Content";
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+		CC67B93E29D59EDC008C6144 /* CatFacts */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = CC67B94D29D59EDD008C6144 /* Build configuration list for PBXNativeTarget "CatFacts" */;
+			buildPhases = (
+				CC67B93B29D59EDC008C6144 /* Sources */,
+				CC67B93C29D59EDC008C6144 /* Frameworks */,
+				CC67B93D29D59EDC008C6144 /* Resources */,
+			);
+			buildRules = (
+				CC0F616029D59F10008DAC80 /* PBXBuildRule */,
+			);
+			dependencies = (
+			);
+			name = CatFacts;
+			packageProductDependencies = (
+				CC0F617029D59F95008DAC80 /* Serde */,
+			);
+			productName = CatFacts;
+			productReference = CC67B93F29D59EDC008C6144 /* CatFacts.app */;
+			productType = "com.apple.product-type.application";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		CC67B93729D59EDC008C6144 /* Project object */ = {
+			isa = PBXProject;
+			attributes = {
+				BuildIndependentTargetsInParallel = 1;
+				LastSwiftUpdateCheck = 1420;
+				LastUpgradeCheck = 1420;
+				TargetAttributes = {
+					CC67B93E29D59EDC008C6144 = {
+						CreatedOnToolsVersion = 14.2;
+					};
+				};
+			};
+			buildConfigurationList = CC67B93A29D59EDC008C6144 /* Build configuration list for PBXProject "CatFacts" */;
+			compatibilityVersion = "Xcode 14.0";
+			developmentRegion = en;
+			hasScannedForEncodings = 0;
+			knownRegions = (
+				en,
+				Base,
+			);
+			mainGroup = CC67B93629D59EDC008C6144;
+			packageReferences = (
+				CC0F616F29D59F95008DAC80 /* XCRemoteSwiftPackageReference "Serde" */,
+			);
+			productRefGroup = CC67B94029D59EDC008C6144 /* Products */;
+			projectDirPath = "";
+			projectReferences = (
+				{
+					ProductGroup = CC0F616229D59F4B008DAC80 /* Products */;
+					ProjectRef = CC0F616129D59F4B008DAC80 /* shared.xcodeproj */;
+				},
+			);
+			projectRoot = "";
+			targets = (
+				CC67B93E29D59EDC008C6144 /* CatFacts */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXReferenceProxy section */
+		CC0F616829D59F4B008DAC80 /* libshared_static.a */ = {
+			isa = PBXReferenceProxy;
+			fileType = archive.ar;
+			path = libshared_static.a;
+			remoteRef = CC0F616729D59F4B008DAC80 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		CC0F616A29D59F4B008DAC80 /* shared.dylib */ = {
+			isa = PBXReferenceProxy;
+			fileType = "compiled.mach-o.dylib";
+			path = shared.dylib;
+			remoteRef = CC0F616929D59F4B008DAC80 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		CC0F616C29D59F4B008DAC80 /* uniffi-bindgen */ = {
+			isa = PBXReferenceProxy;
+			fileType = "compiled.mach-o.executable";
+			path = "uniffi-bindgen";
+			remoteRef = CC0F616B29D59F4B008DAC80 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+/* End PBXReferenceProxy section */
+
+/* Begin PBXResourcesBuildPhase section */
+		CC67B93D29D59EDC008C6144 /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				CC67B94A29D59EDD008C6144 /* Preview Assets.xcassets in Resources */,
+				CC67B94729D59EDD008C6144 /* Assets.xcassets in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+		CC67B93B29D59EDC008C6144 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				CC0F617529D5A1BA008DAC80 /* shared_types.swift in Sources */,
+				CC0F617429D5A0AB008DAC80 /* shared.udl in Sources */,
+				CC67B94529D59EDC008C6144 /* ContentView.swift in Sources */,
+				CC67B94329D59EDC008C6144 /* CatFactsApp.swift in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+		CC67B94B29D59EDD008C6144 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_NONNULL = YES;
+				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_ENABLE_OBJC_WEAK = YES;
+				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_COMMA = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+				CLANG_WARN_STRICT_PROTOTYPES = YES;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				COPY_PHASE_STRIP = NO;
+				DEBUG_INFORMATION_FORMAT = dwarf;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				ENABLE_TESTABILITY = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu11;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"DEBUG=1",
+					"$(inherited)",
+				);
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				IPHONEOS_DEPLOYMENT_TARGET = 16.2;
+				MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
+				MTL_FAST_MATH = YES;
+				ONLY_ACTIVE_ARCH = YES;
+				SDKROOT = iphoneos;
+				SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
+				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+			};
+			name = Debug;
+		};
+		CC67B94C29D59EDD008C6144 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_NONNULL = YES;
+				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_ENABLE_OBJC_WEAK = YES;
+				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_COMMA = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+				CLANG_WARN_STRICT_PROTOTYPES = YES;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				COPY_PHASE_STRIP = NO;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				ENABLE_NS_ASSERTIONS = NO;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu11;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				IPHONEOS_DEPLOYMENT_TARGET = 16.2;
+				MTL_ENABLE_DEBUG_INFO = NO;
+				MTL_FAST_MATH = YES;
+				SDKROOT = iphoneos;
+				SWIFT_COMPILATION_MODE = wholemodule;
+				SWIFT_OPTIMIZATION_LEVEL = "-O";
+				VALIDATE_PRODUCT = YES;
+			};
+			name = Release;
+		};
+		CC67B94E29D59EDD008C6144 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+				ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
+				CODE_SIGN_STYLE = Automatic;
+				CURRENT_PROJECT_VERSION = 1;
+				DEVELOPMENT_ASSET_PATHS = "\"CatFacts/Preview Content\"";
+				DEVELOPMENT_TEAM = E5DS2C9C62;
+				ENABLE_PREVIEWS = YES;
+				GENERATE_INFOPLIST_FILE = YES;
+				INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
+				INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
+				INFOPLIST_KEY_UILaunchScreen_Generation = YES;
+				INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
+				INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
+				LD_RUNPATH_SEARCH_PATHS = (
+					"$(inherited)",
+					"@executable_path/Frameworks",
+				);
+				MARKETING_VERSION = 1.0;
+				PRODUCT_BUNDLE_IDENTIFIER = com.redbadger.crux.CatFacts;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				SWIFT_EMIT_LOC_STRINGS = YES;
+				SWIFT_OBJC_BRIDGING_HEADER = generated/sharedFFI.h;
+				SWIFT_VERSION = 5.0;
+				TARGETED_DEVICE_FAMILY = "1,2";
+			};
+			name = Debug;
+		};
+		CC67B94F29D59EDD008C6144 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+				ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
+				CODE_SIGN_STYLE = Automatic;
+				CURRENT_PROJECT_VERSION = 1;
+				DEVELOPMENT_ASSET_PATHS = "\"CatFacts/Preview Content\"";
+				DEVELOPMENT_TEAM = E5DS2C9C62;
+				ENABLE_PREVIEWS = YES;
+				GENERATE_INFOPLIST_FILE = YES;
+				INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
+				INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
+				INFOPLIST_KEY_UILaunchScreen_Generation = YES;
+				INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
+				INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
+				LD_RUNPATH_SEARCH_PATHS = (
+					"$(inherited)",
+					"@executable_path/Frameworks",
+				);
+				MARKETING_VERSION = 1.0;
+				PRODUCT_BUNDLE_IDENTIFIER = com.redbadger.crux.CatFacts;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				SWIFT_EMIT_LOC_STRINGS = YES;
+				SWIFT_OBJC_BRIDGING_HEADER = generated/sharedFFI.h;
+				SWIFT_VERSION = 5.0;
+				TARGETED_DEVICE_FAMILY = "1,2";
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		CC67B93A29D59EDC008C6144 /* Build configuration list for PBXProject "CatFacts" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				CC67B94B29D59EDD008C6144 /* Debug */,
+				CC67B94C29D59EDD008C6144 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		CC67B94D29D59EDD008C6144 /* Build configuration list for PBXNativeTarget "CatFacts" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				CC67B94E29D59EDD008C6144 /* Debug */,
+				CC67B94F29D59EDD008C6144 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+
+/* Begin XCRemoteSwiftPackageReference section */
+		CC0F616F29D59F95008DAC80 /* XCRemoteSwiftPackageReference "Serde" */ = {
+			isa = XCRemoteSwiftPackageReference;
+			repositoryURL = "https://github.com/starcoin-sdk/Serde.swift";
+			requirement = {
+				branch = main;
+				kind = branch;
+			};
+		};
+/* End XCRemoteSwiftPackageReference section */
+
+/* Begin XCSwiftPackageProductDependency section */
+		CC0F617029D59F95008DAC80 /* Serde */ = {
+			isa = XCSwiftPackageProductDependency;
+			package = CC0F616F29D59F95008DAC80 /* XCRemoteSwiftPackageReference "Serde" */;
+			productName = Serde;
+		};
+/* End XCSwiftPackageProductDependency section */
+	};
+	rootObject = CC67B93729D59EDC008C6144 /* Project object */;
+}
diff --git a/examples/cat_facts/iOS/iOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/examples/cat_facts/iOS/CatFacts.xcodeproj/project.xcworkspace/contents.xcworkspacedata
similarity index 100%
rename from examples/cat_facts/iOS/iOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata
rename to examples/cat_facts/iOS/CatFacts.xcodeproj/project.xcworkspace/contents.xcworkspacedata
diff --git a/examples/cat_facts/iOS/iOS.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/examples/cat_facts/iOS/CatFacts.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
similarity index 100%
rename from examples/cat_facts/iOS/iOS.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
rename to examples/cat_facts/iOS/CatFacts.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
diff --git a/examples/cat_facts/iOS/iOS.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/examples/cat_facts/iOS/CatFacts.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
similarity index 79%
rename from examples/cat_facts/iOS/iOS.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
rename to examples/cat_facts/iOS/CatFacts.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
index 4012fea2..e1a19c8f 100644
--- a/examples/cat_facts/iOS/iOS.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
+++ b/examples/cat_facts/iOS/CatFacts.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
@@ -6,7 +6,7 @@
       "location" : "https://github.com/starcoin-sdk/Serde.swift",
       "state" : {
         "branch" : "main",
-        "revision" : "f4fc4a94200dc8e4cecef25587b4090346c67e1f"
+        "revision" : "cfb9ceac93f175b5600946032d11c68545ce3d62"
       }
     }
   ],
diff --git a/examples/cat_facts/iOS/CatFacts.xcodeproj/xcuserdata/stuartharris.xcuserdatad/xcschemes/xcschememanagement.plist b/examples/cat_facts/iOS/CatFacts.xcodeproj/xcuserdata/stuartharris.xcuserdatad/xcschemes/xcschememanagement.plist
new file mode 100644
index 00000000..306e48c9
--- /dev/null
+++ b/examples/cat_facts/iOS/CatFacts.xcodeproj/xcuserdata/stuartharris.xcuserdatad/xcschemes/xcschememanagement.plist
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>SchemeUserState</key>
+	<dict>
+		<key>CatFacts.xcscheme_^#shared#^_</key>
+		<dict>
+			<key>orderHint</key>
+			<integer>1</integer>
+		</dict>
+	</dict>
+</dict>
+</plist>
diff --git a/examples/cat_facts/iOS/iOS/Assets.xcassets/AccentColor.colorset/Contents.json b/examples/cat_facts/iOS/CatFacts/Assets.xcassets/AccentColor.colorset/Contents.json
similarity index 100%
rename from examples/cat_facts/iOS/iOS/Assets.xcassets/AccentColor.colorset/Contents.json
rename to examples/cat_facts/iOS/CatFacts/Assets.xcassets/AccentColor.colorset/Contents.json
diff --git a/examples/cat_facts/iOS/iOS/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/cat_facts/iOS/CatFacts/Assets.xcassets/AppIcon.appiconset/Contents.json
similarity index 100%
rename from examples/cat_facts/iOS/iOS/Assets.xcassets/AppIcon.appiconset/Contents.json
rename to examples/cat_facts/iOS/CatFacts/Assets.xcassets/AppIcon.appiconset/Contents.json
diff --git a/examples/cat_facts/iOS/iOS/Assets.xcassets/Contents.json b/examples/cat_facts/iOS/CatFacts/Assets.xcassets/Contents.json
similarity index 100%
rename from examples/cat_facts/iOS/iOS/Assets.xcassets/Contents.json
rename to examples/cat_facts/iOS/CatFacts/Assets.xcassets/Contents.json
diff --git a/examples/cat_facts/iOS/iOS/iOSApp.swift b/examples/cat_facts/iOS/CatFacts/CatFactsApp.swift
similarity index 100%
rename from examples/cat_facts/iOS/iOS/iOSApp.swift
rename to examples/cat_facts/iOS/CatFacts/CatFactsApp.swift
diff --git a/examples/cat_facts/iOS/iOS/ContentView.swift b/examples/cat_facts/iOS/CatFacts/ContentView.swift
similarity index 92%
rename from examples/cat_facts/iOS/iOS/ContentView.swift
rename to examples/cat_facts/iOS/CatFacts/ContentView.swift
index 91917005..e55f7f2b 100644
--- a/examples/cat_facts/iOS/iOS/ContentView.swift
+++ b/examples/cat_facts/iOS/CatFacts/ContentView.swift
@@ -38,9 +38,9 @@ class Model: ObservableObject {
 
         switch msg {
         case let .event(m):
-            reqs = try! [Request].bcsDeserialize(input: iOS.processEvent(try! m.bcsSerialize()))
+            reqs = try! [Request].bcsDeserialize(input: CatFacts.processEvent(try! m.bcsSerialize()))
         case let .response(uuid, outcome):
-            reqs = try! [Request].bcsDeserialize(input: iOS.handleResponse(uuid, { switch outcome {
+            reqs = try! [Request].bcsDeserialize(input: CatFacts.handleResponse(uuid, { switch outcome {
             case let .platform(x):
                 return try! x.bcsSerialize()
             case let .time(x):
@@ -54,11 +54,11 @@ class Model: ObservableObject {
 
         for req in reqs {
             switch req.effect {
-            case .render(_): view = try! ViewModel.bcsDeserialize(input: iOS.view())
+            case .render: view = try! ViewModel.bcsDeserialize(input: CatFacts.view())
             case let .http(r): httpGet(uuid: req.uuid, url: r.url)
-            case .time(_):
+            case .time:
                 update(msg: .response(req.uuid, .time(TimeResponse(value: Date().ISO8601Format()))))
-            case .platform(_):
+            case .platform:
                 update(msg: .response(req.uuid, .platform(PlatformResponse(value: get_platform()))))
             case .keyValue(.read):
                 update(msg: .response(req.uuid, .key_value(KeyValueOutput.read(.none))))
diff --git a/examples/cat_facts/iOS/iOS/Preview Content/Preview Assets.xcassets/Contents.json b/examples/cat_facts/iOS/CatFacts/Preview Content/Preview Assets.xcassets/Contents.json
similarity index 100%
rename from examples/cat_facts/iOS/iOS/Preview Content/Preview Assets.xcassets/Contents.json
rename to examples/cat_facts/iOS/CatFacts/Preview Content/Preview Assets.xcassets/Contents.json
diff --git a/examples/cat_facts/iOS/bin/compile-library.sh b/examples/cat_facts/iOS/bin/compile-library.sh
deleted file mode 100644
index c4b73fef..00000000
--- a/examples/cat_facts/iOS/bin/compile-library.sh
+++ /dev/null
@@ -1,52 +0,0 @@
-#!/usr/bin/env bash
-
-if [ "$#" -ne 1 ]; then
-  echo "Usage (note: only call inside XCode!):"
-  echo "$0 <FFI_TARGET>"
-  exit 1
-fi
-
-# what to pass to cargo build -p, e.g. your_lib_ffi
-FFI_TARGET=$1
-
-set -euvx
-
-RELFLAG=
-if [[ "$CONFIGURATION" != "Debug" ]]; then
-  RELFLAG=--release
-fi
-
-IS_SIMULATOR=0
-if [ "${LLVM_TARGET_TRIPLE_SUFFIX-}" = "-simulator" ]; then
-  IS_SIMULATOR=1
-fi
-
-export PATH="$PATH:$HOME/.cargo/bin"
-export LIBRARY_PATH
-
-for arch in $ARCHS; do
-  case "$arch" in
-  x86_64)
-    if [ $IS_SIMULATOR -eq 0 ]; then
-      echo "Building for x86_64, but not a simulator build. What's going on?" >&2
-      exit 2
-    fi
-
-    # Intel iOS simulator
-    export CFLAGS_x86_64_apple_ios="-target x86_64-apple-ios"
-    LIBRARY_PATH="${LIBRARY_PATH-}:$(xcrun --sdk iphonesimulator --show-sdk-path)/usr/lib"
-    cargo build -p "$FFI_TARGET" --lib $RELFLAG --target x86_64-apple-ios
-    ;;
-
-  arm64)
-    if [ $IS_SIMULATOR -eq 0 ]; then
-      # Hardware iOS targets
-      LIBRARY_PATH="${LIBRARY_PATH-}:$(xcrun --sdk iphoneos --show-sdk-path)/usr/lib"
-      cargo build -p "$FFI_TARGET" --lib $RELFLAG --target aarch64-apple-ios
-    else
-      LIBRARY_PATH="${LIBRARY_PATH-}:$(xcrun --sdk iphonesimulator --show-sdk-path)/usr/lib"
-      cargo build -p "$FFI_TARGET" --lib $RELFLAG --target aarch64-apple-ios-sim
-    fi
-    ;;
-  esac
-done
diff --git a/examples/cat_facts/iOS/iOS.xcodeproj/project.pbxproj b/examples/cat_facts/iOS/iOS.xcodeproj/project.pbxproj
deleted file mode 100644
index 40b8ac58..00000000
--- a/examples/cat_facts/iOS/iOS.xcodeproj/project.pbxproj
+++ /dev/null
@@ -1,696 +0,0 @@
-// !$*UTF8*$!
-{
-	archiveVersion = 1;
-	classes = {
-	};
-	objectVersion = 56;
-	objects = {
-
-/* Begin PBXBuildFile section */
-		CC02FE2028F2EA83003DA87D /* sharedFFI.h in Headers */ = {isa = PBXBuildFile; fileRef = CC02FE1F28F2EA83003DA87D /* sharedFFI.h */; settings = {ATTRIBUTES = (Public, ); }; };
-		CC2172C0291EA71100BCD13B /* shared_types.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC2172BF291EA71100BCD13B /* shared_types.swift */; };
-		CC49E0212919260600F5D4C0 /* libshared.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CC49E0202919260600F5D4C0 /* libshared.a */; };
-		CCA5CCE329191A5900325531 /* shared.udl in Sources */ = {isa = PBXBuildFile; fileRef = CCA5CCE229191A5900325531 /* shared.udl */; };
-		CCB21E1A28F199700074368C /* iOSApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCB21E1928F199700074368C /* iOSApp.swift */; };
-		CCB21E1C28F199700074368C /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCB21E1B28F199700074368C /* ContentView.swift */; };
-		CCB21E1E28F199710074368C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CCB21E1D28F199710074368C /* Assets.xcassets */; };
-		CCB21E2128F199710074368C /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CCB21E2028F199710074368C /* Preview Assets.xcassets */; };
-		CCB21E2B28F199710074368C /* iOSTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCB21E2A28F199710074368C /* iOSTests.swift */; };
-		CCB21E3528F199710074368C /* iOSUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCB21E3428F199710074368C /* iOSUITests.swift */; };
-		CCB21E3728F199710074368C /* iOSUITestsLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCB21E3628F199710074368C /* iOSUITestsLaunchTests.swift */; };
-		CCB436432912CD7E0059B3A3 /* Serde in Frameworks */ = {isa = PBXBuildFile; productRef = CCB436422912CD7E0059B3A3 /* Serde */; };
-/* End PBXBuildFile section */
-
-/* Begin PBXBuildRule section */
-		CCB21E4528F19DCD0074368C /* PBXBuildRule */ = {
-			isa = PBXBuildRule;
-			compilerSpec = com.apple.compilers.proxy.script;
-			filePatterns = "*.udl";
-			fileType = pattern.proxy;
-			inputFiles = (
-			);
-			isEditable = 1;
-			outputFiles = (
-				"$(PROJECT_DIR)/generated/$(INPUT_FILE_BASE).swift",
-				"$(PROJECT_DIR)/generated/$(INPUT_FILE_BASE)FFI.h",
-			);
-			runOncePerArchitecture = 0;
-			script = "# Skip during indexing phase in XCode 13+\nif [ $ACTION == \"indexbuild\" ]; then\n   echo \"Not building *.udl files during indexing.\"\n   exit 0\nfi\n\n# Skip for preview builds\nif [ \"${ENABLE_PREVIEWS}\" = \"YES\" ]; then\n   echo \"Not building *.udl files during preview builds.\"\n   exit 0\nfi\n\ncd \"$INPUT_FILE_DIR\"/.. && \"$PROJECT_DIR/../target/debug/uniffi-bindgen\" generate src/\"$INPUT_FILE_NAME\" --language swift --out-dir \"$PROJECT_DIR/generated\"\n";
-		};
-/* End PBXBuildRule section */
-
-/* Begin PBXContainerItemProxy section */
-		CCB21E2728F199710074368C /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = CCB21E0E28F199700074368C /* Project object */;
-			proxyType = 1;
-			remoteGlobalIDString = CCB21E1528F199700074368C;
-			remoteInfo = iOS;
-		};
-		CCB21E3128F199710074368C /* PBXContainerItemProxy */ = {
-			isa = PBXContainerItemProxy;
-			containerPortal = CCB21E0E28F199700074368C /* Project object */;
-			proxyType = 1;
-			remoteGlobalIDString = CCB21E1528F199700074368C;
-			remoteInfo = iOS;
-		};
-/* End PBXContainerItemProxy section */
-
-/* Begin PBXFileReference section */
-		CC02FE1F28F2EA83003DA87D /* sharedFFI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = sharedFFI.h; path = generated/sharedFFI.h; sourceTree = "<group>"; };
-		CC2172BF291EA71100BCD13B /* shared_types.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = shared_types.swift; path = ../shared_types/generated/swift/shared_types.swift; sourceTree = "<group>"; };
-		CC49E0202919260600F5D4C0 /* libshared.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libshared.a; path = ../target/debug/libshared.a; sourceTree = "<group>"; };
-		CCA5CCE229191A5900325531 /* shared.udl */ = {isa = PBXFileReference; lastKnownFileType = text; name = shared.udl; path = ../shared/src/shared.udl; sourceTree = "<group>"; };
-		CCB21E1628F199700074368C /* iOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = iOS.app; sourceTree = BUILT_PRODUCTS_DIR; };
-		CCB21E1928F199700074368C /* iOSApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = iOSApp.swift; sourceTree = "<group>"; };
-		CCB21E1B28F199700074368C /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
-		CCB21E1D28F199710074368C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
-		CCB21E2028F199710074368C /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
-		CCB21E2628F199710074368C /* iOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = iOSTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
-		CCB21E2A28F199710074368C /* iOSTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = iOSTests.swift; sourceTree = "<group>"; };
-		CCB21E3028F199710074368C /* iOSUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = iOSUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
-		CCB21E3428F199710074368C /* iOSUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = iOSUITests.swift; sourceTree = "<group>"; };
-		CCB21E3628F199710074368C /* iOSUITestsLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = iOSUITestsLaunchTests.swift; sourceTree = "<group>"; };
-/* End PBXFileReference section */
-
-/* Begin PBXFrameworksBuildPhase section */
-		CCB21E1328F199700074368C /* Frameworks */ = {
-			isa = PBXFrameworksBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				CC49E0212919260600F5D4C0 /* libshared.a in Frameworks */,
-				CCB436432912CD7E0059B3A3 /* Serde in Frameworks */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		CCB21E2328F199710074368C /* Frameworks */ = {
-			isa = PBXFrameworksBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		CCB21E2D28F199710074368C /* Frameworks */ = {
-			isa = PBXFrameworksBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-/* End PBXFrameworksBuildPhase section */
-
-/* Begin PBXGroup section */
-		CCB21E0D28F199700074368C = {
-			isa = PBXGroup;
-			children = (
-				CC2172BF291EA71100BCD13B /* shared_types.swift */,
-				CCA5CCE229191A5900325531 /* shared.udl */,
-				CC02FE1F28F2EA83003DA87D /* sharedFFI.h */,
-				CCB21E1828F199700074368C /* iOS */,
-				CCB21E2928F199710074368C /* iOSTests */,
-				CCB21E3328F199710074368C /* iOSUITests */,
-				CCB21E1728F199700074368C /* Products */,
-				CCFA7BDC28F5ACC500AEA3EA /* Frameworks */,
-			);
-			sourceTree = "<group>";
-		};
-		CCB21E1728F199700074368C /* Products */ = {
-			isa = PBXGroup;
-			children = (
-				CCB21E1628F199700074368C /* iOS.app */,
-				CCB21E2628F199710074368C /* iOSTests.xctest */,
-				CCB21E3028F199710074368C /* iOSUITests.xctest */,
-			);
-			name = Products;
-			sourceTree = "<group>";
-		};
-		CCB21E1828F199700074368C /* iOS */ = {
-			isa = PBXGroup;
-			children = (
-				CCB21E1928F199700074368C /* iOSApp.swift */,
-				CCB21E1B28F199700074368C /* ContentView.swift */,
-				CCB21E1D28F199710074368C /* Assets.xcassets */,
-				CCB21E1F28F199710074368C /* Preview Content */,
-			);
-			path = iOS;
-			sourceTree = "<group>";
-		};
-		CCB21E1F28F199710074368C /* Preview Content */ = {
-			isa = PBXGroup;
-			children = (
-				CCB21E2028F199710074368C /* Preview Assets.xcassets */,
-			);
-			path = "Preview Content";
-			sourceTree = "<group>";
-		};
-		CCB21E2928F199710074368C /* iOSTests */ = {
-			isa = PBXGroup;
-			children = (
-				CCB21E2A28F199710074368C /* iOSTests.swift */,
-			);
-			path = iOSTests;
-			sourceTree = "<group>";
-		};
-		CCB21E3328F199710074368C /* iOSUITests */ = {
-			isa = PBXGroup;
-			children = (
-				CCB21E3428F199710074368C /* iOSUITests.swift */,
-				CCB21E3628F199710074368C /* iOSUITestsLaunchTests.swift */,
-			);
-			path = iOSUITests;
-			sourceTree = "<group>";
-		};
-		CCFA7BDC28F5ACC500AEA3EA /* Frameworks */ = {
-			isa = PBXGroup;
-			children = (
-				CC49E0202919260600F5D4C0 /* libshared.a */,
-			);
-			name = Frameworks;
-			sourceTree = "<group>";
-		};
-/* End PBXGroup section */
-
-/* Begin PBXHeadersBuildPhase section */
-		CC02FE1E28F2EA5C003DA87D /* Headers */ = {
-			isa = PBXHeadersBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				CC02FE2028F2EA83003DA87D /* sharedFFI.h in Headers */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-/* End PBXHeadersBuildPhase section */
-
-/* Begin PBXNativeTarget section */
-		CCB21E1528F199700074368C /* iOS */ = {
-			isa = PBXNativeTarget;
-			buildConfigurationList = CCB21E3A28F199710074368C /* Build configuration list for PBXNativeTarget "iOS" */;
-			buildPhases = (
-				CCFA7BDF28F5AEB500AEA3EA /* Build Rust library */,
-				CCB21E1228F199700074368C /* Sources */,
-				CC02FE1E28F2EA5C003DA87D /* Headers */,
-				CCB21E1328F199700074368C /* Frameworks */,
-				CCB21E1428F199700074368C /* Resources */,
-			);
-			buildRules = (
-				CCB21E4528F19DCD0074368C /* PBXBuildRule */,
-			);
-			dependencies = (
-			);
-			name = iOS;
-			packageProductDependencies = (
-				CCB436422912CD7E0059B3A3 /* Serde */,
-			);
-			productName = iOS;
-			productReference = CCB21E1628F199700074368C /* iOS.app */;
-			productType = "com.apple.product-type.application";
-		};
-		CCB21E2528F199710074368C /* iOSTests */ = {
-			isa = PBXNativeTarget;
-			buildConfigurationList = CCB21E3D28F199710074368C /* Build configuration list for PBXNativeTarget "iOSTests" */;
-			buildPhases = (
-				CCB21E2228F199710074368C /* Sources */,
-				CCB21E2328F199710074368C /* Frameworks */,
-				CCB21E2428F199710074368C /* Resources */,
-			);
-			buildRules = (
-			);
-			dependencies = (
-				CCB21E2828F199710074368C /* PBXTargetDependency */,
-			);
-			name = iOSTests;
-			productName = iOSTests;
-			productReference = CCB21E2628F199710074368C /* iOSTests.xctest */;
-			productType = "com.apple.product-type.bundle.unit-test";
-		};
-		CCB21E2F28F199710074368C /* iOSUITests */ = {
-			isa = PBXNativeTarget;
-			buildConfigurationList = CCB21E4028F199710074368C /* Build configuration list for PBXNativeTarget "iOSUITests" */;
-			buildPhases = (
-				CCB21E2C28F199710074368C /* Sources */,
-				CCB21E2D28F199710074368C /* Frameworks */,
-				CCB21E2E28F199710074368C /* Resources */,
-			);
-			buildRules = (
-			);
-			dependencies = (
-				CCB21E3228F199710074368C /* PBXTargetDependency */,
-			);
-			name = iOSUITests;
-			productName = iOSUITests;
-			productReference = CCB21E3028F199710074368C /* iOSUITests.xctest */;
-			productType = "com.apple.product-type.bundle.ui-testing";
-		};
-/* End PBXNativeTarget section */
-
-/* Begin PBXProject section */
-		CCB21E0E28F199700074368C /* Project object */ = {
-			isa = PBXProject;
-			attributes = {
-				BuildIndependentTargetsInParallel = 1;
-				LastSwiftUpdateCheck = 1400;
-				LastUpgradeCheck = 1400;
-				TargetAttributes = {
-					CCB21E1528F199700074368C = {
-						CreatedOnToolsVersion = 14.0.1;
-					};
-					CCB21E2528F199710074368C = {
-						CreatedOnToolsVersion = 14.0.1;
-						TestTargetID = CCB21E1528F199700074368C;
-					};
-					CCB21E2F28F199710074368C = {
-						CreatedOnToolsVersion = 14.0.1;
-						TestTargetID = CCB21E1528F199700074368C;
-					};
-				};
-			};
-			buildConfigurationList = CCB21E1128F199700074368C /* Build configuration list for PBXProject "iOS" */;
-			compatibilityVersion = "Xcode 14.0";
-			developmentRegion = en;
-			hasScannedForEncodings = 0;
-			knownRegions = (
-				en,
-				Base,
-			);
-			mainGroup = CCB21E0D28F199700074368C;
-			packageReferences = (
-				CCB436412912CD7E0059B3A3 /* XCRemoteSwiftPackageReference "Serde" */,
-			);
-			productRefGroup = CCB21E1728F199700074368C /* Products */;
-			projectDirPath = "";
-			projectRoot = "";
-			targets = (
-				CCB21E1528F199700074368C /* iOS */,
-				CCB21E2528F199710074368C /* iOSTests */,
-				CCB21E2F28F199710074368C /* iOSUITests */,
-			);
-		};
-/* End PBXProject section */
-
-/* Begin PBXResourcesBuildPhase section */
-		CCB21E1428F199700074368C /* Resources */ = {
-			isa = PBXResourcesBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				CCB21E2128F199710074368C /* Preview Assets.xcassets in Resources */,
-				CCB21E1E28F199710074368C /* Assets.xcassets in Resources */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		CCB21E2428F199710074368C /* Resources */ = {
-			isa = PBXResourcesBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		CCB21E2E28F199710074368C /* Resources */ = {
-			isa = PBXResourcesBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-/* End PBXResourcesBuildPhase section */
-
-/* Begin PBXShellScriptBuildPhase section */
-		CCFA7BDF28F5AEB500AEA3EA /* Build Rust library */ = {
-			isa = PBXShellScriptBuildPhase;
-			alwaysOutOfDate = 1;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			inputFileListPaths = (
-			);
-			inputPaths = (
-			);
-			name = "Build Rust library";
-			outputFileListPaths = (
-			);
-			outputPaths = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-			shellPath = /bin/sh;
-			shellScript = "cd \"${PROJECT_DIR}\"/../shared\nbash \"${PROJECT_DIR}/bin/compile-library.sh\" shared\n";
-		};
-/* End PBXShellScriptBuildPhase section */
-
-/* Begin PBXSourcesBuildPhase section */
-		CCB21E1228F199700074368C /* Sources */ = {
-			isa = PBXSourcesBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				CC2172C0291EA71100BCD13B /* shared_types.swift in Sources */,
-				CCA5CCE329191A5900325531 /* shared.udl in Sources */,
-				CCB21E1C28F199700074368C /* ContentView.swift in Sources */,
-				CCB21E1A28F199700074368C /* iOSApp.swift in Sources */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		CCB21E2228F199710074368C /* Sources */ = {
-			isa = PBXSourcesBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				CCB21E2B28F199710074368C /* iOSTests.swift in Sources */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		CCB21E2C28F199710074368C /* Sources */ = {
-			isa = PBXSourcesBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				CCB21E3728F199710074368C /* iOSUITestsLaunchTests.swift in Sources */,
-				CCB21E3528F199710074368C /* iOSUITests.swift in Sources */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-/* End PBXSourcesBuildPhase section */
-
-/* Begin PBXTargetDependency section */
-		CCB21E2828F199710074368C /* PBXTargetDependency */ = {
-			isa = PBXTargetDependency;
-			target = CCB21E1528F199700074368C /* iOS */;
-			targetProxy = CCB21E2728F199710074368C /* PBXContainerItemProxy */;
-		};
-		CCB21E3228F199710074368C /* PBXTargetDependency */ = {
-			isa = PBXTargetDependency;
-			target = CCB21E1528F199700074368C /* iOS */;
-			targetProxy = CCB21E3128F199710074368C /* PBXContainerItemProxy */;
-		};
-/* End PBXTargetDependency section */
-
-/* Begin XCBuildConfiguration section */
-		CCB21E3828F199710074368C /* Debug */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				ALWAYS_SEARCH_USER_PATHS = NO;
-				CLANG_ANALYZER_NONNULL = YES;
-				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
-				CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
-				CLANG_ENABLE_MODULES = YES;
-				CLANG_ENABLE_OBJC_ARC = YES;
-				CLANG_ENABLE_OBJC_WEAK = YES;
-				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
-				CLANG_WARN_BOOL_CONVERSION = YES;
-				CLANG_WARN_COMMA = YES;
-				CLANG_WARN_CONSTANT_CONVERSION = YES;
-				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
-				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
-				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
-				CLANG_WARN_EMPTY_BODY = YES;
-				CLANG_WARN_ENUM_CONVERSION = YES;
-				CLANG_WARN_INFINITE_RECURSION = YES;
-				CLANG_WARN_INT_CONVERSION = YES;
-				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
-				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
-				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
-				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
-				CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
-				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
-				CLANG_WARN_STRICT_PROTOTYPES = YES;
-				CLANG_WARN_SUSPICIOUS_MOVE = YES;
-				CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
-				CLANG_WARN_UNREACHABLE_CODE = YES;
-				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
-				COPY_PHASE_STRIP = NO;
-				DEBUG_INFORMATION_FORMAT = dwarf;
-				ENABLE_STRICT_OBJC_MSGSEND = YES;
-				ENABLE_TESTABILITY = YES;
-				GCC_C_LANGUAGE_STANDARD = gnu11;
-				GCC_DYNAMIC_NO_PIC = NO;
-				GCC_NO_COMMON_BLOCKS = YES;
-				GCC_OPTIMIZATION_LEVEL = 0;
-				GCC_PREPROCESSOR_DEFINITIONS = (
-					"DEBUG=1",
-					"$(inherited)",
-				);
-				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
-				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
-				GCC_WARN_UNDECLARED_SELECTOR = YES;
-				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
-				GCC_WARN_UNUSED_FUNCTION = YES;
-				GCC_WARN_UNUSED_VARIABLE = YES;
-				IPHONEOS_DEPLOYMENT_TARGET = 16.0;
-				MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
-				MTL_FAST_MATH = YES;
-				ONLY_ACTIVE_ARCH = YES;
-				SDKROOT = iphoneos;
-				SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
-				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
-			};
-			name = Debug;
-		};
-		CCB21E3928F199710074368C /* Release */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				ALWAYS_SEARCH_USER_PATHS = NO;
-				CLANG_ANALYZER_NONNULL = YES;
-				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
-				CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
-				CLANG_ENABLE_MODULES = YES;
-				CLANG_ENABLE_OBJC_ARC = YES;
-				CLANG_ENABLE_OBJC_WEAK = YES;
-				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
-				CLANG_WARN_BOOL_CONVERSION = YES;
-				CLANG_WARN_COMMA = YES;
-				CLANG_WARN_CONSTANT_CONVERSION = YES;
-				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
-				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
-				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
-				CLANG_WARN_EMPTY_BODY = YES;
-				CLANG_WARN_ENUM_CONVERSION = YES;
-				CLANG_WARN_INFINITE_RECURSION = YES;
-				CLANG_WARN_INT_CONVERSION = YES;
-				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
-				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
-				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
-				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
-				CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
-				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
-				CLANG_WARN_STRICT_PROTOTYPES = YES;
-				CLANG_WARN_SUSPICIOUS_MOVE = YES;
-				CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
-				CLANG_WARN_UNREACHABLE_CODE = YES;
-				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
-				COPY_PHASE_STRIP = NO;
-				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
-				ENABLE_NS_ASSERTIONS = NO;
-				ENABLE_STRICT_OBJC_MSGSEND = YES;
-				GCC_C_LANGUAGE_STANDARD = gnu11;
-				GCC_NO_COMMON_BLOCKS = YES;
-				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
-				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
-				GCC_WARN_UNDECLARED_SELECTOR = YES;
-				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
-				GCC_WARN_UNUSED_FUNCTION = YES;
-				GCC_WARN_UNUSED_VARIABLE = YES;
-				IPHONEOS_DEPLOYMENT_TARGET = 16.0;
-				MTL_ENABLE_DEBUG_INFO = NO;
-				MTL_FAST_MATH = YES;
-				SDKROOT = iphoneos;
-				SWIFT_COMPILATION_MODE = wholemodule;
-				SWIFT_OPTIMIZATION_LEVEL = "-O";
-				VALIDATE_PRODUCT = YES;
-			};
-			name = Release;
-		};
-		CCB21E3B28F199710074368C /* Debug */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
-				ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
-				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 1;
-				DEVELOPMENT_ASSET_PATHS = "\"iOS/Preview Content\"";
-				ENABLE_PREVIEWS = YES;
-				GENERATE_INFOPLIST_FILE = YES;
-				INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
-				INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
-				INFOPLIST_KEY_UILaunchScreen_Generation = YES;
-				INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
-				INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
-				LD_RUNPATH_SEARCH_PATHS = (
-					"$(inherited)",
-					"@executable_path/Frameworks",
-				);
-				"LIBRARY_SEARCH_PATHS[sdk=iphoneos*][arch=arm64]" = "$(PROJECT_DIR)/../target/aarch64-apple-ios/debug";
-				"LIBRARY_SEARCH_PATHS[sdk=iphonesimulator*][arch=arm64]" = "$(PROJECT_DIR)/../target/aarch64-apple-ios-sim/debug";
-				"LIBRARY_SEARCH_PATHS[sdk=iphonesimulator*][arch=x86_64]" = "$(PROJECT_DIR)/../target/x86_64-apple-ios/debug";
-				MARKETING_VERSION = 1.0;
-				PRODUCT_BUNDLE_IDENTIFIER = com.redbadger.crux_core.iOS;
-				PRODUCT_NAME = "$(TARGET_NAME)";
-				SWIFT_EMIT_LOC_STRINGS = YES;
-				"SWIFT_OBJC_BRIDGING_HEADER[arch=*]" = generated/sharedFFI.h;
-				SWIFT_PRECOMPILE_BRIDGING_HEADER = YES;
-				SWIFT_VERSION = 5.0;
-				TARGETED_DEVICE_FAMILY = "1,2";
-			};
-			name = Debug;
-		};
-		CCB21E3C28F199710074368C /* Release */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
-				ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
-				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 1;
-				DEVELOPMENT_ASSET_PATHS = "\"iOS/Preview Content\"";
-				ENABLE_PREVIEWS = YES;
-				GENERATE_INFOPLIST_FILE = YES;
-				INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
-				INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
-				INFOPLIST_KEY_UILaunchScreen_Generation = YES;
-				INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
-				INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
-				LD_RUNPATH_SEARCH_PATHS = (
-					"$(inherited)",
-					"@executable_path/Frameworks",
-				);
-				"LIBRARY_SEARCH_PATHS[sdk=iphoneos*][arch=arm64]" = "$(PROJECT_DIR)/../target/aarch64-apple-ios/release";
-				"LIBRARY_SEARCH_PATHS[sdk=iphonesimulator*][arch=arm64]" = "$(PROJECT_DIR)/../target/aarch64-apple-ios-sim/release";
-				"LIBRARY_SEARCH_PATHS[sdk=iphonesimulator*][arch=x86_64]" = "$(PROJECT_DIR)/../target/x86_64-apple-ios/release";
-				MARKETING_VERSION = 1.0;
-				PRODUCT_BUNDLE_IDENTIFIER = com.redbadger.crux_core.iOS;
-				PRODUCT_NAME = "$(TARGET_NAME)";
-				SWIFT_EMIT_LOC_STRINGS = YES;
-				"SWIFT_OBJC_BRIDGING_HEADER[arch=*]" = generated/sharedFFI.h;
-				SWIFT_PRECOMPILE_BRIDGING_HEADER = YES;
-				SWIFT_VERSION = 5.0;
-				TARGETED_DEVICE_FAMILY = "1,2";
-			};
-			name = Release;
-		};
-		CCB21E3E28F199710074368C /* Debug */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
-				BUNDLE_LOADER = "$(TEST_HOST)";
-				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 1;
-				GENERATE_INFOPLIST_FILE = YES;
-				IPHONEOS_DEPLOYMENT_TARGET = 16.0;
-				MARKETING_VERSION = 1.0;
-				PRODUCT_BUNDLE_IDENTIFIER = com.redbadger.crux_core.iOSTests;
-				PRODUCT_NAME = "$(TARGET_NAME)";
-				SWIFT_EMIT_LOC_STRINGS = NO;
-				SWIFT_VERSION = 5.0;
-				TARGETED_DEVICE_FAMILY = "1,2";
-				TEST_HOST = "$(BUILT_PRODUCTS_DIR)/iOS.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/iOS";
-			};
-			name = Debug;
-		};
-		CCB21E3F28F199710074368C /* Release */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
-				BUNDLE_LOADER = "$(TEST_HOST)";
-				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 1;
-				GENERATE_INFOPLIST_FILE = YES;
-				IPHONEOS_DEPLOYMENT_TARGET = 16.0;
-				MARKETING_VERSION = 1.0;
-				PRODUCT_BUNDLE_IDENTIFIER = com.redbadger.crux_core.iOSTests;
-				PRODUCT_NAME = "$(TARGET_NAME)";
-				SWIFT_EMIT_LOC_STRINGS = NO;
-				SWIFT_VERSION = 5.0;
-				TARGETED_DEVICE_FAMILY = "1,2";
-				TEST_HOST = "$(BUILT_PRODUCTS_DIR)/iOS.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/iOS";
-			};
-			name = Release;
-		};
-		CCB21E4128F199710074368C /* Debug */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
-				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 1;
-				GENERATE_INFOPLIST_FILE = YES;
-				MARKETING_VERSION = 1.0;
-				PRODUCT_BUNDLE_IDENTIFIER = com.redbadger.crux_core.iOSUITests;
-				PRODUCT_NAME = "$(TARGET_NAME)";
-				SWIFT_EMIT_LOC_STRINGS = NO;
-				SWIFT_VERSION = 5.0;
-				TARGETED_DEVICE_FAMILY = "1,2";
-				TEST_TARGET_NAME = iOS;
-			};
-			name = Debug;
-		};
-		CCB21E4228F199710074368C /* Release */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
-				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 1;
-				GENERATE_INFOPLIST_FILE = YES;
-				MARKETING_VERSION = 1.0;
-				PRODUCT_BUNDLE_IDENTIFIER = com.redbadger.crux_core.iOSUITests;
-				PRODUCT_NAME = "$(TARGET_NAME)";
-				SWIFT_EMIT_LOC_STRINGS = NO;
-				SWIFT_VERSION = 5.0;
-				TARGETED_DEVICE_FAMILY = "1,2";
-				TEST_TARGET_NAME = iOS;
-			};
-			name = Release;
-		};
-/* End XCBuildConfiguration section */
-
-/* Begin XCConfigurationList section */
-		CCB21E1128F199700074368C /* Build configuration list for PBXProject "iOS" */ = {
-			isa = XCConfigurationList;
-			buildConfigurations = (
-				CCB21E3828F199710074368C /* Debug */,
-				CCB21E3928F199710074368C /* Release */,
-			);
-			defaultConfigurationIsVisible = 0;
-			defaultConfigurationName = Release;
-		};
-		CCB21E3A28F199710074368C /* Build configuration list for PBXNativeTarget "iOS" */ = {
-			isa = XCConfigurationList;
-			buildConfigurations = (
-				CCB21E3B28F199710074368C /* Debug */,
-				CCB21E3C28F199710074368C /* Release */,
-			);
-			defaultConfigurationIsVisible = 0;
-			defaultConfigurationName = Release;
-		};
-		CCB21E3D28F199710074368C /* Build configuration list for PBXNativeTarget "iOSTests" */ = {
-			isa = XCConfigurationList;
-			buildConfigurations = (
-				CCB21E3E28F199710074368C /* Debug */,
-				CCB21E3F28F199710074368C /* Release */,
-			);
-			defaultConfigurationIsVisible = 0;
-			defaultConfigurationName = Release;
-		};
-		CCB21E4028F199710074368C /* Build configuration list for PBXNativeTarget "iOSUITests" */ = {
-			isa = XCConfigurationList;
-			buildConfigurations = (
-				CCB21E4128F199710074368C /* Debug */,
-				CCB21E4228F199710074368C /* Release */,
-			);
-			defaultConfigurationIsVisible = 0;
-			defaultConfigurationName = Release;
-		};
-/* End XCConfigurationList section */
-
-/* Begin XCRemoteSwiftPackageReference section */
-		CCB436412912CD7E0059B3A3 /* XCRemoteSwiftPackageReference "Serde" */ = {
-			isa = XCRemoteSwiftPackageReference;
-			repositoryURL = "https://github.com/starcoin-sdk/Serde.swift";
-			requirement = {
-				branch = main;
-				kind = branch;
-			};
-		};
-/* End XCRemoteSwiftPackageReference section */
-
-/* Begin XCSwiftPackageProductDependency section */
-		CCB436422912CD7E0059B3A3 /* Serde */ = {
-			isa = XCSwiftPackageProductDependency;
-			package = CCB436412912CD7E0059B3A3 /* XCRemoteSwiftPackageReference "Serde" */;
-			productName = Serde;
-		};
-/* End XCSwiftPackageProductDependency section */
-	};
-	rootObject = CCB21E0E28F199700074368C /* Project object */;
-}
diff --git a/examples/cat_facts/iOS/iOSTests/iOSTests.swift b/examples/cat_facts/iOS/iOSTests/iOSTests.swift
deleted file mode 100644
index 28c51b8a..00000000
--- a/examples/cat_facts/iOS/iOSTests/iOSTests.swift
+++ /dev/null
@@ -1,36 +0,0 @@
-//
-//  iOSTests.swift
-//  iOSTests
-//
-//  Created by Stuart Harris on 08/10/2022.
-//
-
-import XCTest
-@testable import iOS
-
-final class iOSTests: XCTestCase {
-
-    override func setUpWithError() throws {
-        // Put setup code here. This method is called before the invocation of each test method in the class.
-    }
-
-    override func tearDownWithError() throws {
-        // Put teardown code here. This method is called after the invocation of each test method in the class.
-    }
-
-    func testExample() throws {
-        // This is an example of a functional test case.
-        // Use XCTAssert and related functions to verify your tests produce the correct results.
-        // Any test you write for XCTest can be annotated as throws and async.
-        // Mark your test throws to produce an unexpected failure when your test encounters an uncaught error.
-        // Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards.
-    }
-
-    func testPerformanceExample() throws {
-        // This is an example of a performance test case.
-        self.measure {
-            // Put the code you want to measure the time of here.
-        }
-    }
-
-}
diff --git a/examples/cat_facts/iOS/iOSUITests/iOSUITests.swift b/examples/cat_facts/iOS/iOSUITests/iOSUITests.swift
deleted file mode 100644
index 87cc985a..00000000
--- a/examples/cat_facts/iOS/iOSUITests/iOSUITests.swift
+++ /dev/null
@@ -1,41 +0,0 @@
-//
-//  iOSUITests.swift
-//  iOSUITests
-//
-//  Created by Stuart Harris on 08/10/2022.
-//
-
-import XCTest
-
-final class iOSUITests: XCTestCase {
-
-    override func setUpWithError() throws {
-        // Put setup code here. This method is called before the invocation of each test method in the class.
-
-        // In UI tests it is usually best to stop immediately when a failure occurs.
-        continueAfterFailure = false
-
-        // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
-    }
-
-    override func tearDownWithError() throws {
-        // Put teardown code here. This method is called after the invocation of each test method in the class.
-    }
-
-    func testExample() throws {
-        // UI tests must launch the application that they test.
-        let app = XCUIApplication()
-        app.launch()
-
-        // Use XCTAssert and related functions to verify your tests produce the correct results.
-    }
-
-    func testLaunchPerformance() throws {
-        if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 7.0, *) {
-            // This measures how long it takes to launch your application.
-            measure(metrics: [XCTApplicationLaunchMetric()]) {
-                XCUIApplication().launch()
-            }
-        }
-    }
-}
diff --git a/examples/cat_facts/iOS/iOSUITests/iOSUITestsLaunchTests.swift b/examples/cat_facts/iOS/iOSUITests/iOSUITestsLaunchTests.swift
deleted file mode 100644
index adc0f202..00000000
--- a/examples/cat_facts/iOS/iOSUITests/iOSUITestsLaunchTests.swift
+++ /dev/null
@@ -1,32 +0,0 @@
-//
-//  iOSUITestsLaunchTests.swift
-//  iOSUITests
-//
-//  Created by Stuart Harris on 08/10/2022.
-//
-
-import XCTest
-
-final class iOSUITestsLaunchTests: XCTestCase {
-
-    override class var runsForEachTargetApplicationUIConfiguration: Bool {
-        true
-    }
-
-    override func setUpWithError() throws {
-        continueAfterFailure = false
-    }
-
-    func testLaunch() throws {
-        let app = XCUIApplication()
-        app.launch()
-
-        // Insert steps here to perform after app launch but before taking a screenshot,
-        // such as logging into a test account or navigating somewhere in the app
-
-        let attachment = XCTAttachment(screenshot: app.screenshot())
-        attachment.name = "Launch Screen"
-        attachment.lifetime = .keepAlways
-        add(attachment)
-    }
-}
diff --git a/examples/cat_facts/shared/shared.xcodeproj/project.pbxproj b/examples/cat_facts/shared/shared.xcodeproj/project.pbxproj
new file mode 100644
index 00000000..eeb1878d
--- /dev/null
+++ b/examples/cat_facts/shared/shared.xcodeproj/project.pbxproj
@@ -0,0 +1,454 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 53;
+	objects = {
+
+/* Begin PBXBuildFile section */
+		CA60D3693CF72A54933F48BD /* Cargo.toml in Sources */ = {isa = PBXBuildFile; fileRef = CA60A8EAC2313EF4668187A5 /* Cargo.toml */; settings = {COMPILER_FLAGS = "--lib"; }; };
+		CA60D3693CF75AAF98D5E0DD /* Cargo.toml in Sources */ = {isa = PBXBuildFile; fileRef = CA60A8EAC2313EF4668187A5 /* Cargo.toml */; settings = {COMPILER_FLAGS = "--lib"; }; };
+		CA60D3693CF79A6F07B14E08 /* Cargo.toml in Sources */ = {isa = PBXBuildFile; fileRef = CA60A8EAC2313EF4668187A5 /* Cargo.toml */; settings = {COMPILER_FLAGS = "--bin 'uniffi-bindgen'"; }; };
+/* End PBXBuildFile section */
+
+/* Begin PBXBuildRule section */
+		CA60A8EAC231AC6C1400ACA8 /* PBXBuildRule */ = {
+			isa = PBXBuildRule;
+			compilerSpec = com.apple.compilers.proxy.script;
+			dependencyFile = "$(DERIVED_FILE_DIR)/$(CARGO_XCODE_TARGET_ARCH)-$(EXECUTABLE_NAME).d";
+			filePatterns = "*/Cargo.toml";
+			fileType = pattern.proxy;
+			inputFiles = (
+			);
+			isEditable = 0;
+			name = "Cargo project build";
+			outputFiles = (
+				"$(OBJECT_FILE_DIR)/$(CARGO_XCODE_TARGET_ARCH)-$(EXECUTABLE_NAME)",
+			);
+			script = "# generated with cargo-xcode 1.5.0\n\nset -eu; export PATH=\"$PATH:$HOME/.cargo/bin:/usr/local/bin\";\nif [ \"${IS_MACCATALYST-NO}\" = YES ]; then\n    CARGO_XCODE_TARGET_TRIPLE=\"${CARGO_XCODE_TARGET_ARCH}-apple-ios-macabi\"\nelse\n    CARGO_XCODE_TARGET_TRIPLE=\"${CARGO_XCODE_TARGET_ARCH}-apple-${CARGO_XCODE_TARGET_OS}\"\nfi\nif [ \"$CARGO_XCODE_TARGET_OS\" != \"darwin\" ]; then\n    PATH=\"${PATH/\\/Contents\\/Developer\\/Toolchains\\/XcodeDefault.xctoolchain\\/usr\\/bin:/xcode-provided-ld-cant-link-lSystem-for-the-host-build-script:}\"\nfi\nPATH=\"$PATH:/opt/homebrew/bin\" # Rust projects often depend on extra tools like nasm, which Xcode lacks\nif [ \"$CARGO_XCODE_BUILD_MODE\" == release ]; then\n    OTHER_INPUT_FILE_FLAGS=\"${OTHER_INPUT_FILE_FLAGS} --release\"\nfi\nif command -v rustup &> /dev/null; then\n    if ! rustup target list --installed | egrep -q \"${CARGO_XCODE_TARGET_TRIPLE}\"; then\n        echo \"warning: this build requires rustup toolchain for $CARGO_XCODE_TARGET_TRIPLE, but it isn't installed\"\n        rustup target add \"${CARGO_XCODE_TARGET_TRIPLE}\" || echo >&2 \"warning: can't install $CARGO_XCODE_TARGET_TRIPLE\"\n    fi\nfi\nif [ \"$ACTION\" = clean ]; then\n ( set -x; cargo clean --manifest-path=\"$SCRIPT_INPUT_FILE\" ${OTHER_INPUT_FILE_FLAGS} --target=\"${CARGO_XCODE_TARGET_TRIPLE}\"; );\nelse\n ( set -x; cargo build --manifest-path=\"$SCRIPT_INPUT_FILE\" --features=\"${CARGO_XCODE_FEATURES:-}\" ${OTHER_INPUT_FILE_FLAGS} --target=\"${CARGO_XCODE_TARGET_TRIPLE}\"; );\nfi\n# it's too hard to explain Cargo's actual exe path to Xcode build graph, so hardlink to a known-good path instead\nBUILT_SRC=\"${CARGO_TARGET_DIR}/${CARGO_XCODE_TARGET_TRIPLE}/${CARGO_XCODE_BUILD_MODE}/${CARGO_XCODE_CARGO_FILE_NAME}\"\nln -f -- \"$BUILT_SRC\" \"$SCRIPT_OUTPUT_FILE_0\"\n\n# xcode generates dep file, but for its own path, so append our rename to it\nDEP_FILE_SRC=\"${CARGO_TARGET_DIR}/${CARGO_XCODE_TARGET_TRIPLE}/${CARGO_XCODE_BUILD_MODE}/${CARGO_XCODE_CARGO_DEP_FILE_NAME}\"\nif [ -f \"$DEP_FILE_SRC\" ]; then\n    DEP_FILE_DST=\"${DERIVED_FILE_DIR}/${CARGO_XCODE_TARGET_ARCH}-${EXECUTABLE_NAME}.d\"\n    cp -f \"$DEP_FILE_SRC\" \"$DEP_FILE_DST\"\n    echo >> \"$DEP_FILE_DST\" \"$SCRIPT_OUTPUT_FILE_0: $BUILT_SRC\"\nfi\n\n# lipo script needs to know all the platform-specific files that have been built\n# archs is in the file name, so that paths don't stay around after archs change\n# must match input for LipoScript\nFILE_LIST=\"${DERIVED_FILE_DIR}/${ARCHS}-${EXECUTABLE_NAME}.xcfilelist\"\ntouch \"$FILE_LIST\"\nif ! egrep -q \"$SCRIPT_OUTPUT_FILE_0\" \"$FILE_LIST\" ; then\n    echo >> \"$FILE_LIST\" \"$SCRIPT_OUTPUT_FILE_0\"\nfi\n";
+		};
+/* End PBXBuildRule section */
+
+/* Begin PBXFileReference section */
+		ADDEDBA66A6E1 /* libresolv.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libresolv.tbd; path = usr/lib/libresolv.tbd; sourceTree = SDKROOT; };
+		CA6027CBEBE510F7F7FCAC5B /* shared.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = shared.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
+		CA60431E8A50FB09138082B7 /* libshared_static.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libshared_static.a; sourceTree = BUILT_PRODUCTS_DIR; };
+		CA605677FFD78109328FB0D5 /* uniffi-bindgen */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "uniffi-bindgen"; sourceTree = BUILT_PRODUCTS_DIR; };
+		CA60A8EAC2313EF4668187A5 /* Cargo.toml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Cargo.toml; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXGroup section */
+		ADDEDBA66A6E2 /* Required for static linking */ = {
+			isa = PBXGroup;
+			children = (
+				ADDEDBA66A6E1 /* libresolv.tbd */,
+			);
+			name = "Required for static linking";
+			sourceTree = "<group>";
+		};
+		CA60A8EAC23122869D176AE5 /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				CA60431E8A50FB09138082B7 /* libshared_static.a */,
+				CA6027CBEBE510F7F7FCAC5B /* shared.dylib */,
+				CA605677FFD78109328FB0D5 /* uniffi-bindgen */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		CA60A8EAC23198AF0B5890DB /* Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				ADDEDBA66A6E2 /* Required for static linking */,
+			);
+			name = Frameworks;
+			sourceTree = "<group>";
+		};
+		CA60A8EAC231D65BC3C892A8 = {
+			isa = PBXGroup;
+			children = (
+				CA60A8EAC2313EF4668187A5 /* Cargo.toml */,
+				CA60A8EAC23122869D176AE5 /* Products */,
+				CA60A8EAC23198AF0B5890DB /* Frameworks */,
+			);
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+		CA6027CBEBE52A54933F48BD /* shared-cdylib */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = CA606533DF1C2A54933F48BD /* Build configuration list for PBXNativeTarget "shared-cdylib" */;
+			buildPhases = (
+				CA605F8744592A54933F48BD /* Sources */,
+				CA60A8EAC231AF6EBB7F357C /* Universal Binary lipo */,
+			);
+			buildRules = (
+				CA60A8EAC231AC6C1400ACA8 /* PBXBuildRule */,
+			);
+			dependencies = (
+			);
+			name = "shared-cdylib";
+			productName = shared.dylib;
+			productReference = CA6027CBEBE510F7F7FCAC5B /* shared.dylib */;
+			productType = "com.apple.product-type.library.dynamic";
+		};
+		CA60431E8A505AAF98D5E0DD /* shared-staticlib */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = CA606533DF1C5AAF98D5E0DD /* Build configuration list for PBXNativeTarget "shared-staticlib" */;
+			buildPhases = (
+				CA605F8744595AAF98D5E0DD /* Sources */,
+				CA60A8EAC231AF6EBB7F357C /* Universal Binary lipo */,
+			);
+			buildRules = (
+				CA60A8EAC231AC6C1400ACA8 /* PBXBuildRule */,
+			);
+			dependencies = (
+			);
+			name = "shared-staticlib";
+			productName = libshared_static.a;
+			productReference = CA60431E8A50FB09138082B7 /* libshared_static.a */;
+			productType = "com.apple.product-type.library.static";
+		};
+		CA605677FFD79A6F07B14E08 /* uniffi-bindgen-bin */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = CA606533DF1C9A6F07B14E08 /* Build configuration list for PBXNativeTarget "uniffi-bindgen-bin" */;
+			buildPhases = (
+				CA605F8744599A6F07B14E08 /* Sources */,
+				CA60A8EAC231AF6EBB7F357C /* Universal Binary lipo */,
+			);
+			buildRules = (
+				CA60A8EAC231AC6C1400ACA8 /* PBXBuildRule */,
+			);
+			dependencies = (
+			);
+			name = "uniffi-bindgen-bin";
+			productName = "uniffi-bindgen";
+			productReference = CA605677FFD78109328FB0D5 /* uniffi-bindgen */;
+			productType = "com.apple.product-type.tool";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		CA60A8EAC231E04653AD465F /* Project object */ = {
+			isa = PBXProject;
+			attributes = {
+				LastUpgradeCheck = 1420;
+				TargetAttributes = {
+					CA6027CBEBE52A54933F48BD = {
+						CreatedOnToolsVersion = 9.2;
+						ProvisioningStyle = Automatic;
+					};
+					CA60431E8A505AAF98D5E0DD = {
+						CreatedOnToolsVersion = 9.2;
+						ProvisioningStyle = Automatic;
+					};
+					CA605677FFD79A6F07B14E08 = {
+						CreatedOnToolsVersion = 9.2;
+						ProvisioningStyle = Automatic;
+					};
+				};
+			};
+			buildConfigurationList = CA60A8EAC23180E02D6C7F57 /* Build configuration list for PBXProject "shared" */;
+			compatibilityVersion = "Xcode 11.4";
+			developmentRegion = en;
+			hasScannedForEncodings = 0;
+			knownRegions = (
+				en,
+				Base,
+			);
+			mainGroup = CA60A8EAC231D65BC3C892A8;
+			productRefGroup = CA60A8EAC23122869D176AE5 /* Products */;
+			projectDirPath = "";
+			projectRoot = "";
+			targets = (
+				CA60431E8A505AAF98D5E0DD /* shared-staticlib */,
+				CA6027CBEBE52A54933F48BD /* shared-cdylib */,
+				CA605677FFD79A6F07B14E08 /* uniffi-bindgen-bin */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXShellScriptBuildPhase section */
+		CA60A8EAC231AF6EBB7F357C /* Universal Binary lipo */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputFileListPaths = (
+			);
+			inputPaths = (
+				"$(DERIVED_FILE_DIR)/$(ARCHS)-$(EXECUTABLE_NAME).xcfilelist",
+			);
+			name = "Universal Binary lipo";
+			outputFileListPaths = (
+			);
+			outputPaths = (
+				"$(TARGET_BUILD_DIR)/$(EXECUTABLE_PATH)",
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "# generated with cargo-xcode 1.5.0\n\n            set -eux; cat \"$DERIVED_FILE_DIR/$ARCHS-$EXECUTABLE_NAME.xcfilelist\" | tr '\\n' '\\0' | xargs -0 lipo -create -output \"$TARGET_BUILD_DIR/$EXECUTABLE_PATH\"\n            if [ ${LD_DYLIB_INSTALL_NAME:+1} ]; then\n                install_name_tool -id \"$LD_DYLIB_INSTALL_NAME\" \"$TARGET_BUILD_DIR/$EXECUTABLE_PATH\"\n            fi\n        ";
+		};
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+		CA605F8744592A54933F48BD /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				CA60D3693CF72A54933F48BD /* Cargo.toml in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		CA605F8744595AAF98D5E0DD /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				CA60D3693CF75AAF98D5E0DD /* Cargo.toml in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		CA605F8744599A6F07B14E08 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				CA60D3693CF79A6F07B14E08 /* Cargo.toml in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+		CA60C2B5F3F9228BE02872F8 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CARGO_TARGET_DIR = "$(PROJECT_TEMP_DIR)/cargo_target";
+				CARGO_XCODE_BUILD_MODE = debug;
+				CARGO_XCODE_FEATURES = "";
+				"CARGO_XCODE_TARGET_ARCH[arch=arm64*]" = aarch64;
+				"CARGO_XCODE_TARGET_ARCH[arch=i386]" = i686;
+				"CARGO_XCODE_TARGET_ARCH[arch=x86_64*]" = x86_64;
+				"CARGO_XCODE_TARGET_OS[sdk=appletvos*]" = tvos;
+				"CARGO_XCODE_TARGET_OS[sdk=appletvsimulator*]" = tvos;
+				"CARGO_XCODE_TARGET_OS[sdk=iphoneos*]" = ios;
+				"CARGO_XCODE_TARGET_OS[sdk=iphonesimulator*]" = "ios-sim";
+				"CARGO_XCODE_TARGET_OS[sdk=iphonesimulator*][arch=x86_64*]" = ios;
+				"CARGO_XCODE_TARGET_OS[sdk=macosx*]" = darwin;
+				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_COMMA = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+				CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+				CLANG_WARN_STRICT_PROTOTYPES = YES;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				CURRENT_PROJECT_VERSION = 0.1;
+				DEAD_CODE_STRIPPING = YES;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				ENABLE_TESTABILITY = YES;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				MARKETING_VERSION = 0.1.0;
+				ONLY_ACTIVE_ARCH = YES;
+				PRODUCT_NAME = shared;
+				SDKROOT = macosx;
+				SUPPORTS_MACCATALYST = YES;
+			};
+			name = Debug;
+		};
+		CA60C2B5F3F93CC16B37690B /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CARGO_TARGET_DIR = "$(PROJECT_TEMP_DIR)/cargo_target";
+				CARGO_XCODE_BUILD_MODE = release;
+				CARGO_XCODE_FEATURES = "";
+				"CARGO_XCODE_TARGET_ARCH[arch=arm64*]" = aarch64;
+				"CARGO_XCODE_TARGET_ARCH[arch=i386]" = i686;
+				"CARGO_XCODE_TARGET_ARCH[arch=x86_64*]" = x86_64;
+				"CARGO_XCODE_TARGET_OS[sdk=appletvos*]" = tvos;
+				"CARGO_XCODE_TARGET_OS[sdk=appletvsimulator*]" = tvos;
+				"CARGO_XCODE_TARGET_OS[sdk=iphoneos*]" = ios;
+				"CARGO_XCODE_TARGET_OS[sdk=iphonesimulator*]" = "ios-sim";
+				"CARGO_XCODE_TARGET_OS[sdk=iphonesimulator*][arch=x86_64*]" = ios;
+				"CARGO_XCODE_TARGET_OS[sdk=macosx*]" = darwin;
+				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_COMMA = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+				CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+				CLANG_WARN_STRICT_PROTOTYPES = YES;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				CURRENT_PROJECT_VERSION = 0.1;
+				DEAD_CODE_STRIPPING = YES;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				MARKETING_VERSION = 0.1.0;
+				PRODUCT_NAME = shared;
+				SDKROOT = macosx;
+				SUPPORTS_MACCATALYST = YES;
+			};
+			name = Release;
+		};
+		CA60C94467582A54933F48BD /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				CARGO_XCODE_CARGO_DEP_FILE_NAME = libshared.d;
+				CARGO_XCODE_CARGO_FILE_NAME = libshared.dylib;
+				CLANG_ENABLE_OBJC_WEAK = YES;
+				DEAD_CODE_STRIPPING = YES;
+				DYLIB_COMPATIBILITY_VERSION = 0;
+				PRODUCT_NAME = shared;
+				SUPPORTED_PLATFORMS = macosx;
+			};
+			name = Debug;
+		};
+		CA60C94467585AAF98D5E0DD /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				CARGO_XCODE_CARGO_DEP_FILE_NAME = libshared.d;
+				CARGO_XCODE_CARGO_FILE_NAME = libshared.a;
+				CLANG_ENABLE_OBJC_WEAK = YES;
+				DEAD_CODE_STRIPPING = YES;
+				INSTALL_GROUP = "";
+				INSTALL_MODE_FLAG = "";
+				INSTALL_OWNER = "";
+				PRODUCT_NAME = shared_static;
+				SKIP_INSTALL = YES;
+				SUPPORTED_PLATFORMS = "macosx iphonesimulator iphoneos appletvsimulator appletvos";
+			};
+			name = Debug;
+		};
+		CA60C94467589A6F07B14E08 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				CARGO_XCODE_CARGO_DEP_FILE_NAME = "uniffi-bindgen.d";
+				CARGO_XCODE_CARGO_FILE_NAME = "uniffi-bindgen";
+				CLANG_ENABLE_OBJC_WEAK = YES;
+				CODE_SIGN_IDENTITY = "-";
+				DEAD_CODE_STRIPPING = YES;
+				PRODUCT_NAME = "uniffi-bindgen";
+				SUPPORTED_PLATFORMS = macosx;
+			};
+			name = Debug;
+		};
+		CA60D92769E82A54933F48BD /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				CARGO_XCODE_CARGO_DEP_FILE_NAME = libshared.d;
+				CARGO_XCODE_CARGO_FILE_NAME = libshared.dylib;
+				CLANG_ENABLE_OBJC_WEAK = YES;
+				DEAD_CODE_STRIPPING = YES;
+				DYLIB_COMPATIBILITY_VERSION = 0;
+				PRODUCT_NAME = shared;
+				SUPPORTED_PLATFORMS = macosx;
+			};
+			name = Release;
+		};
+		CA60D92769E85AAF98D5E0DD /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				CARGO_XCODE_CARGO_DEP_FILE_NAME = libshared.d;
+				CARGO_XCODE_CARGO_FILE_NAME = libshared.a;
+				CLANG_ENABLE_OBJC_WEAK = YES;
+				DEAD_CODE_STRIPPING = YES;
+				INSTALL_GROUP = "";
+				INSTALL_MODE_FLAG = "";
+				INSTALL_OWNER = "";
+				PRODUCT_NAME = shared_static;
+				SKIP_INSTALL = YES;
+				SUPPORTED_PLATFORMS = "macosx iphonesimulator iphoneos appletvsimulator appletvos";
+			};
+			name = Release;
+		};
+		CA60D92769E89A6F07B14E08 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				CARGO_XCODE_CARGO_DEP_FILE_NAME = "uniffi-bindgen.d";
+				CARGO_XCODE_CARGO_FILE_NAME = "uniffi-bindgen";
+				CLANG_ENABLE_OBJC_WEAK = YES;
+				CODE_SIGN_IDENTITY = "-";
+				DEAD_CODE_STRIPPING = YES;
+				PRODUCT_NAME = "uniffi-bindgen";
+				SUPPORTED_PLATFORMS = macosx;
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		CA606533DF1C2A54933F48BD /* Build configuration list for PBXNativeTarget "shared-cdylib" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				CA60D92769E82A54933F48BD /* Release */,
+				CA60C94467582A54933F48BD /* Debug */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		CA606533DF1C5AAF98D5E0DD /* Build configuration list for PBXNativeTarget "shared-staticlib" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				CA60D92769E85AAF98D5E0DD /* Release */,
+				CA60C94467585AAF98D5E0DD /* Debug */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		CA606533DF1C9A6F07B14E08 /* Build configuration list for PBXNativeTarget "uniffi-bindgen-bin" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				CA60D92769E89A6F07B14E08 /* Release */,
+				CA60C94467589A6F07B14E08 /* Debug */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		CA60A8EAC23180E02D6C7F57 /* Build configuration list for PBXProject "shared" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				CA60C2B5F3F93CC16B37690B /* Release */,
+				CA60C2B5F3F9228BE02872F8 /* Debug */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = CA60A8EAC231E04653AD465F /* Project object */;
+}
diff --git a/examples/cat_facts/shared/shared.xcodeproj/xcuserdata/stuartharris.xcuserdatad/xcschemes/xcschememanagement.plist b/examples/cat_facts/shared/shared.xcodeproj/xcuserdata/stuartharris.xcuserdatad/xcschemes/xcschememanagement.plist
new file mode 100644
index 00000000..6d14cbc6
--- /dev/null
+++ b/examples/cat_facts/shared/shared.xcodeproj/xcuserdata/stuartharris.xcuserdatad/xcschemes/xcschememanagement.plist
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>SchemeUserState</key>
+	<dict>
+		<key>shared-cdylib.xcscheme_^#shared#^_</key>
+		<dict>
+			<key>orderHint</key>
+			<integer>0</integer>
+		</dict>
+		<key>shared-staticlib.xcscheme_^#shared#^_</key>
+		<dict>
+			<key>orderHint</key>
+			<integer>3</integer>
+		</dict>
+		<key>uniffi-bindgen-bin.xcscheme_^#shared#^_</key>
+		<dict>
+			<key>orderHint</key>
+			<integer>2</integer>
+		</dict>
+	</dict>
+</dict>
+</plist>
diff --git a/examples/counter/README.md b/examples/counter/README.md
index f6582a31..86c80fe7 100644
--- a/examples/counter/README.md
+++ b/examples/counter/README.md
@@ -67,7 +67,7 @@ cd iOS
 open CounterApp.xcodeproj
 ```
 
-You should be able to press "Play" to start the app in the simulator.
+You should be able to press "Play" to start the app in the simulator, or on an iPhone.
 
 ### Notes:
 
diff --git a/examples/counter/iOS/CounterApp.xcodeproj/project.pbxproj b/examples/counter/iOS/CounterApp.xcodeproj/project.pbxproj
index b2d21ffe..5a93d4f5 100644
--- a/examples/counter/iOS/CounterApp.xcodeproj/project.pbxproj
+++ b/examples/counter/iOS/CounterApp.xcodeproj/project.pbxproj
@@ -7,19 +7,18 @@
 	objects = {
 
 /* Begin PBXBuildFile section */
-		CC49939C29507FAB00225E0E /* Serde in Frameworks */ = {isa = PBXBuildFile; productRef = CC49939B29507FAB00225E0E /* Serde */; };
-		CC49939E29507FD300225E0E /* shared_types.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC49939D29507FD300225E0E /* shared_types.swift */; };
-		CC8A3A6729507C6800ED2D9F /* CounterAppApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC8A3A6629507C6800ED2D9F /* CounterAppApp.swift */; };
-		CC8A3A6929507C6800ED2D9F /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC8A3A6829507C6800ED2D9F /* ContentView.swift */; };
-		CC8A3A6B29507C6900ED2D9F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CC8A3A6A29507C6900ED2D9F /* Assets.xcassets */; };
-		CC8A3A6E29507C6900ED2D9F /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CC8A3A6D29507C6900ED2D9F /* Preview Assets.xcassets */; };
-		CC8A3A7829507E0D00ED2D9F /* shared.udl in Sources */ = {isa = PBXBuildFile; fileRef = CC8A3A7729507E0D00ED2D9F /* shared.udl */; };
-		CC8A3A7B29507E9A00ED2D9F /* sharedFFI.h in Headers */ = {isa = PBXBuildFile; fileRef = CC8A3A7A29507E9A00ED2D9F /* sharedFFI.h */; };
-		CC8A3A7E29507EC900ED2D9F /* libshared.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CC8A3A7D29507EC900ED2D9F /* libshared.a */; };
+		CC2C4F3629D598A600CF927F /* CounterAppApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC2C4F3529D598A600CF927F /* CounterAppApp.swift */; };
+		CC2C4F3829D598A600CF927F /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC2C4F3729D598A600CF927F /* ContentView.swift */; };
+		CC2C4F3A29D598A700CF927F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CC2C4F3929D598A700CF927F /* Assets.xcassets */; };
+		CC2C4F3D29D598A700CF927F /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CC2C4F3C29D598A700CF927F /* Preview Assets.xcassets */; };
+		CCF1A53729D5997600F159DF /* shared.udl in Sources */ = {isa = PBXBuildFile; fileRef = CCF1A53629D5997600F159DF /* shared.udl */; };
+		CCF1A54529D59AA800F159DF /* libshared_static.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CCF1A53F29D599B800F159DF /* libshared_static.a */; };
+		CCF1A54829D59AC100F159DF /* Serde in Frameworks */ = {isa = PBXBuildFile; productRef = CCF1A54729D59AC100F159DF /* Serde */; };
+		CCF1A54A29D59B0100F159DF /* shared_types.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCF1A54929D59B0100F159DF /* shared_types.swift */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXBuildRule section */
-		CC8A3A7429507CA200ED2D9F /* PBXBuildRule */ = {
+		CCF1A53529D5992500F159DF /* PBXBuildRule */ = {
 			isa = PBXBuildRule;
 			compilerSpec = com.apple.compilers.proxy.script;
 			filePatterns = "*.udl";
@@ -32,135 +31,154 @@
 				"$(PROJECT_DIR)/generated/$(INPUT_FILE_BASE)FFI.h",
 			);
 			runOncePerArchitecture = 0;
-			script = "# Skip during indexing phase in XCode 13+\nif [ $ACTION == \"indexbuild\" ]; then\n   echo \"Not building *.udl files during indexing.\"\n   exit 0\nfi\n\n# Skip for preview builds\nif [ \"${ENABLE_PREVIEWS}\" = \"YES\" ]; then\n   echo \"Not building *.udl files during preview builds.\"\n   exit 0\nfi\n\ncd \"$INPUT_FILE_DIR\"/.. && \"$PROJECT_DIR/../target/debug/uniffi-bindgen\" generate src/\"$INPUT_FILE_NAME\" --language swift --out-dir \"$PROJECT_DIR/generated\"\n";
+			script = "# Skip during indexing phase in XCode 13+\nif [ $ACTION == \"indexbuild\" ]; then\n   echo \"Not building *.udl files during indexing.\"\n   exit 0\nfi\n\n# Skip for preview builds\nif [ \"${ENABLE_PREVIEWS}\" = \"YES\" ]; then\n   echo \"Not building *.udl files during preview builds.\"\n   exit 0\nfi\n\n# note, for now, run a cargo build manually to ensure the binary exists for this step\ncd \"$INPUT_FILE_DIR\"/.. && \"$PROJECT_DIR/../target/debug/uniffi-bindgen\" generate src/\"$INPUT_FILE_NAME\" --language swift --out-dir \"$PROJECT_DIR/generated\"\n";
 		};
 /* End PBXBuildRule section */
 
+/* Begin PBXContainerItemProxy section */
+		CCF1A53E29D599B800F159DF /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = CCF1A53829D599B700F159DF /* shared.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = CA6069A09261FB09138082B7;
+			remoteInfo = "shared-staticlib";
+		};
+		CCF1A54029D599B800F159DF /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = CCF1A53829D599B700F159DF /* shared.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = CA60ECB8EC0A10F7F7FCAC5B;
+			remoteInfo = "shared-cdylib";
+		};
+		CCF1A54229D599B800F159DF /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = CCF1A53829D599B700F159DF /* shared.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = CA60BEE814088109328FB0D5;
+			remoteInfo = "uniffi-bindgen-bin";
+		};
+/* End PBXContainerItemProxy section */
+
 /* Begin PBXFileReference section */
-		CC49939D29507FD300225E0E /* shared_types.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = shared_types.swift; path = ../shared_types/generated/swift/shared_types.swift; sourceTree = "<group>"; };
-		CC8A3A6329507C6800ED2D9F /* CounterApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CounterApp.app; sourceTree = BUILT_PRODUCTS_DIR; };
-		CC8A3A6629507C6800ED2D9F /* CounterAppApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CounterAppApp.swift; sourceTree = "<group>"; };
-		CC8A3A6829507C6800ED2D9F /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
-		CC8A3A6A29507C6900ED2D9F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
-		CC8A3A6D29507C6900ED2D9F /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
-		CC8A3A7729507E0D00ED2D9F /* shared.udl */ = {isa = PBXFileReference; lastKnownFileType = text; name = shared.udl; path = ../shared/src/shared.udl; sourceTree = "<group>"; };
-		CC8A3A7A29507E9A00ED2D9F /* sharedFFI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = sharedFFI.h; path = generated/sharedFFI.h; sourceTree = "<group>"; };
-		CC8A3A7D29507EC900ED2D9F /* libshared.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libshared.a; path = "../../target/aarch64-apple-ios-sim/debug/libshared.a"; sourceTree = "<group>"; };
+		CC2C4F3229D598A600CF927F /* CounterApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CounterApp.app; sourceTree = BUILT_PRODUCTS_DIR; };
+		CC2C4F3529D598A600CF927F /* CounterAppApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CounterAppApp.swift; sourceTree = "<group>"; };
+		CC2C4F3729D598A600CF927F /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
+		CC2C4F3929D598A700CF927F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
+		CC2C4F3C29D598A700CF927F /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
+		CCF1A53629D5997600F159DF /* shared.udl */ = {isa = PBXFileReference; lastKnownFileType = text; name = shared.udl; path = ../shared/src/shared.udl; sourceTree = "<group>"; };
+		CCF1A53829D599B700F159DF /* shared.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = shared.xcodeproj; path = ../shared/shared.xcodeproj; sourceTree = "<group>"; };
+		CCF1A54929D59B0100F159DF /* shared_types.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = shared_types.swift; path = ../shared_types/generated/swift/shared_types.swift; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
-		CC8A3A6029507C6800ED2D9F /* Frameworks */ = {
+		CC2C4F2F29D598A600CF927F /* Frameworks */ = {
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				CC49939C29507FAB00225E0E /* Serde in Frameworks */,
-				CC8A3A7E29507EC900ED2D9F /* libshared.a in Frameworks */,
+				CCF1A54829D59AC100F159DF /* Serde in Frameworks */,
+				CCF1A54529D59AA800F159DF /* libshared_static.a in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 /* End PBXFrameworksBuildPhase section */
 
 /* Begin PBXGroup section */
-		CC8A3A5A29507C6800ED2D9F = {
+		CC2C4F2929D598A600CF927F = {
 			isa = PBXGroup;
 			children = (
-				CC49939D29507FD300225E0E /* shared_types.swift */,
-				CC8A3A7A29507E9A00ED2D9F /* sharedFFI.h */,
-				CC8A3A7729507E0D00ED2D9F /* shared.udl */,
-				CC8A3A6529507C6800ED2D9F /* CounterApp */,
-				CC8A3A6429507C6800ED2D9F /* Products */,
-				CC8A3A7C29507EC900ED2D9F /* Frameworks */,
+				CCF1A54929D59B0100F159DF /* shared_types.swift */,
+				CCF1A53829D599B700F159DF /* shared.xcodeproj */,
+				CCF1A53629D5997600F159DF /* shared.udl */,
+				CC2C4F3429D598A600CF927F /* CounterApp */,
+				CC2C4F3329D598A600CF927F /* Products */,
+				CCF1A54429D59AA800F159DF /* Frameworks */,
 			);
 			sourceTree = "<group>";
 		};
-		CC8A3A6429507C6800ED2D9F /* Products */ = {
+		CC2C4F3329D598A600CF927F /* Products */ = {
 			isa = PBXGroup;
 			children = (
-				CC8A3A6329507C6800ED2D9F /* CounterApp.app */,
+				CC2C4F3229D598A600CF927F /* CounterApp.app */,
 			);
 			name = Products;
 			sourceTree = "<group>";
 		};
-		CC8A3A6529507C6800ED2D9F /* CounterApp */ = {
+		CC2C4F3429D598A600CF927F /* CounterApp */ = {
 			isa = PBXGroup;
 			children = (
-				CC8A3A6629507C6800ED2D9F /* CounterAppApp.swift */,
-				CC8A3A6829507C6800ED2D9F /* ContentView.swift */,
-				CC8A3A6A29507C6900ED2D9F /* Assets.xcassets */,
-				CC8A3A6C29507C6900ED2D9F /* Preview Content */,
+				CC2C4F3529D598A600CF927F /* CounterAppApp.swift */,
+				CC2C4F3729D598A600CF927F /* ContentView.swift */,
+				CC2C4F3929D598A700CF927F /* Assets.xcassets */,
+				CC2C4F3B29D598A700CF927F /* Preview Content */,
 			);
 			path = CounterApp;
 			sourceTree = "<group>";
 		};
-		CC8A3A6C29507C6900ED2D9F /* Preview Content */ = {
+		CC2C4F3B29D598A700CF927F /* Preview Content */ = {
 			isa = PBXGroup;
 			children = (
-				CC8A3A6D29507C6900ED2D9F /* Preview Assets.xcassets */,
+				CC2C4F3C29D598A700CF927F /* Preview Assets.xcassets */,
 			);
 			path = "Preview Content";
 			sourceTree = "<group>";
 		};
-		CC8A3A7C29507EC900ED2D9F /* Frameworks */ = {
+		CCF1A53929D599B700F159DF /* Products */ = {
 			isa = PBXGroup;
 			children = (
-				CC8A3A7D29507EC900ED2D9F /* libshared.a */,
+				CCF1A53F29D599B800F159DF /* libshared_static.a */,
+				CCF1A54129D599B800F159DF /* shared.dylib */,
+				CCF1A54329D599B800F159DF /* uniffi-bindgen */,
 			);
-			name = Frameworks;
+			name = Products;
 			sourceTree = "<group>";
 		};
-/* End PBXGroup section */
-
-/* Begin PBXHeadersBuildPhase section */
-		CC8A3A7929507E6F00ED2D9F /* Headers */ = {
-			isa = PBXHeadersBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				CC8A3A7B29507E9A00ED2D9F /* sharedFFI.h in Headers */,
+		CCF1A54429D59AA800F159DF /* Frameworks */ = {
+			isa = PBXGroup;
+			children = (
 			);
-			runOnlyForDeploymentPostprocessing = 0;
+			name = Frameworks;
+			sourceTree = "<group>";
 		};
-/* End PBXHeadersBuildPhase section */
+/* End PBXGroup section */
 
 /* Begin PBXNativeTarget section */
-		CC8A3A6229507C6800ED2D9F /* CounterApp */ = {
+		CC2C4F3129D598A600CF927F /* CounterApp */ = {
 			isa = PBXNativeTarget;
-			buildConfigurationList = CC8A3A7129507C6900ED2D9F /* Build configuration list for PBXNativeTarget "CounterApp" */;
+			buildConfigurationList = CC2C4F4029D598A700CF927F /* Build configuration list for PBXNativeTarget "CounterApp" */;
 			buildPhases = (
-				CC8A3A7629507DD000ED2D9F /* Build Rust library */,
-				CC8A3A7929507E6F00ED2D9F /* Headers */,
-				CC8A3A5F29507C6800ED2D9F /* Sources */,
-				CC8A3A6029507C6800ED2D9F /* Frameworks */,
-				CC8A3A6129507C6800ED2D9F /* Resources */,
+				CC2C4F2E29D598A600CF927F /* Sources */,
+				CC2C4F2F29D598A600CF927F /* Frameworks */,
+				CC2C4F3029D598A600CF927F /* Resources */,
 			);
 			buildRules = (
-				CC8A3A7429507CA200ED2D9F /* PBXBuildRule */,
+				CCF1A53529D5992500F159DF /* PBXBuildRule */,
 			);
 			dependencies = (
 			);
 			name = CounterApp;
 			packageProductDependencies = (
-				CC49939B29507FAB00225E0E /* Serde */,
+				CCF1A54729D59AC100F159DF /* Serde */,
 			);
 			productName = CounterApp;
-			productReference = CC8A3A6329507C6800ED2D9F /* CounterApp.app */;
+			productReference = CC2C4F3229D598A600CF927F /* CounterApp.app */;
 			productType = "com.apple.product-type.application";
 		};
 /* End PBXNativeTarget section */
 
 /* Begin PBXProject section */
-		CC8A3A5B29507C6800ED2D9F /* Project object */ = {
+		CC2C4F2A29D598A600CF927F /* Project object */ = {
 			isa = PBXProject;
 			attributes = {
 				BuildIndependentTargetsInParallel = 1;
 				LastSwiftUpdateCheck = 1420;
 				LastUpgradeCheck = 1420;
 				TargetAttributes = {
-					CC8A3A6229507C6800ED2D9F = {
+					CC2C4F3129D598A600CF927F = {
 						CreatedOnToolsVersion = 14.2;
 					};
 				};
 			};
-			buildConfigurationList = CC8A3A5E29507C6800ED2D9F /* Build configuration list for PBXProject "CounterApp" */;
+			buildConfigurationList = CC2C4F2D29D598A600CF927F /* Build configuration list for PBXProject "CounterApp" */;
 			compatibilityVersion = "Xcode 14.0";
 			developmentRegion = en;
 			hasScannedForEncodings = 0;
@@ -168,69 +186,77 @@
 				en,
 				Base,
 			);
-			mainGroup = CC8A3A5A29507C6800ED2D9F;
+			mainGroup = CC2C4F2929D598A600CF927F;
 			packageReferences = (
-				CC49939A29507FAB00225E0E /* XCRemoteSwiftPackageReference "Serde" */,
+				CCF1A54629D59AC100F159DF /* XCRemoteSwiftPackageReference "Serde" */,
 			);
-			productRefGroup = CC8A3A6429507C6800ED2D9F /* Products */;
+			productRefGroup = CC2C4F3329D598A600CF927F /* Products */;
 			projectDirPath = "";
+			projectReferences = (
+				{
+					ProductGroup = CCF1A53929D599B700F159DF /* Products */;
+					ProjectRef = CCF1A53829D599B700F159DF /* shared.xcodeproj */;
+				},
+			);
 			projectRoot = "";
 			targets = (
-				CC8A3A6229507C6800ED2D9F /* CounterApp */,
+				CC2C4F3129D598A600CF927F /* CounterApp */,
 			);
 		};
 /* End PBXProject section */
 
+/* Begin PBXReferenceProxy section */
+		CCF1A53F29D599B800F159DF /* libshared_static.a */ = {
+			isa = PBXReferenceProxy;
+			fileType = archive.ar;
+			path = libshared_static.a;
+			remoteRef = CCF1A53E29D599B800F159DF /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		CCF1A54129D599B800F159DF /* shared.dylib */ = {
+			isa = PBXReferenceProxy;
+			fileType = "compiled.mach-o.dylib";
+			path = shared.dylib;
+			remoteRef = CCF1A54029D599B800F159DF /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		CCF1A54329D599B800F159DF /* uniffi-bindgen */ = {
+			isa = PBXReferenceProxy;
+			fileType = "compiled.mach-o.executable";
+			path = "uniffi-bindgen";
+			remoteRef = CCF1A54229D599B800F159DF /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+/* End PBXReferenceProxy section */
+
 /* Begin PBXResourcesBuildPhase section */
-		CC8A3A6129507C6800ED2D9F /* Resources */ = {
+		CC2C4F3029D598A600CF927F /* Resources */ = {
 			isa = PBXResourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				CC8A3A6E29507C6900ED2D9F /* Preview Assets.xcassets in Resources */,
-				CC8A3A6B29507C6900ED2D9F /* Assets.xcassets in Resources */,
+				CC2C4F3D29D598A700CF927F /* Preview Assets.xcassets in Resources */,
+				CC2C4F3A29D598A700CF927F /* Assets.xcassets in Resources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 /* End PBXResourcesBuildPhase section */
 
-/* Begin PBXShellScriptBuildPhase section */
-		CC8A3A7629507DD000ED2D9F /* Build Rust library */ = {
-			isa = PBXShellScriptBuildPhase;
-			alwaysOutOfDate = 1;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			inputFileListPaths = (
-			);
-			inputPaths = (
-			);
-			name = "Build Rust library";
-			outputFileListPaths = (
-			);
-			outputPaths = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-			shellPath = /bin/sh;
-			shellScript = "cd \"${PROJECT_DIR}\"/../shared\nbash \"${PROJECT_DIR}/bin/compile-library.sh\" shared\n";
-		};
-/* End PBXShellScriptBuildPhase section */
-
 /* Begin PBXSourcesBuildPhase section */
-		CC8A3A5F29507C6800ED2D9F /* Sources */ = {
+		CC2C4F2E29D598A600CF927F /* Sources */ = {
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				CC49939E29507FD300225E0E /* shared_types.swift in Sources */,
-				CC8A3A7829507E0D00ED2D9F /* shared.udl in Sources */,
-				CC8A3A6929507C6800ED2D9F /* ContentView.swift in Sources */,
-				CC8A3A6729507C6800ED2D9F /* CounterAppApp.swift in Sources */,
+				CCF1A54A29D59B0100F159DF /* shared_types.swift in Sources */,
+				CCF1A53729D5997600F159DF /* shared.udl in Sources */,
+				CC2C4F3829D598A600CF927F /* ContentView.swift in Sources */,
+				CC2C4F3629D598A600CF927F /* CounterAppApp.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 /* End PBXSourcesBuildPhase section */
 
 /* Begin XCBuildConfiguration section */
-		CC8A3A6F29507C6900ED2D9F /* Debug */ = {
+		CC2C4F3E29D598A700CF927F /* Debug */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
 				ALWAYS_SEARCH_USER_PATHS = NO;
@@ -290,7 +316,7 @@
 			};
 			name = Debug;
 		};
-		CC8A3A7029507C6900ED2D9F /* Release */ = {
+		CC2C4F3F29D598A700CF927F /* Release */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
 				ALWAYS_SEARCH_USER_PATHS = NO;
@@ -344,7 +370,7 @@
 			};
 			name = Release;
 		};
-		CC8A3A7229507C6900ED2D9F /* Debug */ = {
+		CC2C4F4129D598A700CF927F /* Debug */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
@@ -352,6 +378,7 @@
 				CODE_SIGN_STYLE = Automatic;
 				CURRENT_PROJECT_VERSION = 1;
 				DEVELOPMENT_ASSET_PATHS = "\"CounterApp/Preview Content\"";
+				DEVELOPMENT_TEAM = E5DS2C9C62;
 				ENABLE_PREVIEWS = YES;
 				GENERATE_INFOPLIST_FILE = YES;
 				INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
@@ -363,20 +390,17 @@
 					"$(inherited)",
 					"@executable_path/Frameworks",
 				);
-				"LIBRARY_SEARCH_PATHS[sdk=iphoneos*][arch=arm64]" = "$(PROJECT_DIR)/../target/aarch64-apple-ios/debug";
-				"LIBRARY_SEARCH_PATHS[sdk=iphonesimulator*][arch=arm64]" = "$(PROJECT_DIR)/../target/aarch64-apple-ios-sim/debug";
-				"LIBRARY_SEARCH_PATHS[sdk=iphonesimulator*][arch=x86_64]" = "$(PROJECT_DIR)/../target/x86_64-apple-ios/debug";
 				MARKETING_VERSION = 1.0;
 				PRODUCT_BUNDLE_IDENTIFIER = com.redbadger.crux.CounterApp;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SWIFT_EMIT_LOC_STRINGS = YES;
-				"SWIFT_OBJC_BRIDGING_HEADER[arch=*]" = generated/sharedFFI.h;
+				SWIFT_OBJC_BRIDGING_HEADER = generated/sharedFFI.h;
 				SWIFT_VERSION = 5.0;
 				TARGETED_DEVICE_FAMILY = "1,2";
 			};
 			name = Debug;
 		};
-		CC8A3A7329507C6900ED2D9F /* Release */ = {
+		CC2C4F4229D598A700CF927F /* Release */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
@@ -384,6 +408,7 @@
 				CODE_SIGN_STYLE = Automatic;
 				CURRENT_PROJECT_VERSION = 1;
 				DEVELOPMENT_ASSET_PATHS = "\"CounterApp/Preview Content\"";
+				DEVELOPMENT_TEAM = E5DS2C9C62;
 				ENABLE_PREVIEWS = YES;
 				GENERATE_INFOPLIST_FILE = YES;
 				INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
@@ -395,14 +420,11 @@
 					"$(inherited)",
 					"@executable_path/Frameworks",
 				);
-				"LIBRARY_SEARCH_PATHS[sdk=iphoneos*][arch=arm64]" = "$(PROJECT_DIR)/../target/aarch64-apple-ios/release";
-				"LIBRARY_SEARCH_PATHS[sdk=iphonesimulator*][arch=arm64]" = "$(PROJECT_DIR)/../target/aarch64-apple-ios-sim/release";
-				"LIBRARY_SEARCH_PATHS[sdk=iphonesimulator*][arch=x86_64]" = "$(PROJECT_DIR)/../target/x86_64-apple-ios/release";
 				MARKETING_VERSION = 1.0;
 				PRODUCT_BUNDLE_IDENTIFIER = com.redbadger.crux.CounterApp;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SWIFT_EMIT_LOC_STRINGS = YES;
-				"SWIFT_OBJC_BRIDGING_HEADER[arch=*]" = generated/sharedFFI.h;
+				SWIFT_OBJC_BRIDGING_HEADER = generated/sharedFFI.h;
 				SWIFT_VERSION = 5.0;
 				TARGETED_DEVICE_FAMILY = "1,2";
 			};
@@ -411,20 +433,20 @@
 /* End XCBuildConfiguration section */
 
 /* Begin XCConfigurationList section */
-		CC8A3A5E29507C6800ED2D9F /* Build configuration list for PBXProject "CounterApp" */ = {
+		CC2C4F2D29D598A600CF927F /* Build configuration list for PBXProject "CounterApp" */ = {
 			isa = XCConfigurationList;
 			buildConfigurations = (
-				CC8A3A6F29507C6900ED2D9F /* Debug */,
-				CC8A3A7029507C6900ED2D9F /* Release */,
+				CC2C4F3E29D598A700CF927F /* Debug */,
+				CC2C4F3F29D598A700CF927F /* Release */,
 			);
 			defaultConfigurationIsVisible = 0;
 			defaultConfigurationName = Release;
 		};
-		CC8A3A7129507C6900ED2D9F /* Build configuration list for PBXNativeTarget "CounterApp" */ = {
+		CC2C4F4029D598A700CF927F /* Build configuration list for PBXNativeTarget "CounterApp" */ = {
 			isa = XCConfigurationList;
 			buildConfigurations = (
-				CC8A3A7229507C6900ED2D9F /* Debug */,
-				CC8A3A7329507C6900ED2D9F /* Release */,
+				CC2C4F4129D598A700CF927F /* Debug */,
+				CC2C4F4229D598A700CF927F /* Release */,
 			);
 			defaultConfigurationIsVisible = 0;
 			defaultConfigurationName = Release;
@@ -432,7 +454,7 @@
 /* End XCConfigurationList section */
 
 /* Begin XCRemoteSwiftPackageReference section */
-		CC49939A29507FAB00225E0E /* XCRemoteSwiftPackageReference "Serde" */ = {
+		CCF1A54629D59AC100F159DF /* XCRemoteSwiftPackageReference "Serde" */ = {
 			isa = XCRemoteSwiftPackageReference;
 			repositoryURL = "https://github.com/starcoin-sdk/Serde.swift";
 			requirement = {
@@ -443,12 +465,12 @@
 /* End XCRemoteSwiftPackageReference section */
 
 /* Begin XCSwiftPackageProductDependency section */
-		CC49939B29507FAB00225E0E /* Serde */ = {
+		CCF1A54729D59AC100F159DF /* Serde */ = {
 			isa = XCSwiftPackageProductDependency;
-			package = CC49939A29507FAB00225E0E /* XCRemoteSwiftPackageReference "Serde" */;
+			package = CCF1A54629D59AC100F159DF /* XCRemoteSwiftPackageReference "Serde" */;
 			productName = Serde;
 		};
 /* End XCSwiftPackageProductDependency section */
 	};
-	rootObject = CC8A3A5B29507C6800ED2D9F /* Project object */;
+	rootObject = CC2C4F2A29D598A600CF927F /* Project object */;
 }
diff --git a/examples/counter/iOS/CounterApp.xcodeproj/xcuserdata/stuartharris.xcuserdatad/xcschemes/xcschememanagement.plist b/examples/counter/iOS/CounterApp.xcodeproj/xcuserdata/stuartharris.xcuserdatad/xcschemes/xcschememanagement.plist
index 55656b8f..33df982d 100644
--- a/examples/counter/iOS/CounterApp.xcodeproj/xcuserdata/stuartharris.xcuserdatad/xcschemes/xcschememanagement.plist
+++ b/examples/counter/iOS/CounterApp.xcodeproj/xcuserdata/stuartharris.xcuserdatad/xcschemes/xcschememanagement.plist
@@ -7,7 +7,7 @@
 		<key>CounterApp.xcscheme_^#shared#^_</key>
 		<dict>
 			<key>orderHint</key>
-			<integer>0</integer>
+			<integer>1</integer>
 		</dict>
 	</dict>
 </dict>
diff --git a/examples/counter/iOS/CounterApp/ContentView.swift b/examples/counter/iOS/CounterApp/ContentView.swift
index b81477c3..f322383a 100644
--- a/examples/counter/iOS/CounterApp/ContentView.swift
+++ b/examples/counter/iOS/CounterApp/ContentView.swift
@@ -44,7 +44,8 @@ class Model: ObservableObject {
         Task {
             let (asyncBytes, response) = try! await URLSession.shared.bytes(for: req)
             guard let httpResponse = response as? HTTPURLResponse,
-                  (200...299).contains(httpResponse.statusCode) else {
+                  (200 ... 299).contains(httpResponse.statusCode)
+            else {
                 // TODO: handle error
                 return
             }
@@ -110,13 +111,13 @@ struct ActionButton: View {
 
 struct ContentView: View {
     @ObservedObject var model: Model
-    
+
     var body: some View {
         VStack {
             Text("Crux Counter Example").font(.headline)
             Text("Rust Core, Swift Shell (SwiftUI)").padding()
             Text(String(model.view.text))
-                .foregroundColor( model.view.confirmed ? Color.black : Color.gray)
+                .foregroundColor(model.view.confirmed ? Color.black : Color.gray)
                 .padding()
             HStack {
                 ActionButton(label: "Decrement", color: .yellow) {
diff --git a/examples/counter/iOS/CounterApp/CounterAppApp.swift b/examples/counter/iOS/CounterApp/CounterAppApp.swift
index 5d77533e..3dab3f32 100644
--- a/examples/counter/iOS/CounterApp/CounterAppApp.swift
+++ b/examples/counter/iOS/CounterApp/CounterAppApp.swift
@@ -2,7 +2,7 @@
 //  CounterAppApp.swift
 //  CounterApp
 //
-//  Created by Stuart Harris on 19/12/2022.
+//  Created by Stuart Harris on 30/03/2023.
 //
 
 import SwiftUI
diff --git a/examples/counter/iOS/bin/compile-library.sh b/examples/counter/iOS/bin/compile-library.sh
deleted file mode 100644
index c4b73fef..00000000
--- a/examples/counter/iOS/bin/compile-library.sh
+++ /dev/null
@@ -1,52 +0,0 @@
-#!/usr/bin/env bash
-
-if [ "$#" -ne 1 ]; then
-  echo "Usage (note: only call inside XCode!):"
-  echo "$0 <FFI_TARGET>"
-  exit 1
-fi
-
-# what to pass to cargo build -p, e.g. your_lib_ffi
-FFI_TARGET=$1
-
-set -euvx
-
-RELFLAG=
-if [[ "$CONFIGURATION" != "Debug" ]]; then
-  RELFLAG=--release
-fi
-
-IS_SIMULATOR=0
-if [ "${LLVM_TARGET_TRIPLE_SUFFIX-}" = "-simulator" ]; then
-  IS_SIMULATOR=1
-fi
-
-export PATH="$PATH:$HOME/.cargo/bin"
-export LIBRARY_PATH
-
-for arch in $ARCHS; do
-  case "$arch" in
-  x86_64)
-    if [ $IS_SIMULATOR -eq 0 ]; then
-      echo "Building for x86_64, but not a simulator build. What's going on?" >&2
-      exit 2
-    fi
-
-    # Intel iOS simulator
-    export CFLAGS_x86_64_apple_ios="-target x86_64-apple-ios"
-    LIBRARY_PATH="${LIBRARY_PATH-}:$(xcrun --sdk iphonesimulator --show-sdk-path)/usr/lib"
-    cargo build -p "$FFI_TARGET" --lib $RELFLAG --target x86_64-apple-ios
-    ;;
-
-  arm64)
-    if [ $IS_SIMULATOR -eq 0 ]; then
-      # Hardware iOS targets
-      LIBRARY_PATH="${LIBRARY_PATH-}:$(xcrun --sdk iphoneos --show-sdk-path)/usr/lib"
-      cargo build -p "$FFI_TARGET" --lib $RELFLAG --target aarch64-apple-ios
-    else
-      LIBRARY_PATH="${LIBRARY_PATH-}:$(xcrun --sdk iphonesimulator --show-sdk-path)/usr/lib"
-      cargo build -p "$FFI_TARGET" --lib $RELFLAG --target aarch64-apple-ios-sim
-    fi
-    ;;
-  esac
-done
diff --git a/examples/counter/shared/shared.xcodeproj/project.pbxproj b/examples/counter/shared/shared.xcodeproj/project.pbxproj
new file mode 100644
index 00000000..effee869
--- /dev/null
+++ b/examples/counter/shared/shared.xcodeproj/project.pbxproj
@@ -0,0 +1,450 @@
+// !$*UTF8*$!
+{
+    /* generated with cargo-xcode 1.5.0 */
+    archiveVersion = 1;
+    classes = {
+    };
+    objectVersion = 53;
+    objects = {
+/* Begin PBXBuildFile section */
+        
+                CA60BA0D84F0F29647B252D5 /* Cargo.toml in Sources */ = {
+                    isa = PBXBuildFile;
+                    fileRef = CA607A311B533EF4668187A5 /* Cargo.toml */;
+                    settings = {
+                        COMPILER_FLAGS = "--lib"; /* == OTHER_INPUT_FILE_FLAGS */
+                    };
+                };
+                
+                CA60BA0D84F05BFC144F4C6E /* Cargo.toml in Sources */ = {
+                    isa = PBXBuildFile;
+                    fileRef = CA607A311B533EF4668187A5 /* Cargo.toml */;
+                    settings = {
+                        COMPILER_FLAGS = "--lib"; /* == OTHER_INPUT_FILE_FLAGS */
+                    };
+                };
+                
+                CA60BA0D84F0C5EF52D43448 /* Cargo.toml in Sources */ = {
+                    isa = PBXBuildFile;
+                    fileRef = CA607A311B533EF4668187A5 /* Cargo.toml */;
+                    settings = {
+                        COMPILER_FLAGS = "--bin 'uniffi-bindgen'"; /* == OTHER_INPUT_FILE_FLAGS */
+                    };
+                };
+                
+/* End PBXBuildFile section */
+
+/* Begin PBXBuildRule section */
+        CA607A311B53AC6C1400ACA8 /* PBXBuildRule */ = {
+            isa = PBXBuildRule;
+            compilerSpec = com.apple.compilers.proxy.script;
+            dependencyFile = "$(DERIVED_FILE_DIR)/$(CARGO_XCODE_TARGET_ARCH)-$(EXECUTABLE_NAME).d";
+            filePatterns = "*/Cargo.toml"; /* must contain asterisk */
+            fileType = pattern.proxy;
+            inputFiles = ();
+            isEditable = 0;
+            name = "Cargo project build";
+            outputFiles = (
+                "$(OBJECT_FILE_DIR)/$(CARGO_XCODE_TARGET_ARCH)-$(EXECUTABLE_NAME)",
+            );
+            script = "# generated with cargo-xcode 1.5.0\n\nset -eu; export PATH=\"$PATH:$HOME/.cargo/bin:/usr/local/bin\";\nif [ \"${IS_MACCATALYST-NO}\" = YES ]; then\n    CARGO_XCODE_TARGET_TRIPLE=\"${CARGO_XCODE_TARGET_ARCH}-apple-ios-macabi\"\nelse\n    CARGO_XCODE_TARGET_TRIPLE=\"${CARGO_XCODE_TARGET_ARCH}-apple-${CARGO_XCODE_TARGET_OS}\"\nfi\nif [ \"$CARGO_XCODE_TARGET_OS\" != \"darwin\" ]; then\n    PATH=\"${PATH/\\/Contents\\/Developer\\/Toolchains\\/XcodeDefault.xctoolchain\\/usr\\/bin:/xcode-provided-ld-cant-link-lSystem-for-the-host-build-script:}\"\nfi\nPATH=\"$PATH:/opt/homebrew/bin\" # Rust projects often depend on extra tools like nasm, which Xcode lacks\nif [ \"$CARGO_XCODE_BUILD_MODE\" == release ]; then\n    OTHER_INPUT_FILE_FLAGS=\"${OTHER_INPUT_FILE_FLAGS} --release\"\nfi\nif command -v rustup &> /dev/null; then\n    if ! rustup target list --installed | egrep -q \"${CARGO_XCODE_TARGET_TRIPLE}\"; then\n        echo \"warning: this build requires rustup toolchain for $CARGO_XCODE_TARGET_TRIPLE, but it isn\'t installed\"\n        rustup target add \"${CARGO_XCODE_TARGET_TRIPLE}\" || echo >&2 \"warning: can\'t install $CARGO_XCODE_TARGET_TRIPLE\"\n    fi\nfi\nif [ \"$ACTION\" = clean ]; then\n ( set -x; cargo clean --manifest-path=\"$SCRIPT_INPUT_FILE\" ${OTHER_INPUT_FILE_FLAGS} --target=\"${CARGO_XCODE_TARGET_TRIPLE}\"; );\nelse\n ( set -x; cargo build --manifest-path=\"$SCRIPT_INPUT_FILE\" --features=\"${CARGO_XCODE_FEATURES:-}\" ${OTHER_INPUT_FILE_FLAGS} --target=\"${CARGO_XCODE_TARGET_TRIPLE}\"; );\nfi\n# it\'s too hard to explain Cargo\'s actual exe path to Xcode build graph, so hardlink to a known-good path instead\nBUILT_SRC=\"${CARGO_TARGET_DIR}/${CARGO_XCODE_TARGET_TRIPLE}/${CARGO_XCODE_BUILD_MODE}/${CARGO_XCODE_CARGO_FILE_NAME}\"\nln -f -- \"$BUILT_SRC\" \"$SCRIPT_OUTPUT_FILE_0\"\n\n# xcode generates dep file, but for its own path, so append our rename to it\nDEP_FILE_SRC=\"${CARGO_TARGET_DIR}/${CARGO_XCODE_TARGET_TRIPLE}/${CARGO_XCODE_BUILD_MODE}/${CARGO_XCODE_CARGO_DEP_FILE_NAME}\"\nif [ -f \"$DEP_FILE_SRC\" ]; then\n    DEP_FILE_DST=\"${DERIVED_FILE_DIR}/${CARGO_XCODE_TARGET_ARCH}-${EXECUTABLE_NAME}.d\"\n    cp -f \"$DEP_FILE_SRC\" \"$DEP_FILE_DST\"\n    echo >> \"$DEP_FILE_DST\" \"$SCRIPT_OUTPUT_FILE_0: $BUILT_SRC\"\nfi\n\n# lipo script needs to know all the platform-specific files that have been built\n# archs is in the file name, so that paths don\'t stay around after archs change\n# must match input for LipoScript\nFILE_LIST=\"${DERIVED_FILE_DIR}/${ARCHS}-${EXECUTABLE_NAME}.xcfilelist\"\ntouch \"$FILE_LIST\"\nif ! egrep -q \"$SCRIPT_OUTPUT_FILE_0\" \"$FILE_LIST\" ; then\n    echo >> \"$FILE_LIST\" \"$SCRIPT_OUTPUT_FILE_0\"\nfi\n";
+        };
+/* End PBXBuildRule section */
+
+/* Begin PBXFileReference section */
+        
+        CA6069A09261FB09138082B7 /* staticlib */ = {
+            isa = PBXFileReference;
+            explicitFileType = "archive.ar";
+            includeInIndex = 0;
+            name = "libshared_static.a";
+            sourceTree = TARGET_BUILD_DIR;
+        };
+        CA60ECB8EC0A10F7F7FCAC5B /* cdylib */ = {
+            isa = PBXFileReference;
+            explicitFileType = "compiled.mach-o.dylib";
+            includeInIndex = 0;
+            name = "shared.dylib";
+            sourceTree = TARGET_BUILD_DIR;
+        };
+        CA60BEE814088109328FB0D5 /* bin */ = {
+            isa = PBXFileReference;
+            explicitFileType = "compiled.mach-o.executable";
+            includeInIndex = 0;
+            name = "uniffi-bindgen";
+            sourceTree = TARGET_BUILD_DIR;
+        };
+                CA607A311B533EF4668187A5 /* Cargo.toml */ = {
+                    isa = PBXFileReference;
+                    lastKnownFileType = text;
+                    fileEncoding = 4;
+                    name = "Cargo.toml";
+                    path = "Cargo.toml";
+                    sourceTree = "<group>";
+            };
+                    /* Rust needs libresolv */
+                    ADDEDBA66A6E1 = {
+                        isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition";
+                        name = libresolv.tbd; path = usr/lib/libresolv.tbd; sourceTree = SDKROOT;
+                    };
+                
+/* End PBXFileReference section */
+
+/* Begin PBXGroup section */
+        CA607A311B5398AF0B5890DB /* Frameworks */ = {
+            isa = PBXGroup;
+            children = (
+                ADDEDBA66A6E2,
+
+            );
+            name = Frameworks;
+            sourceTree = "<group>";
+        };
+
+        
+                ADDEDBA66A6E2 /* Required for static linking */ = {
+                    isa = PBXGroup;
+                    children = (
+                        ADDEDBA66A6E1
+                    );
+                    name = "Required for static linking";
+                    sourceTree = "<group>";
+                };
+
+        CA607A311B5322869D176AE5 /* Products */ = {
+            isa = PBXGroup;
+            children = (
+                CA6069A09261FB09138082B7,
+CA60ECB8EC0A10F7F7FCAC5B,
+CA60BEE814088109328FB0D5,
+
+            );
+            name = Products;
+            sourceTree = "<group>";
+        };
+
+        CA607A311B53D65BC3C892A8 /* Main */ = {
+            isa = PBXGroup;
+            children = (
+                CA607A311B533EF4668187A5,
+CA607A311B5322869D176AE5,
+CA607A311B5398AF0B5890DB,
+
+            );
+            sourceTree = "<group>";
+        };
+
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+        CA6069A09261F29647B252D5 /* shared-staticlib */ = {
+            isa = PBXNativeTarget;
+            buildConfigurationList = CA601D0E01A2F29647B252D5;
+            buildPhases = (
+                CA60249E15BBF29647B252D5 /* Sources */,
+                CA607A311B53AF6EBB7F357C /* Universal Binary lipo */,
+            );
+            buildRules = (
+                CA607A311B53AC6C1400ACA8 /* PBXBuildRule */,
+            );
+            dependencies = (
+            );
+            name = "shared-staticlib";
+            productName = "libshared_static.a";
+            productReference = CA6069A09261FB09138082B7;
+            productType = "com.apple.product-type.library.static";
+        };
+        CA60ECB8EC0A5BFC144F4C6E /* shared-cdylib */ = {
+            isa = PBXNativeTarget;
+            buildConfigurationList = CA601D0E01A25BFC144F4C6E;
+            buildPhases = (
+                CA60249E15BB5BFC144F4C6E /* Sources */,
+                CA607A311B53AF6EBB7F357C /* Universal Binary lipo */,
+            );
+            buildRules = (
+                CA607A311B53AC6C1400ACA8 /* PBXBuildRule */,
+            );
+            dependencies = (
+            );
+            name = "shared-cdylib";
+            productName = "shared.dylib";
+            productReference = CA60ECB8EC0A10F7F7FCAC5B;
+            productType = "com.apple.product-type.library.dynamic";
+        };
+        CA60BEE81408C5EF52D43448 /* uniffi-bindgen-bin */ = {
+            isa = PBXNativeTarget;
+            buildConfigurationList = CA601D0E01A2C5EF52D43448;
+            buildPhases = (
+                CA60249E15BBC5EF52D43448 /* Sources */,
+                CA607A311B53AF6EBB7F357C /* Universal Binary lipo */,
+            );
+            buildRules = (
+                CA607A311B53AC6C1400ACA8 /* PBXBuildRule */,
+            );
+            dependencies = (
+            );
+            name = "uniffi-bindgen-bin";
+            productName = "uniffi-bindgen";
+            productReference = CA60BEE814088109328FB0D5;
+            productType = "com.apple.product-type.tool";
+        };
+        
+/* End PBXNativeTarget section */
+
+        CA60249E15BBF29647B252D5 = {
+                    isa = PBXSourcesBuildPhase;
+                    buildActionMask = 2147483647;
+                    files = (
+                        CA60BA0D84F0F29647B252D5
+                    );
+                    runOnlyForDeploymentPostprocessing = 0;
+                };
+                
+        CA601D0E01A2F29647B252D5 /* staticlib */ = {
+            isa = XCConfigurationList;
+            buildConfigurations = (
+                CA60A54A875FF29647B252D5 /* Release */,
+                CA60B67B300EF29647B252D5 /* Debug */,
+            );
+            defaultConfigurationIsVisible = 0;
+            defaultConfigurationName = Release;
+        };
+            CA60A54A875FF29647B252D5 /* staticlib */ = {
+                isa = XCBuildConfiguration;
+                buildSettings = {
+                    PRODUCT_NAME = "shared_static";
+                    "CARGO_XCODE_CARGO_FILE_NAME" = "libshared.a";
+                    "CARGO_XCODE_CARGO_DEP_FILE_NAME" = "libshared.d";
+                    SUPPORTED_PLATFORMS = "macosx iphonesimulator iphoneos appletvsimulator appletvos";
+                    SKIP_INSTALL = YES;
+                INSTALL_GROUP = "";
+                INSTALL_MODE_FLAG = "";
+                INSTALL_OWNER = "";
+                    
+                };
+                name = Release;
+            };
+            CA60B67B300EF29647B252D5 /* staticlib */ = {
+                isa = XCBuildConfiguration;
+                buildSettings = {
+                    PRODUCT_NAME = "shared_static";
+                    "CARGO_XCODE_CARGO_FILE_NAME" = "libshared.a";
+                    "CARGO_XCODE_CARGO_DEP_FILE_NAME" = "libshared.d";
+                    SUPPORTED_PLATFORMS = "macosx iphonesimulator iphoneos appletvsimulator appletvos";
+                    SKIP_INSTALL = YES;
+                INSTALL_GROUP = "";
+                INSTALL_MODE_FLAG = "";
+                INSTALL_OWNER = "";
+                    
+                };
+                name = Debug;
+            };CA60249E15BB5BFC144F4C6E = {
+                    isa = PBXSourcesBuildPhase;
+                    buildActionMask = 2147483647;
+                    files = (
+                        CA60BA0D84F05BFC144F4C6E
+                    );
+                    runOnlyForDeploymentPostprocessing = 0;
+                };
+                
+        CA601D0E01A25BFC144F4C6E /* cdylib */ = {
+            isa = XCConfigurationList;
+            buildConfigurations = (
+                CA60A54A875F5BFC144F4C6E /* Release */,
+                CA60B67B300E5BFC144F4C6E /* Debug */,
+            );
+            defaultConfigurationIsVisible = 0;
+            defaultConfigurationName = Release;
+        };
+            CA60A54A875F5BFC144F4C6E /* cdylib */ = {
+                isa = XCBuildConfiguration;
+                buildSettings = {
+                    PRODUCT_NAME = "shared";
+                    "CARGO_XCODE_CARGO_FILE_NAME" = "libshared.dylib";
+                    "CARGO_XCODE_CARGO_DEP_FILE_NAME" = "libshared.d";
+                    SUPPORTED_PLATFORMS = "macosx";
+                    
+                    DYLIB_COMPATIBILITY_VERSION = "0";
+                };
+                name = Release;
+            };
+            CA60B67B300E5BFC144F4C6E /* cdylib */ = {
+                isa = XCBuildConfiguration;
+                buildSettings = {
+                    PRODUCT_NAME = "shared";
+                    "CARGO_XCODE_CARGO_FILE_NAME" = "libshared.dylib";
+                    "CARGO_XCODE_CARGO_DEP_FILE_NAME" = "libshared.d";
+                    SUPPORTED_PLATFORMS = "macosx";
+                    
+                    DYLIB_COMPATIBILITY_VERSION = "0";
+                };
+                name = Debug;
+            };CA60249E15BBC5EF52D43448 = {
+                    isa = PBXSourcesBuildPhase;
+                    buildActionMask = 2147483647;
+                    files = (
+                        CA60BA0D84F0C5EF52D43448
+                    );
+                    runOnlyForDeploymentPostprocessing = 0;
+                };
+                
+        CA601D0E01A2C5EF52D43448 /* bin */ = {
+            isa = XCConfigurationList;
+            buildConfigurations = (
+                CA60A54A875FC5EF52D43448 /* Release */,
+                CA60B67B300EC5EF52D43448 /* Debug */,
+            );
+            defaultConfigurationIsVisible = 0;
+            defaultConfigurationName = Release;
+        };
+            CA60A54A875FC5EF52D43448 /* bin */ = {
+                isa = XCBuildConfiguration;
+                buildSettings = {
+                    PRODUCT_NAME = "uniffi-bindgen";
+                    "CARGO_XCODE_CARGO_FILE_NAME" = "uniffi-bindgen";
+                    "CARGO_XCODE_CARGO_DEP_FILE_NAME" = "uniffi-bindgen.d";
+                    SUPPORTED_PLATFORMS = "macosx";
+                    
+                    
+                };
+                name = Release;
+            };
+            CA60B67B300EC5EF52D43448 /* bin */ = {
+                isa = XCBuildConfiguration;
+                buildSettings = {
+                    PRODUCT_NAME = "uniffi-bindgen";
+                    "CARGO_XCODE_CARGO_FILE_NAME" = "uniffi-bindgen";
+                    "CARGO_XCODE_CARGO_DEP_FILE_NAME" = "uniffi-bindgen.d";
+                    SUPPORTED_PLATFORMS = "macosx";
+                    
+                    
+                };
+                name = Debug;
+            };
+
+        CA607A311B53AF6EBB7F357C /* LipoScript */ = {
+            name = "Universal Binary lipo";
+            isa = PBXShellScriptBuildPhase;
+            buildActionMask = 2147483647;
+            files = ();
+            inputFileListPaths = ();
+            inputPaths = (
+                "$(DERIVED_FILE_DIR)/$(ARCHS)-$(EXECUTABLE_NAME).xcfilelist",
+            );
+            outputFileListPaths = ();
+            outputPaths = (
+                "$(TARGET_BUILD_DIR)/$(EXECUTABLE_PATH)"
+            );
+            runOnlyForDeploymentPostprocessing = 0;
+            shellPath = /bin/sh;
+            shellScript = "# generated with cargo-xcode 1.5.0\n\n            set -eux; cat \"$DERIVED_FILE_DIR/$ARCHS-$EXECUTABLE_NAME.xcfilelist\" | tr \'\\n\' \'\\0\' | xargs -0 lipo -create -output \"$TARGET_BUILD_DIR/$EXECUTABLE_PATH\"\n            if [ ${LD_DYLIB_INSTALL_NAME:+1} ]; then\n                install_name_tool -id \"$LD_DYLIB_INSTALL_NAME\" \"$TARGET_BUILD_DIR/$EXECUTABLE_PATH\"\n            fi\n        ";
+        };
+
+        CA607A311B5380E02D6C7F57 = {
+            isa = XCConfigurationList;
+            buildConfigurations = (
+                CA60BA882D473CC16B37690B /* Release */,
+                CA60BA882D47228BE02872F8 /* Debug */,
+            );
+            defaultConfigurationIsVisible = 0;
+            defaultConfigurationName = Release;
+        };
+
+        CA60BA882D473CC16B37690B = {
+            isa = XCBuildConfiguration;
+            buildSettings = {
+                
+            ALWAYS_SEARCH_USER_PATHS = NO;
+            SUPPORTS_MACCATALYST = YES;
+            CARGO_TARGET_DIR = "$(PROJECT_TEMP_DIR)/cargo_target"; /* for cargo */
+            CARGO_XCODE_FEATURES = ""; /* configure yourself */
+            "CARGO_XCODE_TARGET_ARCH[arch=arm64*]" = "aarch64";
+            "CARGO_XCODE_TARGET_ARCH[arch=x86_64*]" = "x86_64"; /* catalyst adds h suffix */
+            "CARGO_XCODE_TARGET_ARCH[arch=i386]" = "i686";
+            "CARGO_XCODE_TARGET_OS[sdk=macosx*]" = "darwin";
+            "CARGO_XCODE_TARGET_OS[sdk=iphonesimulator*]" = "ios-sim";
+            "CARGO_XCODE_TARGET_OS[sdk=iphonesimulator*][arch=x86_64*]" = "ios";
+            "CARGO_XCODE_TARGET_OS[sdk=iphoneos*]" = "ios";
+            "CARGO_XCODE_TARGET_OS[sdk=appletvsimulator*]" = "tvos";
+            "CARGO_XCODE_TARGET_OS[sdk=appletvos*]" = "tvos";
+            PRODUCT_NAME = "shared";
+            MARKETING_VERSION = "0.1.0";
+            CURRENT_PROJECT_VERSION = "0.1";
+            SDKROOT = macosx;
+        
+                "CARGO_XCODE_BUILD_MODE" = "release"; /* for xcode scripts */
+            };
+            name = Release;
+        };
+
+        CA60BA882D47228BE02872F8 = {
+            isa = XCBuildConfiguration;
+            buildSettings = {
+                
+            ALWAYS_SEARCH_USER_PATHS = NO;
+            SUPPORTS_MACCATALYST = YES;
+            CARGO_TARGET_DIR = "$(PROJECT_TEMP_DIR)/cargo_target"; /* for cargo */
+            CARGO_XCODE_FEATURES = ""; /* configure yourself */
+            "CARGO_XCODE_TARGET_ARCH[arch=arm64*]" = "aarch64";
+            "CARGO_XCODE_TARGET_ARCH[arch=x86_64*]" = "x86_64"; /* catalyst adds h suffix */
+            "CARGO_XCODE_TARGET_ARCH[arch=i386]" = "i686";
+            "CARGO_XCODE_TARGET_OS[sdk=macosx*]" = "darwin";
+            "CARGO_XCODE_TARGET_OS[sdk=iphonesimulator*]" = "ios-sim";
+            "CARGO_XCODE_TARGET_OS[sdk=iphonesimulator*][arch=x86_64*]" = "ios";
+            "CARGO_XCODE_TARGET_OS[sdk=iphoneos*]" = "ios";
+            "CARGO_XCODE_TARGET_OS[sdk=appletvsimulator*]" = "tvos";
+            "CARGO_XCODE_TARGET_OS[sdk=appletvos*]" = "tvos";
+            PRODUCT_NAME = "shared";
+            MARKETING_VERSION = "0.1.0";
+            CURRENT_PROJECT_VERSION = "0.1";
+            SDKROOT = macosx;
+        
+                "CARGO_XCODE_BUILD_MODE" = "debug"; /* for xcode scripts */
+                ONLY_ACTIVE_ARCH = YES;
+            };
+            name = Debug;
+        };
+
+        CA607A311B53E04653AD465F = {
+            isa = PBXProject;
+            attributes = {
+                LastUpgradeCheck = 1300;
+                TargetAttributes = {
+                    CA6069A09261F29647B252D5 = {
+                        CreatedOnToolsVersion = 9.2;
+                        ProvisioningStyle = Automatic;
+                    };
+                    CA60ECB8EC0A5BFC144F4C6E = {
+                        CreatedOnToolsVersion = 9.2;
+                        ProvisioningStyle = Automatic;
+                    };
+                    CA60BEE81408C5EF52D43448 = {
+                        CreatedOnToolsVersion = 9.2;
+                        ProvisioningStyle = Automatic;
+                    };
+                                    };
+            };
+            buildConfigurationList = CA607A311B5380E02D6C7F57;
+            compatibilityVersion = "Xcode 11.4";
+             developmentRegion = en;
+            hasScannedForEncodings = 0;
+            knownRegions = (
+                    en,
+                    Base,
+            );
+            mainGroup = CA607A311B53D65BC3C892A8;
+            productRefGroup = CA607A311B5322869D176AE5 /* Products */;
+            projectDirPath = "";
+            projectRoot = "";
+            targets = (
+                CA6069A09261F29647B252D5,
+CA60ECB8EC0A5BFC144F4C6E,
+CA60BEE81408C5EF52D43448,
+
+            );
+        };
+
+    };
+    rootObject = CA607A311B53E04653AD465F;
+}
+    
\ No newline at end of file
diff --git a/examples/counter/shared/shared.xcodeproj/xcuserdata/stuartharris.xcuserdatad/xcschemes/xcschememanagement.plist b/examples/counter/shared/shared.xcodeproj/xcuserdata/stuartharris.xcuserdatad/xcschemes/xcschememanagement.plist
new file mode 100644
index 00000000..6d14cbc6
--- /dev/null
+++ b/examples/counter/shared/shared.xcodeproj/xcuserdata/stuartharris.xcuserdatad/xcschemes/xcschememanagement.plist
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>SchemeUserState</key>
+	<dict>
+		<key>shared-cdylib.xcscheme_^#shared#^_</key>
+		<dict>
+			<key>orderHint</key>
+			<integer>0</integer>
+		</dict>
+		<key>shared-staticlib.xcscheme_^#shared#^_</key>
+		<dict>
+			<key>orderHint</key>
+			<integer>3</integer>
+		</dict>
+		<key>uniffi-bindgen-bin.xcscheme_^#shared#^_</key>
+		<dict>
+			<key>orderHint</key>
+			<integer>2</integer>
+		</dict>
+	</dict>
+</dict>
+</plist>
diff --git a/examples/notes/ios/Notes.xcodeproj/project.pbxproj b/examples/notes/ios/Notes.xcodeproj/project.pbxproj
index 9fe96871..34c6fbc9 100644
--- a/examples/notes/ios/Notes.xcodeproj/project.pbxproj
+++ b/examples/notes/ios/Notes.xcodeproj/project.pbxproj
@@ -7,21 +7,18 @@
 	objects = {
 
 /* Begin PBXBuildFile section */
-		776CEC402989616C007ED363 /* NotesApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 776CEC3F2989616C007ED363 /* NotesApp.swift */; };
-		776CEC422989616C007ED363 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 776CEC412989616C007ED363 /* ContentView.swift */; };
-		776CEC442989616E007ED363 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 776CEC432989616E007ED363 /* Assets.xcassets */; };
-		776CEC472989616E007ED363 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 776CEC462989616E007ED363 /* Preview Assets.xcassets */; };
-		776CEC512989616E007ED363 /* NotesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 776CEC502989616E007ED363 /* NotesTests.swift */; };
-		776CEC5B2989616E007ED363 /* NotesUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 776CEC5A2989616E007ED363 /* NotesUITests.swift */; };
-		776CEC5D2989616E007ED363 /* NotesUITestsLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 776CEC5C2989616E007ED363 /* NotesUITestsLaunchTests.swift */; };
-		776CEC6B298962A7007ED363 /* shared.udl in Sources */ = {isa = PBXBuildFile; fileRef = 776CEC6A298962A7007ED363 /* shared.udl */; };
-		776CEC6F2989833A007ED363 /* libshared.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 776CEC6E2989833A007ED363 /* libshared.a */; };
-		776CEC7229898385007ED363 /* Serde in Frameworks */ = {isa = PBXBuildFile; productRef = 776CEC7129898385007ED363 /* Serde */; };
-		776CEC742989841C007ED363 /* shared_types.swift in Sources */ = {isa = PBXBuildFile; fileRef = 776CEC732989841C007ED363 /* shared_types.swift */; };
+		CC81055629D5A3B00026FC57 /* shared.udl in Sources */ = {isa = PBXBuildFile; fileRef = CC81055529D5A3B00026FC57 /* shared.udl */; };
+		CC81057029D5A5460026FC57 /* libshared_static.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CC81056A29D5A5370026FC57 /* libshared_static.a */; };
+		CC81057429D5A5840026FC57 /* shared_types.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC81057329D5A5840026FC57 /* shared_types.swift */; };
+		CC81057729D5A6100026FC57 /* Serde in Frameworks */ = {isa = PBXBuildFile; productRef = CC81057629D5A6100026FC57 /* Serde */; };
+		CCC4BE2329D5A28400F3E6BA /* NotesApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCC4BE2229D5A28400F3E6BA /* NotesApp.swift */; };
+		CCC4BE2529D5A28400F3E6BA /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCC4BE2429D5A28400F3E6BA /* ContentView.swift */; };
+		CCC4BE2729D5A28500F3E6BA /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CCC4BE2629D5A28500F3E6BA /* Assets.xcassets */; };
+		CCC4BE2A29D5A28500F3E6BA /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CCC4BE2929D5A28500F3E6BA /* Preview Assets.xcassets */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXBuildRule section */
-		776CEC6929896227007ED363 /* PBXBuildRule */ = {
+		CC81055429D5A3780026FC57 /* PBXBuildRule */ = {
 			isa = PBXBuildRule;
 			compilerSpec = com.apple.compilers.proxy.script;
 			filePatterns = "*.udl";
@@ -39,217 +36,149 @@
 /* End PBXBuildRule section */
 
 /* Begin PBXContainerItemProxy section */
-		776CEC4D2989616E007ED363 /* PBXContainerItemProxy */ = {
+		CC81056929D5A5370026FC57 /* PBXContainerItemProxy */ = {
 			isa = PBXContainerItemProxy;
-			containerPortal = 776CEC342989616C007ED363 /* Project object */;
-			proxyType = 1;
-			remoteGlobalIDString = 776CEC3B2989616C007ED363;
-			remoteInfo = Notes;
+			containerPortal = CC81056329D5A5370026FC57 /* shared.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = CA60CB052880FB09138082B7;
+			remoteInfo = "shared-staticlib";
 		};
-		776CEC572989616E007ED363 /* PBXContainerItemProxy */ = {
+		CC81056B29D5A5370026FC57 /* PBXContainerItemProxy */ = {
 			isa = PBXContainerItemProxy;
-			containerPortal = 776CEC342989616C007ED363 /* Project object */;
-			proxyType = 1;
-			remoteGlobalIDString = 776CEC3B2989616C007ED363;
-			remoteInfo = Notes;
+			containerPortal = CC81056329D5A5370026FC57 /* shared.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = CA602C9F76CC10F7F7FCAC5B;
+			remoteInfo = "shared-cdylib";
+		};
+		CC81056D29D5A5370026FC57 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = CC81056329D5A5370026FC57 /* shared.xcodeproj */;
+			proxyType = 2;
+			remoteGlobalIDString = CA6091720E328109328FB0D5;
+			remoteInfo = "uniffi-bindgen-bin";
 		};
 /* End PBXContainerItemProxy section */
 
 /* Begin PBXFileReference section */
-		776CEC3C2989616C007ED363 /* Notes.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Notes.app; sourceTree = BUILT_PRODUCTS_DIR; };
-		776CEC3F2989616C007ED363 /* NotesApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotesApp.swift; sourceTree = "<group>"; };
-		776CEC412989616C007ED363 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
-		776CEC432989616E007ED363 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
-		776CEC462989616E007ED363 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
-		776CEC4C2989616E007ED363 /* NotesTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NotesTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
-		776CEC502989616E007ED363 /* NotesTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotesTests.swift; sourceTree = "<group>"; };
-		776CEC562989616E007ED363 /* NotesUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NotesUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
-		776CEC5A2989616E007ED363 /* NotesUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotesUITests.swift; sourceTree = "<group>"; };
-		776CEC5C2989616E007ED363 /* NotesUITestsLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotesUITestsLaunchTests.swift; sourceTree = "<group>"; };
-		776CEC6A298962A7007ED363 /* shared.udl */ = {isa = PBXFileReference; lastKnownFileType = text; name = shared.udl; path = ../shared/src/shared.udl; sourceTree = "<group>"; };
-		776CEC6E2989833A007ED363 /* libshared.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libshared.a; path = ../target/debug/libshared.a; sourceTree = "<group>"; };
-		776CEC732989841C007ED363 /* shared_types.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = shared_types.swift; path = ../shared_types/generated/swift/shared_types.swift; sourceTree = "<group>"; };
+		CC81055529D5A3B00026FC57 /* shared.udl */ = {isa = PBXFileReference; lastKnownFileType = text; name = shared.udl; path = ../shared/src/shared.udl; sourceTree = "<group>"; };
+		CC81056329D5A5370026FC57 /* shared.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = shared.xcodeproj; path = ../shared/shared.xcodeproj; sourceTree = "<group>"; };
+		CC81057329D5A5840026FC57 /* shared_types.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = shared_types.swift; path = ../shared_types/generated/swift/shared_types.swift; sourceTree = "<group>"; };
+		CCC4BE1F29D5A28400F3E6BA /* Notes.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Notes.app; sourceTree = BUILT_PRODUCTS_DIR; };
+		CCC4BE2229D5A28400F3E6BA /* NotesApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotesApp.swift; sourceTree = "<group>"; };
+		CCC4BE2429D5A28400F3E6BA /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
+		CCC4BE2629D5A28500F3E6BA /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
+		CCC4BE2929D5A28500F3E6BA /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
-		776CEC392989616C007ED363 /* Frameworks */ = {
-			isa = PBXFrameworksBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				776CEC7229898385007ED363 /* Serde in Frameworks */,
-				776CEC6F2989833A007ED363 /* libshared.a in Frameworks */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		776CEC492989616E007ED363 /* Frameworks */ = {
-			isa = PBXFrameworksBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		776CEC532989616E007ED363 /* Frameworks */ = {
+		CCC4BE1C29D5A28400F3E6BA /* Frameworks */ = {
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				CC81057729D5A6100026FC57 /* Serde in Frameworks */,
+				CC81057029D5A5460026FC57 /* libshared_static.a in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 /* End PBXFrameworksBuildPhase section */
 
 /* Begin PBXGroup section */
-		776CEC332989616C007ED363 = {
-			isa = PBXGroup;
-			children = (
-				776CEC732989841C007ED363 /* shared_types.swift */,
-				776CEC6A298962A7007ED363 /* shared.udl */,
-				776CEC3E2989616C007ED363 /* Notes */,
-				776CEC4F2989616E007ED363 /* NotesTests */,
-				776CEC592989616E007ED363 /* NotesUITests */,
-				776CEC3D2989616C007ED363 /* Products */,
-				776CEC6D2989833A007ED363 /* Frameworks */,
-			);
-			sourceTree = "<group>";
-		};
-		776CEC3D2989616C007ED363 /* Products */ = {
+		CC81056429D5A5370026FC57 /* Products */ = {
 			isa = PBXGroup;
 			children = (
-				776CEC3C2989616C007ED363 /* Notes.app */,
-				776CEC4C2989616E007ED363 /* NotesTests.xctest */,
-				776CEC562989616E007ED363 /* NotesUITests.xctest */,
+				CC81056A29D5A5370026FC57 /* libshared_static.a */,
+				CC81056C29D5A5370026FC57 /* shared.dylib */,
+				CC81056E29D5A5370026FC57 /* uniffi-bindgen */,
 			);
 			name = Products;
 			sourceTree = "<group>";
 		};
-		776CEC3E2989616C007ED363 /* Notes */ = {
+		CC81056F29D5A5460026FC57 /* Frameworks */ = {
 			isa = PBXGroup;
 			children = (
-				776CEC3F2989616C007ED363 /* NotesApp.swift */,
-				776CEC412989616C007ED363 /* ContentView.swift */,
-				776CEC432989616E007ED363 /* Assets.xcassets */,
-				776CEC452989616E007ED363 /* Preview Content */,
 			);
-			path = Notes;
+			name = Frameworks;
 			sourceTree = "<group>";
 		};
-		776CEC452989616E007ED363 /* Preview Content */ = {
+		CCC4BE1629D5A28400F3E6BA = {
 			isa = PBXGroup;
 			children = (
-				776CEC462989616E007ED363 /* Preview Assets.xcassets */,
+				CC81057329D5A5840026FC57 /* shared_types.swift */,
+				CC81056329D5A5370026FC57 /* shared.xcodeproj */,
+				CC81055529D5A3B00026FC57 /* shared.udl */,
+				CCC4BE2129D5A28400F3E6BA /* Notes */,
+				CCC4BE2029D5A28400F3E6BA /* Products */,
+				CC81056F29D5A5460026FC57 /* Frameworks */,
 			);
-			path = "Preview Content";
 			sourceTree = "<group>";
 		};
-		776CEC4F2989616E007ED363 /* NotesTests */ = {
+		CCC4BE2029D5A28400F3E6BA /* Products */ = {
 			isa = PBXGroup;
 			children = (
-				776CEC502989616E007ED363 /* NotesTests.swift */,
+				CCC4BE1F29D5A28400F3E6BA /* Notes.app */,
 			);
-			path = NotesTests;
+			name = Products;
 			sourceTree = "<group>";
 		};
-		776CEC592989616E007ED363 /* NotesUITests */ = {
+		CCC4BE2129D5A28400F3E6BA /* Notes */ = {
 			isa = PBXGroup;
 			children = (
-				776CEC5A2989616E007ED363 /* NotesUITests.swift */,
-				776CEC5C2989616E007ED363 /* NotesUITestsLaunchTests.swift */,
+				CCC4BE2229D5A28400F3E6BA /* NotesApp.swift */,
+				CCC4BE2429D5A28400F3E6BA /* ContentView.swift */,
+				CCC4BE2629D5A28500F3E6BA /* Assets.xcassets */,
+				CCC4BE2829D5A28500F3E6BA /* Preview Content */,
 			);
-			path = NotesUITests;
+			path = Notes;
 			sourceTree = "<group>";
 		};
-		776CEC6D2989833A007ED363 /* Frameworks */ = {
+		CCC4BE2829D5A28500F3E6BA /* Preview Content */ = {
 			isa = PBXGroup;
 			children = (
-				776CEC6E2989833A007ED363 /* libshared.a */,
+				CCC4BE2929D5A28500F3E6BA /* Preview Assets.xcassets */,
 			);
-			name = Frameworks;
+			path = "Preview Content";
 			sourceTree = "<group>";
 		};
 /* End PBXGroup section */
 
 /* Begin PBXNativeTarget section */
-		776CEC3B2989616C007ED363 /* Notes */ = {
+		CCC4BE1E29D5A28400F3E6BA /* Notes */ = {
 			isa = PBXNativeTarget;
-			buildConfigurationList = 776CEC602989616E007ED363 /* Build configuration list for PBXNativeTarget "Notes" */;
+			buildConfigurationList = CCC4BE2D29D5A28500F3E6BA /* Build configuration list for PBXNativeTarget "Notes" */;
 			buildPhases = (
-				776CEC6C29897521007ED363 /* ShellScript */,
-				776CEC382989616C007ED363 /* Sources */,
-				776CEC392989616C007ED363 /* Frameworks */,
-				776CEC3A2989616C007ED363 /* Resources */,
+				CCC4BE1B29D5A28400F3E6BA /* Sources */,
+				CCC4BE1C29D5A28400F3E6BA /* Frameworks */,
+				CCC4BE1D29D5A28400F3E6BA /* Resources */,
 			);
 			buildRules = (
-				776CEC6929896227007ED363 /* PBXBuildRule */,
+				CC81055429D5A3780026FC57 /* PBXBuildRule */,
 			);
 			dependencies = (
 			);
 			name = Notes;
 			packageProductDependencies = (
-				776CEC7129898385007ED363 /* Serde */,
+				CC81057629D5A6100026FC57 /* Serde */,
 			);
 			productName = Notes;
-			productReference = 776CEC3C2989616C007ED363 /* Notes.app */;
+			productReference = CCC4BE1F29D5A28400F3E6BA /* Notes.app */;
 			productType = "com.apple.product-type.application";
 		};
-		776CEC4B2989616E007ED363 /* NotesTests */ = {
-			isa = PBXNativeTarget;
-			buildConfigurationList = 776CEC632989616E007ED363 /* Build configuration list for PBXNativeTarget "NotesTests" */;
-			buildPhases = (
-				776CEC482989616E007ED363 /* Sources */,
-				776CEC492989616E007ED363 /* Frameworks */,
-				776CEC4A2989616E007ED363 /* Resources */,
-			);
-			buildRules = (
-			);
-			dependencies = (
-				776CEC4E2989616E007ED363 /* PBXTargetDependency */,
-			);
-			name = NotesTests;
-			productName = NotesTests;
-			productReference = 776CEC4C2989616E007ED363 /* NotesTests.xctest */;
-			productType = "com.apple.product-type.bundle.unit-test";
-		};
-		776CEC552989616E007ED363 /* NotesUITests */ = {
-			isa = PBXNativeTarget;
-			buildConfigurationList = 776CEC662989616E007ED363 /* Build configuration list for PBXNativeTarget "NotesUITests" */;
-			buildPhases = (
-				776CEC522989616E007ED363 /* Sources */,
-				776CEC532989616E007ED363 /* Frameworks */,
-				776CEC542989616E007ED363 /* Resources */,
-			);
-			buildRules = (
-			);
-			dependencies = (
-				776CEC582989616E007ED363 /* PBXTargetDependency */,
-			);
-			name = NotesUITests;
-			productName = NotesUITests;
-			productReference = 776CEC562989616E007ED363 /* NotesUITests.xctest */;
-			productType = "com.apple.product-type.bundle.ui-testing";
-		};
 /* End PBXNativeTarget section */
 
 /* Begin PBXProject section */
-		776CEC342989616C007ED363 /* Project object */ = {
+		CCC4BE1729D5A28400F3E6BA /* Project object */ = {
 			isa = PBXProject;
 			attributes = {
 				BuildIndependentTargetsInParallel = 1;
 				LastSwiftUpdateCheck = 1420;
 				LastUpgradeCheck = 1420;
 				TargetAttributes = {
-					776CEC3B2989616C007ED363 = {
+					CCC4BE1E29D5A28400F3E6BA = {
 						CreatedOnToolsVersion = 14.2;
 					};
-					776CEC4B2989616E007ED363 = {
-						CreatedOnToolsVersion = 14.2;
-						TestTargetID = 776CEC3B2989616C007ED363;
-					};
-					776CEC552989616E007ED363 = {
-						CreatedOnToolsVersion = 14.2;
-						TestTargetID = 776CEC3B2989616C007ED363;
-					};
 				};
 			};
-			buildConfigurationList = 776CEC372989616C007ED363 /* Build configuration list for PBXProject "Notes" */;
+			buildConfigurationList = CCC4BE1A29D5A28400F3E6BA /* Build configuration list for PBXProject "Notes" */;
 			compatibilityVersion = "Xcode 14.0";
 			developmentRegion = en;
 			hasScannedForEncodings = 0;
@@ -257,114 +186,77 @@
 				en,
 				Base,
 			);
-			mainGroup = 776CEC332989616C007ED363;
+			mainGroup = CCC4BE1629D5A28400F3E6BA;
 			packageReferences = (
-				776CEC7029898385007ED363 /* XCRemoteSwiftPackageReference "Serde" */,
+				CC81057529D5A6100026FC57 /* XCRemoteSwiftPackageReference "Serde" */,
 			);
-			productRefGroup = 776CEC3D2989616C007ED363 /* Products */;
+			productRefGroup = CCC4BE2029D5A28400F3E6BA /* Products */;
 			projectDirPath = "";
+			projectReferences = (
+				{
+					ProductGroup = CC81056429D5A5370026FC57 /* Products */;
+					ProjectRef = CC81056329D5A5370026FC57 /* shared.xcodeproj */;
+				},
+			);
 			projectRoot = "";
 			targets = (
-				776CEC3B2989616C007ED363 /* Notes */,
-				776CEC4B2989616E007ED363 /* NotesTests */,
-				776CEC552989616E007ED363 /* NotesUITests */,
+				CCC4BE1E29D5A28400F3E6BA /* Notes */,
 			);
 		};
 /* End PBXProject section */
 
+/* Begin PBXReferenceProxy section */
+		CC81056A29D5A5370026FC57 /* libshared_static.a */ = {
+			isa = PBXReferenceProxy;
+			fileType = archive.ar;
+			path = libshared_static.a;
+			remoteRef = CC81056929D5A5370026FC57 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		CC81056C29D5A5370026FC57 /* shared.dylib */ = {
+			isa = PBXReferenceProxy;
+			fileType = "compiled.mach-o.dylib";
+			path = shared.dylib;
+			remoteRef = CC81056B29D5A5370026FC57 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+		CC81056E29D5A5370026FC57 /* uniffi-bindgen */ = {
+			isa = PBXReferenceProxy;
+			fileType = "compiled.mach-o.executable";
+			path = "uniffi-bindgen";
+			remoteRef = CC81056D29D5A5370026FC57 /* PBXContainerItemProxy */;
+			sourceTree = BUILT_PRODUCTS_DIR;
+		};
+/* End PBXReferenceProxy section */
+
 /* Begin PBXResourcesBuildPhase section */
-		776CEC3A2989616C007ED363 /* Resources */ = {
-			isa = PBXResourcesBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				776CEC472989616E007ED363 /* Preview Assets.xcassets in Resources */,
-				776CEC442989616E007ED363 /* Assets.xcassets in Resources */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		776CEC4A2989616E007ED363 /* Resources */ = {
-			isa = PBXResourcesBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		776CEC542989616E007ED363 /* Resources */ = {
+		CCC4BE1D29D5A28400F3E6BA /* Resources */ = {
 			isa = PBXResourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				CCC4BE2A29D5A28500F3E6BA /* Preview Assets.xcassets in Resources */,
+				CCC4BE2729D5A28500F3E6BA /* Assets.xcassets in Resources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 /* End PBXResourcesBuildPhase section */
 
-/* Begin PBXShellScriptBuildPhase section */
-		776CEC6C29897521007ED363 /* ShellScript */ = {
-			isa = PBXShellScriptBuildPhase;
-			alwaysOutOfDate = 1;
-			buildActionMask = 2147483647;
-			files = (
-			);
-			inputFileListPaths = (
-			);
-			inputPaths = (
-			);
-			outputFileListPaths = (
-			);
-			outputPaths = (
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-			shellPath = /bin/sh;
-			shellScript = "cd \"$PROJECT_DIR/../shared\"\nbash \"$PROJECT_DIR/bin/rust_build.sh\" shared\n";
-		};
-/* End PBXShellScriptBuildPhase section */
-
 /* Begin PBXSourcesBuildPhase section */
-		776CEC382989616C007ED363 /* Sources */ = {
+		CCC4BE1B29D5A28400F3E6BA /* Sources */ = {
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				776CEC742989841C007ED363 /* shared_types.swift in Sources */,
-				776CEC6B298962A7007ED363 /* shared.udl in Sources */,
-				776CEC422989616C007ED363 /* ContentView.swift in Sources */,
-				776CEC402989616C007ED363 /* NotesApp.swift in Sources */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		776CEC482989616E007ED363 /* Sources */ = {
-			isa = PBXSourcesBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				776CEC512989616E007ED363 /* NotesTests.swift in Sources */,
-			);
-			runOnlyForDeploymentPostprocessing = 0;
-		};
-		776CEC522989616E007ED363 /* Sources */ = {
-			isa = PBXSourcesBuildPhase;
-			buildActionMask = 2147483647;
-			files = (
-				776CEC5D2989616E007ED363 /* NotesUITestsLaunchTests.swift in Sources */,
-				776CEC5B2989616E007ED363 /* NotesUITests.swift in Sources */,
+				CC81057429D5A5840026FC57 /* shared_types.swift in Sources */,
+				CC81055629D5A3B00026FC57 /* shared.udl in Sources */,
+				CCC4BE2529D5A28400F3E6BA /* ContentView.swift in Sources */,
+				CCC4BE2329D5A28400F3E6BA /* NotesApp.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 /* End PBXSourcesBuildPhase section */
 
-/* Begin PBXTargetDependency section */
-		776CEC4E2989616E007ED363 /* PBXTargetDependency */ = {
-			isa = PBXTargetDependency;
-			target = 776CEC3B2989616C007ED363 /* Notes */;
-			targetProxy = 776CEC4D2989616E007ED363 /* PBXContainerItemProxy */;
-		};
-		776CEC582989616E007ED363 /* PBXTargetDependency */ = {
-			isa = PBXTargetDependency;
-			target = 776CEC3B2989616C007ED363 /* Notes */;
-			targetProxy = 776CEC572989616E007ED363 /* PBXContainerItemProxy */;
-		};
-/* End PBXTargetDependency section */
-
 /* Begin XCBuildConfiguration section */
-		776CEC5E2989616E007ED363 /* Debug */ = {
+		CCC4BE2B29D5A28500F3E6BA /* Debug */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
 				ALWAYS_SEARCH_USER_PATHS = NO;
@@ -420,12 +312,11 @@
 				ONLY_ACTIVE_ARCH = YES;
 				SDKROOT = iphoneos;
 				SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
-				"SWIFT_OBJC_BRIDGING_HEADER[arch=*]" = generated/sharedFFI.h;
 				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
 			};
 			name = Debug;
 		};
-		776CEC5F2989616E007ED363 /* Release */ = {
+		CCC4BE2C29D5A28500F3E6BA /* Release */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
 				ALWAYS_SEARCH_USER_PATHS = NO;
@@ -474,13 +365,12 @@
 				MTL_FAST_MATH = YES;
 				SDKROOT = iphoneos;
 				SWIFT_COMPILATION_MODE = wholemodule;
-				"SWIFT_OBJC_BRIDGING_HEADER[arch=*]" = generated/sharedFFI.h;
 				SWIFT_OPTIMIZATION_LEVEL = "-O";
 				VALIDATE_PRODUCT = YES;
 			};
 			name = Release;
 		};
-		776CEC612989616E007ED363 /* Debug */ = {
+		CCC4BE2E29D5A28500F3E6BA /* Debug */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
@@ -488,6 +378,7 @@
 				CODE_SIGN_STYLE = Automatic;
 				CURRENT_PROJECT_VERSION = 1;
 				DEVELOPMENT_ASSET_PATHS = "\"Notes/Preview Content\"";
+				DEVELOPMENT_TEAM = E5DS2C9C62;
 				ENABLE_PREVIEWS = YES;
 				GENERATE_INFOPLIST_FILE = YES;
 				INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
@@ -499,18 +390,17 @@
 					"$(inherited)",
 					"@executable_path/Frameworks",
 				);
-				"LIBRARY_SEARCH_PATHS[sdk=iphoneos*]" = "$(PROJECT_DIR)/../target/aarch64-apple-ios/debug";
-				"LIBRARY_SEARCH_PATHS[sdk=iphonesimulator*]" = "$(PROJECT_DIR)/../target/aarch64-apple-ios-sim/debug";
 				MARKETING_VERSION = 1.0;
-				PRODUCT_BUNDLE_IDENTIFIER = "com.red-badger.Notes";
+				PRODUCT_BUNDLE_IDENTIFIER = com.redbadger.crux.Notes;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SWIFT_EMIT_LOC_STRINGS = YES;
+				SWIFT_OBJC_BRIDGING_HEADER = generated/sharedFFI.h;
 				SWIFT_VERSION = 5.0;
 				TARGETED_DEVICE_FAMILY = "1,2";
 			};
 			name = Debug;
 		};
-		776CEC622989616E007ED363 /* Release */ = {
+		CCC4BE2F29D5A28500F3E6BA /* Release */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
@@ -518,6 +408,7 @@
 				CODE_SIGN_STYLE = Automatic;
 				CURRENT_PROJECT_VERSION = 1;
 				DEVELOPMENT_ASSET_PATHS = "\"Notes/Preview Content\"";
+				DEVELOPMENT_TEAM = E5DS2C9C62;
 				ENABLE_PREVIEWS = YES;
 				GENERATE_INFOPLIST_FILE = YES;
 				INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
@@ -529,124 +420,33 @@
 					"$(inherited)",
 					"@executable_path/Frameworks",
 				);
-				"LIBRARY_SEARCH_PATHS[sdk=iphoneos*]" = "$(PROJECT_DIR)/../target/aarch64-apple-ios/release";
-				"LIBRARY_SEARCH_PATHS[sdk=iphonesimulator*]" = "$(PROJECT_DIR)/../target/aarch64-apple-ios-sim/release";
 				MARKETING_VERSION = 1.0;
-				PRODUCT_BUNDLE_IDENTIFIER = "com.red-badger.Notes";
+				PRODUCT_BUNDLE_IDENTIFIER = com.redbadger.crux.Notes;
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SWIFT_EMIT_LOC_STRINGS = YES;
+				SWIFT_OBJC_BRIDGING_HEADER = generated/sharedFFI.h;
 				SWIFT_VERSION = 5.0;
 				TARGETED_DEVICE_FAMILY = "1,2";
 			};
 			name = Release;
 		};
-		776CEC642989616E007ED363 /* Debug */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
-				BUNDLE_LOADER = "$(TEST_HOST)";
-				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 1;
-				GENERATE_INFOPLIST_FILE = YES;
-				IPHONEOS_DEPLOYMENT_TARGET = 16.2;
-				MARKETING_VERSION = 1.0;
-				PRODUCT_BUNDLE_IDENTIFIER = "com.red-badger.NotesTests";
-				PRODUCT_NAME = "$(TARGET_NAME)";
-				SWIFT_EMIT_LOC_STRINGS = NO;
-				SWIFT_VERSION = 5.0;
-				TARGETED_DEVICE_FAMILY = "1,2";
-				TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Notes.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Notes";
-			};
-			name = Debug;
-		};
-		776CEC652989616E007ED363 /* Release */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
-				BUNDLE_LOADER = "$(TEST_HOST)";
-				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 1;
-				GENERATE_INFOPLIST_FILE = YES;
-				IPHONEOS_DEPLOYMENT_TARGET = 16.2;
-				MARKETING_VERSION = 1.0;
-				PRODUCT_BUNDLE_IDENTIFIER = "com.red-badger.NotesTests";
-				PRODUCT_NAME = "$(TARGET_NAME)";
-				SWIFT_EMIT_LOC_STRINGS = NO;
-				SWIFT_VERSION = 5.0;
-				TARGETED_DEVICE_FAMILY = "1,2";
-				TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Notes.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Notes";
-			};
-			name = Release;
-		};
-		776CEC672989616E007ED363 /* Debug */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
-				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 1;
-				GENERATE_INFOPLIST_FILE = YES;
-				MARKETING_VERSION = 1.0;
-				PRODUCT_BUNDLE_IDENTIFIER = "com.red-badger.NotesUITests";
-				PRODUCT_NAME = "$(TARGET_NAME)";
-				SWIFT_EMIT_LOC_STRINGS = NO;
-				SWIFT_VERSION = 5.0;
-				TARGETED_DEVICE_FAMILY = "1,2";
-				TEST_TARGET_NAME = Notes;
-			};
-			name = Debug;
-		};
-		776CEC682989616E007ED363 /* Release */ = {
-			isa = XCBuildConfiguration;
-			buildSettings = {
-				ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
-				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 1;
-				GENERATE_INFOPLIST_FILE = YES;
-				MARKETING_VERSION = 1.0;
-				PRODUCT_BUNDLE_IDENTIFIER = "com.red-badger.NotesUITests";
-				PRODUCT_NAME = "$(TARGET_NAME)";
-				SWIFT_EMIT_LOC_STRINGS = NO;
-				SWIFT_VERSION = 5.0;
-				TARGETED_DEVICE_FAMILY = "1,2";
-				TEST_TARGET_NAME = Notes;
-			};
-			name = Release;
-		};
 /* End XCBuildConfiguration section */
 
 /* Begin XCConfigurationList section */
-		776CEC372989616C007ED363 /* Build configuration list for PBXProject "Notes" */ = {
-			isa = XCConfigurationList;
-			buildConfigurations = (
-				776CEC5E2989616E007ED363 /* Debug */,
-				776CEC5F2989616E007ED363 /* Release */,
-			);
-			defaultConfigurationIsVisible = 0;
-			defaultConfigurationName = Release;
-		};
-		776CEC602989616E007ED363 /* Build configuration list for PBXNativeTarget "Notes" */ = {
-			isa = XCConfigurationList;
-			buildConfigurations = (
-				776CEC612989616E007ED363 /* Debug */,
-				776CEC622989616E007ED363 /* Release */,
-			);
-			defaultConfigurationIsVisible = 0;
-			defaultConfigurationName = Release;
-		};
-		776CEC632989616E007ED363 /* Build configuration list for PBXNativeTarget "NotesTests" */ = {
+		CCC4BE1A29D5A28400F3E6BA /* Build configuration list for PBXProject "Notes" */ = {
 			isa = XCConfigurationList;
 			buildConfigurations = (
-				776CEC642989616E007ED363 /* Debug */,
-				776CEC652989616E007ED363 /* Release */,
+				CCC4BE2B29D5A28500F3E6BA /* Debug */,
+				CCC4BE2C29D5A28500F3E6BA /* Release */,
 			);
 			defaultConfigurationIsVisible = 0;
 			defaultConfigurationName = Release;
 		};
-		776CEC662989616E007ED363 /* Build configuration list for PBXNativeTarget "NotesUITests" */ = {
+		CCC4BE2D29D5A28500F3E6BA /* Build configuration list for PBXNativeTarget "Notes" */ = {
 			isa = XCConfigurationList;
 			buildConfigurations = (
-				776CEC672989616E007ED363 /* Debug */,
-				776CEC682989616E007ED363 /* Release */,
+				CCC4BE2E29D5A28500F3E6BA /* Debug */,
+				CCC4BE2F29D5A28500F3E6BA /* Release */,
 			);
 			defaultConfigurationIsVisible = 0;
 			defaultConfigurationName = Release;
@@ -654,7 +454,7 @@
 /* End XCConfigurationList section */
 
 /* Begin XCRemoteSwiftPackageReference section */
-		776CEC7029898385007ED363 /* XCRemoteSwiftPackageReference "Serde" */ = {
+		CC81057529D5A6100026FC57 /* XCRemoteSwiftPackageReference "Serde" */ = {
 			isa = XCRemoteSwiftPackageReference;
 			repositoryURL = "https://github.com/starcoin-sdk/Serde.swift";
 			requirement = {
@@ -665,12 +465,12 @@
 /* End XCRemoteSwiftPackageReference section */
 
 /* Begin XCSwiftPackageProductDependency section */
-		776CEC7129898385007ED363 /* Serde */ = {
+		CC81057629D5A6100026FC57 /* Serde */ = {
 			isa = XCSwiftPackageProductDependency;
-			package = 776CEC7029898385007ED363 /* XCRemoteSwiftPackageReference "Serde" */;
+			package = CC81057529D5A6100026FC57 /* XCRemoteSwiftPackageReference "Serde" */;
 			productName = Serde;
 		};
 /* End XCSwiftPackageProductDependency section */
 	};
-	rootObject = 776CEC342989616C007ED363 /* Project object */;
+	rootObject = CCC4BE1729D5A28400F3E6BA /* Project object */;
 }
diff --git a/examples/notes/ios/Notes.xcodeproj/xcuserdata/viktor.xcuserdatad/xcschemes/xcschememanagement.plist b/examples/notes/ios/Notes.xcodeproj/xcuserdata/stuartharris.xcuserdatad/xcschemes/xcschememanagement.plist
similarity index 100%
rename from examples/notes/ios/Notes.xcodeproj/xcuserdata/viktor.xcuserdatad/xcschemes/xcschememanagement.plist
rename to examples/notes/ios/Notes.xcodeproj/xcuserdata/stuartharris.xcuserdatad/xcschemes/xcschememanagement.plist
diff --git a/examples/notes/ios/Notes/ContentView.swift b/examples/notes/ios/Notes/ContentView.swift
index 2202977f..61998cd3 100644
--- a/examples/notes/ios/Notes/ContentView.swift
+++ b/examples/notes/ios/Notes/ContentView.swift
@@ -2,7 +2,7 @@
 //  ContentView.swift
 //  Notes
 //
-//  Created by Viktor Charypar on 31/01/2023.
+//  Created by Stuart Harris on 30/03/2023.
 //
 
 import SwiftUI
@@ -22,7 +22,7 @@ typealias Uuid = [UInt8]
 
 enum CoreEvent {
     case event(Event)
-    // TODO response
+    // TODO: response
 }
 
 class Core: ObservableObject {
@@ -62,12 +62,14 @@ class Core: ObservableObject {
 
         for req in requests {
             switch req.effect {
-            case .render(_):
+            case .render:
                 view = try! ViewModel.bcsDeserialize(input: Notes.view())
             case let .pubSub(.publish(bytes)):
                 print(["Publish", bytes.count, "bytes"])
             case .pubSub(.subscribe):
                 print("Subscribe")
+            case .keyValue(_): ()
+            case .timer(_): ()
             }
         }
     }
@@ -123,7 +125,7 @@ struct TextEditor: UIViewRepresentable {
         var onEdit: ((TextChange) -> Void)?
         private var changes: [TextChange] = []
 
-        func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
+        func textView(_: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
             let change = TextChange(range: range, replacementText: text)
 
             // Stage the change
@@ -132,7 +134,7 @@ struct TextEditor: UIViewRepresentable {
             return true
         }
 
-        func textViewDidChange(_ textView: UITextView) {
+        func textViewDidChange(_: UITextView) {
             // Commit changes
             for change in changes {
                 onEdit?(change)
@@ -158,7 +160,6 @@ extension TextEditor {
     }
 }
 
-
 struct ContentView_Previews: PreviewProvider {
     static var previews: some View {
         ContentView()
diff --git a/examples/notes/ios/Notes/NotesApp.swift b/examples/notes/ios/Notes/NotesApp.swift
index 44e20b04..58e40420 100644
--- a/examples/notes/ios/Notes/NotesApp.swift
+++ b/examples/notes/ios/Notes/NotesApp.swift
@@ -2,7 +2,7 @@
 //  NotesApp.swift
 //  Notes
 //
-//  Created by Viktor Charypar on 31/01/2023.
+//  Created by Stuart Harris on 30/03/2023.
 //
 
 import SwiftUI
diff --git a/examples/notes/ios/NotesTests/NotesTests.swift b/examples/notes/ios/NotesTests/NotesTests.swift
deleted file mode 100644
index d6335efe..00000000
--- a/examples/notes/ios/NotesTests/NotesTests.swift
+++ /dev/null
@@ -1,36 +0,0 @@
-//
-//  NotesTests.swift
-//  NotesTests
-//
-//  Created by Viktor Charypar on 31/01/2023.
-//
-
-import XCTest
-@testable import Notes
-
-final class NotesTests: XCTestCase {
-
-    override func setUpWithError() throws {
-        // Put setup code here. This method is called before the invocation of each test method in the class.
-    }
-
-    override func tearDownWithError() throws {
-        // Put teardown code here. This method is called after the invocation of each test method in the class.
-    }
-
-    func testExample() throws {
-        // This is an example of a functional test case.
-        // Use XCTAssert and related functions to verify your tests produce the correct results.
-        // Any test you write for XCTest can be annotated as throws and async.
-        // Mark your test throws to produce an unexpected failure when your test encounters an uncaught error.
-        // Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards.
-    }
-
-    func testPerformanceExample() throws {
-        // This is an example of a performance test case.
-        self.measure {
-            // Put the code you want to measure the time of here.
-        }
-    }
-
-}
diff --git a/examples/notes/ios/NotesUITests/NotesUITests.swift b/examples/notes/ios/NotesUITests/NotesUITests.swift
deleted file mode 100644
index 74b94f05..00000000
--- a/examples/notes/ios/NotesUITests/NotesUITests.swift
+++ /dev/null
@@ -1,41 +0,0 @@
-//
-//  NotesUITests.swift
-//  NotesUITests
-//
-//  Created by Viktor Charypar on 31/01/2023.
-//
-
-import XCTest
-
-final class NotesUITests: XCTestCase {
-
-    override func setUpWithError() throws {
-        // Put setup code here. This method is called before the invocation of each test method in the class.
-
-        // In UI tests it is usually best to stop immediately when a failure occurs.
-        continueAfterFailure = false
-
-        // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
-    }
-
-    override func tearDownWithError() throws {
-        // Put teardown code here. This method is called after the invocation of each test method in the class.
-    }
-
-    func testExample() throws {
-        // UI tests must launch the application that they test.
-        let app = XCUIApplication()
-        app.launch()
-
-        // Use XCTAssert and related functions to verify your tests produce the correct results.
-    }
-
-    func testLaunchPerformance() throws {
-        if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 7.0, *) {
-            // This measures how long it takes to launch your application.
-            measure(metrics: [XCTApplicationLaunchMetric()]) {
-                XCUIApplication().launch()
-            }
-        }
-    }
-}
diff --git a/examples/notes/ios/NotesUITests/NotesUITestsLaunchTests.swift b/examples/notes/ios/NotesUITests/NotesUITestsLaunchTests.swift
deleted file mode 100644
index 8ebb6f80..00000000
--- a/examples/notes/ios/NotesUITests/NotesUITestsLaunchTests.swift
+++ /dev/null
@@ -1,32 +0,0 @@
-//
-//  NotesUITestsLaunchTests.swift
-//  NotesUITests
-//
-//  Created by Viktor Charypar on 31/01/2023.
-//
-
-import XCTest
-
-final class NotesUITestsLaunchTests: XCTestCase {
-
-    override class var runsForEachTargetApplicationUIConfiguration: Bool {
-        true
-    }
-
-    override func setUpWithError() throws {
-        continueAfterFailure = false
-    }
-
-    func testLaunch() throws {
-        let app = XCUIApplication()
-        app.launch()
-
-        // Insert steps here to perform after app launch but before taking a screenshot,
-        // such as logging into a test account or navigating somewhere in the app
-
-        let attachment = XCTAttachment(screenshot: app.screenshot())
-        attachment.name = "Launch Screen"
-        attachment.lifetime = .keepAlways
-        add(attachment)
-    }
-}
diff --git a/examples/notes/ios/bin/rust_build.sh b/examples/notes/ios/bin/rust_build.sh
deleted file mode 100644
index c4b73fef..00000000
--- a/examples/notes/ios/bin/rust_build.sh
+++ /dev/null
@@ -1,52 +0,0 @@
-#!/usr/bin/env bash
-
-if [ "$#" -ne 1 ]; then
-  echo "Usage (note: only call inside XCode!):"
-  echo "$0 <FFI_TARGET>"
-  exit 1
-fi
-
-# what to pass to cargo build -p, e.g. your_lib_ffi
-FFI_TARGET=$1
-
-set -euvx
-
-RELFLAG=
-if [[ "$CONFIGURATION" != "Debug" ]]; then
-  RELFLAG=--release
-fi
-
-IS_SIMULATOR=0
-if [ "${LLVM_TARGET_TRIPLE_SUFFIX-}" = "-simulator" ]; then
-  IS_SIMULATOR=1
-fi
-
-export PATH="$PATH:$HOME/.cargo/bin"
-export LIBRARY_PATH
-
-for arch in $ARCHS; do
-  case "$arch" in
-  x86_64)
-    if [ $IS_SIMULATOR -eq 0 ]; then
-      echo "Building for x86_64, but not a simulator build. What's going on?" >&2
-      exit 2
-    fi
-
-    # Intel iOS simulator
-    export CFLAGS_x86_64_apple_ios="-target x86_64-apple-ios"
-    LIBRARY_PATH="${LIBRARY_PATH-}:$(xcrun --sdk iphonesimulator --show-sdk-path)/usr/lib"
-    cargo build -p "$FFI_TARGET" --lib $RELFLAG --target x86_64-apple-ios
-    ;;
-
-  arm64)
-    if [ $IS_SIMULATOR -eq 0 ]; then
-      # Hardware iOS targets
-      LIBRARY_PATH="${LIBRARY_PATH-}:$(xcrun --sdk iphoneos --show-sdk-path)/usr/lib"
-      cargo build -p "$FFI_TARGET" --lib $RELFLAG --target aarch64-apple-ios
-    else
-      LIBRARY_PATH="${LIBRARY_PATH-}:$(xcrun --sdk iphonesimulator --show-sdk-path)/usr/lib"
-      cargo build -p "$FFI_TARGET" --lib $RELFLAG --target aarch64-apple-ios-sim
-    fi
-    ;;
-  esac
-done
diff --git a/examples/notes/shared/shared.xcodeproj/project.pbxproj b/examples/notes/shared/shared.xcodeproj/project.pbxproj
new file mode 100644
index 00000000..71604869
--- /dev/null
+++ b/examples/notes/shared/shared.xcodeproj/project.pbxproj
@@ -0,0 +1,479 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 53;
+	objects = {
+
+/* Begin PBXBuildFile section */
+		CA60B00B9D2015C9C272420B /* Cargo.toml in Sources */ = {isa = PBXBuildFile; fileRef = CA608D1842CB3EF4668187A5 /* Cargo.toml */; settings = {COMPILER_FLAGS = "--lib"; }; };
+		CA60B00B9D20ADF5C218A6BC /* Cargo.toml in Sources */ = {isa = PBXBuildFile; fileRef = CA608D1842CB3EF4668187A5 /* Cargo.toml */; settings = {COMPILER_FLAGS = "--bin 'uniffi-bindgen'"; }; };
+		CA60B00B9D20C5F2CD80BAA8 /* Cargo.toml in Sources */ = {isa = PBXBuildFile; fileRef = CA608D1842CB3EF4668187A5 /* Cargo.toml */; settings = {COMPILER_FLAGS = "--lib"; }; };
+/* End PBXBuildFile section */
+
+/* Begin PBXBuildRule section */
+		CA608D1842CBAC6C1400ACA8 /* PBXBuildRule */ = {
+			isa = PBXBuildRule;
+			compilerSpec = com.apple.compilers.proxy.script;
+			dependencyFile = "$(DERIVED_FILE_DIR)/$(CARGO_XCODE_TARGET_ARCH)-$(EXECUTABLE_NAME).d";
+			filePatterns = "*/Cargo.toml";
+			fileType = pattern.proxy;
+			inputFiles = (
+			);
+			isEditable = 0;
+			name = "Cargo project build";
+			outputFiles = (
+				"$(OBJECT_FILE_DIR)/$(CARGO_XCODE_TARGET_ARCH)-$(EXECUTABLE_NAME)",
+			);
+			script = "# generated with cargo-xcode 1.5.0\n\nset -eu; export PATH=\"$PATH:$HOME/.cargo/bin:/usr/local/bin\";\nif [ \"${IS_MACCATALYST-NO}\" = YES ]; then\n    CARGO_XCODE_TARGET_TRIPLE=\"${CARGO_XCODE_TARGET_ARCH}-apple-ios-macabi\"\nelse\n    CARGO_XCODE_TARGET_TRIPLE=\"${CARGO_XCODE_TARGET_ARCH}-apple-${CARGO_XCODE_TARGET_OS}\"\nfi\nif [ \"$CARGO_XCODE_TARGET_OS\" != \"darwin\" ]; then\n    PATH=\"${PATH/\\/Contents\\/Developer\\/Toolchains\\/XcodeDefault.xctoolchain\\/usr\\/bin:/xcode-provided-ld-cant-link-lSystem-for-the-host-build-script:}\"\nfi\nPATH=\"$PATH:/opt/homebrew/bin\" # Rust projects often depend on extra tools like nasm, which Xcode lacks\nif [ \"$CARGO_XCODE_BUILD_MODE\" == release ]; then\n    OTHER_INPUT_FILE_FLAGS=\"${OTHER_INPUT_FILE_FLAGS} --release\"\nfi\nif command -v rustup &> /dev/null; then\n    if ! rustup target list --installed | egrep -q \"${CARGO_XCODE_TARGET_TRIPLE}\"; then\n        echo \"warning: this build requires rustup toolchain for $CARGO_XCODE_TARGET_TRIPLE, but it isn't installed\"\n        rustup target add \"${CARGO_XCODE_TARGET_TRIPLE}\" || echo >&2 \"warning: can't install $CARGO_XCODE_TARGET_TRIPLE\"\n    fi\nfi\nif [ \"$ACTION\" = clean ]; then\n ( set -x; cargo clean --manifest-path=\"$SCRIPT_INPUT_FILE\" ${OTHER_INPUT_FILE_FLAGS} --target=\"${CARGO_XCODE_TARGET_TRIPLE}\"; );\nelse\n ( set -x; cargo build --manifest-path=\"$SCRIPT_INPUT_FILE\" --features=\"${CARGO_XCODE_FEATURES:-}\" ${OTHER_INPUT_FILE_FLAGS} --target=\"${CARGO_XCODE_TARGET_TRIPLE}\"; );\nfi\n# it's too hard to explain Cargo's actual exe path to Xcode build graph, so hardlink to a known-good path instead\nBUILT_SRC=\"${CARGO_TARGET_DIR}/${CARGO_XCODE_TARGET_TRIPLE}/${CARGO_XCODE_BUILD_MODE}/${CARGO_XCODE_CARGO_FILE_NAME}\"\nln -f -- \"$BUILT_SRC\" \"$SCRIPT_OUTPUT_FILE_0\"\n\n# xcode generates dep file, but for its own path, so append our rename to it\nDEP_FILE_SRC=\"${CARGO_TARGET_DIR}/${CARGO_XCODE_TARGET_TRIPLE}/${CARGO_XCODE_BUILD_MODE}/${CARGO_XCODE_CARGO_DEP_FILE_NAME}\"\nif [ -f \"$DEP_FILE_SRC\" ]; then\n    DEP_FILE_DST=\"${DERIVED_FILE_DIR}/${CARGO_XCODE_TARGET_ARCH}-${EXECUTABLE_NAME}.d\"\n    cp -f \"$DEP_FILE_SRC\" \"$DEP_FILE_DST\"\n    echo >> \"$DEP_FILE_DST\" \"$SCRIPT_OUTPUT_FILE_0: $BUILT_SRC\"\nfi\n\n# lipo script needs to know all the platform-specific files that have been built\n# archs is in the file name, so that paths don't stay around after archs change\n# must match input for LipoScript\nFILE_LIST=\"${DERIVED_FILE_DIR}/${ARCHS}-${EXECUTABLE_NAME}.xcfilelist\"\ntouch \"$FILE_LIST\"\nif ! egrep -q \"$SCRIPT_OUTPUT_FILE_0\" \"$FILE_LIST\" ; then\n    echo >> \"$FILE_LIST\" \"$SCRIPT_OUTPUT_FILE_0\"\nfi\n";
+		};
+/* End PBXBuildRule section */
+
+/* Begin PBXFileReference section */
+		ADDEDBA66A6E1 /* libresolv.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libresolv.tbd; path = usr/lib/libresolv.tbd; sourceTree = SDKROOT; };
+		CA602C9F76CC10F7F7FCAC5B /* shared.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = shared.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
+		CA608D1842CB3EF4668187A5 /* Cargo.toml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Cargo.toml; sourceTree = "<group>"; };
+		CA6091720E328109328FB0D5 /* uniffi-bindgen */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "uniffi-bindgen"; sourceTree = BUILT_PRODUCTS_DIR; };
+		CA60CB052880FB09138082B7 /* libshared_static.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libshared_static.a; sourceTree = BUILT_PRODUCTS_DIR; };
+/* End PBXFileReference section */
+
+/* Begin PBXGroup section */
+		ADDEDBA66A6E2 /* Required for static linking */ = {
+			isa = PBXGroup;
+			children = (
+				ADDEDBA66A6E1 /* libresolv.tbd */,
+			);
+			name = "Required for static linking";
+			sourceTree = "<group>";
+		};
+		CA608D1842CB22869D176AE5 /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				CA60CB052880FB09138082B7 /* libshared_static.a */,
+				CA602C9F76CC10F7F7FCAC5B /* shared.dylib */,
+				CA6091720E328109328FB0D5 /* uniffi-bindgen */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		CA608D1842CB98AF0B5890DB /* Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				ADDEDBA66A6E2 /* Required for static linking */,
+			);
+			name = Frameworks;
+			sourceTree = "<group>";
+		};
+		CA608D1842CBD65BC3C892A8 = {
+			isa = PBXGroup;
+			children = (
+				CA608D1842CB3EF4668187A5 /* Cargo.toml */,
+				CA608D1842CB22869D176AE5 /* Products */,
+				CA608D1842CB98AF0B5890DB /* Frameworks */,
+			);
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+		CA602C9F76CCC5F2CD80BAA8 /* shared-cdylib */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = CA6017C07286C5F2CD80BAA8 /* Build configuration list for PBXNativeTarget "shared-cdylib" */;
+			buildPhases = (
+				CA606E439420C5F2CD80BAA8 /* Sources */,
+				CA608D1842CBAF6EBB7F357C /* Universal Binary lipo */,
+			);
+			buildRules = (
+				CA608D1842CBAC6C1400ACA8 /* PBXBuildRule */,
+			);
+			dependencies = (
+			);
+			name = "shared-cdylib";
+			productName = shared.dylib;
+			productReference = CA602C9F76CC10F7F7FCAC5B /* shared.dylib */;
+			productType = "com.apple.product-type.library.dynamic";
+		};
+		CA6091720E32ADF5C218A6BC /* uniffi-bindgen-bin */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = CA6017C07286ADF5C218A6BC /* Build configuration list for PBXNativeTarget "uniffi-bindgen-bin" */;
+			buildPhases = (
+				CA606E439420ADF5C218A6BC /* Sources */,
+				CA608D1842CBAF6EBB7F357C /* Universal Binary lipo */,
+			);
+			buildRules = (
+				CA608D1842CBAC6C1400ACA8 /* PBXBuildRule */,
+			);
+			dependencies = (
+			);
+			name = "uniffi-bindgen-bin";
+			productName = "uniffi-bindgen";
+			productReference = CA6091720E328109328FB0D5 /* uniffi-bindgen */;
+			productType = "com.apple.product-type.tool";
+		};
+		CA60CB05288015C9C272420B /* shared-staticlib */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = CA6017C0728615C9C272420B /* Build configuration list for PBXNativeTarget "shared-staticlib" */;
+			buildPhases = (
+				CA606E43942015C9C272420B /* Sources */,
+				CA608D1842CBAF6EBB7F357C /* Universal Binary lipo */,
+			);
+			buildRules = (
+				CA608D1842CBAC6C1400ACA8 /* PBXBuildRule */,
+			);
+			dependencies = (
+			);
+			name = "shared-staticlib";
+			packageProductDependencies = (
+				CC81057229D5A5660026FC57 /* Serde */,
+			);
+			productName = libshared_static.a;
+			productReference = CA60CB052880FB09138082B7 /* libshared_static.a */;
+			productType = "com.apple.product-type.library.static";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		CA608D1842CBE04653AD465F /* Project object */ = {
+			isa = PBXProject;
+			attributes = {
+				LastUpgradeCheck = 1420;
+				TargetAttributes = {
+					CA602C9F76CCC5F2CD80BAA8 = {
+						CreatedOnToolsVersion = 9.2;
+						ProvisioningStyle = Automatic;
+					};
+					CA6091720E32ADF5C218A6BC = {
+						CreatedOnToolsVersion = 9.2;
+						ProvisioningStyle = Automatic;
+					};
+					CA60CB05288015C9C272420B = {
+						CreatedOnToolsVersion = 9.2;
+						ProvisioningStyle = Automatic;
+					};
+				};
+			};
+			buildConfigurationList = CA608D1842CB80E02D6C7F57 /* Build configuration list for PBXProject "shared" */;
+			compatibilityVersion = "Xcode 11.4";
+			developmentRegion = en;
+			hasScannedForEncodings = 0;
+			knownRegions = (
+				en,
+				Base,
+			);
+			mainGroup = CA608D1842CBD65BC3C892A8;
+			packageReferences = (
+				CC81057129D5A5660026FC57 /* XCRemoteSwiftPackageReference "Serde" */,
+			);
+			productRefGroup = CA608D1842CB22869D176AE5 /* Products */;
+			projectDirPath = "";
+			projectRoot = "";
+			targets = (
+				CA60CB05288015C9C272420B /* shared-staticlib */,
+				CA602C9F76CCC5F2CD80BAA8 /* shared-cdylib */,
+				CA6091720E32ADF5C218A6BC /* uniffi-bindgen-bin */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXShellScriptBuildPhase section */
+		CA608D1842CBAF6EBB7F357C /* Universal Binary lipo */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputFileListPaths = (
+			);
+			inputPaths = (
+				"$(DERIVED_FILE_DIR)/$(ARCHS)-$(EXECUTABLE_NAME).xcfilelist",
+			);
+			name = "Universal Binary lipo";
+			outputFileListPaths = (
+			);
+			outputPaths = (
+				"$(TARGET_BUILD_DIR)/$(EXECUTABLE_PATH)",
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "# generated with cargo-xcode 1.5.0\n\n            set -eux; cat \"$DERIVED_FILE_DIR/$ARCHS-$EXECUTABLE_NAME.xcfilelist\" | tr '\\n' '\\0' | xargs -0 lipo -create -output \"$TARGET_BUILD_DIR/$EXECUTABLE_PATH\"\n            if [ ${LD_DYLIB_INSTALL_NAME:+1} ]; then\n                install_name_tool -id \"$LD_DYLIB_INSTALL_NAME\" \"$TARGET_BUILD_DIR/$EXECUTABLE_PATH\"\n            fi\n        ";
+		};
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+		CA606E43942015C9C272420B /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				CA60B00B9D2015C9C272420B /* Cargo.toml in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		CA606E439420ADF5C218A6BC /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				CA60B00B9D20ADF5C218A6BC /* Cargo.toml in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		CA606E439420C5F2CD80BAA8 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				CA60B00B9D20C5F2CD80BAA8 /* Cargo.toml in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+		CA60088A3D0D15C9C272420B /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				CARGO_XCODE_CARGO_DEP_FILE_NAME = libshared.d;
+				CARGO_XCODE_CARGO_FILE_NAME = libshared.a;
+				CLANG_ENABLE_OBJC_WEAK = YES;
+				DEAD_CODE_STRIPPING = YES;
+				INSTALL_GROUP = "";
+				INSTALL_MODE_FLAG = "";
+				INSTALL_OWNER = "";
+				PRODUCT_NAME = shared_static;
+				SKIP_INSTALL = YES;
+				SUPPORTED_PLATFORMS = "macosx iphonesimulator iphoneos appletvsimulator appletvos";
+			};
+			name = Debug;
+		};
+		CA60088A3D0DADF5C218A6BC /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				CARGO_XCODE_CARGO_DEP_FILE_NAME = "uniffi-bindgen.d";
+				CARGO_XCODE_CARGO_FILE_NAME = "uniffi-bindgen";
+				CLANG_ENABLE_OBJC_WEAK = YES;
+				CODE_SIGN_IDENTITY = "-";
+				DEAD_CODE_STRIPPING = YES;
+				PRODUCT_NAME = "uniffi-bindgen";
+				SUPPORTED_PLATFORMS = macosx;
+			};
+			name = Debug;
+		};
+		CA60088A3D0DC5F2CD80BAA8 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				CARGO_XCODE_CARGO_DEP_FILE_NAME = libshared.d;
+				CARGO_XCODE_CARGO_FILE_NAME = libshared.dylib;
+				CLANG_ENABLE_OBJC_WEAK = YES;
+				DEAD_CODE_STRIPPING = YES;
+				DYLIB_COMPATIBILITY_VERSION = 0;
+				PRODUCT_NAME = shared;
+				SUPPORTED_PLATFORMS = macosx;
+			};
+			name = Debug;
+		};
+		CA60B0465E63228BE02872F8 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CARGO_TARGET_DIR = "$(PROJECT_TEMP_DIR)/cargo_target";
+				CARGO_XCODE_BUILD_MODE = debug;
+				CARGO_XCODE_FEATURES = "";
+				"CARGO_XCODE_TARGET_ARCH[arch=arm64*]" = aarch64;
+				"CARGO_XCODE_TARGET_ARCH[arch=i386]" = i686;
+				"CARGO_XCODE_TARGET_ARCH[arch=x86_64*]" = x86_64;
+				"CARGO_XCODE_TARGET_OS[sdk=appletvos*]" = tvos;
+				"CARGO_XCODE_TARGET_OS[sdk=appletvsimulator*]" = tvos;
+				"CARGO_XCODE_TARGET_OS[sdk=iphoneos*]" = ios;
+				"CARGO_XCODE_TARGET_OS[sdk=iphonesimulator*]" = "ios-sim";
+				"CARGO_XCODE_TARGET_OS[sdk=iphonesimulator*][arch=x86_64*]" = ios;
+				"CARGO_XCODE_TARGET_OS[sdk=macosx*]" = darwin;
+				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_COMMA = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+				CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+				CLANG_WARN_STRICT_PROTOTYPES = YES;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				CURRENT_PROJECT_VERSION = 0.1;
+				DEAD_CODE_STRIPPING = YES;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				ENABLE_TESTABILITY = YES;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				MARKETING_VERSION = 0.1.0;
+				ONLY_ACTIVE_ARCH = YES;
+				PRODUCT_NAME = shared;
+				SDKROOT = macosx;
+				SUPPORTS_MACCATALYST = YES;
+			};
+			name = Debug;
+		};
+		CA60B0465E633CC16B37690B /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CARGO_TARGET_DIR = "$(PROJECT_TEMP_DIR)/cargo_target";
+				CARGO_XCODE_BUILD_MODE = release;
+				CARGO_XCODE_FEATURES = "";
+				"CARGO_XCODE_TARGET_ARCH[arch=arm64*]" = aarch64;
+				"CARGO_XCODE_TARGET_ARCH[arch=i386]" = i686;
+				"CARGO_XCODE_TARGET_ARCH[arch=x86_64*]" = x86_64;
+				"CARGO_XCODE_TARGET_OS[sdk=appletvos*]" = tvos;
+				"CARGO_XCODE_TARGET_OS[sdk=appletvsimulator*]" = tvos;
+				"CARGO_XCODE_TARGET_OS[sdk=iphoneos*]" = ios;
+				"CARGO_XCODE_TARGET_OS[sdk=iphonesimulator*]" = "ios-sim";
+				"CARGO_XCODE_TARGET_OS[sdk=iphonesimulator*][arch=x86_64*]" = ios;
+				"CARGO_XCODE_TARGET_OS[sdk=macosx*]" = darwin;
+				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_COMMA = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+				CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+				CLANG_WARN_STRICT_PROTOTYPES = YES;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				CURRENT_PROJECT_VERSION = 0.1;
+				DEAD_CODE_STRIPPING = YES;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				MARKETING_VERSION = 0.1.0;
+				PRODUCT_NAME = shared;
+				SDKROOT = macosx;
+				SUPPORTS_MACCATALYST = YES;
+			};
+			name = Release;
+		};
+		CA60BFCA111015C9C272420B /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				CARGO_XCODE_CARGO_DEP_FILE_NAME = libshared.d;
+				CARGO_XCODE_CARGO_FILE_NAME = libshared.a;
+				CLANG_ENABLE_OBJC_WEAK = YES;
+				DEAD_CODE_STRIPPING = YES;
+				INSTALL_GROUP = "";
+				INSTALL_MODE_FLAG = "";
+				INSTALL_OWNER = "";
+				PRODUCT_NAME = shared_static;
+				SKIP_INSTALL = YES;
+				SUPPORTED_PLATFORMS = "macosx iphonesimulator iphoneos appletvsimulator appletvos";
+			};
+			name = Release;
+		};
+		CA60BFCA1110ADF5C218A6BC /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				CARGO_XCODE_CARGO_DEP_FILE_NAME = "uniffi-bindgen.d";
+				CARGO_XCODE_CARGO_FILE_NAME = "uniffi-bindgen";
+				CLANG_ENABLE_OBJC_WEAK = YES;
+				CODE_SIGN_IDENTITY = "-";
+				DEAD_CODE_STRIPPING = YES;
+				PRODUCT_NAME = "uniffi-bindgen";
+				SUPPORTED_PLATFORMS = macosx;
+			};
+			name = Release;
+		};
+		CA60BFCA1110C5F2CD80BAA8 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				CARGO_XCODE_CARGO_DEP_FILE_NAME = libshared.d;
+				CARGO_XCODE_CARGO_FILE_NAME = libshared.dylib;
+				CLANG_ENABLE_OBJC_WEAK = YES;
+				DEAD_CODE_STRIPPING = YES;
+				DYLIB_COMPATIBILITY_VERSION = 0;
+				PRODUCT_NAME = shared;
+				SUPPORTED_PLATFORMS = macosx;
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		CA6017C0728615C9C272420B /* Build configuration list for PBXNativeTarget "shared-staticlib" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				CA60BFCA111015C9C272420B /* Release */,
+				CA60088A3D0D15C9C272420B /* Debug */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		CA6017C07286ADF5C218A6BC /* Build configuration list for PBXNativeTarget "uniffi-bindgen-bin" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				CA60BFCA1110ADF5C218A6BC /* Release */,
+				CA60088A3D0DADF5C218A6BC /* Debug */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		CA6017C07286C5F2CD80BAA8 /* Build configuration list for PBXNativeTarget "shared-cdylib" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				CA60BFCA1110C5F2CD80BAA8 /* Release */,
+				CA60088A3D0DC5F2CD80BAA8 /* Debug */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		CA608D1842CB80E02D6C7F57 /* Build configuration list for PBXProject "shared" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				CA60B0465E633CC16B37690B /* Release */,
+				CA60B0465E63228BE02872F8 /* Debug */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+
+/* Begin XCRemoteSwiftPackageReference section */
+		CC81057129D5A5660026FC57 /* XCRemoteSwiftPackageReference "Serde" */ = {
+			isa = XCRemoteSwiftPackageReference;
+			repositoryURL = "https://github.com/starcoin-sdk/Serde.swift";
+			requirement = {
+				branch = main;
+				kind = branch;
+			};
+		};
+/* End XCRemoteSwiftPackageReference section */
+
+/* Begin XCSwiftPackageProductDependency section */
+		CC81057229D5A5660026FC57 /* Serde */ = {
+			isa = XCSwiftPackageProductDependency;
+			package = CC81057129D5A5660026FC57 /* XCRemoteSwiftPackageReference "Serde" */;
+			productName = Serde;
+		};
+/* End XCSwiftPackageProductDependency section */
+	};
+	rootObject = CA608D1842CBE04653AD465F /* Project object */;
+}
diff --git a/examples/notes/shared/shared.xcodeproj/xcuserdata/stuartharris.xcuserdatad/xcschemes/xcschememanagement.plist b/examples/notes/shared/shared.xcodeproj/xcuserdata/stuartharris.xcuserdatad/xcschemes/xcschememanagement.plist
new file mode 100644
index 00000000..c07df663
--- /dev/null
+++ b/examples/notes/shared/shared.xcodeproj/xcuserdata/stuartharris.xcuserdatad/xcschemes/xcschememanagement.plist
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>SchemeUserState</key>
+	<dict>
+		<key>shared-cdylib.xcscheme_^#shared#^_</key>
+		<dict>
+			<key>orderHint</key>
+			<integer>3</integer>
+		</dict>
+		<key>shared-staticlib.xcscheme_^#shared#^_</key>
+		<dict>
+			<key>orderHint</key>
+			<integer>2</integer>
+		</dict>
+		<key>uniffi-bindgen-bin.xcscheme_^#shared#^_</key>
+		<dict>
+			<key>orderHint</key>
+			<integer>1</integer>
+		</dict>
+	</dict>
+</dict>
+</plist>
diff --git a/scripts/ios_build.sh b/scripts/ios_build.sh
deleted file mode 100755
index c4b73fef..00000000
--- a/scripts/ios_build.sh
+++ /dev/null
@@ -1,52 +0,0 @@
-#!/usr/bin/env bash
-
-if [ "$#" -ne 1 ]; then
-  echo "Usage (note: only call inside XCode!):"
-  echo "$0 <FFI_TARGET>"
-  exit 1
-fi
-
-# what to pass to cargo build -p, e.g. your_lib_ffi
-FFI_TARGET=$1
-
-set -euvx
-
-RELFLAG=
-if [[ "$CONFIGURATION" != "Debug" ]]; then
-  RELFLAG=--release
-fi
-
-IS_SIMULATOR=0
-if [ "${LLVM_TARGET_TRIPLE_SUFFIX-}" = "-simulator" ]; then
-  IS_SIMULATOR=1
-fi
-
-export PATH="$PATH:$HOME/.cargo/bin"
-export LIBRARY_PATH
-
-for arch in $ARCHS; do
-  case "$arch" in
-  x86_64)
-    if [ $IS_SIMULATOR -eq 0 ]; then
-      echo "Building for x86_64, but not a simulator build. What's going on?" >&2
-      exit 2
-    fi
-
-    # Intel iOS simulator
-    export CFLAGS_x86_64_apple_ios="-target x86_64-apple-ios"
-    LIBRARY_PATH="${LIBRARY_PATH-}:$(xcrun --sdk iphonesimulator --show-sdk-path)/usr/lib"
-    cargo build -p "$FFI_TARGET" --lib $RELFLAG --target x86_64-apple-ios
-    ;;
-
-  arm64)
-    if [ $IS_SIMULATOR -eq 0 ]; then
-      # Hardware iOS targets
-      LIBRARY_PATH="${LIBRARY_PATH-}:$(xcrun --sdk iphoneos --show-sdk-path)/usr/lib"
-      cargo build -p "$FFI_TARGET" --lib $RELFLAG --target aarch64-apple-ios
-    else
-      LIBRARY_PATH="${LIBRARY_PATH-}:$(xcrun --sdk iphonesimulator --show-sdk-path)/usr/lib"
-      cargo build -p "$FFI_TARGET" --lib $RELFLAG --target aarch64-apple-ios-sim
-    fi
-    ;;
-  esac
-done


Test patch: