     }
 }
 
+// MARK: - Helpers
+
+extension PBXProject {
+    /// Adds reference for remote Swift package
+    private func addSwiftPackageReference(repositoryURL: String,
+                                          productName: String,
+                                          versionRequirement: XCRemoteSwiftPackageReference.VersionRequirement) throws -> XCRemoteSwiftPackageReference {
+        let reference: XCRemoteSwiftPackageReference
+        if let package = packages.first(where: { $0.repositoryURL == repositoryURL }) {
+            guard package.versionRequirement == versionRequirement else {
+                throw PBXProjError.multipleRemotePackages(productName: productName)
+            }
+            reference = package
+        } else {
+            reference = XCRemoteSwiftPackageReference(repositoryURL: repositoryURL, versionRequirement: versionRequirement)
+            try self.objects().add(object: reference)
+            packages.append(reference)
+        }
+        
+        return reference
+    }
+    
+    /// Adds package product for remote Swift package
+    private func addSwiftPackageProduct(reference: XCRemoteSwiftPackageReference,
+                                        productName: String,
+                                        target: PBXTarget) throws -> XCSwiftPackageProductDependency {
+        let objects = try self.objects()
+        
+        let productDependency: XCSwiftPackageProductDependency
+        // Avoid duplication
+        if let product = objects.swiftPackageProductDependencies.first(where: { $0.value.package == reference })?.value {
+            productDependency = product
+        } else {
+            productDependency = XCSwiftPackageProductDependency(productName: productName, package: reference)
+            objects.add(object: productDependency)
+        }
+        target.packageProductDependencies.append(productDependency)
+        
+        return productDependency
+    }
+    
+    /// Adds package product for local Swift package
+    private func addLocalSwiftPackageProduct(path: Path,
+                                             productName: String,
+                                             target: PBXTarget) throws -> XCSwiftPackageProductDependency {
+        let objects = try self.objects()
+        
+        let productDependency: XCSwiftPackageProductDependency
+        // Avoid duplication
+        if let product = objects.swiftPackageProductDependencies.first(where: { $0.value.productName == productName }) {
+            guard objects.fileReferences.first(where: { $0.value.name == productName })?.value.path == path.string else {
+                throw PBXProjError.multipleLocalPackages(productName: productName)
+            }
+            productDependency = product.value
+        } else {
+            productDependency = XCSwiftPackageProductDependency(productName: productName)
+            objects.add(object: productDependency)
+        }
+        target.packageProductDependencies.append(productDependency)
+        
+        return productDependency
+    }
+}
+
 // MARK: - PlistSerializable
 
 extension PBXProject: PlistSerializable {

        guard let target = targets.first(where: { $0.name == targetName}) else { throw PBXProjError.targetNotFound(targetName: targetName) }
        
        // Reference
        let reference: XCRemoteSwiftPackageReference
        if let package = packages.first(where: { $0.repositoryURL == repositoryURL }) {
            guard package.versionRequirement == versionRequirement else {
                throw PBXProjError.multipleRemotePackages(productName: productName)
            }
            reference = package
        } else {
            reference = XCRemoteSwiftPackageReference(repositoryURL: repositoryURL, versionRequirement: versionRequirement)
            objects.add(object: reference)
            packages.append(reference)
        }

        // Product
        let productDependency: XCSwiftPackageProductDependency
        // Avoid duplication
        if let product = objects.swiftPackageProductDependencies.first(where: { $0.value.package == reference })?.value {
            productDependency = product
        } else {
            productDependency = XCSwiftPackageProductDependency(productName: productName, package: reference)
            objects.add(object: productDependency)
        }
        target.packageProductDependencies.append(productDependency)

        // Build file
        let buildFile = PBXBuildFile(product: productDependency)
        objects.add(object: buildFile)

        guard let target = targets.first(where: { $0.name == targetName}) else { throw PBXProjError.targetNotFound(targetName: targetName) }
        
        // Product
        let productDependency = try addLocalSwiftPackageProduct(path: path,
                                                                productName: productName,
                                                                target: target)
        
        // Build file
        let buildFile = PBXBuildFile(product: productDependency)
        objects.add(object: buildFile)
