From 9c9479a1c2dc712869e274d843292b32dbf4dc44 Mon Sep 17 00:00:00 2001
From: Thomas Goyne <thomas.goyne@mongodb.com>
Date: Tue, 30 Apr 2024 12:13:52 -0700
Subject: [PATCH] Allow Realm to be built as a dynamic library when installing
 via SPM (#8561)

This is required for compliance with the new privacy manifest rules. While App
Store Connect supports static libraries, Xcode doesn't actually build static
libraries for static targets; it just links the object files directly into the
app. It also doesn't implement the xcprivacy manifest merging that the
documentation claims exists, so our privacy manfiest is never actually used.
---
 CHANGELOG.md                                  | 17 ++++++++++++-
 Package.swift                                 |  4 +++-
 Realm/NSError+RLMSync.m                       |  2 +-
 Realm/RLMInitialSubscriptionsConfiguration.h  |  1 -
 Realm/RLMInitialSubscriptionsConfiguration.m  |  3 +--
 Realm/RLMSyncConfiguration.mm                 |  3 ++-
 RealmSwift/PrivacyInfo.xcprivacy              | 19 ++++++++++++++-
 .../project.pbxproj                           |  8 -------
 .../project.pbxproj                           | 24 -------------------
 9 files changed, 41 insertions(+), 40 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 01659b63c5..ad74450074 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,7 +8,22 @@ x.y.z Release notes (yyyy-MM-dd)
   each of the metadata Realms rather than sharing one between them
   ([Core #7552](https://github.com/realm/realm-core/pull/7552)).
 * Improve perfomance of IN queries and chained OR equality queries for
-  UUID/ObjectId types. ([.Net * #3566](https://github.com/realm/realm-dotnet/issues/3566))
+  UUID/ObjectId types. ([.Net #3566](https://github.com/realm/realm-dotnet/issues/3566))
+* Enable building RealmSwift as a dynamic framework when installing via SPM, which
+  lets us supply a privacy manifest. When RealmSwift is built as a static
+  library you must supply your own manifest, as Xcode does not build static
+  libraries in a way compatible with xcprivacy embedding. Due to some bugs in
+  Xcode, this may require manual changes to your project:
+   - Targets must now depend on only Realm or RealmSwift. If you use both the
+     obj-c and swift API, depending on RealmSwift will let you import Realm.
+     Trying to directly depend on both will give the error "Swift package
+     target 'Realm' is linked as a static library by 'App' and 'Realm', but
+     cannot be built dynamically because there is a package product with the
+     same name."
+   - To actually build RealmSwift as a dynamic framework, change "Do Not Embed"
+     to "Embed & Sign" in the "Frameworks, Libraries, and Embedded Content"
+     section on the General tab of your target's settings.
+  ([#8561](https://github.com/realm/realm-swift/pull/8561)).
 
 ### Fixed
 * `-[RLMUser allSessions]` did not include sessions which were currently
diff --git a/Package.swift b/Package.swift
index 80c924ffd1..a239efdd77 100644
--- a/Package.swift
+++ b/Package.swift
@@ -147,10 +147,12 @@ let package = Package(
     products: [
         .library(
             name: "Realm",
+            type: .dynamic,
             targets: ["Realm"]),
         .library(
             name: "RealmSwift",
-            targets: ["Realm", "RealmSwift"]),
+            type: .dynamic,
+            targets: ["RealmSwift"]),
     ],
     dependencies: [
         .package(url: "https://github.com/realm/realm-core.git", exact: coreVersion)
diff --git a/Realm/NSError+RLMSync.m b/Realm/NSError+RLMSync.m
index 4825c014e7..8a707aaca5 100644
--- a/Realm/NSError+RLMSync.m
+++ b/Realm/NSError+RLMSync.m
@@ -16,7 +16,7 @@
 //
 ////////////////////////////////////////////////////////////////////////////
 
-#import "NSError+RLMSync.h"
+#import <Realm/NSError+RLMSync.h>
 
 #import "RLMError.h"
 
diff --git a/Realm/RLMInitialSubscriptionsConfiguration.h b/Realm/RLMInitialSubscriptionsConfiguration.h
index 15d9ab64bf..e4b37cab18 100644
--- a/Realm/RLMInitialSubscriptionsConfiguration.h
+++ b/Realm/RLMInitialSubscriptionsConfiguration.h
@@ -16,7 +16,6 @@
 //
 ////////////////////////////////////////////////////////////////////////////
 
-
 #import <Foundation/Foundation.h>
 #import <Realm/RLMRealm.h>
 
diff --git a/Realm/RLMInitialSubscriptionsConfiguration.m b/Realm/RLMInitialSubscriptionsConfiguration.m
index 51a3a3e566..0bd9d29702 100644
--- a/Realm/RLMInitialSubscriptionsConfiguration.m
+++ b/Realm/RLMInitialSubscriptionsConfiguration.m
@@ -16,8 +16,7 @@
 //
 ////////////////////////////////////////////////////////////////////////////
 
-
-#import "RLMInitialSubscriptionsConfiguration.h"
+#import <Realm/RLMInitialSubscriptionsConfiguration.h>
 
 @implementation RLMInitialSubscriptionsConfiguration
 
diff --git a/Realm/RLMSyncConfiguration.mm b/Realm/RLMSyncConfiguration.mm
index 7a26319d6f..14400ef9c2 100644
--- a/Realm/RLMSyncConfiguration.mm
+++ b/Realm/RLMSyncConfiguration.mm
@@ -18,10 +18,11 @@
 
 #import "RLMSyncConfiguration_Private.hpp"
 
+#import <Realm/RLMInitialSubscriptionsConfiguration.h>
+
 #import "RLMApp_Private.hpp"
 #import "RLMBSON_Private.hpp"
 #import "RLMError_Private.hpp"
-#import "RLMInitialSubscriptionsConfiguration.h"
 #import "RLMRealm_Private.hpp"
 #import "RLMRealmConfiguration_Private.h"
 #import "RLMRealmConfiguration_Private.hpp"
diff --git a/RealmSwift/PrivacyInfo.xcprivacy b/RealmSwift/PrivacyInfo.xcprivacy
index 987771fa7f..2e4e915747 100644
--- a/RealmSwift/PrivacyInfo.xcprivacy
+++ b/RealmSwift/PrivacyInfo.xcprivacy
@@ -7,7 +7,24 @@
 	<key>NSPrivacyCollectedDataTypes</key>
 	<array/>
 	<key>NSPrivacyAccessedAPITypes</key>
-	<array/>
+	<array>
+		<dict>
+			<key>NSPrivacyAccessedAPITypeReasons</key>
+			<array>
+				<string>C617.1</string>
+			</array>
+			<key>NSPrivacyAccessedAPIType</key>
+			<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
+		</dict>
+		<dict>
+			<key>NSPrivacyAccessedAPITypeReasons</key>
+			<array>
+				<string>E174.1</string>
+			</array>
+			<key>NSPrivacyAccessedAPIType</key>
+			<string>NSPrivacyAccessedAPICategoryDiskSpace</string>
+		</dict>
+	</array>
 	<key>NSPrivacyTracking</key>
 	<false/>
 </dict>
diff --git a/examples/installation/SwiftPackageManager.notxcodeproj/project.pbxproj b/examples/installation/SwiftPackageManager.notxcodeproj/project.pbxproj
index cad3b4110d..874d329ad3 100644
--- a/examples/installation/SwiftPackageManager.notxcodeproj/project.pbxproj
+++ b/examples/installation/SwiftPackageManager.notxcodeproj/project.pbxproj
@@ -10,7 +10,6 @@
 		3FEC916A2A4D3B140044BFF5 /* SwiftExampleApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3FEC91692A4D3B140044BFF5 /* SwiftExampleApp.swift */; };
 		3FEC916E2A4D3B150044BFF5 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3FEC916D2A4D3B150044BFF5 /* Assets.xcassets */; };
 		3FEC91722A4D3B150044BFF5 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3FEC91712A4D3B150044BFF5 /* Preview Assets.xcassets */; };
-		3FEC917A2A4D3DB90044BFF5 /* Realm in Frameworks */ = {isa = PBXBuildFile; productRef = 3FEC91792A4D3DB90044BFF5 /* Realm */; };
 		3FEC917C2A4D3DB90044BFF5 /* RealmSwift in Frameworks */ = {isa = PBXBuildFile; productRef = 3FEC917B2A4D3DB90044BFF5 /* RealmSwift */; };
 /* End PBXBuildFile section */
 
@@ -27,7 +26,6 @@
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				3FEC917A2A4D3DB90044BFF5 /* Realm in Frameworks */,
 				3FEC917C2A4D3DB90044BFF5 /* RealmSwift in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
@@ -87,7 +85,6 @@
 			);
 			name = App;
 			packageProductDependencies = (
-				3FEC91792A4D3DB90044BFF5 /* Realm */,
 				3FEC917B2A4D3DB90044BFF5 /* RealmSwift */,
 			);
 			productName = SwiftPM;
@@ -383,11 +380,6 @@
 /* End XCRemoteSwiftPackageReference section */
 
 /* Begin XCSwiftPackageProductDependency section */
-		3FEC91792A4D3DB90044BFF5 /* Realm */ = {
-			isa = XCSwiftPackageProductDependency;
-			package = 3FEC91782A4D3DB90044BFF5 /* XCRemoteSwiftPackageReference "realm-swift" */;
-			productName = Realm;
-		};
 		3FEC917B2A4D3DB90044BFF5 /* RealmSwift */ = {
 			isa = XCSwiftPackageProductDependency;
 			package = 3FEC91782A4D3DB90044BFF5 /* XCRemoteSwiftPackageReference "realm-swift" */;
diff --git a/examples/installation/SwiftPackageManagerDynamic.notxcodeproj/project.pbxproj b/examples/installation/SwiftPackageManagerDynamic.notxcodeproj/project.pbxproj
index 2eba9a8aa0..88f55b2795 100644
--- a/examples/installation/SwiftPackageManagerDynamic.notxcodeproj/project.pbxproj
+++ b/examples/installation/SwiftPackageManagerDynamic.notxcodeproj/project.pbxproj
@@ -10,15 +10,12 @@
 		3FEC916A2A4D3B140044BFF5 /* SwiftExampleApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3FEC91692A4D3B140044BFF5 /* SwiftExampleApp.swift */; };
 		3FEC916E2A4D3B150044BFF5 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3FEC916D2A4D3B150044BFF5 /* Assets.xcassets */; };
 		3FEC91722A4D3B150044BFF5 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3FEC91712A4D3B150044BFF5 /* Preview Assets.xcassets */; };
-		3FEC917A2A4D3DB90044BFF5 /* Realm in Frameworks */ = {isa = PBXBuildFile; productRef = 3FEC91792A4D3DB90044BFF5 /* Realm */; };
 		3FEC917C2A4D3DB90044BFF5 /* RealmSwift in Frameworks */ = {isa = PBXBuildFile; productRef = 3FEC917B2A4D3DB90044BFF5 /* RealmSwift */; };
 		3FF673252A684E4400500A25 /* Framework1.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3FF6731F2A684E4400500A25 /* Framework1.framework */; };
 		3FF673262A684E4400500A25 /* Framework1.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3FF6731F2A684E4400500A25 /* Framework1.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
 		3FF673362A684E4E00500A25 /* Framework2.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3FF673302A684E4E00500A25 /* Framework2.framework */; };
 		3FF673372A684E4E00500A25 /* Framework2.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3FF673302A684E4E00500A25 /* Framework2.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
-		3FF6733D2A684E7200500A25 /* Realm in Frameworks */ = {isa = PBXBuildFile; productRef = 3FF6733C2A684E7200500A25 /* Realm */; };
 		3FF6733F2A684E7200500A25 /* RealmSwift in Frameworks */ = {isa = PBXBuildFile; productRef = 3FF6733E2A684E7200500A25 /* RealmSwift */; };
-		3FF673412A684E7700500A25 /* Realm in Frameworks */ = {isa = PBXBuildFile; productRef = 3FF673402A684E7700500A25 /* Realm */; };
 		3FF673432A684E7700500A25 /* RealmSwift in Frameworks */ = {isa = PBXBuildFile; productRef = 3FF673422A684E7700500A25 /* RealmSwift */; };
 /* End PBXBuildFile section */
 
@@ -71,7 +68,6 @@
 			files = (
 				3FF673252A684E4400500A25 /* Framework1.framework in Frameworks */,
 				3FF673362A684E4E00500A25 /* Framework2.framework in Frameworks */,
-				3FEC917A2A4D3DB90044BFF5 /* Realm in Frameworks */,
 				3FEC917C2A4D3DB90044BFF5 /* RealmSwift in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
@@ -80,7 +76,6 @@
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				3FF6733D2A684E7200500A25 /* Realm in Frameworks */,
 				3FF6733F2A684E7200500A25 /* RealmSwift in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
@@ -89,7 +84,6 @@
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				3FF673412A684E7700500A25 /* Realm in Frameworks */,
 				3FF673432A684E7700500A25 /* RealmSwift in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
@@ -179,7 +173,6 @@
 			);
 			name = App;
 			packageProductDependencies = (
-				3FEC91792A4D3DB90044BFF5 /* Realm */,
 				3FEC917B2A4D3DB90044BFF5 /* RealmSwift */,
 			);
 			productName = SwiftPM;
@@ -201,7 +194,6 @@
 			);
 			name = Framework1;
 			packageProductDependencies = (
-				3FF6733C2A684E7200500A25 /* Realm */,
 				3FF6733E2A684E7200500A25 /* RealmSwift */,
 			);
 			productName = Framework1;
@@ -223,7 +215,6 @@
 			);
 			name = Framework2;
 			packageProductDependencies = (
-				3FF673402A684E7700500A25 /* Realm */,
 				3FF673422A684E7700500A25 /* RealmSwift */,
 			);
 			productName = Framework2;
@@ -743,31 +734,16 @@
 /* End XCRemoteSwiftPackageReference section */
 
 /* Begin XCSwiftPackageProductDependency section */
-		3FEC91792A4D3DB90044BFF5 /* Realm */ = {
-			isa = XCSwiftPackageProductDependency;
-			package = 3FEC91782A4D3DB90044BFF5 /* XCRemoteSwiftPackageReference "realm-swift" */;
-			productName = Realm;
-		};
 		3FEC917B2A4D3DB90044BFF5 /* RealmSwift */ = {
 			isa = XCSwiftPackageProductDependency;
 			package = 3FEC91782A4D3DB90044BFF5 /* XCRemoteSwiftPackageReference "realm-swift" */;
 			productName = RealmSwift;
 		};
-		3FF6733C2A684E7200500A25 /* Realm */ = {
-			isa = XCSwiftPackageProductDependency;
-			package = 3FEC91782A4D3DB90044BFF5 /* XCRemoteSwiftPackageReference "realm-swift" */;
-			productName = Realm;
-		};
 		3FF6733E2A684E7200500A25 /* RealmSwift */ = {
 			isa = XCSwiftPackageProductDependency;
 			package = 3FEC91782A4D3DB90044BFF5 /* XCRemoteSwiftPackageReference "realm-swift" */;
 			productName = RealmSwift;
 		};
-		3FF673402A684E7700500A25 /* Realm */ = {
-			isa = XCSwiftPackageProductDependency;
-			package = 3FEC91782A4D3DB90044BFF5 /* XCRemoteSwiftPackageReference "realm-swift" */;
-			productName = Realm;
-		};
 		3FF673422A684E7700500A25 /* RealmSwift */ = {
 			isa = XCSwiftPackageProductDependency;
 			package = 3FEC91782A4D3DB90044BFF5 /* XCRemoteSwiftPackageReference "realm-swift" */;