From 8213ddbc879238d783032a31aac7be77fc543dbb Mon Sep 17 00:00:00 2001
From: Tim Oliver <timoliver@meta.com>
Date: Sun, 17 Mar 2024 21:54:13 -0700
Subject: [PATCH] Add privacy manifest file to IGListKit

Summary:
By popular demand, adds a `PrivacyInfo.xcprivacy` defining the privacy policies of IGListKit. As a purely UI based library, there are no privacy implications of IGListKit, but it is still necessary to add an empty manifest file to indicate this.

The privacy manifest has been added to CocoaPods, SPM and to generated dynamic frameworks for Carthage.

I had to change the behaviour of `IGListSwiftKit` to rely on the same symlink mechanism as the Obj-C libraries in order to combine the Swift files and the privacy manifest into the same directory that can then be pointed at by SPM.

Reviewed By: benhgreen

Differential Revision: D54935762

fbshipit-source-id: 5b0ab5dd4b807097c2c9589bc250424550bf1d83
---
 IGListDiffKit.podspec                         |   1 +
 IGListKit.podspec                             |   1 +
 IGListKit.xcodeproj/project.pbxproj           | 119 +++++++++++++++++-
 IGListSwiftKit.podspec                        |   1 +
 Package.swift                                 |  11 +-
 Source/PrivacyInfo.xcprivacy                  |  20 +++
 scripts/generate_spm_sources_layout.sh        |  61 ++++++++-
 .../IGListDiffKit/PrivacyInfo.xcprivacy       |   1 +
 spm/Sources/IGListKit/PrivacyInfo.xcprivacy   |   1 +
 .../IGListCollectionContext+Refinements.swift |   1 +
 ...tSingleSectionController+Refinements.swift |   1 +
 .../IGListSwiftKit/ListIdentifiable.swift     |   1 +
 .../ListValueSectionController.swift          |   1 +
 .../IGListSwiftKit/PrivacyInfo.xcprivacy      |   1 +
 14 files changed, 215 insertions(+), 6 deletions(-)
 create mode 100644 Source/PrivacyInfo.xcprivacy
 create mode 120000 spm/Sources/IGListDiffKit/PrivacyInfo.xcprivacy
 create mode 120000 spm/Sources/IGListKit/PrivacyInfo.xcprivacy
 create mode 120000 spm/Sources/IGListSwiftKit/IGListCollectionContext+Refinements.swift
 create mode 120000 spm/Sources/IGListSwiftKit/IGListSingleSectionController+Refinements.swift
 create mode 120000 spm/Sources/IGListSwiftKit/ListIdentifiable.swift
 create mode 120000 spm/Sources/IGListSwiftKit/ListValueSectionController.swift
 create mode 120000 spm/Sources/IGListSwiftKit/PrivacyInfo.xcprivacy

diff --git a/IGListDiffKit.podspec b/IGListDiffKit.podspec
index cba54dbac..c89cf7243 100644
--- a/IGListDiffKit.podspec
+++ b/IGListDiffKit.podspec
@@ -23,6 +23,7 @@ Pod::Spec.new do |s|
   s.source_files = 'Source/IGListDiffKit/**/*.{h,m,mm}'
   s.private_header_files = 'Source/IGListDiffKit/Internal/*.h'
 
+  s.resources = ['Source/PrivacyInfo.xcprivacy']
   s.requires_arc = true
 
   s.ios.deployment_target = '11.0'
diff --git a/IGListKit.podspec b/IGListKit.podspec
index 170e0f646..907307a41 100644
--- a/IGListKit.podspec
+++ b/IGListKit.podspec
@@ -35,6 +35,7 @@ Pod::Spec.new do |s|
 
   s.osx.source_files = 'Source/IGListKit/IGListKit.h'
 
+  s.resources = ['Source/PrivacyInfo.xcprivacy']
   s.requires_arc = true
 
   s.ios.deployment_target = '11.0'
diff --git a/IGListKit.xcodeproj/project.pbxproj b/IGListKit.xcodeproj/project.pbxproj
index 4e82b5257..851ebb2cb 100644
--- a/IGListKit.xcodeproj/project.pbxproj
+++ b/IGListKit.xcodeproj/project.pbxproj
@@ -424,6 +424,14 @@
 		F10C8F582B982EE7009F4690 /* IGListDefaultExperiments.h in Headers */ = {isa = PBXBuildFile; fileRef = F10C8F562B982DFD009F4690 /* IGListDefaultExperiments.h */; };
 		F10C8F5B2B9830F0009F4690 /* IGListTestCollectionViewLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = F10C8F592B9830E6009F4690 /* IGListTestCollectionViewLayout.m */; };
 		F10C8F5C2B9830F1009F4690 /* IGListTestCollectionViewLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = F10C8F592B9830E6009F4690 /* IGListTestCollectionViewLayout.m */; };
+		F15F1DE02BA40D05002AF3FE /* PrivacyInfo.xcprivacy in Copy Privacy Manifest */ = {isa = PBXBuildFile; fileRef = F15F1DDA2BA408C1002AF3FE /* PrivacyInfo.xcprivacy */; };
+		F15F1DE22BA40D22002AF3FE /* PrivacyInfo.xcprivacy in Copy Privacy Manifest */ = {isa = PBXBuildFile; fileRef = F15F1DDA2BA408C1002AF3FE /* PrivacyInfo.xcprivacy */; };
+		F15F1DE42BA40D2A002AF3FE /* PrivacyInfo.xcprivacy in Copy Privacy Manifest */ = {isa = PBXBuildFile; fileRef = F15F1DDA2BA408C1002AF3FE /* PrivacyInfo.xcprivacy */; };
+		F15F1DE62BA40D41002AF3FE /* PrivacyInfo.xcprivacy in Copy Privacy Manifest */ = {isa = PBXBuildFile; fileRef = F15F1DDA2BA408C1002AF3FE /* PrivacyInfo.xcprivacy */; };
+		F15F1DE82BA40D64002AF3FE /* PrivacyInfo.xcprivacy in Copy Privacy Manifest */ = {isa = PBXBuildFile; fileRef = F15F1DDA2BA408C1002AF3FE /* PrivacyInfo.xcprivacy */; };
+		F15F1DEA2BA40D74002AF3FE /* PrivacyInfo.xcprivacy in Copy Privacy Manifest */ = {isa = PBXBuildFile; fileRef = F15F1DDA2BA408C1002AF3FE /* PrivacyInfo.xcprivacy */; };
+		F15F1DEC2BA40D90002AF3FE /* PrivacyInfo.xcprivacy in Copy Privacy Manifest */ = {isa = PBXBuildFile; fileRef = F15F1DDA2BA408C1002AF3FE /* PrivacyInfo.xcprivacy */; };
+		F15F1DEE2BA40D9C002AF3FE /* PrivacyInfo.xcprivacy in Copy Privacy Manifest */ = {isa = PBXBuildFile; fileRef = F15F1DDA2BA408C1002AF3FE /* PrivacyInfo.xcprivacy */; };
 		F1855A4C29BC565600558D18 /* IGListDiffDescriptionStringTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F1855A4B29BC565600558D18 /* IGListDiffDescriptionStringTests.m */; };
 		F1855A4D29BC565600558D18 /* IGListDiffDescriptionStringTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F1855A4B29BC565600558D18 /* IGListDiffDescriptionStringTests.m */; };
 		F1855A4E29BC565600558D18 /* IGListDiffDescriptionStringTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F1855A4B29BC565600558D18 /* IGListDiffDescriptionStringTests.m */; };
@@ -511,6 +519,97 @@
 		};
 /* End PBXContainerItemProxy section */
 
+/* Begin PBXCopyFilesBuildPhase section */
+		F15F1DDF2BA40CF4002AF3FE /* Copy Privacy Manifest */ = {
+			isa = PBXCopyFilesBuildPhase;
+			buildActionMask = 2147483647;
+			dstPath = "";
+			dstSubfolderSpec = 7;
+			files = (
+				F15F1DE02BA40D05002AF3FE /* PrivacyInfo.xcprivacy in Copy Privacy Manifest */,
+			);
+			name = "Copy Privacy Manifest";
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		F15F1DE12BA40D15002AF3FE /* Copy Privacy Manifest */ = {
+			isa = PBXCopyFilesBuildPhase;
+			buildActionMask = 2147483647;
+			dstPath = "";
+			dstSubfolderSpec = 7;
+			files = (
+				F15F1DE22BA40D22002AF3FE /* PrivacyInfo.xcprivacy in Copy Privacy Manifest */,
+			);
+			name = "Copy Privacy Manifest";
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		F15F1DE32BA40D27002AF3FE /* Copy Privacy Manifest */ = {
+			isa = PBXCopyFilesBuildPhase;
+			buildActionMask = 2147483647;
+			dstPath = "";
+			dstSubfolderSpec = 7;
+			files = (
+				F15F1DE42BA40D2A002AF3FE /* PrivacyInfo.xcprivacy in Copy Privacy Manifest */,
+			);
+			name = "Copy Privacy Manifest";
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		F15F1DE52BA40D37002AF3FE /* Copy Privacy Manifest */ = {
+			isa = PBXCopyFilesBuildPhase;
+			buildActionMask = 2147483647;
+			dstPath = "";
+			dstSubfolderSpec = 7;
+			files = (
+				F15F1DE62BA40D41002AF3FE /* PrivacyInfo.xcprivacy in Copy Privacy Manifest */,
+			);
+			name = "Copy Privacy Manifest";
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		F15F1DE72BA40D5E002AF3FE /* Copy Privacy Manifest */ = {
+			isa = PBXCopyFilesBuildPhase;
+			buildActionMask = 2147483647;
+			dstPath = "";
+			dstSubfolderSpec = 7;
+			files = (
+				F15F1DE82BA40D64002AF3FE /* PrivacyInfo.xcprivacy in Copy Privacy Manifest */,
+			);
+			name = "Copy Privacy Manifest";
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		F15F1DE92BA40D6D002AF3FE /* Copy Privacy Manifest */ = {
+			isa = PBXCopyFilesBuildPhase;
+			buildActionMask = 2147483647;
+			dstPath = "";
+			dstSubfolderSpec = 7;
+			files = (
+				F15F1DEA2BA40D74002AF3FE /* PrivacyInfo.xcprivacy in Copy Privacy Manifest */,
+			);
+			name = "Copy Privacy Manifest";
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		F15F1DEB2BA40D7C002AF3FE /* Copy Privacy Manifest */ = {
+			isa = PBXCopyFilesBuildPhase;
+			buildActionMask = 2147483647;
+			dstPath = "";
+			dstSubfolderSpec = 7;
+			files = (
+				F15F1DEC2BA40D90002AF3FE /* PrivacyInfo.xcprivacy in Copy Privacy Manifest */,
+			);
+			name = "Copy Privacy Manifest";
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		F15F1DED2BA40D94002AF3FE /* Copy Privacy Manifest */ = {
+			isa = PBXCopyFilesBuildPhase;
+			buildActionMask = 2147483647;
+			dstPath = "";
+			dstSubfolderSpec = 7;
+			files = (
+				F15F1DEE2BA40D9C002AF3FE /* PrivacyInfo.xcprivacy in Copy Privacy Manifest */,
+			);
+			name = "Copy Privacy Manifest";
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXCopyFilesBuildPhase section */
+
 /* Begin PBXFileReference section */
 		13DF01711FA0FD400092A320 /* IGListTestAdapterReorderingDataSource.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = IGListTestAdapterReorderingDataSource.h; sourceTree = "<group>"; };
 		13DF01721FA0FD400092A320 /* IGListTestAdapterReorderingDataSource.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = IGListTestAdapterReorderingDataSource.m; sourceTree = "<group>"; };
@@ -758,6 +857,11 @@
 		F10C8F562B982DFD009F4690 /* IGListDefaultExperiments.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = IGListDefaultExperiments.h; sourceTree = "<group>"; };
 		F10C8F592B9830E6009F4690 /* IGListTestCollectionViewLayout.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = IGListTestCollectionViewLayout.m; sourceTree = "<group>"; };
 		F10C8F5A2B9830E6009F4690 /* IGListTestCollectionViewLayout.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = IGListTestCollectionViewLayout.h; sourceTree = "<group>"; };
+		F15F1DDA2BA408C1002AF3FE /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
+		F15F1DDB2BA40B84002AF3FE /* Package.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = SOURCE_ROOT; };
+		F15F1DDC2BA40BC9002AF3FE /* IGListKit.podspec */ = {isa = PBXFileReference; lastKnownFileType = text; path = IGListKit.podspec; sourceTree = "<group>"; };
+		F15F1DDD2BA40BC9002AF3FE /* IGListDiffKit.podspec */ = {isa = PBXFileReference; lastKnownFileType = text; path = IGListDiffKit.podspec; sourceTree = "<group>"; };
+		F15F1DDE2BA40BC9002AF3FE /* IGListSwiftKit.podspec */ = {isa = PBXFileReference; lastKnownFileType = text; path = IGListSwiftKit.podspec; sourceTree = "<group>"; };
 		F1855A4B29BC565600558D18 /* IGListDiffDescriptionStringTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IGListDiffDescriptionStringTests.m; sourceTree = "<group>"; };
 		F18CC75B29EFBB9400DC3B9A /* IGListCollectionViewTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IGListCollectionViewTests.m; sourceTree = "<group>"; };
 		F18CC75E29EFBBB300DC3B9A /* IGListBindingSingleSectionControllerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IGListBindingSingleSectionControllerTests.m; sourceTree = "<group>"; };
@@ -867,6 +971,7 @@
 				7A02CEC6236150C400B49FAE /* IGListKit */,
 				7A92EA9823A8A42000E5A13D /* IGListSwiftKit */,
 				7A02D0AC236153CE00B49FAE /* Info.plist */,
+				F15F1DDA2BA408C1002AF3FE /* PrivacyInfo.xcprivacy */,
 			);
 			path = Source;
 			sourceTree = "<group>";
@@ -1144,10 +1249,14 @@
 		887D0B2C1D870D7E009E01F7 = {
 			isa = PBXGroup;
 			children = (
-				887D0B371D870D7E009E01F7 /* Products */,
 				0B3B927E1E08D7F5008390ED /* Source */,
 				887D0B551D870E1E009E01F7 /* Tests */,
 				15D054C1829CB3E2E2196A55 /* Pods */,
+				887D0B371D870D7E009E01F7 /* Products */,
+				F15F1DDD2BA40BC9002AF3FE /* IGListDiffKit.podspec */,
+				F15F1DDC2BA40BC9002AF3FE /* IGListKit.podspec */,
+				F15F1DDE2BA40BC9002AF3FE /* IGListSwiftKit.podspec */,
+				F15F1DDB2BA40B84002AF3FE /* Package.swift */,
 			);
 			sourceTree = "<group>";
 			usesTabs = 0;
@@ -1463,6 +1572,7 @@
 			isa = PBXNativeTarget;
 			buildConfigurationList = 7A02D0222361520200B49FAE /* Build configuration list for PBXNativeTarget "IGListDiffKit" */;
 			buildPhases = (
+				F15F1DE52BA40D37002AF3FE /* Copy Privacy Manifest */,
 				7A02D0182361520200B49FAE /* Headers */,
 				7A02D0192361520200B49FAE /* Sources */,
 				7A02D01A2361520200B49FAE /* Frameworks */,
@@ -1480,6 +1590,7 @@
 			isa = PBXNativeTarget;
 			buildConfigurationList = 7A02D0302361525800B49FAE /* Build configuration list for PBXNativeTarget "IGListDiffKit-tvOS" */;
 			buildPhases = (
+				F15F1DE72BA40D5E002AF3FE /* Copy Privacy Manifest */,
 				7A02D0262361525800B49FAE /* Headers */,
 				7A02D0272361525800B49FAE /* Sources */,
 				7A02D0282361525800B49FAE /* Frameworks */,
@@ -1497,6 +1608,7 @@
 			isa = PBXNativeTarget;
 			buildConfigurationList = 7A02D03D2361526600B49FAE /* Build configuration list for PBXNativeTarget "IGListDiffKit-macOS" */;
 			buildPhases = (
+				F15F1DE92BA40D6D002AF3FE /* Copy Privacy Manifest */,
 				7A02D0332361526600B49FAE /* Headers */,
 				7A02D0342361526600B49FAE /* Sources */,
 				7A02D0352361526600B49FAE /* Frameworks */,
@@ -1514,6 +1626,7 @@
 			isa = PBXNativeTarget;
 			buildConfigurationList = 7A92EA9C23A8A42000E5A13D /* Build configuration list for PBXNativeTarget "IGListSwiftKit" */;
 			buildPhases = (
+				F15F1DEB2BA40D7C002AF3FE /* Copy Privacy Manifest */,
 				7A92EA9223A8A42000E5A13D /* Headers */,
 				7A92EA9323A8A42000E5A13D /* Sources */,
 				7A92EA9423A8A42000E5A13D /* Frameworks */,
@@ -1534,6 +1647,7 @@
 			isa = PBXNativeTarget;
 			buildConfigurationList = 7A92EAAD23A8A50100E5A13D /* Build configuration list for PBXNativeTarget "IGListSwiftKit-tvOS" */;
 			buildPhases = (
+				F15F1DED2BA40D94002AF3FE /* Copy Privacy Manifest */,
 				7A92EAA323A8A50100E5A13D /* Headers */,
 				7A92EAA423A8A50100E5A13D /* Sources */,
 				7A92EAA523A8A50100E5A13D /* Frameworks */,
@@ -1554,6 +1668,7 @@
 			isa = PBXNativeTarget;
 			buildConfigurationList = 885FE1E91DC51A0D009CE2B4 /* Build configuration list for PBXNativeTarget "IGListKit-tvOS" */;
 			buildPhases = (
+				F15F1DE12BA40D15002AF3FE /* Copy Privacy Manifest */,
 				885FE1CF1DC51A0D009CE2B4 /* Sources */,
 				885FE1D01DC51A0D009CE2B4 /* Frameworks */,
 				885FE1D11DC51A0D009CE2B4 /* Headers */,
@@ -1590,6 +1705,7 @@
 			isa = PBXNativeTarget;
 			buildConfigurationList = 887D0B4A1D870D7F009E01F7 /* Build configuration list for PBXNativeTarget "IGListKit" */;
 			buildPhases = (
+				F15F1DDF2BA40CF4002AF3FE /* Copy Privacy Manifest */,
 				887D0B311D870D7E009E01F7 /* Sources */,
 				887D0B321D870D7E009E01F7 /* Frameworks */,
 				887D0B331D870D7E009E01F7 /* Headers */,
@@ -1644,6 +1760,7 @@
 			isa = PBXNativeTarget;
 			buildConfigurationList = DD3152A91DE227FA00AC9D2C /* Build configuration list for PBXNativeTarget "IGListKit-macOS" */;
 			buildPhases = (
+				F15F1DE32BA40D27002AF3FE /* Copy Privacy Manifest */,
 				DD3152671DE227FA00AC9D2C /* Sources */,
 				DD31527B1DE227FA00AC9D2C /* Frameworks */,
 				DD31527C1DE227FA00AC9D2C /* Headers */,
diff --git a/IGListSwiftKit.podspec b/IGListSwiftKit.podspec
index f50e0fea7..363dab8c1 100644
--- a/IGListSwiftKit.podspec
+++ b/IGListSwiftKit.podspec
@@ -28,6 +28,7 @@ Pod::Spec.new do |s|
     ]
   end
 
+  s.resources = ['Source/PrivacyInfo.xcprivacy']
   s.requires_arc = true
 
   s.swift_versions = ['4.0', '5.0', '5.1']
diff --git a/Package.swift b/Package.swift
index f42caff2b..892919bcd 100644
--- a/Package.swift
+++ b/Package.swift
@@ -1,4 +1,4 @@
-// swift-tools-version:5.0
+// swift-tools-version:5.3
 import PackageDescription
 
 let package = Package(
@@ -21,17 +21,20 @@ let package = Package(
     targets: [
         .target(
             name: "IGListDiffKit",
-            path: "spm/Sources/IGListDiffKit"
+            path: "spm/Sources/IGListDiffKit",
+            resources: [.copy("PrivacyInfo.xcprivacy")]
         ),
         .target(
             name: "IGListKit",
             dependencies: ["IGListDiffKit"],
-            path: "spm/Sources/IGListKit"
+            path: "spm/Sources/IGListKit",
+            resources: [.copy("PrivacyInfo.xcprivacy")]
         ),
         .target(
             name: "IGListSwiftKit",
             dependencies: ["IGListKit"],
-            path: "Source/IGListSwiftKit"
+            path: "spm/Sources/IGListSwiftKit",
+            resources: [.copy("PrivacyInfo.xcprivacy")]
         ),
     ],
     cLanguageStandard: .c11,
diff --git a/Source/PrivacyInfo.xcprivacy b/Source/PrivacyInfo.xcprivacy
new file mode 100644
index 000000000..d4e729edc
--- /dev/null
+++ b/Source/PrivacyInfo.xcprivacy
@@ -0,0 +1,20 @@
+<?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">
+<!--
+    Copyright (c) Meta Platforms, Inc. and affiliates.
+
+    This source code is licensed under the MIT license found in the
+    LICENSE file in the root directory of this source tree.
+-->
+<plist version="1.0">
+    <dict>
+        <key>NSPrivacyAccessedAPITypes</key>
+        <array/>
+        <key>NSPrivacyCollectedDataTypes</key>
+        <array/>
+        <key>NSPrivacyTracking</key>
+        <false/>
+        <key>NSPrivacyTrackingDomains</key>
+        <array/>
+    </dict>
+</plist>
diff --git a/scripts/generate_spm_sources_layout.sh b/scripts/generate_spm_sources_layout.sh
index 60ebb22e9..5c8add8fa 100755
--- a/scripts/generate_spm_sources_layout.sh
+++ b/scripts/generate_spm_sources_layout.sh
@@ -204,6 +204,59 @@ function generate_ig_list_kit() {
     generate_ig_list_kit_spm_sources
 }
 
+#### IGListSwiftKit
+SPM_IG_LIST_SWIFT_KIT_SOURCES_PATH="spm/Sources/IGListSwiftKit"
+
+function generate_ig_list_swift_kit_spm_sources() {
+    echo "Generate symbolic links for all public implementations. *.swift"
+    echo "Generated under ${SPM_IG_LIST_SWIFT_KIT_SOURCES_PATH}"
+
+    sources_list=$(
+        find "Source/IGListSwiftKit" \
+        -type f -name "*.swift" \
+        -not -path "spm/*" | sed "s| \([^/]\)|:\1|g")
+
+    SRC_ROOT=$(pwd)
+    cd $SPM_IG_LIST_SWIFT_KIT_SOURCES_PATH
+
+    for source_file in $sources_list; do
+        file_to_link=$(echo $source_file | sed "s|:| |g")
+
+        ln -s ../../../$file_to_link
+
+    done
+
+    cd $SRC_ROOT
+
+    echo "      Done"
+    echo ""
+}
+
+function generate_ig_list_swift_kit() {
+    generate_ig_list_swift_kit_spm_sources
+}
+
+function generate_ig_privacy_manifest_spm() {
+    echo "Generate symbolic links for privacy manifest"
+
+    directories=(${SPM_IG_LIST_KIT_SOURCES_PATH} 
+                    ${SPM_IG_LIST_DIFF_KIT_SOURCES_PATH} 
+                    ${SPM_IG_LIST_SWIFT_KIT_SOURCES_PATH})
+    manifest_file="Source/PrivacyInfo.xcprivacy"
+    SRC_ROOT=$(pwd)
+
+    for directory in ${directories[@]}; do
+        echo "Generated under ${directory}"
+        cd ${directory}
+        file_to_link=$(echo $manifest_file | sed "s|:| |g")
+        ln -s ../../../$file_to_link
+        cd $SRC_ROOT
+    done
+
+    echo "      Done"
+    echo ""
+}
+
 # Delete all symbolik links from `spm` folder
 function cleanup() {
     rm -rf $SPM_IG_LIST_DIFF_KIT_PUBLIC_HEADERS_PATH/*.*
@@ -211,6 +264,8 @@ function cleanup() {
     #IGListKit
     rm -rf $SPM_IG_LIST_KIT_PUBLIC_HEADERS_PATH/*.*
     rm -rf $SPM_IG_LIST_KIT_SOURCES_PATH/*.*
+    #IGListSwiftKit
+    rm -rf $SPM_IG_LIST_SWIFT_KIT_SOURCES_PATH/*.*
 }
 
 ########## SPM generator pipeline #############
@@ -218,5 +273,9 @@ function cleanup() {
 cleanup
 #2
 generate_ig_list_diff_kit
-# #3
+#3
 generate_ig_list_kit
+#4
+generate_ig_list_swift_kit
+#5
+generate_ig_privacy_manifest_spm
diff --git a/spm/Sources/IGListDiffKit/PrivacyInfo.xcprivacy b/spm/Sources/IGListDiffKit/PrivacyInfo.xcprivacy
new file mode 120000
index 000000000..48976e4ae
--- /dev/null
+++ b/spm/Sources/IGListDiffKit/PrivacyInfo.xcprivacy
@@ -0,0 +1 @@
+../../../Source/PrivacyInfo.xcprivacy
\ No newline at end of file
diff --git a/spm/Sources/IGListKit/PrivacyInfo.xcprivacy b/spm/Sources/IGListKit/PrivacyInfo.xcprivacy
new file mode 120000
index 000000000..48976e4ae
--- /dev/null
+++ b/spm/Sources/IGListKit/PrivacyInfo.xcprivacy
@@ -0,0 +1 @@
+../../../Source/PrivacyInfo.xcprivacy
\ No newline at end of file
diff --git a/spm/Sources/IGListSwiftKit/IGListCollectionContext+Refinements.swift b/spm/Sources/IGListSwiftKit/IGListCollectionContext+Refinements.swift
new file mode 120000
index 000000000..9ba4dcff3
--- /dev/null
+++ b/spm/Sources/IGListSwiftKit/IGListCollectionContext+Refinements.swift
@@ -0,0 +1 @@
+../../../Source/IGListSwiftKit/IGListCollectionContext+Refinements.swift
\ No newline at end of file
diff --git a/spm/Sources/IGListSwiftKit/IGListSingleSectionController+Refinements.swift b/spm/Sources/IGListSwiftKit/IGListSingleSectionController+Refinements.swift
new file mode 120000
index 000000000..5617c96f6
--- /dev/null
+++ b/spm/Sources/IGListSwiftKit/IGListSingleSectionController+Refinements.swift
@@ -0,0 +1 @@
+../../../Source/IGListSwiftKit/IGListSingleSectionController+Refinements.swift
\ No newline at end of file
diff --git a/spm/Sources/IGListSwiftKit/ListIdentifiable.swift b/spm/Sources/IGListSwiftKit/ListIdentifiable.swift
new file mode 120000
index 000000000..15d78ce3c
--- /dev/null
+++ b/spm/Sources/IGListSwiftKit/ListIdentifiable.swift
@@ -0,0 +1 @@
+../../../Source/IGListSwiftKit/ListIdentifiable.swift
\ No newline at end of file
diff --git a/spm/Sources/IGListSwiftKit/ListValueSectionController.swift b/spm/Sources/IGListSwiftKit/ListValueSectionController.swift
new file mode 120000
index 000000000..ab81b29cc
--- /dev/null
+++ b/spm/Sources/IGListSwiftKit/ListValueSectionController.swift
@@ -0,0 +1 @@
+../../../Source/IGListSwiftKit/ListValueSectionController.swift
\ No newline at end of file
diff --git a/spm/Sources/IGListSwiftKit/PrivacyInfo.xcprivacy b/spm/Sources/IGListSwiftKit/PrivacyInfo.xcprivacy
new file mode 120000
index 000000000..48976e4ae
--- /dev/null
+++ b/spm/Sources/IGListSwiftKit/PrivacyInfo.xcprivacy
@@ -0,0 +1 @@
+../../../Source/PrivacyInfo.xcprivacy
\ No newline at end of file