This is an automated email from the ASF dual-hosted git repository.

erisu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cordova-ios.git


The following commit(s) were added to refs/heads/master by this push:
     new 3fc73751 feat(spm): Support plugins as Swift packages (#1515)
3fc73751 is described below

commit 3fc737518f73aabcf2b9f3a0ff83952c8f7e64be
Author: Darryl Pogue <dar...@dpogue.ca>
AuthorDate: Mon Jun 2 22:31:35 2025 -0700

    feat(spm): Support plugins as Swift packages (#1515)
    
    * feat(spm): Add CordovaPlugins SPM to template
    * feat(spm): Update Package.swift on plugin add/remove
    * feat(spm): Copy plugins and rewrite Cordova dependency
    * feat(spm): Move CordovaPlugins into the packages dir
    
    This helps keep the top level project directory a bit cleaner by hiding
    our CordovaPlugins SPM accumulator package inside the packages
    directory.
    
    * feat(spm): Handle plugins with npm namespaces
    * feat(spm): Support linked cordova-ios
    * feat(spm): support nospm flag for plugin pods
    * feat: add nospm flag for pod, add package attribute in platform tag
    * feat: use plugin.xml for check podspec import
    * fix: skip pod installation correctly
    * feat: use isSwiftPacakge method to choose necessary pod tags
    * fix: cocoapod lib install condition
    * feat: add test code for cocoapod nospm attribute
    * test: update unit tests code
    * feat: improve test code
    
    ---------
    
    Co-authored-by: jcesarmobile <jcesarmob...@gmail.com>
    Co-authored-by: knaito-asial 
<81949829+knaito-as...@users.noreply.github.com>
---
 lib/Api.js                                         |  73 ++++---
 lib/SwiftPackage.js                                | 114 +++++++++++
 lib/create.js                                      |   3 +-
 lib/plugman/pluginHandlers.js                      |  21 ++
 lib/prepare.js                                     |   2 +-
 templates/project/App.xcodeproj/project.pbxproj    |  20 +-
 .../packages/cordova-ios-plugins/Package.swift     |  37 ++++
 .../Sources/CordovaPlugins/CordovaPlugins.swift    |  21 ++
 tests/spec/coverage.json                           |   4 +-
 tests/spec/unit/Api.spec.js                        |  52 +++++
 tests/spec/unit/Plugman/pluginHandler.spec.js      |  57 +++---
 tests/spec/unit/SwiftPackage.spec.js               | 218 +++++++++++++++++++++
 .../ios-config-xml/App.xcodeproj/project.pbxproj   |  20 +-
 .../ios-config-xml/CordovaPlugins/Package.swift    |  37 ++++
 .../Sources/CordovaPlugins/CordovaPlugins.swift    |  21 ++
 .../App.xcodeproj/project.pbxproj                  |  20 +-
 .../project.xcworkspace/contents.xcworkspacedata   |  25 +++
 .../xcshareddata/IDEWorkspaceChecks.plist          |   8 +
 .../App.xcworkspace/contents.xcworkspacedata       |  25 +++
 .../xcshareddata/IDEWorkspaceChecks.plist          |   8 +
 .../xcshareddata/xcschemes/App.xcscheme            | 109 +++++++++++
 .../ios-packageswift-config-xml/App/.gitignore     |   5 +
 .../ios-packageswift-config-xml/App/App-Info.plist |  63 ++++++
 .../ios-packageswift-config-xml/App/AppDelegate.h  |  29 +++
 .../App/AppDelegate.swift                          |  29 +++
 .../AppIcon.appiconset/Contents.json               |  20 ++
 .../Assets.xcassets/AppIcon.appiconset/icon.png    | Bin 0 -> 31816 bytes
 .../BackgroundColor.colorset/Contents.json         |  15 ++
 .../App/Assets.xcassets/Contents.json              |   6 +
 .../LaunchStoryboard.imageset/Contents.json        | 168 ++++++++++++++++
 .../Contents.json                                  |  15 ++
 .../Contents.json                                  |  15 ++
 .../App/Base.lproj/CDVLaunchScreen.storyboard      |  65 ++++++
 .../App/Base.lproj/Main.storyboard                 |  66 +++++++
 .../App/Bridging-Header.h                          |  25 +++
 .../App/Entitlements-Debug.plist                   |  24 +++
 .../App/Entitlements-Release.plist                 |  24 +++
 .../App/MainViewController.h                       |  29 +++
 .../ios-packageswift-config-xml/App/Plugins/README |  20 ++
 .../App/PrivacyInfo.xcprivacy                      |  32 +++
 .../App/Resources/README                           |  20 ++
 .../App/SceneDelegate.swift                        |  25 +++
 .../App/ViewController.swift                       |  27 +++
 .../ios-packageswift-config-xml/App/config.xml     |  82 ++++++++
 .../CordovaPlugins/Package.swift                   |  37 ++++
 .../Sources/CordovaPlugins/CordovaPlugins.swift    |  21 ++
 .../cordova/defaults.xml                           |  59 ++++++
 .../packages/cordova-ios-plugins/Package.swift     |  40 ++++
 .../packages/cordova-ios/Package.swift             |  47 +++++
 .../platform_www/.gitkeep                          |   0
 .../ios-packageswift-config-xml/www/.gitkeep       |   0
 .../Package.swift                                  |  47 +++++
 .../package.json                                   |  12 ++
 .../plugin.xml                                     |  43 ++++
 .../src/ios/PackagePodPlugin.swift                 |  46 +++++
 .../Package.swift                                  |  46 +++++
 .../org.test.plugins.swiftpackageplugin/plugin.xml |  33 ++++
 .../src/ios/PackagePlugin.swift                    |  27 +++
 tests/spec/unit/fixtures/test-Package.swift        |  37 ++++
 59 files changed, 2132 insertions(+), 62 deletions(-)

diff --git a/lib/Api.js b/lib/Api.js
index c131f1b8..9153cce8 100644
--- a/lib/Api.js
+++ b/lib/Api.js
@@ -34,6 +34,12 @@ const {
     PluginManager
 } = require('cordova-common');
 
+// check the value is true or 'true' or 'TRUE' or 1
+const _isTrue = (value) => {
+    return (value === true) ||
+    (typeof value === 'string' && value.toLowerCase() === 'true') || value === 
1;
+};
+
 function setupEvents (externalEventEmitter) {
     if (externalEventEmitter) {
         // This will make the platform internal events visible outside
@@ -226,6 +232,7 @@ class Api {
      */
     addPlugin (plugin, installOptions) {
         const xcodeproj = projectFile.parse(this.locations);
+        const { SwiftPackage, isSwiftPackagePlugin } = 
require('./SwiftPackage');
 
         installOptions = installOptions || {};
         installOptions.variables = installOptions.variables || {};
@@ -237,7 +244,13 @@ class Api {
         return PluginManager.get(this.platform, this.locations, xcodeproj)
             .addPlugin(plugin, installOptions)
             .then(() => {
-                if (plugin != null) {
+                if (plugin != null && isSwiftPackagePlugin(plugin)) {
+                    const spm = new SwiftPackage(this.locations.root);
+                    spm.addPlugin(plugin, installOptions);
+                }
+            })
+            .then(() => {
+                if (plugin != null && !isSwiftPackagePlugin(plugin)) {
                     const headerTags = plugin.getHeaderFiles(this.platform);
                     const bridgingHeaders = headerTags.filter(obj => obj.type 
=== 'BridgingHeader');
                     if (bridgingHeaders.length > 0) {
@@ -279,11 +292,18 @@ class Api {
      */
     removePlugin (plugin, uninstallOptions) {
         const xcodeproj = projectFile.parse(this.locations);
+        const { SwiftPackage, isSwiftPackagePlugin } = 
require('./SwiftPackage');
 
         return PluginManager.get(this.platform, this.locations, xcodeproj)
             .removePlugin(plugin, uninstallOptions)
             .then(() => {
-                if (plugin != null) {
+                if (plugin != null && isSwiftPackagePlugin(plugin)) {
+                    const spm = new SwiftPackage(this.locations.root);
+                    spm.removePlugin(plugin);
+                }
+            })
+            .then(() => {
+                if (plugin != null && !isSwiftPackagePlugin(plugin)) {
                     const headerTags = plugin.getHeaderFiles(this.platform);
                     const bridgingHeaders = headerTags.filter(obj => obj.type 
=== 'BridgingHeader');
                     if (bridgingHeaders.length > 0) {
@@ -322,6 +342,7 @@ class Api {
         if (!podSpecs.length) {
             return;
         }
+        const { isSwiftPackagePlugin } = require('./SwiftPackage');
 
         const project_dir = this.locations.root;
         const project_name = 
this.locations.xcodeCordovaProj.split(path.sep).pop();
@@ -370,20 +391,21 @@ class Api {
                     }
                 });
             }
-
-            // libraries
             if (obj.libraries) {
+                const isSPM = isSwiftPackagePlugin(plugin);
                 Object.keys(obj.libraries).forEach(key => {
                     let podJson = Object.assign({}, obj.libraries[key]);
-                    podJson = replacePodSpecVariables(podJson, installOptions);
-                    const val = podsjsonFile.getLibrary(key);
-                    if (val) {
-                        events.emit('warn', `${plugin.id} depends on 
${podJson.name}, which may conflict with another plugin. 
${podJson.name}@${val.spec} is already installed and was not overwritten.`);
-                        podsjsonFile.incrementLibrary(key);
-                    } else {
-                        podJson.count = 1;
-                        podsjsonFile.setJsonLibrary(key, podJson);
-                        podfileFile.addSpec(podJson.name, podJson);
+                    if (!isSPM || (isSPM && !_isTrue(podJson.nospm))) {
+                        podJson = replacePodSpecVariables(podJson, 
installOptions);
+                        const val = podsjsonFile.getLibrary(key);
+                        if (val) {
+                            events.emit('warn', `${plugin.id} depends on 
${podJson.name}, which may conflict with another plugin. 
${podJson.name}@${val.spec} is already installed and was not overwritten.`);
+                            podsjsonFile.incrementLibrary(key);
+                        } else {
+                            podJson.count = 1;
+                            podsjsonFile.setJsonLibrary(key, podJson);
+                            podfileFile.addSpec(podJson.name, podJson);
+                        }
                     }
                 });
             }
@@ -415,6 +437,8 @@ class Api {
      */
 
     removePodSpecs (plugin, podSpecs, uninstallOptions) {
+        const { isSwiftPackagePlugin } = require('./SwiftPackage');
+
         const project_dir = this.locations.root;
         const project_name = 
this.locations.xcodeCordovaProj.split(path.sep).pop();
 
@@ -462,18 +486,21 @@ class Api {
                     }
                 });
                 // libraries
+                const isSPM = isSwiftPackagePlugin(plugin);
                 Object.keys(obj.libraries).forEach(key => {
                     let podJson = Object.assign({}, obj.libraries[key]);
-                    podJson = replacePodSpecVariables(podJson, 
uninstallOptions);
-                    const val = podsjsonFile.getLibrary(key);
-                    if (val) {
-                        podsjsonFile.decrementLibrary(key);
-                    } else {
-                        const message = util.format('plugin \"%s\" podspec 
\"%s\" does not seem to be in pods.json, nothing to remove. Will attempt to 
remove from Podfile.', plugin.id, podJson.name); /* eslint no-useless-escape : 
0 */
-                        events.emit('verbose', message);
-                    }
-                    if (!val || val.count === 0) {
-                        podfileFile.removeSpec(podJson.name);
+                    if (!isSPM || (isSPM && !_isTrue(podJson.nospm))) {
+                        podJson = replacePodSpecVariables(podJson, 
uninstallOptions);
+                        const val = podsjsonFile.getLibrary(key);
+                        if (val) {
+                            podsjsonFile.decrementLibrary(key);
+                        } else {
+                            const message = util.format('plugin \"%s\" podspec 
\"%s\" does not seem to be in pods.json, nothing to remove. Will attempt to 
remove from Podfile.', plugin.id, podJson.name); /* eslint no-useless-escape : 
0 */
+                            events.emit('verbose', message);
+                        }
+                        if (!val || val.count === 0) {
+                            podfileFile.removeSpec(podJson.name);
+                        }
                     }
                 });
             });
diff --git a/lib/SwiftPackage.js b/lib/SwiftPackage.js
new file mode 100644
index 00000000..a4323ad9
--- /dev/null
+++ b/lib/SwiftPackage.js
@@ -0,0 +1,114 @@
+/**
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+*/
+
+const fs = require('node:fs');
+const path = require('node:path');
+const { CordovaError } = require('cordova-common');
+
+const ROOT = path.join(__dirname, '..');
+
+class SwiftPackage {
+    constructor (projectRoot) {
+        this.root = projectRoot;
+        this.path = path.join(this.root, 'packages', 'cordova-ios-plugins', 
'Package.swift');
+
+        if (!fs.existsSync(this.path)) {
+            throw new CordovaError('Package.swift is not found.');
+        }
+    }
+
+    _pluginReference (plugin, pluginPath) {
+        return `
+package.dependencies.append(.package(name: "${plugin.id}", path: 
"${pluginPath.replaceAll(path.sep, path.posix.sep)}"))
+package.targets.first?.dependencies.append(.product(name: "${plugin.id}", 
package: "${plugin.id}"))
+`;
+    }
+
+    addPlugin (plugin, opts = {}) {
+        let pluginPath = path.relative(path.dirname(this.path), 
path.join(this.root, 'packages', plugin.id));
+        if (opts.link) {
+            pluginPath = path.relative(path.dirname(this.path), plugin.dir);
+        } else {
+            // Copy the plugin into the packages directory
+            const localPluginPath = path.join(this.root, 'packages', 
plugin.id);
+            fs.cpSync(plugin.dir, localPluginPath, { recursive: true });
+
+            const pkgSwiftPath = path.join(localPluginPath, 'Package.swift');
+
+            let cordovaPath = path.relative(localPluginPath, 
path.join(this.root, 'packages', 'cordova-ios'));
+            if (!fs.existsSync(path.join(localPluginPath, cordovaPath))) {
+                cordovaPath = path.relative(localPluginPath, ROOT);
+            }
+
+            const pkg_fd = fs.openSync(pkgSwiftPath, 'r+');
+            let packageContent = fs.readFileSync(pkg_fd, 'utf8');
+
+            // Note: May match unintended packages, e.g. 'cordova-ios-plugin',
+            // due to flexible patterns. Strict filtering would risk valid
+            // exclusions.
+            packageContent = 
packageContent.replace(/package\(.+cordova-ios.+\)/gm, `package(name: 
"cordova-ios", path: "${cordovaPath.replaceAll(path.sep, path.posix.sep)}")`);
+
+            fs.ftruncateSync(pkg_fd);
+            fs.writeSync(pkg_fd, packageContent, 0, 'utf8');
+            fs.closeSync(pkg_fd);
+        }
+
+        const fd = fs.openSync(this.path, 'a');
+        fs.writeFileSync(fd, this._pluginReference(plugin, pluginPath), 
'utf8');
+        fs.closeSync(fd);
+    }
+
+    removePlugin (plugin) {
+        const fd = fs.openSync(this.path, 'r+');
+
+        if (fs.existsSync(path.join(this.root, 'packages', plugin.id))) {
+            fs.rmSync(path.join(this.root, 'packages', plugin.id), { 
recursive: true, force: true });
+        }
+
+        let packageContent = fs.readFileSync(fd, 'utf8');
+
+        // We don't know if it was originally linked or not, so try to remove 
both
+        const pluginPath = path.relative(path.dirname(this.path), 
path.join(this.root, 'packages', plugin.id));
+        const pluginLink = path.relative(path.dirname(this.path), plugin.dir);
+        packageContent = packageContent.replace(this._pluginReference(plugin, 
pluginPath), '');
+        packageContent = packageContent.replace(this._pluginReference(plugin, 
pluginLink), '');
+
+        fs.ftruncateSync(fd);
+        fs.writeSync(fd, packageContent, 0, 'utf8');
+        fs.closeSync(fd);
+    }
+}
+
+// Use this as a hidden property on the plugin so that we can cache the result
+// of the Swift Package check for the lifetime of that PluginInfo object,
+// without caching it based on plugin name.
+const _isSwiftPackage = Symbol('isSwiftPackage');
+
+function isSwiftPackagePlugin (plugin) {
+    if (!plugin[_isSwiftPackage]) {
+        plugin[_isSwiftPackage] = plugin.getPlatforms().some((platform) => {
+            return platform.name === 'ios' && !!platform.package;
+        });
+    }
+
+    return plugin[_isSwiftPackage];
+}
+
+module.exports.SwiftPackage = SwiftPackage;
+module.exports.isSwiftPackagePlugin = isSwiftPackagePlugin;
diff --git a/lib/create.js b/lib/create.js
index 9aab4ee3..5ae41cf0 100755
--- a/lib/create.js
+++ b/lib/create.js
@@ -114,7 +114,8 @@ class ProjectCreator {
         fs.cpSync(defaultXmlPath, configXmlPath);
 
         const config = new ConfigParser(configXmlPath);
-        xmlHelpers.mergeXml(this.options.rootConfig.doc.getroot(), 
config.doc.getroot(), 'ios', /* clobber= */true);
+        const src = this.options.rootConfig.doc.getroot();
+        xmlHelpers.mergeXml(src, config.doc.getroot(), 'ios', /* clobber= 
*/true);
         config.write();
     }
 
diff --git a/lib/plugman/pluginHandlers.js b/lib/plugman/pluginHandlers.js
index 572fba4e..3ce239a7 100644
--- a/lib/plugman/pluginHandlers.js
+++ b/lib/plugman/pluginHandlers.js
@@ -20,6 +20,7 @@ const path = require('node:path');
 const util = require('node:util');
 const events = require('cordova-common').events;
 const CordovaError = require('cordova-common').CordovaError;
+const { isSwiftPackagePlugin } = require('../SwiftPackage');
 
 // These frameworks are required by cordova-ios by default. We should never 
add/remove them.
 const keep_these_frameworks = [
@@ -31,22 +32,32 @@ const keep_these_frameworks = [
 const handlers = {
     'source-file': {
         install: function (obj, plugin, project, options) {
+            if (isSwiftPackagePlugin(plugin)) return;
+
             installHelper('source-file', obj, plugin.dir, project.projectDir, 
plugin.id, options, project);
         },
         uninstall: function (obj, plugin, project, options) {
+            if (isSwiftPackagePlugin(plugin)) return;
+
             uninstallHelper('source-file', obj, project.projectDir, plugin.id, 
options, project);
         }
     },
     'header-file': {
         install: function (obj, plugin, project, options) {
+            if (isSwiftPackagePlugin(plugin)) return;
+
             installHelper('header-file', obj, plugin.dir, project.projectDir, 
plugin.id, options, project);
         },
         uninstall: function (obj, plugin, project, options) {
+            if (isSwiftPackagePlugin(plugin)) return;
+
             uninstallHelper('header-file', obj, project.projectDir, plugin.id, 
options, project);
         }
     },
     'resource-file': {
         install: function (obj, plugin, project, options) {
+            if (isSwiftPackagePlugin(plugin)) return;
+
             const src = obj.src;
             let target = obj.target;
             const srcFile = path.resolve(plugin.dir, src);
@@ -67,6 +78,8 @@ const handlers = {
             copyFile(plugin.dir, src, project.projectDir, destFile, link);
         },
         uninstall: function (obj, plugin, project, options) {
+            if (isSwiftPackagePlugin(plugin)) return;
+
             const src = obj.src;
             let target = obj.target;
 
@@ -81,6 +94,8 @@ const handlers = {
     },
     framework: { // CB-5238 custom frameworks only
         install: function (obj, plugin, project, options) {
+            if (isSwiftPackagePlugin(plugin)) return;
+
             const src = obj.src;
             const custom = !!(obj.custom); // convert to boolean (if 
truthy/falsy)
             const embed = !!(obj.embed); // convert to boolean (if 
truthy/falsy)
@@ -129,6 +144,8 @@ const handlers = {
             events.emit('verbose', util.format('Custom framework added to 
project. %s -> %s', src, JSON.stringify(opt)));
         },
         uninstall: function (obj, plugin, project, options) {
+            if (isSwiftPackagePlugin(plugin)) return;
+
             const src = obj.src;
 
             if (!obj.custom) { // CB-9825 cocoapod integration for plugins
@@ -167,6 +184,8 @@ const handlers = {
     },
     asset: {
         install: function (obj, plugin, project, options) {
+            if (isSwiftPackagePlugin(plugin)) return;
+
             if (!obj.src) {
                 throw new CordovaError(generateAttributeError('src', 'asset', 
plugin.id));
             }
@@ -178,6 +197,8 @@ const handlers = {
             if (options && options.usePlatformWww) copyFile(plugin.dir, 
obj.src, project.platformWww, obj.target);
         },
         uninstall: function (obj, plugin, project, options) {
+            if (isSwiftPackagePlugin(plugin)) return;
+
             const target = obj.target;
 
             if (!target) {
diff --git a/lib/prepare.js b/lib/prepare.js
index 10e1e06d..58466ed0 100644
--- a/lib/prepare.js
+++ b/lib/prepare.js
@@ -154,8 +154,8 @@ function updateConfigFile (sourceConfig, configMunger, 
locations) {
     const config = new ConfigParser(locations.configXml);
     xmlHelpers.mergeXml(sourceConfig.doc.getroot(),
         config.doc.getroot(), 'ios', /* clobber= */true);
-
     config.write();
+
     return config;
 }
 
diff --git a/templates/project/App.xcodeproj/project.pbxproj 
b/templates/project/App.xcodeproj/project.pbxproj
index b10423b7..29ec0061 100755
--- a/templates/project/App.xcodeproj/project.pbxproj
+++ b/templates/project/App.xcodeproj/project.pbxproj
@@ -35,6 +35,7 @@
                90CBB5282C06968500B805A2 /* AppDelegate.swift in Sources */ = 
{isa = PBXBuildFile; fileRef = 90CBB5272C06968500B805A2 /* AppDelegate.swift 
*/; };
                90CBB52A2C06968500B805A2 /* SceneDelegate.swift in Sources */ = 
{isa = PBXBuildFile; fileRef = 90CBB5292C06968500B805A2 /* SceneDelegate.swift 
*/; };
                90CBB52C2C06968500B805A2 /* ViewController.swift in Sources */ 
= {isa = PBXBuildFile; fileRef = 90CBB52B2C06968500B805A2 /* 
ViewController.swift */; };
+               90D82ABD2CF19AEA001383CF /* CordovaPlugins in Frameworks */ = 
{isa = PBXBuildFile; productRef = 90D82ABC2CF19AEA001383CF /* CordovaPlugins 
*/; };
 /* End PBXBuildFile section */
 
 /* Begin PBXCopyFilesBuildPhase section */
@@ -81,6 +82,7 @@
                        buildActionMask = 2147483647;
                        files = (
                                90A914592CA3D370003DB979 /* Cordova in 
Frameworks */,
+                               90D82ABD2CF19AEA001383CF /* CordovaPlugins in 
Frameworks */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
@@ -191,6 +193,7 @@
                        name = App;
                        packageProductDependencies = (
                                90A914582CA3D370003DB979 /* Cordova */,
+                               90D82ABC2CF19AEA001383CF /* CordovaPlugins */,
                        );
                        productName = App;
                        productReference = 90BD9B6C2C06907D000DEBAB /* App.app 
*/;
@@ -222,6 +225,7 @@
                        mainGroup = 90BD9B632C06907D000DEBAB /* CustomTemplate 
*/;
                        packageReferences = (
                                90A914572CA3D370003DB979 /* 
XCLocalSwiftPackageReference "../../../cordova-ios" */,
+                               90D82ABB2CF19AEA001383CF /* 
XCLocalSwiftPackageReference "CordovaPlugins" */,
                        );
                        productRefGroup = 90BD9B6D2C06907D000DEBAB /* Products 
*/;
                        projectDirPath = "";
@@ -317,8 +321,8 @@
                                COPY_PHASE_STRIP = NO;
                                DEBUG_INFORMATION_FORMAT = dwarf;
                                "DEPLOYMENT_LOCATION[sdk=iphonesimulator*]" = 
YES;
-                               "DEPLOYMENT_LOCATION[sdk=xrsimulator*]" = YES;
                                "DEPLOYMENT_LOCATION[sdk=macosx*]" = YES;
+                               "DEPLOYMENT_LOCATION[sdk=xrsimulator*]" = YES;
                                DSTROOT = "$(SRCROOT)/build";
                                ENABLE_STRICT_OBJC_MSGSEND = YES;
                                ENABLE_TESTABILITY = YES;
@@ -338,8 +342,8 @@
                                GCC_WARN_UNUSED_FUNCTION = YES;
                                GCC_WARN_UNUSED_VARIABLE = YES;
                                "INSTALL_PATH[sdk=iphonesimulator*]" = 
"$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)";
-                               "INSTALL_PATH[sdk=xrsimulator*]" = 
"$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)";
                                "INSTALL_PATH[sdk=macosx*]" = 
"$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)";
+                               "INSTALL_PATH[sdk=xrsimulator*]" = 
"$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)";
                                IPHONEOS_DEPLOYMENT_TARGET = 13.0;
                                LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
                                MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
@@ -391,8 +395,8 @@
                                COPY_PHASE_STRIP = NO;
                                DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
                                "DEPLOYMENT_LOCATION[sdk=iphonesimulator*]" = 
YES;
-                               "DEPLOYMENT_LOCATION[sdk=xrsimulator*]" = YES;
                                "DEPLOYMENT_LOCATION[sdk=macosx*]" = YES;
+                               "DEPLOYMENT_LOCATION[sdk=xrsimulator*]" = YES;
                                DSTROOT = "$(SRCROOT)/build";
                                ENABLE_NS_ASSERTIONS = NO;
                                ENABLE_STRICT_OBJC_MSGSEND = YES;
@@ -406,8 +410,8 @@
                                GCC_WARN_UNUSED_FUNCTION = YES;
                                GCC_WARN_UNUSED_VARIABLE = YES;
                                "INSTALL_PATH[sdk=iphonesimulator*]" = 
"$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)";
-                               "INSTALL_PATH[sdk=xrsimulator*]" = 
"$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)";
                                "INSTALL_PATH[sdk=macosx*]" = 
"$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)";
+                               "INSTALL_PATH[sdk=xrsimulator*]" = 
"$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)";
                                IPHONEOS_DEPLOYMENT_TARGET = 13.0;
                                LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
                                MTL_ENABLE_DEBUG_INFO = NO;
@@ -525,6 +529,10 @@
                        isa = XCLocalSwiftPackageReference;
                        relativePath = "../../../cordova-ios";
                };
+               90D82ABB2CF19AEA001383CF /* XCLocalSwiftPackageReference 
"packages/cordova-ios-plugins" */ = {
+                       isa = XCLocalSwiftPackageReference;
+                       relativePath = "packages/cordova-ios-plugins";
+               };
 /* End XCLocalSwiftPackageReference section */
 
 /* Begin XCSwiftPackageProductDependency section */
@@ -532,6 +540,10 @@
                        isa = XCSwiftPackageProductDependency;
                        productName = Cordova;
                };
+               90D82ABC2CF19AEA001383CF /* CordovaPlugins */ = {
+                       isa = XCSwiftPackageProductDependency;
+                       productName = CordovaPlugins;
+               };
 /* End XCSwiftPackageProductDependency section */
        };
        rootObject = 90BD9B642C06907D000DEBAB /* Project object */;
diff --git a/templates/project/packages/cordova-ios-plugins/Package.swift 
b/templates/project/packages/cordova-ios-plugins/Package.swift
new file mode 100644
index 00000000..705e2778
--- /dev/null
+++ b/templates/project/packages/cordova-ios-plugins/Package.swift
@@ -0,0 +1,37 @@
+// swift-tools-version:5.5
+
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+import PackageDescription
+
+let package = Package(
+    name: "CordovaPlugins",
+    platforms: [
+        .iOS(.v13),
+        .macCatalyst(.v13)
+    ],
+    products: [
+        .library(name: "CordovaPlugins", targets: ["CordovaPlugins"])
+    ],
+    targets: [
+        .target(name: "CordovaPlugins")
+    ]
+)
+
diff --git 
a/templates/project/packages/cordova-ios-plugins/Sources/CordovaPlugins/CordovaPlugins.swift
 
b/templates/project/packages/cordova-ios-plugins/Sources/CordovaPlugins/CordovaPlugins.swift
new file mode 100644
index 00000000..92baa917
--- /dev/null
+++ 
b/templates/project/packages/cordova-ios-plugins/Sources/CordovaPlugins/CordovaPlugins.swift
@@ -0,0 +1,21 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+// We need something here so that the empty package will compile successfully
+public let isCordovaApp = true
diff --git a/tests/spec/coverage.json b/tests/spec/coverage.json
index f70d3440..c74f863e 100644
--- a/tests/spec/coverage.json
+++ b/tests/spec/coverage.json
@@ -1,8 +1,8 @@
 {
   "spec_dir": "tests/spec",
   "spec_files": [
-      "unit/**/*[sS]pec.js",
-      "createAndBuild.spec.js"
+    "unit/**/*[sS]pec.js",
+    "createAndBuild.spec.js"
   ],
   "stopSpecOnExpectationFailure": false,
   "random": false
diff --git a/tests/spec/unit/Api.spec.js b/tests/spec/unit/Api.spec.js
index ac638584..d2498d06 100644
--- a/tests/spec/unit/Api.spec.js
+++ b/tests/spec/unit/Api.spec.js
@@ -36,6 +36,7 @@ if (process.platform === 'darwin') {
 
 const projectFile = require('../../../lib/projectFile');
 const BridgingHeader_mod = require('../../../lib/BridgingHeader.js');
+const SwiftPackage_mod = require('../../../lib/SwiftPackage.js');
 const Podfile_mod = require('../../../lib/Podfile');
 const PodsJson_mod = require('../../../lib/PodsJson');
 const FIXTURES = path.join(__dirname, 'fixtures');
@@ -108,6 +109,7 @@ describe('Platform Api', () => {
 
         describe('addPlugin', () => {
             const my_plugin = {
+                getPlatforms () { return [{ name: 'ios' }]; },
                 getHeaderFiles: function () { return []; },
                 getFrameworks: function () { return []; },
                 getPodSpecs: function () { return []; }
@@ -117,6 +119,7 @@ describe('Platform Api', () => {
                     addPlugin: function () { return Promise.resolve(); }
                 });
                 spyOn(BridgingHeader_mod, 'BridgingHeader');
+                spyOn(SwiftPackage_mod, 'SwiftPackage');
                 spyOn(Podfile_mod, 'Podfile');
                 spyOn(PodsJson_mod, 'PodsJson');
             });
@@ -145,6 +148,30 @@ describe('Platform Api', () => {
                         });
                 });
             });
+
+            describe('adding plugin with Swift package', () => {
+                let swiftPackage_mock;
+                const swift_plugin = {
+                    id: 'swift_plugin',
+                    getPlatforms () { return [{ name: 'ios', package: 'swift' 
}]; },
+                    getHeaderFiles: function () { return []; },
+                    getFrameworks: function () { return []; },
+                    getPodSpecs: function () { return []; }
+                };
+
+                beforeEach(() => {
+                    swiftPackage_mock = jasmine.createSpyObj('swiftpackage 
mock', ['addPlugin']);
+                    
SwiftPackage_mod.SwiftPackage.and.returnValue(swiftPackage_mock);
+                });
+
+                it('should add the plugin reference to Package.swift', () => {
+                    return api.addPlugin(swift_plugin)
+                        .then(() => {
+                            
expect(swiftPackage_mock.addPlugin).toHaveBeenCalledWith(swift_plugin, 
jasmine.any(Object));
+                        });
+                });
+            });
+
             describe('adding pods since the plugin contained <podspecs>', () 
=> {
                 let podsjson_mock;
                 let podfile_mock;
@@ -301,6 +328,7 @@ describe('Platform Api', () => {
         });
         describe('removePlugin', () => {
             const my_plugin = {
+                getPlatforms () { return [{ name: 'ios' }]; },
                 getHeaderFiles: function () { return []; },
                 getFrameworks: function () {},
                 getPodSpecs: function () { return []; }
@@ -309,9 +337,33 @@ describe('Platform Api', () => {
                 spyOn(PluginManager, 'get').and.returnValue({
                     removePlugin: function () { return Promise.resolve(); }
                 });
+                spyOn(SwiftPackage_mod, 'SwiftPackage');
                 spyOn(Podfile_mod, 'Podfile');
                 spyOn(PodsJson_mod, 'PodsJson');
             });
+
+            describe('removing plugin with Swift package', () => {
+                let swiftPackage_mock;
+                const swift_plugin = {
+                    id: 'swift_plugin',
+                    getPlatforms () { return [{ name: 'ios', package: 'swift' 
}]; },
+                    getHeaderFiles: function () { return []; },
+                    getFrameworks: function () { return []; },
+                    getPodSpecs: function () { return []; }
+                };
+
+                beforeEach(() => {
+                    swiftPackage_mock = jasmine.createSpyObj('swiftpackage 
mock', ['removePlugin']);
+                    
SwiftPackage_mod.SwiftPackage.and.returnValue(swiftPackage_mock);
+                });
+
+                it('should remove the plugin reference from Package.swift', () 
=> {
+                    return api.removePlugin(swift_plugin)
+                        .then(() => {
+                            
expect(swiftPackage_mock.removePlugin).toHaveBeenCalledWith(swift_plugin);
+                        });
+                });
+            });
             describe('removing pods since the plugin contained <podspecs>', () 
=> {
                 let podsjson_mock;
                 let podfile_mock;
diff --git a/tests/spec/unit/Plugman/pluginHandler.spec.js 
b/tests/spec/unit/Plugman/pluginHandler.spec.js
index 368f5f5a..e8ee1d0c 100644
--- a/tests/spec/unit/Plugman/pluginHandler.spec.js
+++ b/tests/spec/unit/Plugman/pluginHandler.spec.js
@@ -39,6 +39,7 @@ const faultyplugin = path.join(FIXTURES, 
'org.test.plugins.faultyplugin');
 const dummyplugin = path.join(FIXTURES, 'org.test.plugins.dummyplugin');
 const weblessplugin = path.join(FIXTURES, 'org.test.plugins.weblessplugin');
 const embedlinkplugin = path.join(FIXTURES, 
'org.test.plugins.embedlinkplugin');
+const swiftpackageplugin = path.join(FIXTURES, 
'org.test.plugins.swiftpackageplugin');
 
 const dummyPluginInfo = new PluginInfo(dummyplugin);
 const dummy_id = dummyPluginInfo.id;
@@ -60,16 +61,12 @@ const weblessPluginInfo = new PluginInfo(weblessplugin);
 const embedlinkPluginInfo = new PluginInfo(embedlinkplugin);
 const embed_link_interaction_frameworks = 
embedlinkPluginInfo.getFrameworks('ios');
 
+const swiftpackagePluginInfo = new PluginInfo(swiftpackageplugin);
+
 function copyArray (arr) {
     return Array.prototype.slice.call(arr, 0);
 }
 
-function slashJoin () {
-    // In some places we need to use forward slash instead of path.join().
-    // See CB-7311.
-    return Array.prototype.join.call(arguments, '/');
-}
-
 describe('ios plugin handler', () => {
     let dummyProject;
 
@@ -114,13 +111,13 @@ describe('ios plugin handler', () => {
                 const source = copyArray(valid_source).filter(s => s.targetDir 
=== undefined);
                 install(source[0], dummyPluginInfo, dummyProject);
                 expect(dummyProject.xcode.addSourceFile)
-                    .toHaveBeenCalledWith(slashJoin('Plugins', dummy_id, 
'DummyPluginCommand.m'), {});
+                    .toHaveBeenCalledWith(path.posix.join('Plugins', dummy_id, 
'DummyPluginCommand.m'), {});
             });
             it('Test 004 : should call into xcodeproj\'s addSourceFile 
appropriately when element has a target-dir', () => {
                 const source = copyArray(valid_source).filter(s => s.targetDir 
!== undefined);
                 install(source[0], dummyPluginInfo, dummyProject);
                 expect(dummyProject.xcode.addSourceFile)
-                    .toHaveBeenCalledWith(slashJoin('Plugins', dummy_id, 
'targetDir', 'TargetDirTest.m'), {});
+                    .toHaveBeenCalledWith(path.posix.join('Plugins', dummy_id, 
'targetDir', 'TargetDirTest.m'), {});
             });
             it('Test 005 : should cp the file to the right target location 
when element has no target-dir', () => {
                 const source = copyArray(valid_source).filter(s => s.targetDir 
=== undefined);
@@ -141,6 +138,13 @@ describe('ios plugin handler', () => {
                 expect(dummyProject.xcode.addFramework)
                     .toHaveBeenCalledWith(path.join('App', 'Plugins', 
dummy_id, 'SourceWithFramework.m'), { weak: false });
             });
+
+            it('should not add source files for SPM plugins', () => {
+                const source = 
copyArray(swiftpackagePluginInfo.getSourceFiles('ios'));
+                install(source[0], swiftpackagePluginInfo, dummyProject);
+
+                
expect(dummyProject.xcode.addSourceFile).not.toHaveBeenCalled();
+            });
         });
 
         describe('of <header-file> elements', () => {
@@ -169,13 +173,13 @@ describe('ios plugin handler', () => {
                 const headers = copyArray(valid_headers).filter(s => 
s.targetDir === undefined);
                 install(headers[0], dummyPluginInfo, dummyProject);
                 expect(dummyProject.xcode.addHeaderFile)
-                    .toHaveBeenCalledWith(slashJoin('Plugins', dummy_id, 
'DummyPluginCommand.h'));
+                    .toHaveBeenCalledWith(path.posix.join('Plugins', dummy_id, 
'DummyPluginCommand.h'));
             });
             it('Test 011 : should call into xcodeproj\'s addHeaderFile 
appropriately when element a target-dir', () => {
                 const headers = copyArray(valid_headers).filter(s => 
s.targetDir !== undefined);
                 install(headers[0], dummyPluginInfo, dummyProject);
                 expect(dummyProject.xcode.addHeaderFile)
-                    .toHaveBeenCalledWith(slashJoin('Plugins', dummy_id, 
'targetDir', 'TargetDirTest.h'));
+                    .toHaveBeenCalledWith(path.posix.join('Plugins', dummy_id, 
'targetDir', 'TargetDirTest.h'));
             });
             it('Test 012 : should cp the file to the right target location 
when element has no target-dir', () => {
                 const headers = copyArray(valid_headers).filter(s => 
s.targetDir === undefined);
@@ -407,17 +411,17 @@ describe('ios plugin handler', () => {
                     }).xcode;
 
                     // from org.test.plugins.dummyplugin
-                    
expect(xcode.hasFile(slashJoin('DummyPlugin.bundle'))).toEqual(jasmine.any(Object));
-                    
expect(xcode.hasFile(slashJoin('org.test.plugins.dummyplugin', 
'DummyPluginCommand.h'))).toEqual(jasmine.any(Object));
-                    
expect(xcode.hasFile(slashJoin('org.test.plugins.dummyplugin', 
'DummyPluginCommand.m'))).toEqual(jasmine.any(Object));
-                    
expect(xcode.hasFile(slashJoin('org.test.plugins.dummyplugin', 'targetDir', 
'TargetDirTest.h'))).toEqual(jasmine.any(Object));
-                    
expect(xcode.hasFile(slashJoin('org.test.plugins.dummyplugin', 'targetDir', 
'TargetDirTest.m'))).toEqual(jasmine.any(Object));
+                    
expect(xcode.hasFile(path.posix.join('DummyPlugin.bundle'))).toEqual(jasmine.any(Object));
+                    
expect(xcode.hasFile(path.posix.join('org.test.plugins.dummyplugin', 
'DummyPluginCommand.h'))).toEqual(jasmine.any(Object));
+                    
expect(xcode.hasFile(path.posix.join('org.test.plugins.dummyplugin', 
'DummyPluginCommand.m'))).toEqual(jasmine.any(Object));
+                    
expect(xcode.hasFile(path.posix.join('org.test.plugins.dummyplugin', 
'targetDir', 'TargetDirTest.h'))).toEqual(jasmine.any(Object));
+                    
expect(xcode.hasFile(path.posix.join('org.test.plugins.dummyplugin', 
'targetDir', 'TargetDirTest.m'))).toEqual(jasmine.any(Object));
                     
expect(xcode.hasFile('usr/lib/libsqlite3.dylib')).toEqual(jasmine.any(Object));
-                    expect(xcode.hasFile(slashJoin('App', 'Plugins', 
'org.test.plugins.dummyplugin', 
'Custom.framework'))).toEqual(jasmine.any(Object));
+                    expect(xcode.hasFile(path.posix.join('App', 'Plugins', 
'org.test.plugins.dummyplugin', 
'Custom.framework'))).toEqual(jasmine.any(Object));
                     // from org.test.plugins.weblessplugin
-                    
expect(xcode.hasFile(slashJoin('WeblessPluginViewController.xib'))).toEqual(jasmine.any(Object));
-                    
expect(xcode.hasFile(slashJoin('org.test.plugins.weblessplugin', 
'WeblessPluginCommand.h'))).toEqual(jasmine.any(Object));
-                    
expect(xcode.hasFile(slashJoin('org.test.plugins.weblessplugin', 
'WeblessPluginCommand.m'))).toEqual(jasmine.any(Object));
+                    
expect(xcode.hasFile(path.posix.join('WeblessPluginViewController.xib'))).toEqual(jasmine.any(Object));
+                    
expect(xcode.hasFile(path.posix.join('org.test.plugins.weblessplugin', 
'WeblessPluginCommand.h'))).toEqual(jasmine.any(Object));
+                    
expect(xcode.hasFile(path.posix.join('org.test.plugins.weblessplugin', 
'WeblessPluginCommand.m'))).toEqual(jasmine.any(Object));
                     
expect(xcode.hasFile('usr/lib/libsqlite3.dylib')).toEqual(jasmine.any(Object));
                 });
         });
@@ -434,12 +438,12 @@ describe('ios plugin handler', () => {
             it('Test 029 : should call into xcodeproj\'s removeSourceFile 
appropriately when element has no target-dir', () => {
                 const source = copyArray(valid_source).filter(s => s.targetDir 
=== undefined);
                 uninstall(source[0], dummyPluginInfo, dummyProject);
-                
expect(dummyProject.xcode.removeSourceFile).toHaveBeenCalledWith(slashJoin('Plugins',
 dummy_id, 'DummyPluginCommand.m'));
+                
expect(dummyProject.xcode.removeSourceFile).toHaveBeenCalledWith(path.posix.join('Plugins',
 dummy_id, 'DummyPluginCommand.m'));
             });
             it('Test 030 : should call into xcodeproj\'s removeSourceFile 
appropriately when element a target-dir', () => {
                 const source = copyArray(valid_source).filter(s => s.targetDir 
!== undefined);
                 uninstall(source[0], dummyPluginInfo, dummyProject);
-                
expect(dummyProject.xcode.removeSourceFile).toHaveBeenCalledWith(slashJoin('Plugins',
 dummy_id, 'targetDir', 'TargetDirTest.m'));
+                
expect(dummyProject.xcode.removeSourceFile).toHaveBeenCalledWith(path.posix.join('Plugins',
 dummy_id, 'targetDir', 'TargetDirTest.m'));
             });
             it('Test 031 : should rm the file from the right target location 
when element has no target-dir', () => {
                 const source = copyArray(valid_source).filter(s => s.targetDir 
=== undefined);
@@ -458,6 +462,13 @@ describe('ios plugin handler', () => {
                 uninstall(source[0], dummyPluginInfo, dummyProject);
                 
expect(dummyProject.xcode.removeFramework).toHaveBeenCalledWith(path.join('App',
 'Plugins', dummy_id, 'SourceWithFramework.m'));
             });
+
+            it('should not remove source files for SPM plugins', () => {
+                const source = 
copyArray(swiftpackagePluginInfo.getSourceFiles('ios'));
+                uninstall(source[0], swiftpackagePluginInfo, dummyProject);
+
+                
expect(dummyProject.xcode.removeSourceFile).not.toHaveBeenCalled();
+            });
         });
 
         describe('of <header-file> elements', () => {
@@ -469,12 +480,12 @@ describe('ios plugin handler', () => {
             it('Test 034 : should call into xcodeproj\'s removeHeaderFile 
appropriately when element has no target-dir', () => {
                 const headers = copyArray(valid_headers).filter(s => 
s.targetDir === undefined);
                 uninstall(headers[0], dummyPluginInfo, dummyProject);
-                
expect(dummyProject.xcode.removeHeaderFile).toHaveBeenCalledWith(slashJoin('Plugins',
 dummy_id, 'DummyPluginCommand.h'));
+                
expect(dummyProject.xcode.removeHeaderFile).toHaveBeenCalledWith(path.posix.join('Plugins',
 dummy_id, 'DummyPluginCommand.h'));
             });
             it('Test 035 : should call into xcodeproj\'s removeHeaderFile 
appropriately when element a target-dir', () => {
                 const headers = copyArray(valid_headers).filter(s => 
s.targetDir !== undefined);
                 uninstall(headers[0], dummyPluginInfo, dummyProject);
-                
expect(dummyProject.xcode.removeHeaderFile).toHaveBeenCalledWith(slashJoin('Plugins',
 dummy_id, 'targetDir', 'TargetDirTest.h'));
+                
expect(dummyProject.xcode.removeHeaderFile).toHaveBeenCalledWith(path.posix.join('Plugins',
 dummy_id, 'targetDir', 'TargetDirTest.h'));
             });
             it('Test 036 : should rm the file from the right target location', 
() => {
                 const headers = copyArray(valid_headers).filter(s => 
s.targetDir !== undefined);
diff --git a/tests/spec/unit/SwiftPackage.spec.js 
b/tests/spec/unit/SwiftPackage.spec.js
new file mode 100644
index 00000000..4e966cb4
--- /dev/null
+++ b/tests/spec/unit/SwiftPackage.spec.js
@@ -0,0 +1,218 @@
+/**
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+const fs = require('node:fs');
+const path = require('node:path');
+const tmp = require('tmp');
+const SwiftPackage = require('../../../lib/SwiftPackage.js').SwiftPackage;
+const Api = require('../../../lib/Api');
+const EventEmitter = require('node:events').EventEmitter;
+const ConfigParser = require('cordova-common').ConfigParser;
+const PluginInfo = require('cordova-common').PluginInfo;
+const Podfile_mod = require('../../../lib/Podfile');
+const PodsJson_mod = require('../../../lib/PodsJson');
+
+tmp.setGracefulCleanup();
+
+const fixturePackage = fs.readFileSync(path.join(__dirname, 'fixtures', 
'test-Package.swift'), 'utf-8');
+
+describe('SwiftPackage', () => {
+    let tmpDir;
+    beforeEach(() => {
+        tmpDir = tmp.dirSync();
+    });
+
+    afterEach(() => {
+        fs.rmSync(tmpDir.name, { recursive: true, force: true });
+    });
+
+    it('should error if Package.swift file does not exist', () => {
+        expect(() => {
+            const _ = new SwiftPackage(tmpDir.name);
+            expect(_).not.toEqual(null); // To avoid ESLINT error "Do not use 
'new' for side effects"
+        }).toThrow();
+    });
+
+    it('should skip cocoapod library if nospm is true', () => {
+        const PROJ_NAME = 'dummyProj';
+        const FIXTURES = path.join(__dirname, 'fixtures');
+        const iosProjectFixture = path.join(FIXTURES, 
'ios-packageswift-config-xml');
+        const iosProject = path.join(FIXTURES, PROJ_NAME);
+        fs.cpSync(iosProject, tmpDir.name, { recursive: true });
+        const iosProjectTest = tmpDir.name;
+        const iosPlatformTest = path.join(iosProjectTest, 'platforms', 'ios');
+        fs.cpSync(iosProjectFixture, iosPlatformTest, { recursive: true });
+        const cocoapod_swift_plugin = path.join(FIXTURES, 
'org.test.plugins.swiftpackagecocoapodplugin');
+        spyOn(Podfile_mod.Podfile.prototype, 
'install').and.returnValue(Promise.resolve());
+        spyOn(PodsJson_mod.PodsJson.prototype, 
'setSwiftVersionForCocoaPodsLibraries').and.stub();
+        const api = new Api('ios', iosPlatformTest, new EventEmitter());
+        const project = {
+            root: iosProjectTest,
+            projectConfig: new ConfigParser(path.join(iosProjectTest, 
'config.xml')),
+            locations: {
+                plugins: path.join(iosProjectTest, 'plugins'),
+                www: path.join(iosProjectTest, 'www')
+            }
+        };
+        return api.prepare(project, {})
+            .then(() => {
+                return api.addPlugin(new PluginInfo(cocoapod_swift_plugin), 
{});
+            })
+            .then(() => {
+                const podFilePath = path.join(iosPlatformTest, 'Podfile');
+                const podFile = fs.readFileSync(podFilePath, 'utf8');
+                expect(podFile).toContain('pod \'DummyObjCPodAlpha\'');
+                expect(podFile).not.toContain('pod \'DummyObjCPodBeta\'');
+                expect(podFile).toContain('pod \'DummyObjCPodGamma\'');
+            });
+    });
+
+    describe('addPlugin', () => {
+        const my_plugin = {
+            id: 'my-plugin',
+            dir: path.join(__dirname, 'fixtures', 
'org.test.plugins.swiftpackageplugin')
+        };
+
+        const namespaced_plugin = {
+            id: '@username/my-plugin',
+            dir: path.join(__dirname, 'fixtures', 
'org.test.plugins.swiftpackageplugin')
+        };
+
+        let pkg;
+        beforeEach(() => {
+            fs.mkdirSync(path.join(tmpDir.name, 'packages', 
'cordova-ios-plugins'), { recursive: true });
+            fs.writeFileSync(path.join(tmpDir.name, 'packages', 
'cordova-ios-plugins', 'Package.swift'), fixturePackage, 'utf8');
+
+            pkg = new SwiftPackage(tmpDir.name);
+        });
+
+        it('should add plugin references to the package file', () => {
+            pkg.addPlugin(my_plugin);
+
+            const pkgPath = path.join(tmpDir.name, 'packages', 
'cordova-ios-plugins', 'Package.swift');
+            const content = fs.readFileSync(pkgPath, 'utf8');
+            expect(content).toContain('.package(name: "my-plugin", path: 
"../my-plugin")');
+            expect(content).toContain('.product(name: "my-plugin", package: 
"my-plugin")');
+        });
+
+        it('should copy the plugin into the packages directory', () => {
+            pkg.addPlugin(my_plugin);
+
+            expect(fs.existsSync(path.join(tmpDir.name, 'packages', 
'my-plugin'))).toBeTruthy();
+        });
+
+        it('should update the CordovaLib dependency (copied)', () => {
+            fs.mkdirSync(path.join(tmpDir.name, 'packages', 'cordova-ios'), { 
recursive: true });
+
+            pkg.addPlugin(my_plugin);
+
+            const pkgPath = path.join(tmpDir.name, 'packages', 'my-plugin', 
'Package.swift');
+            const content = fs.readFileSync(pkgPath, 'utf8');
+
+            const relativePath = path.posix.join('..', 'cordova-ios');
+
+            expect(content).toContain(`package(name: "cordova-ios", path: 
"${relativePath}"`);
+            expect(content).not.toContain('github.com/apache/cordova-ios');
+        });
+
+        it('should update the CordovaLib dependency (linked)', () => {
+            pkg.addPlugin(my_plugin);
+
+            const pkgPath = path.join(tmpDir.name, 'packages', 'my-plugin', 
'Package.swift');
+            const content = fs.readFileSync(pkgPath, 'utf8');
+
+            // Because we don't have the full project here, it behaves as if 
linked
+            const packageLoc = 
path.dirname(require.resolve('../../../package.json'));
+            const relativeLink = path.relative(path.dirname(pkgPath), 
packageLoc).replaceAll(path.sep, path.posix.sep);
+
+            expect(content).toContain(`package(name: "cordova-ios", path: 
"${relativeLink}"`);
+            expect(content).not.toContain('github.com/apache/cordova-ios');
+        });
+
+        it('should add namespaced plugin references to the package file', () 
=> {
+            pkg.addPlugin(namespaced_plugin);
+
+            const pkgPath = path.join(tmpDir.name, 'packages', 
'cordova-ios-plugins', 'Package.swift');
+            const content = fs.readFileSync(pkgPath, 'utf8');
+            expect(content).toContain('.package(name: "@username/my-plugin", 
path: "../@username/my-plugin")');
+            expect(content).toContain('.product(name: "@username/my-plugin", 
package: "@username/my-plugin")');
+        });
+
+        it('should copy the namespaced plugin into the packages directory', () 
=> {
+            pkg.addPlugin(namespaced_plugin);
+
+            expect(fs.existsSync(path.join(tmpDir.name, 'packages', 
'@username', 'my-plugin'))).toBeTruthy();
+        });
+
+        it('should add plugin references to the package file when linked', () 
=> {
+            pkg.addPlugin(my_plugin, { link: true });
+
+            const pkgPath = path.join(tmpDir.name, 'packages', 
'cordova-ios-plugins', 'Package.swift');
+            const content = fs.readFileSync(pkgPath, 'utf8');
+
+            expect(content).toContain('.package(name: "my-plugin", path: "');
+            expect(content).not.toContain('.package(name: "my-plugin", path: 
"../my-plugin")');
+            expect(content).toContain('.product(name: "my-plugin", package: 
"my-plugin")');
+        });
+
+        it('should copy a linked plugin into the packages directory', () => {
+            pkg.addPlugin(my_plugin, { link: true });
+
+            expect(fs.existsSync(path.join(tmpDir.name, 'packages', 
'my-plugin'))).toBeFalsy();
+        });
+    });
+
+    describe('removePlugin', () => {
+        const my_plugin = {
+            id: 'my-plugin',
+            dir: path.join(__dirname, 'fixtures', 
'org.test.plugins.swiftpackageplugin')
+        };
+
+        let pkg;
+        beforeEach(() => {
+            fs.mkdirSync(path.join(tmpDir.name, 'packages', 
'cordova-ios-plugins'), { recursive: true });
+            const pkgPath = path.join(tmpDir.name, 'packages', 
'cordova-ios-plugins', 'Package.swift');
+            fs.writeFileSync(pkgPath, fixturePackage, 'utf8');
+
+            pkg = new SwiftPackage(tmpDir.name);
+            fs.writeFileSync(pkgPath, fixturePackage + 
pkg._pluginReference(my_plugin, '../my-plugin'), 'utf8');
+        });
+
+        it('should remove plugin references to the package file', () => {
+            pkg.removePlugin(my_plugin);
+
+            const pkgPath = path.join(tmpDir.name, 'packages', 
'cordova-ios-plugins', 'Package.swift');
+            const content = fs.readFileSync(pkgPath, 'utf8');
+
+            expect(content).not.toContain('.package(name: "my-plugin"');
+            expect(content).not.toContain('.product(name: "my-plugin", 
package: "my-plugin")');
+        });
+
+        it('should remove the plugin from the packages directory', () => {
+            fs.mkdirSync(path.join(tmpDir.name, 'packages', 'my-plugin'), { 
recursive: true });
+            fs.writeFileSync(path.join(tmpDir.name, 'packages', 'my-plugin', 
'test.txt'), 'Test', 'utf-8');
+
+            expect(fs.existsSync(path.join(tmpDir.name, 'packages', 
'my-plugin'))).toBeTruthy();
+
+            pkg.removePlugin(my_plugin);
+
+            expect(fs.existsSync(path.join(tmpDir.name, 'packages', 
'my-plugin'))).toBeFalsy();
+        });
+    });
+});
diff --git 
a/tests/spec/unit/fixtures/ios-config-xml/App.xcodeproj/project.pbxproj 
b/tests/spec/unit/fixtures/ios-config-xml/App.xcodeproj/project.pbxproj
index 597e416f..da8158b2 100755
--- a/tests/spec/unit/fixtures/ios-config-xml/App.xcodeproj/project.pbxproj
+++ b/tests/spec/unit/fixtures/ios-config-xml/App.xcodeproj/project.pbxproj
@@ -35,6 +35,7 @@
                90CBB5282C06968500B805A2 /* AppDelegate.swift in Sources */ = 
{isa = PBXBuildFile; fileRef = 90CBB5272C06968500B805A2 /* AppDelegate.swift 
*/; };
                90CBB52A2C06968500B805A2 /* SceneDelegate.swift in Sources */ = 
{isa = PBXBuildFile; fileRef = 90CBB5292C06968500B805A2 /* SceneDelegate.swift 
*/; };
                90CBB52C2C06968500B805A2 /* ViewController.swift in Sources */ 
= {isa = PBXBuildFile; fileRef = 90CBB52B2C06968500B805A2 /* 
ViewController.swift */; };
+               90D82ABD2CF19AEA001383CF /* CordovaPlugins in Frameworks */ = 
{isa = PBXBuildFile; productRef = 90D82ABC2CF19AEA001383CF /* CordovaPlugins 
*/; };
 /* End PBXBuildFile section */
 
 /* Begin PBXCopyFilesBuildPhase section */
@@ -80,6 +81,7 @@
                        isa = PBXFrameworksBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
+                               90D82ABD2CF19AEA001383CF /* CordovaPlugins in 
Frameworks */,
                                90A914592CA3D370003DB979 /* CordovaLib in 
Frameworks */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
@@ -191,6 +193,7 @@
                        name = App;
                        packageProductDependencies = (
                                90A914582CA3D370003DB979 /* CordovaLib */,
+                               90D82ABC2CF19AEA001383CF /* CordovaPlugins */,
                        );
                        productName = App;
                        productReference = 90BD9B6C2C06907D000DEBAB /* App.app 
*/;
@@ -222,6 +225,7 @@
                        mainGroup = 90BD9B632C06907D000DEBAB /* CustomTemplate 
*/;
                        packageReferences = (
                                90A914572CA3D370003DB979 /* 
XCLocalSwiftPackageReference "../../../cordova-ios" */,
+                               90D82ABB2CF19AEA001383CF /* 
XCLocalSwiftPackageReference "CordovaPlugins" */,
                        );
                        productRefGroup = 90BD9B6D2C06907D000DEBAB /* Products 
*/;
                        projectDirPath = "";
@@ -317,8 +321,8 @@
                                COPY_PHASE_STRIP = NO;
                                DEBUG_INFORMATION_FORMAT = dwarf;
                                "DEPLOYMENT_LOCATION[sdk=iphonesimulator*]" = 
YES;
-                               "DEPLOYMENT_LOCATION[sdk=xrsimulator*]" = YES;
                                "DEPLOYMENT_LOCATION[sdk=macosx*]" = YES;
+                               "DEPLOYMENT_LOCATION[sdk=xrsimulator*]" = YES;
                                DSTROOT = "$(SRCROOT)/build";
                                ENABLE_STRICT_OBJC_MSGSEND = YES;
                                ENABLE_TESTABILITY = YES;
@@ -338,8 +342,8 @@
                                GCC_WARN_UNUSED_FUNCTION = YES;
                                GCC_WARN_UNUSED_VARIABLE = YES;
                                "INSTALL_PATH[sdk=iphonesimulator*]" = 
"$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)";
-                               "INSTALL_PATH[sdk=xrsimulator*]" = 
"$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)";
                                "INSTALL_PATH[sdk=macosx*]" = 
"$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)";
+                               "INSTALL_PATH[sdk=xrsimulator*]" = 
"$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)";
                                IPHONEOS_DEPLOYMENT_TARGET = 13.0;
                                LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
                                MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
@@ -391,8 +395,8 @@
                                COPY_PHASE_STRIP = NO;
                                DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
                                "DEPLOYMENT_LOCATION[sdk=iphonesimulator*]" = 
YES;
-                               "DEPLOYMENT_LOCATION[sdk=xrsimulator*]" = YES;
                                "DEPLOYMENT_LOCATION[sdk=macosx*]" = YES;
+                               "DEPLOYMENT_LOCATION[sdk=xrsimulator*]" = YES;
                                DSTROOT = "$(SRCROOT)/build";
                                ENABLE_NS_ASSERTIONS = NO;
                                ENABLE_STRICT_OBJC_MSGSEND = YES;
@@ -406,8 +410,8 @@
                                GCC_WARN_UNUSED_FUNCTION = YES;
                                GCC_WARN_UNUSED_VARIABLE = YES;
                                "INSTALL_PATH[sdk=iphonesimulator*]" = 
"$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)";
-                               "INSTALL_PATH[sdk=xrsimulator*]" = 
"$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)";
                                "INSTALL_PATH[sdk=macosx*]" = 
"$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)";
+                               "INSTALL_PATH[sdk=xrsimulator*]" = 
"$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)";
                                IPHONEOS_DEPLOYMENT_TARGET = 13.0;
                                LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
                                MTL_ENABLE_DEBUG_INFO = NO;
@@ -525,6 +529,10 @@
                        isa = XCLocalSwiftPackageReference;
                        relativePath = "../../../../../../cordova-ios";
                };
+               90D82ABB2CF19AEA001383CF /* XCLocalSwiftPackageReference 
"CordovaPlugins" */ = {
+                       isa = XCLocalSwiftPackageReference;
+                       relativePath = CordovaPlugins;
+               };
 /* End XCLocalSwiftPackageReference section */
 
 /* Begin XCSwiftPackageProductDependency section */
@@ -532,6 +540,10 @@
                        isa = XCSwiftPackageProductDependency;
                        productName = CordovaLib;
                };
+               90D82ABC2CF19AEA001383CF /* CordovaPlugins */ = {
+                       isa = XCSwiftPackageProductDependency;
+                       productName = CordovaPlugins;
+               };
 /* End XCSwiftPackageProductDependency section */
        };
        rootObject = 90BD9B642C06907D000DEBAB /* Project object */;
diff --git 
a/tests/spec/unit/fixtures/ios-config-xml/CordovaPlugins/Package.swift 
b/tests/spec/unit/fixtures/ios-config-xml/CordovaPlugins/Package.swift
new file mode 100644
index 00000000..705e2778
--- /dev/null
+++ b/tests/spec/unit/fixtures/ios-config-xml/CordovaPlugins/Package.swift
@@ -0,0 +1,37 @@
+// swift-tools-version:5.5
+
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+import PackageDescription
+
+let package = Package(
+    name: "CordovaPlugins",
+    platforms: [
+        .iOS(.v13),
+        .macCatalyst(.v13)
+    ],
+    products: [
+        .library(name: "CordovaPlugins", targets: ["CordovaPlugins"])
+    ],
+    targets: [
+        .target(name: "CordovaPlugins")
+    ]
+)
+
diff --git 
a/tests/spec/unit/fixtures/ios-config-xml/CordovaPlugins/Sources/CordovaPlugins/CordovaPlugins.swift
 
b/tests/spec/unit/fixtures/ios-config-xml/CordovaPlugins/Sources/CordovaPlugins/CordovaPlugins.swift
new file mode 100644
index 00000000..92baa917
--- /dev/null
+++ 
b/tests/spec/unit/fixtures/ios-config-xml/CordovaPlugins/Sources/CordovaPlugins/CordovaPlugins.swift
@@ -0,0 +1,21 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+// We need something here so that the empty package will compile successfully
+public let isCordovaApp = true
diff --git 
a/tests/spec/unit/fixtures/ios-config-xml/App.xcodeproj/project.pbxproj 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App.xcodeproj/project.pbxproj
similarity index 97%
copy from tests/spec/unit/fixtures/ios-config-xml/App.xcodeproj/project.pbxproj
copy to 
tests/spec/unit/fixtures/ios-packageswift-config-xml/App.xcodeproj/project.pbxproj
index 597e416f..da8158b2 100755
--- a/tests/spec/unit/fixtures/ios-config-xml/App.xcodeproj/project.pbxproj
+++ 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App.xcodeproj/project.pbxproj
@@ -35,6 +35,7 @@
                90CBB5282C06968500B805A2 /* AppDelegate.swift in Sources */ = 
{isa = PBXBuildFile; fileRef = 90CBB5272C06968500B805A2 /* AppDelegate.swift 
*/; };
                90CBB52A2C06968500B805A2 /* SceneDelegate.swift in Sources */ = 
{isa = PBXBuildFile; fileRef = 90CBB5292C06968500B805A2 /* SceneDelegate.swift 
*/; };
                90CBB52C2C06968500B805A2 /* ViewController.swift in Sources */ 
= {isa = PBXBuildFile; fileRef = 90CBB52B2C06968500B805A2 /* 
ViewController.swift */; };
+               90D82ABD2CF19AEA001383CF /* CordovaPlugins in Frameworks */ = 
{isa = PBXBuildFile; productRef = 90D82ABC2CF19AEA001383CF /* CordovaPlugins 
*/; };
 /* End PBXBuildFile section */
 
 /* Begin PBXCopyFilesBuildPhase section */
@@ -80,6 +81,7 @@
                        isa = PBXFrameworksBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
+                               90D82ABD2CF19AEA001383CF /* CordovaPlugins in 
Frameworks */,
                                90A914592CA3D370003DB979 /* CordovaLib in 
Frameworks */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
@@ -191,6 +193,7 @@
                        name = App;
                        packageProductDependencies = (
                                90A914582CA3D370003DB979 /* CordovaLib */,
+                               90D82ABC2CF19AEA001383CF /* CordovaPlugins */,
                        );
                        productName = App;
                        productReference = 90BD9B6C2C06907D000DEBAB /* App.app 
*/;
@@ -222,6 +225,7 @@
                        mainGroup = 90BD9B632C06907D000DEBAB /* CustomTemplate 
*/;
                        packageReferences = (
                                90A914572CA3D370003DB979 /* 
XCLocalSwiftPackageReference "../../../cordova-ios" */,
+                               90D82ABB2CF19AEA001383CF /* 
XCLocalSwiftPackageReference "CordovaPlugins" */,
                        );
                        productRefGroup = 90BD9B6D2C06907D000DEBAB /* Products 
*/;
                        projectDirPath = "";
@@ -317,8 +321,8 @@
                                COPY_PHASE_STRIP = NO;
                                DEBUG_INFORMATION_FORMAT = dwarf;
                                "DEPLOYMENT_LOCATION[sdk=iphonesimulator*]" = 
YES;
-                               "DEPLOYMENT_LOCATION[sdk=xrsimulator*]" = YES;
                                "DEPLOYMENT_LOCATION[sdk=macosx*]" = YES;
+                               "DEPLOYMENT_LOCATION[sdk=xrsimulator*]" = YES;
                                DSTROOT = "$(SRCROOT)/build";
                                ENABLE_STRICT_OBJC_MSGSEND = YES;
                                ENABLE_TESTABILITY = YES;
@@ -338,8 +342,8 @@
                                GCC_WARN_UNUSED_FUNCTION = YES;
                                GCC_WARN_UNUSED_VARIABLE = YES;
                                "INSTALL_PATH[sdk=iphonesimulator*]" = 
"$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)";
-                               "INSTALL_PATH[sdk=xrsimulator*]" = 
"$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)";
                                "INSTALL_PATH[sdk=macosx*]" = 
"$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)";
+                               "INSTALL_PATH[sdk=xrsimulator*]" = 
"$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)";
                                IPHONEOS_DEPLOYMENT_TARGET = 13.0;
                                LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
                                MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
@@ -391,8 +395,8 @@
                                COPY_PHASE_STRIP = NO;
                                DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
                                "DEPLOYMENT_LOCATION[sdk=iphonesimulator*]" = 
YES;
-                               "DEPLOYMENT_LOCATION[sdk=xrsimulator*]" = YES;
                                "DEPLOYMENT_LOCATION[sdk=macosx*]" = YES;
+                               "DEPLOYMENT_LOCATION[sdk=xrsimulator*]" = YES;
                                DSTROOT = "$(SRCROOT)/build";
                                ENABLE_NS_ASSERTIONS = NO;
                                ENABLE_STRICT_OBJC_MSGSEND = YES;
@@ -406,8 +410,8 @@
                                GCC_WARN_UNUSED_FUNCTION = YES;
                                GCC_WARN_UNUSED_VARIABLE = YES;
                                "INSTALL_PATH[sdk=iphonesimulator*]" = 
"$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)";
-                               "INSTALL_PATH[sdk=xrsimulator*]" = 
"$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)";
                                "INSTALL_PATH[sdk=macosx*]" = 
"$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)";
+                               "INSTALL_PATH[sdk=xrsimulator*]" = 
"$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)";
                                IPHONEOS_DEPLOYMENT_TARGET = 13.0;
                                LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
                                MTL_ENABLE_DEBUG_INFO = NO;
@@ -525,6 +529,10 @@
                        isa = XCLocalSwiftPackageReference;
                        relativePath = "../../../../../../cordova-ios";
                };
+               90D82ABB2CF19AEA001383CF /* XCLocalSwiftPackageReference 
"CordovaPlugins" */ = {
+                       isa = XCLocalSwiftPackageReference;
+                       relativePath = CordovaPlugins;
+               };
 /* End XCLocalSwiftPackageReference section */
 
 /* Begin XCSwiftPackageProductDependency section */
@@ -532,6 +540,10 @@
                        isa = XCSwiftPackageProductDependency;
                        productName = CordovaLib;
                };
+               90D82ABC2CF19AEA001383CF /* CordovaPlugins */ = {
+                       isa = XCSwiftPackageProductDependency;
+                       productName = CordovaPlugins;
+               };
 /* End XCSwiftPackageProductDependency section */
        };
        rootObject = 90BD9B642C06907D000DEBAB /* Project object */;
diff --git 
a/tests/spec/unit/fixtures/ios-packageswift-config-xml/App.xcodeproj/project.xcworkspace/contents.xcworkspacedata
 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App.xcodeproj/project.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 00000000..21fc716e
--- /dev/null
+++ 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one
+   or more contributor license agreements.  See the NOTICE file
+   distributed with this work for additional information
+   regarding copyright ownership.  The ASF licenses this file
+   to you under the Apache License, Version 2.0 (the
+   "License"); you may not use this file except in compliance
+   with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing,
+   software distributed under the License is distributed on an
+   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+   KIND, either express or implied.  See the License for the
+   specific language governing permissions and limitations
+   under the License.
+-->
+<Workspace
+   version = "1.0">
+   <FileRef
+      location = "self:">
+   </FileRef>
+</Workspace>
diff --git 
a/tests/spec/unit/fixtures/ios-packageswift-config-xml/App.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 00000000..18d98100
--- /dev/null
+++ 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+<?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>IDEDidComputeMac32BitWarning</key>
+       <true/>
+</dict>
+</plist>
diff --git 
a/tests/spec/unit/fixtures/ios-packageswift-config-xml/App.xcworkspace/contents.xcworkspacedata
 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 00000000..4bae5d8d
--- /dev/null
+++ 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one
+   or more contributor license agreements.  See the NOTICE file
+   distributed with this work for additional information
+   regarding copyright ownership.  The ASF licenses this file
+   to you under the Apache License, Version 2.0 (the
+   "License"); you may not use this file except in compliance
+   with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing,
+   software distributed under the License is distributed on an
+   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+   KIND, either express or implied.  See the License for the
+   specific language governing permissions and limitations
+   under the License.
+-->
+<Workspace
+   version = "1.0">
+   <FileRef
+      location = "group:App.xcodeproj">
+   </FileRef>
+</Workspace>
diff --git 
a/tests/spec/unit/fixtures/ios-packageswift-config-xml/App.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 00000000..18d98100
--- /dev/null
+++ 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+<?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>IDEDidComputeMac32BitWarning</key>
+       <true/>
+</dict>
+</plist>
diff --git 
a/tests/spec/unit/fixtures/ios-packageswift-config-xml/App.xcworkspace/xcshareddata/xcschemes/App.xcscheme
 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App.xcworkspace/xcshareddata/xcschemes/App.xcscheme
new file mode 100644
index 00000000..2df61af2
--- /dev/null
+++ 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App.xcworkspace/xcshareddata/xcschemes/App.xcscheme
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one
+   or more contributor license agreements.  See the NOTICE file
+   distributed with this work for additional information
+   regarding copyright ownership.  The ASF licenses this file
+   to you under the Apache License, Version 2.0 (the
+   "License"); you may not use this file except in compliance
+   with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing,
+   software distributed under the License is distributed on an
+   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+   KIND, either express or implied.  See the License for the
+   specific language governing permissions and limitations
+   under the License.
+-->
+<Scheme
+   LastUpgradeVersion = "0730"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "1D6058900D05DD3D006BFB54"
+               BuildableName = "App.app"
+               BlueprintName = "App"
+               ReferencedContainer = "container:App.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+      <Testables>
+      </Testables>
+      <MacroExpansion>
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "1D6058900D05DD3D006BFB54"
+            BuildableName = "App.app"
+            BlueprintName = "App"
+            ReferencedContainer = "container:App.xcodeproj">
+         </BuildableReference>
+      </MacroExpansion>
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "1D6058900D05DD3D006BFB54"
+            BuildableName = "App.app"
+            BlueprintName = "App"
+            ReferencedContainer = "container:App.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "1D6058900D05DD3D006BFB54"
+            BuildableName = "App.app"
+            BlueprintName = "App"
+            ReferencedContainer = "container:App.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git 
a/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/.gitignore 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/.gitignore
new file mode 100644
index 00000000..cc76483f
--- /dev/null
+++ b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/.gitignore
@@ -0,0 +1,5 @@
+*.mode1v3
+*.perspectivev3
+*.pbxuser
+.DS_Store
+build/
diff --git 
a/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/App-Info.plist 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/App-Info.plist
new file mode 100644
index 00000000..96685af8
--- /dev/null
+++ b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/App-Info.plist
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+               http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+-->
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" 
"http://www.apple.com/DTDs/PropertyList-1.0.dtd";>
+<plist version="1.0">
+<dict>
+       <key>UTImportedTypeDeclarations</key>
+       <array>
+               <dict>
+                       <key>UTTypeConformsTo</key>
+                       <array>
+                               <string>public.data</string>
+                       </array>
+                       <key>UTTypeDescription</key>
+                       <string>WebAssembly</string>
+                       <key>UTTypeIdentifier</key>
+                       <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+                       <key>UTTypeTagSpecification</key>
+                       <dict>
+                               <key>public.filename-extension</key>
+                               <string>wasm</string>
+                               <key>public.mime-type</key>
+                               <string>application/wasm</string>
+                       </dict>
+               </dict>
+       </array>
+       <key>UIApplicationSceneManifest</key>
+       <dict>
+               <key>UIApplicationSupportsMultipleScenes</key>
+               <false/>
+               <key>UISceneConfigurations</key>
+               <dict>
+                       <key>UIWindowSceneSessionRoleApplication</key>
+                       <array>
+                               <dict>
+                                       <key>UISceneConfigurationName</key>
+                                       <string>Default Configuration</string>
+                                       <key>UISceneDelegateClassName</key>
+                                       
<string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
+                                       <key>UISceneStoryboardFile</key>
+                                       <string>Main</string>
+                               </dict>
+                       </array>
+               </dict>
+       </dict>
+</dict>
+</plist>
diff --git 
a/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/AppDelegate.h 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/AppDelegate.h
new file mode 100644
index 00000000..62a77631
--- /dev/null
+++ b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/AppDelegate.h
@@ -0,0 +1,29 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+#import <Cordova/CDVAppDelegate.h>
+
+#ifndef __CORDOVA_SILENCE_HEADER_DEPRECATIONS
+    #warning It is unsafe to rely on the AppDelegate class as an extension 
point. \
+             Update your code to extend CDVAppDelegate instead -- \
+             This code will stop working in Cordova iOS 9!
+#endif
+
+@interface AppDelegate : CDVAppDelegate
+@end
diff --git 
a/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/AppDelegate.swift 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/AppDelegate.swift
new file mode 100644
index 00000000..e6ef28ff
--- /dev/null
+++ b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/AppDelegate.swift
@@ -0,0 +1,29 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+import UIKit
+
+@main
+@_objcImplementation
+extension AppDelegate {
+    open override func application(_ application: UIApplication, 
configurationForConnecting connectingSceneSession: UISceneSession, options: 
UIScene.ConnectionOptions) -> UISceneConfiguration {
+        return UISceneConfiguration(name: "Default Configuration", 
sessionRole: connectingSceneSession.role)
+    }
+}
+
diff --git 
a/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/Assets.xcassets/AppIcon.appiconset/Contents.json
 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/Assets.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 00000000..2c8c083a
--- /dev/null
+++ 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,20 @@
+{
+  "images" : [
+    {
+      "filename" : "icon.png",
+      "idiom" : "universal",
+      "platform": "ios",
+      "size" : "1024x1024"
+    },
+    {
+      "filename" : "icon.png",
+      "idiom" : "universal",
+      "platform": "watchos",
+      "size" : "1024x1024"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
diff --git 
a/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/Assets.xcassets/AppIcon.appiconset/icon.png
 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/Assets.xcassets/AppIcon.appiconset/icon.png
new file mode 100644
index 00000000..b9250b12
Binary files /dev/null and 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/Assets.xcassets/AppIcon.appiconset/icon.png
 differ
diff --git 
a/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/Assets.xcassets/BackgroundColor.colorset/Contents.json
 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/Assets.xcassets/BackgroundColor.colorset/Contents.json
new file mode 100644
index 00000000..462830f8
--- /dev/null
+++ 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/Assets.xcassets/BackgroundColor.colorset/Contents.json
@@ -0,0 +1,15 @@
+{
+  "colors" : [
+    {
+      "color" : {
+        "platform" : "ios",
+        "reference" : "systemBackgroundColor"
+      },
+      "idiom" : "universal"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git 
a/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/Assets.xcassets/Contents.json
 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/Assets.xcassets/Contents.json
new file mode 100644
index 00000000..da4a164c
--- /dev/null
+++ 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/Assets.xcassets/Contents.json
@@ -0,0 +1,6 @@
+{
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file
diff --git 
a/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/Assets.xcassets/LaunchStoryboard.imageset/Contents.json
 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/Assets.xcassets/LaunchStoryboard.imageset/Contents.json
new file mode 100644
index 00000000..eab1cd11
--- /dev/null
+++ 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/Assets.xcassets/LaunchStoryboard.imageset/Contents.json
@@ -0,0 +1,168 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "1x",
+      "height-class" : "compact"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x",
+      "height-class" : "compact"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x",
+      "height-class" : "compact"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "1x",
+      "width-class" : "compact"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x",
+      "width-class" : "compact"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x",
+      "width-class" : "compact"
+    },
+    {
+      "idiom" : "universal",
+      "width-class" : "compact",
+      "height-class" : "compact",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "width-class" : "compact",
+      "height-class" : "compact",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "width-class" : "compact",
+      "height-class" : "compact",
+      "scale" : "3x"
+    },
+    {
+      "idiom" : "iphone",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "iphone",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "iphone",
+      "scale" : "3x"
+    },
+    {
+      "idiom" : "iphone",
+      "scale" : "1x",
+      "height-class" : "compact"
+    },
+    {
+      "idiom" : "iphone",
+      "scale" : "2x",
+      "height-class" : "compact"
+    },
+    {
+      "idiom" : "iphone",
+      "scale" : "3x",
+      "height-class" : "compact"
+    },
+    {
+      "idiom" : "iphone",
+      "scale" : "1x",
+      "width-class" : "compact"
+    },
+    {
+      "idiom" : "iphone",
+      "scale" : "2x",
+      "width-class" : "compact"
+    },
+    {
+      "idiom" : "iphone",
+      "scale" : "3x",
+      "width-class" : "compact"
+    },
+    {
+      "idiom" : "iphone",
+      "width-class" : "compact",
+      "height-class" : "compact",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "iphone",
+      "width-class" : "compact",
+      "height-class" : "compact",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "iphone",
+      "width-class" : "compact",
+      "height-class" : "compact",
+      "scale" : "3x"
+    },
+    {
+      "idiom" : "ipad",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "ipad",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "ipad",
+      "scale" : "1x",
+      "height-class" : "compact"
+    },
+    {
+      "idiom" : "ipad",
+      "scale" : "2x",
+      "height-class" : "compact"
+    },
+    {
+      "idiom" : "ipad",
+      "scale" : "1x",
+      "width-class" : "compact"
+    },
+    {
+      "idiom" : "ipad",
+      "scale" : "2x",
+      "width-class" : "compact"
+    },
+    {
+      "idiom" : "ipad",
+      "width-class" : "compact",
+      "height-class" : "compact",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "ipad",
+      "width-class" : "compact",
+      "height-class" : "compact",
+      "scale" : "2x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file
diff --git 
a/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/Assets.xcassets/SplashScreenBackgroundColor.colorset/Contents.json
 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/Assets.xcassets/SplashScreenBackgroundColor.colorset/Contents.json
new file mode 100644
index 00000000..462830f8
--- /dev/null
+++ 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/Assets.xcassets/SplashScreenBackgroundColor.colorset/Contents.json
@@ -0,0 +1,15 @@
+{
+  "colors" : [
+    {
+      "color" : {
+        "platform" : "ios",
+        "reference" : "systemBackgroundColor"
+      },
+      "idiom" : "universal"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git 
a/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/Assets.xcassets/StatusBarBackgroundColor.colorset/Contents.json
 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/Assets.xcassets/StatusBarBackgroundColor.colorset/Contents.json
new file mode 100644
index 00000000..462830f8
--- /dev/null
+++ 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/Assets.xcassets/StatusBarBackgroundColor.colorset/Contents.json
@@ -0,0 +1,15 @@
+{
+  "colors" : [
+    {
+      "color" : {
+        "platform" : "ios",
+        "reference" : "systemBackgroundColor"
+      },
+      "idiom" : "universal"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git 
a/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/Base.lproj/CDVLaunchScreen.storyboard
 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/Base.lproj/CDVLaunchScreen.storyboard
new file mode 100644
index 00000000..be89abe1
--- /dev/null
+++ 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/Base.lproj/CDVLaunchScreen.storyboard
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" 
version="3.0" toolsVersion="15705" targetRuntime="iOS.CocoaTouch" 
propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" 
useTraitCollections="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
+    <device id="retina6_1" orientation="portrait" appearance="light"/>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" 
version="15706"/>
+        <capability name="Named colors" minToolsVersion="9.0"/>
+        <capability name="documents saved in the Xcode 8 format" 
minToolsVersion="8.0"/>
+    </dependencies>
+    <scenes>
+        <!--View Controller-->
+        <scene sceneID="EHf-IW-A2E">
+            <objects>
+                <viewController id="01J-lp-oVM" sceneMemberID="viewController">
+                    <layoutGuides>
+                        <viewControllerLayoutGuide type="top" id="Llm-lL-Icb"/>
+                        <viewControllerLayoutGuide type="bottom" 
id="xb3-aO-Qok"/>
+                    </layoutGuides>
+                    <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
+                        <rect key="frame" x="0.0" y="0.0" width="414" 
height="896"/>
+                        <autoresizingMask key="autoresizingMask" 
widthSizable="YES" heightSizable="YES"/>
+                        <subviews>
+                            <imageView userInteractionEnabled="NO" 
contentMode="scaleAspectFill" horizontalHuggingPriority="251" 
verticalHuggingPriority="251" image="LaunchStoryboard" 
translatesAutoresizingMaskIntoConstraints="NO" id="2ns-9I-Qjs">
+                                <rect key="frame" x="0.0" y="0.0" width="414" 
height="896"/>
+                            </imageView>
+                        </subviews>
+                        <color key="backgroundColor" 
name="SplashScreenBackgroundColor"/>
+                        <constraints>
+                            <constraint firstAttribute="trailing" 
secondItem="2ns-9I-Qjs" secondAttribute="trailing" id="FZL-3Z-NFz"/>
+                            <constraint firstItem="2ns-9I-Qjs" 
firstAttribute="bottom" secondItem="Ze5-6b-2t3" secondAttribute="bottom" 
id="L9l-pw-wXj"/>
+                            <constraint firstItem="2ns-9I-Qjs" 
firstAttribute="top" secondItem="Ze5-6b-2t3" secondAttribute="top" 
id="oGN-hc-Uzj"/>
+                            <constraint firstItem="2ns-9I-Qjs" 
firstAttribute="leading" secondItem="Ze5-6b-2t3" secondAttribute="leading" 
id="rS9-Wd-zY4"/>
+                        </constraints>
+                    </view>
+                </viewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" 
id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="53" y="375"/>
+        </scene>
+    </scenes>
+    <resources>
+        <image name="LaunchStoryboard" width="1366" height="1366"/>
+        <namedColor name="SplashScreenBackgroundColor">
+            <color white="1" alpha="1" colorSpace="custom" 
customColorSpace="genericGamma22GrayColorSpace"/>
+        </namedColor>
+    </resources>
+</document>
diff --git 
a/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/Base.lproj/Main.storyboard
 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/Base.lproj/Main.storyboard
new file mode 100644
index 00000000..3372d5d2
--- /dev/null
+++ 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/Base.lproj/Main.storyboard
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" 
version="3.0" toolsVersion="15705" targetRuntime="iOS.CocoaTouch" 
propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" 
useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" 
version="15706"/>
+        <capability name="Named colors" minToolsVersion="9.0"/>
+        <capability name="documents saved in the Xcode 8 format" 
minToolsVersion="8.0"/>
+    </dependencies>
+    <scenes>
+        <!--View Controller-->
+        <scene sceneID="tne-QT-ifu">
+            <objects>
+                <viewController id="BYZ-38-t0r" customClass="ViewController" 
customModule="$(PRODUCT_MODULE_NAME)" customModuleProvider="target" 
sceneMemberID="viewController">
+                    <view key="view" contentMode="scaleToFill" 
insetsLayoutMarginsFromSafeArea="NO" id="8bC-Xf-vdC">
+                        <rect key="frame" x="0.0" y="0.0" width="393" 
height="852"/>
+                        <autoresizingMask key="autoresizingMask" 
widthSizable="YES" heightSizable="YES"/>
+                        <color key="backgroundColor" name="BackgroundColor"/>
+                    </view>
+                    <userDefinedRuntimeAttributes>
+                        <userDefinedRuntimeAttribute type="color" 
keyPath="backgroundColor">
+                            <color key="value" name="BackgroundColor"/>
+                        </userDefinedRuntimeAttribute>
+                        <userDefinedRuntimeAttribute type="color" 
keyPath="splashBackgroundColor">
+                            <color key="value" 
name="SplashScreenBackgroundColor"/>
+                        </userDefinedRuntimeAttribute>
+                        <userDefinedRuntimeAttribute type="boolean" 
keyPath="showSplashScreen" value="YES"/>
+                        <userDefinedRuntimeAttribute type="color" 
keyPath="statusBarBackgroundColor">
+                            <color key="value" 
name="StatusBarBackgroundColor"/>
+                        </userDefinedRuntimeAttribute>
+                    </userDefinedRuntimeAttributes>
+                </viewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" 
id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
+            </objects>
+        </scene>
+    </scenes>
+    <resources>
+        <namedColor name="BackgroundColor">
+            <color white="1" alpha="1" colorSpace="custom" 
customColorSpace="genericGamma22GrayColorSpace"/>
+        </namedColor>
+        <namedColor name="SplashScreenBackgroundColor">
+            <color white="1" alpha="1" colorSpace="custom" 
customColorSpace="genericGamma22GrayColorSpace"/>
+        </namedColor>
+        <namedColor name="StatusBarBackgroundColor">
+            <color white="1" alpha="1" colorSpace="custom" 
customColorSpace="genericGamma22GrayColorSpace"/>
+        </namedColor>
+    </resources>
+</document>
+
diff --git 
a/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/Bridging-Header.h 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/Bridging-Header.h
new file mode 100644
index 00000000..9dec5295
--- /dev/null
+++ b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/Bridging-Header.h
@@ -0,0 +1,25 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import <Cordova/Cordova.h>
+
+#define __CORDOVA_SILENCE_HEADER_DEPRECATIONS
+#import "AppDelegate.h"
+#import "MainViewController.h"
+#undef __CORDOVA_SILENCE_HEADER_DEPRECATIONS
diff --git 
a/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/Entitlements-Debug.plist
 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/Entitlements-Debug.plist
new file mode 100644
index 00000000..1ed4ae5b
--- /dev/null
+++ 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/Entitlements-Debug.plist
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" 
"http://www.apple.com/DTDs/PropertyList-1.0.dtd";>
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+-->
+<plist version="1.0">
+    <dict>
+    </dict>
+</plist>
diff --git 
a/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/Entitlements-Release.plist
 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/Entitlements-Release.plist
new file mode 100644
index 00000000..1ed4ae5b
--- /dev/null
+++ 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/Entitlements-Release.plist
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" 
"http://www.apple.com/DTDs/PropertyList-1.0.dtd";>
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+-->
+<plist version="1.0">
+    <dict>
+    </dict>
+</plist>
diff --git 
a/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/MainViewController.h 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/MainViewController.h
new file mode 100644
index 00000000..ddb37c4a
--- /dev/null
+++ 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/MainViewController.h
@@ -0,0 +1,29 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+#import <Cordova/CDVViewController.h>
+
+#ifndef __CORDOVA_SILENCE_HEADER_DEPRECATIONS
+    #warning It is unsafe to rely on the MainViewController class as an 
extension point. \
+             Update your code to extend CDVViewController instead -- \
+             This code will stop working in Cordova iOS 9!
+#endif
+
+@interface MainViewController : CDVViewController
+@end
diff --git 
a/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/Plugins/README 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/Plugins/README
new file mode 100644
index 00000000..87df09f2
--- /dev/null
+++ b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/Plugins/README
@@ -0,0 +1,20 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+# 
+# http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+#  KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+Put the .h and .m files of your plugin here. The .js files of your plugin 
belong in the www folder.
diff --git 
a/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/PrivacyInfo.xcprivacy
 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/PrivacyInfo.xcprivacy
new file mode 100644
index 00000000..4b2e70fd
--- /dev/null
+++ 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/PrivacyInfo.xcprivacy
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+               http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+-->
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" 
"http://www.apple.com/DTDs/PropertyList-1.0.dtd";>
+<plist version="1.0">
+<dict>
+       <key>NSPrivacyTracking</key>
+       <false/>
+       <key>NSPrivacyCollectedDataTypes</key>
+       <array/>
+       <key>NSPrivacyAccessedAPITypes</key>
+       <array/>
+       <key>NSPrivacyTrackingDomains</key>
+       <array/>
+</dict>
+</plist>
diff --git 
a/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/Resources/README 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/Resources/README
new file mode 100644
index 00000000..1872c8e9
--- /dev/null
+++ b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/Resources/README
@@ -0,0 +1,20 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+# 
+# http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+#  KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+Put resource files to embed in the app bundle here.
diff --git 
a/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/SceneDelegate.swift 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/SceneDelegate.swift
new file mode 100644
index 00000000..83fd3110
--- /dev/null
+++ 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/SceneDelegate.swift
@@ -0,0 +1,25 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+import UIKit
+
+class SceneDelegate: UIResponder, UIWindowSceneDelegate {
+    var window: UIWindow?
+}
+
diff --git 
a/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/ViewController.swift 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/ViewController.swift
new file mode 100644
index 00000000..87837032
--- /dev/null
+++ 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/ViewController.swift
@@ -0,0 +1,27 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+import Cordova
+
+@_objcImplementation
+extension MainViewController {
+}
+
+class ViewController: MainViewController {
+}
diff --git 
a/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/config.xml 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/config.xml
new file mode 100644
index 00000000..31a7c387
--- /dev/null
+++ b/tests/spec/unit/fixtures/ios-packageswift-config-xml/App/config.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<widget id="sample.app" version="1.0.0" xmlns="http://www.w3.org/ns/widgets"; 
xmlns:cdv="http://cordova.apache.org/ns/1.0";>
+    <name>SampleApp</name>
+
+    <description>
+        A sample Apache Cordova application that responds to the deviceready 
event.
+    </description>
+
+    <author href="http://cordova.io"; email="d...@cordova.apache.org">
+        Apache Cordova Team
+    </author>
+
+    <content src="index.html" />
+
+    <!-- AllowList docs: https://cordova.apache.org/docs/en/latest/ -->
+    <access origin="*" />
+    <!-- Grant certain URLs the ability to launch external applications. This
+         behaviour is set to match that of Cordova versions before 3.6.0, and
+         should be reviewed before launching an application in production. It
+         may be changed in the future. -->
+    <allow-intent href="http://*/*"; />
+    <allow-intent href="https://*/*"; />
+    <allow-intent href="tel:*" />
+    <allow-intent href="sms:*" />
+    <allow-intent href="mailto:*"; />
+    <allow-intent href="geo:*" />
+    <allow-intent href="itms:*" />
+    <allow-intent href="itms-apps:*" />
+
+    <!-- Preferences for iOS -->
+    <preference name="AllowInlineMediaPlayback" value="false" />
+    <preference name="DisallowOverscroll" value="false" />
+    <preference name="EnableViewportScale" value="false" />
+    <preference name="MediaTypesRequiringUserActionForPlayback" value="false" 
/>
+    <preference name="SuppressesIncrementalRendering" value="false" />
+    <preference name="SuppressesLongPressGesture" value="false" />
+    <preference name="Suppresses3DTouchGesture" value="false" />
+
+    <feature name="CDVWebViewEngine">
+        <param name="ios-package" value="CDVWebViewEngine" />
+    </feature>
+    <feature name="LaunchScreen">
+        <param name="ios-package" value="CDVLaunchScreen"/>
+    </feature>
+    <feature name="LocalStorage">
+        <param name="ios-package" value="CDVLocalStorage"/>
+    </feature>
+    <feature name="Console">
+        <param name="ios-package" value="CDVLogger"/>
+        <param name="onload" value="true"/>
+    </feature>
+    <feature name="HandleOpenUrl">
+        <param name="ios-package" value="CDVHandleOpenURL"/>
+        <param name="onload" value="true"/>
+    </feature>
+    <feature name="IntentAndNavigationFilter">
+        <param name="ios-package" value="CDVIntentAndNavigationFilter"/>
+        <param name="onload" value="true"/>
+    </feature>
+    <feature name="GestureHandler">
+        <param name="ios-package" value="CDVGestureHandler"/>
+        <param name="onload" value="true"/>
+    </feature>
+</widget>
diff --git 
a/tests/spec/unit/fixtures/ios-packageswift-config-xml/CordovaPlugins/Package.swift
 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/CordovaPlugins/Package.swift
new file mode 100644
index 00000000..705e2778
--- /dev/null
+++ 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/CordovaPlugins/Package.swift
@@ -0,0 +1,37 @@
+// swift-tools-version:5.5
+
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+import PackageDescription
+
+let package = Package(
+    name: "CordovaPlugins",
+    platforms: [
+        .iOS(.v13),
+        .macCatalyst(.v13)
+    ],
+    products: [
+        .library(name: "CordovaPlugins", targets: ["CordovaPlugins"])
+    ],
+    targets: [
+        .target(name: "CordovaPlugins")
+    ]
+)
+
diff --git 
a/tests/spec/unit/fixtures/ios-packageswift-config-xml/CordovaPlugins/Sources/CordovaPlugins/CordovaPlugins.swift
 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/CordovaPlugins/Sources/CordovaPlugins/CordovaPlugins.swift
new file mode 100644
index 00000000..92baa917
--- /dev/null
+++ 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/CordovaPlugins/Sources/CordovaPlugins/CordovaPlugins.swift
@@ -0,0 +1,21 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+// We need something here so that the empty package will compile successfully
+public let isCordovaApp = true
diff --git 
a/tests/spec/unit/fixtures/ios-packageswift-config-xml/cordova/defaults.xml 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/cordova/defaults.xml
new file mode 100644
index 00000000..1a7287d2
--- /dev/null
+++ b/tests/spec/unit/fixtures/ios-packageswift-config-xml/cordova/defaults.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<widget xmlns     = "http://www.w3.org/ns/widgets";
+        id        = "io.cordova.helloCordova"
+        version   = "2.0.0">
+
+    <!-- Preferences for iOS -->
+    <preference name="AllowInlineMediaPlayback" value="false" />
+    <preference name="DisallowOverscroll" value="false" />
+    <preference name="EnableViewportScale" value="false" />
+    <preference name="MediaTypesRequiringUserActionForPlayback" value="none" />
+    <preference name="SuppressesIncrementalRendering" value="false" />
+    <preference name="SuppressesLongPressGesture" value="false" />
+    <preference name="Suppresses3DTouchGesture" value="false" />
+
+    <feature name="CDVWebViewEngine">
+        <param name="ios-package" value="CDVWebViewEngine" />
+    </feature>
+    <feature name="LaunchScreen">
+        <param name="ios-package" value="CDVLaunchScreen"/>
+    </feature>
+    <feature name="LocalStorage">
+        <param name="ios-package" value="CDVLocalStorage"/>
+    </feature>
+    <feature name="Console">
+        <param name="ios-package" value="CDVLogger"/>
+        <param name="onload" value="true"/>
+    </feature>
+    <feature name="HandleOpenUrl">
+        <param name="ios-package" value="CDVHandleOpenURL"/>
+        <param name="onload" value="true"/>
+    </feature>
+    <feature name="IntentAndNavigationFilter">
+        <param name="ios-package" value="CDVIntentAndNavigationFilter"/>
+        <param name="onload" value="true"/>
+    </feature>
+    <feature name="GestureHandler">
+        <param name="ios-package" value="CDVGestureHandler"/>
+        <param name="onload" value="true"/>
+    </feature>
+
+</widget>
diff --git 
a/tests/spec/unit/fixtures/ios-packageswift-config-xml/packages/cordova-ios-plugins/Package.swift
 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/packages/cordova-ios-plugins/Package.swift
new file mode 100644
index 00000000..8f306e98
--- /dev/null
+++ 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/packages/cordova-ios-plugins/Package.swift
@@ -0,0 +1,40 @@
+// swift-tools-version:5.5
+
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+import PackageDescription
+
+let package = Package(
+    name: "CordovaPlugins",
+    platforms: [
+        .iOS(.v13),
+        .macCatalyst(.v13)
+    ],
+    products: [
+        .library(name: "CordovaPlugins", targets: ["CordovaPlugins"])
+    ],
+    targets: [
+        .target(name: "CordovaPlugins")
+    ]
+)
+
+
+package.dependencies.append(.package(name: 
"org.test.plugins.swiftpackagecocoapodplugin", path: 
"../org.test.plugins.swiftpackagecocoapodplugin"))
+package.targets.first?.dependencies.append(.product(name: 
"org.test.plugins.swiftpackagecocoapodplugin", package: 
"org.test.plugins.swiftpackagecocoapodplugin"))
diff --git 
a/tests/spec/unit/fixtures/ios-packageswift-config-xml/packages/cordova-ios/Package.swift
 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/packages/cordova-ios/Package.swift
new file mode 100644
index 00000000..6571d093
--- /dev/null
+++ 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/packages/cordova-ios/Package.swift
@@ -0,0 +1,47 @@
+// swift-tools-version:5.5
+
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+import PackageDescription
+
+let package = Package(
+    name: "Cordova",
+    platforms: [
+        .iOS(.v13),
+        .macCatalyst(.v13)
+    ],
+    products: [
+        .library(name: "Cordova", targets: ["Cordova"])
+    ],
+    dependencies: [],
+    targets: [
+        .target(
+            name: "Cordova",
+            path: "CordovaLib/",
+            exclude: ["Info.plist"],
+            resources: [
+                .copy("PrivacyInfo.xcprivacy")
+            ],
+            cSettings: [
+                .headerSearchPath("Classes/Private")
+            ]
+        )
+    ]
+)
diff --git 
a/tests/spec/unit/fixtures/ios-packageswift-config-xml/platform_www/.gitkeep 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/platform_www/.gitkeep
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/spec/unit/fixtures/ios-packageswift-config-xml/www/.gitkeep 
b/tests/spec/unit/fixtures/ios-packageswift-config-xml/www/.gitkeep
new file mode 100644
index 00000000..e69de29b
diff --git 
a/tests/spec/unit/fixtures/org.test.plugins.swiftpackagecocoapodplugin/Package.swift
 
b/tests/spec/unit/fixtures/org.test.plugins.swiftpackagecocoapodplugin/Package.swift
new file mode 100644
index 00000000..094dfbf4
--- /dev/null
+++ 
b/tests/spec/unit/fixtures/org.test.plugins.swiftpackagecocoapodplugin/Package.swift
@@ -0,0 +1,47 @@
+// swift-tools-version:5.5
+
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+import PackageDescription
+
+let package = Package(
+    name: "org.test.plugins.swiftpackagecocoapodplugin",
+    platforms: [
+        .iOS(.v13),
+        .macCatalyst(.v13)
+    ],
+    products: [
+        .library(name: "org.test.plugins.swiftpackagecocoapodplugin", targets: 
["PackagePodPlugin"])
+    ],
+    dependencies: [
+        .package(url: "https://github.com/apache/cordova-ios.git";, branch: 
"master")
+    ],
+    targets: [
+        .target(
+            name: "PackagePodPlugin",
+            dependencies: [
+                .product(name: "Cordova", package: "cordova-ios")
+            ],
+            path: "src/ios"
+        )
+    ]
+)
+
+
diff --git 
a/tests/spec/unit/fixtures/org.test.plugins.swiftpackagecocoapodplugin/package.json
 
b/tests/spec/unit/fixtures/org.test.plugins.swiftpackagecocoapodplugin/package.json
new file mode 100644
index 00000000..e06ed48b
--- /dev/null
+++ 
b/tests/spec/unit/fixtures/org.test.plugins.swiftpackagecocoapodplugin/package.json
@@ -0,0 +1,12 @@
+{
+    "name": "org.test.plugins.swiftpackagecocoapodplugin",
+    "version": "1.0.0",
+    "description": "",
+    "main": "index.js",
+    "scripts": {
+      "test": "echo \"Error: no test specified\" && exit 1"
+    },
+    "keywords": [],
+    "author": "",
+    "license": "Apache License, Version 2.0"
+  }
\ No newline at end of file
diff --git 
a/tests/spec/unit/fixtures/org.test.plugins.swiftpackagecocoapodplugin/plugin.xml
 
b/tests/spec/unit/fixtures/org.test.plugins.swiftpackagecocoapodplugin/plugin.xml
new file mode 100644
index 00000000..1a1511da
--- /dev/null
+++ 
b/tests/spec/unit/fixtures/org.test.plugins.swiftpackagecocoapodplugin/plugin.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+-->
+<plugin xmlns="http://cordova.apache.org/ns/plugins/1.0"; 
id="org.test.plugins.swiftpackagecocoapodplugin" version="1.0.0">
+    <name>Swift Package CocoaPod Plugin</name>
+
+    <!-- ios -->
+    <platform name="ios" package="swift">
+        <config-file parent="/*" target="config.xml">
+            <feature name="PackagePodPlugin">
+                <param name="ios-package" value="PackagePodPlugin" />
+                <param name="onload" value="true" />
+            </feature>
+        </config-file>
+        <source-file src="src/ios/PackagePodPlugin.swift" />
+        <podspec>
+            <config>
+                <source url="https://cdn.cocoapods.org/"/>
+            </config>
+            <pods use-frameworks="true">
+                <pod name="DummyObjCPodAlpha" spec="1.0.0" nospm="false" />
+                <pod name="DummyObjCPodBeta" spec="1.0.0" nospm="true" />
+                <pod name="DummyObjCPodGamma" spec="1.0.0"/>
+            </pods>
+        </podspec>        
+    </platform>
+</plugin>
diff --git 
a/tests/spec/unit/fixtures/org.test.plugins.swiftpackagecocoapodplugin/src/ios/PackagePodPlugin.swift
 
b/tests/spec/unit/fixtures/org.test.plugins.swiftpackagecocoapodplugin/src/ios/PackagePodPlugin.swift
new file mode 100644
index 00000000..7bf201c8
--- /dev/null
+++ 
b/tests/spec/unit/fixtures/org.test.plugins.swiftpackagecocoapodplugin/src/ios/PackagePodPlugin.swift
@@ -0,0 +1,46 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+
+/***********************************************
+ This Swift file is intentionally commented out.
+
+ The purpose of this plugin is to test the new `nospm="true"` attribute in the 
<pod> element of plugin.xml,
+ which controls whether a CocoaPods library should be included when the plugin 
is installed as a Swift Package.
+
+ While the plugin is structured as a Swift Package, it currently cannot 
function as a valid Cordova plugin 
+ because the Cordova framework itself (specifically CDVPlugin and related 
classes) is not yet accessible 
+ from within Swift Packages. Attempting to compile this file results in a 
build error due to the unresolved
+ `import Cordova` statement.
+
+ To allow testing of CocoaPods integration without triggering build failures 
related to Swift Package usage,
+ the contents of this file are commented out.
+
+ Once Cordova fully supports being used as a Swift Package dependency, this 
file can be uncommented 
+ and used to implement plugin functionality.
+***********************************************/
+
+import Cordova
+
+@objc(PackagePodPlugin)
+class PackagePodPlugin : CDVPlugin {
+    override func pluginInitialize() {
+        NSLog("Initialized Swift Package Pod Plugin");
+    }
+}
diff --git 
a/tests/spec/unit/fixtures/org.test.plugins.swiftpackageplugin/Package.swift 
b/tests/spec/unit/fixtures/org.test.plugins.swiftpackageplugin/Package.swift
new file mode 100644
index 00000000..0e8e0f82
--- /dev/null
+++ b/tests/spec/unit/fixtures/org.test.plugins.swiftpackageplugin/Package.swift
@@ -0,0 +1,46 @@
+// swift-tools-version:5.5
+
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+import PackageDescription
+
+let package = Package(
+    name: "PackagePlugin",
+    platforms: [
+        .iOS(.v13),
+        .macCatalyst(.v13)
+    ],
+    products: [
+        .library(name: "PackagePlugin", targets: ["PackagePlugin"])
+    ],
+    dependencies: [
+        .package(url: "https://github.com/apache/cordova-ios.git";, branch: 
"master")
+    ],
+    targets: [
+        .target(
+            name: "PackagePlugin",
+            dependencies: [
+                .product(name: "Cordova", package: "cordova-ios")
+            ],
+            path: "src/ios"
+        )
+    ]
+)
+
diff --git 
a/tests/spec/unit/fixtures/org.test.plugins.swiftpackageplugin/plugin.xml 
b/tests/spec/unit/fixtures/org.test.plugins.swiftpackageplugin/plugin.xml
new file mode 100644
index 00000000..08ddec80
--- /dev/null
+++ b/tests/spec/unit/fixtures/org.test.plugins.swiftpackageplugin/plugin.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+-->
+<plugin xmlns="http://cordova.apache.org/ns/plugins/1.0"; 
id="org.test.plugins.swiftpackageplugin" version="1.0.0">
+    <name>Swift Package Plugin</name>
+
+    <!-- ios -->
+    <platform name="ios" package="swift">
+        <config-file parent="/*" target="config.xml">
+            <feature name="PackagePlugin">
+                <param name="ios-package" value="PackagePlugin" />
+            </feature>
+        </config-file>
+
+        <source-file src="src/ios/PackagePlugin.swift" />
+    </platform>
+</plugin>
diff --git 
a/tests/spec/unit/fixtures/org.test.plugins.swiftpackageplugin/src/ios/PackagePlugin.swift
 
b/tests/spec/unit/fixtures/org.test.plugins.swiftpackageplugin/src/ios/PackagePlugin.swift
new file mode 100644
index 00000000..311031da
--- /dev/null
+++ 
b/tests/spec/unit/fixtures/org.test.plugins.swiftpackageplugin/src/ios/PackagePlugin.swift
@@ -0,0 +1,27 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+import Cordova
+
+@objc
+class PackagePlugin : CDVPlugin {
+    override func pluginInitialize() {
+        NSLog("Initialized Swift Package Plugin");
+    }
+}
diff --git a/tests/spec/unit/fixtures/test-Package.swift 
b/tests/spec/unit/fixtures/test-Package.swift
new file mode 100644
index 00000000..705e2778
--- /dev/null
+++ b/tests/spec/unit/fixtures/test-Package.swift
@@ -0,0 +1,37 @@
+// swift-tools-version:5.5
+
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+import PackageDescription
+
+let package = Package(
+    name: "CordovaPlugins",
+    platforms: [
+        .iOS(.v13),
+        .macCatalyst(.v13)
+    ],
+    products: [
+        .library(name: "CordovaPlugins", targets: ["CordovaPlugins"])
+    ],
+    targets: [
+        .target(name: "CordovaPlugins")
+    ]
+)
+


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@cordova.apache.org
For additional commands, e-mail: commits-h...@cordova.apache.org


Reply via email to