Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP - feat: Add support for SPM plugins #1430

Closed
wants to merge 11 commits into from
32 changes: 32 additions & 0 deletions lib/Api.js
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,11 @@ class Api {
return this.addPodSpecs(plugin, podSpecs, installOptions);
}
})
.then(() => {
if (plugin != null && plugin.dir && fs.existsSync(path.join(plugin.dir, 'Package.swift'))) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at this PR again, and the one thing I don't really love is the "magic" behaviour based on the existence of a Package.swift file in the plugin folder. It feels safer to rely on an explicit declaration in the plugin.xml file.

We've already overloaded the <framework> tag to do a billion things, so adding this wouldn't be totally unreasonable. i.e.,

<framework src="Package.swift" type="spm" />

Alternatively, the lib-file tag exists on Android but you could maybe stretch the definition to encompass Swift packages.

Using source-file is an option, but feels like that goes back to "magic" behaviour based on file names.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The point of having a Package.swift file is to turn the plugin into a swift package itself.
Having the Package.swift file makes it possible to add other swift packages the plugin wants to use as dependencies the “swift package way”.

Adding the Package.swift file in a framework tag makes no sense, in any case we could totally ditch the Package.swift file from plugins and use the framework tag to declare SPM dependencies, and then read the tag and write the dependencies in the CordovaPluginsSPM/Package.swift file but the tag will fall short for all the possible options and will end up creating a new tag in a future release as we did for CocoaPods.
The CLI should also copy the plugin files to the CordovaPluginsSPM project instead of to the app as if the plugin relies in the dependency and the dependency is in CordovaPluginsSPM project the plugin files should be there.

return this.updatePackageSwift(plugin, 'add');
}
})
// CB-11022 Return truthy value to prevent running prepare after
.then(() => true);
}
Expand Down Expand Up @@ -325,6 +330,11 @@ class Api {
return this.removePodSpecs(plugin, podSpecs, uninstallOptions);
}
})
.then(() => {
if (plugin != null && plugin.dir && fs.existsSync(path.join(plugin.dir, 'Package.swift'))) {
return this.updatePackageSwift(plugin, 'remove');
}
})
// CB-11022 Return truthy value to prevent running prepare after
.then(() => true);
}
Expand Down Expand Up @@ -512,6 +522,28 @@ class Api {
return Promise.resolve();
}

/**
* Updates the Package.swift file to add or remove plugin dependencies
* @param {PluginInfo} plugin plugin to edit the Package.swift with
* @param {String} mode Add or remove plugin
*/
updatePackageSwift (plugin, mode) {
const project_dir = this.locations.root;
const pluginDep = `
package.dependencies.append(.package(name: "${plugin.id}", path: "../../../plugins/${plugin.id}"))
package.targets.first?.dependencies.append(.product(name: "${plugin.id}", package: "${plugin.id}"))
`;
const packagePath = path.join(project_dir, 'CordovaPluginsSPM', 'Package.swift');
let packageContent = fs.readFileSync(packagePath, 'utf8');
if (mode === 'add') {
packageContent = packageContent + pluginDep;
} else {
packageContent = packageContent.replace(pluginDep, '');
}
fs.writeFileSync(packagePath, packageContent);
return Promise.resolve();
}

/**
* set Swift Version for all CocoaPods libraries
*
Expand Down
35 changes: 35 additions & 0 deletions templates/project/CordovaPluginsSPM/Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// 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: "CordovaPluginsSPM",
platforms: [.iOS(.v11)],
products: [
.library(
name: "CordovaPluginsSPM",
targets: ["CordovaPluginsSPM"])
],
targets: [
.target(
name: "CordovaPluginsSPM"
)
]
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
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.
*/

public let isCordovaApp = true
22 changes: 22 additions & 0 deletions templates/project/__PROJECT_NAME__.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
0207DA581B56EA530066E2B4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0207DA571B56EA530066E2B4 /* Assets.xcassets */; };
1D3623260D0F684500981E51 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D3623250D0F684500981E51 /* AppDelegate.m */; };
1D60589B0D05DD56006BFB54 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; };
2F4E7E782BDF21E200DF2ACD /* CordovaPluginsSPM in Frameworks */ = {isa = PBXBuildFile; productRef = 2F4E7E772BDF21E200DF2ACD /* CordovaPluginsSPM */; };
301BF552109A68D80062928A /* libCordova.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 301BF535109A57CC0062928A /* libCordova.a */; settings = {ATTRIBUTES = (Required, ); }; };
302D95F114D2391D003F00A1 /* MainViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 302D95EF14D2391D003F00A1 /* MainViewController.m */; };
302D95F214D2391D003F00A1 /* MainViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 302D95F014D2391D003F00A1 /* MainViewController.xib */; };
Expand Down Expand Up @@ -106,6 +107,7 @@
buildActionMask = 2147483647;
files = (
301BF552109A68D80062928A /* libCordova.a in Frameworks */,
2F4E7E782BDF21E200DF2ACD /* CordovaPluginsSPM in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -225,6 +227,9 @@
301BF551109A68C00062928A /* PBXTargetDependency */,
);
name = "__PROJECT_NAME__";
packageProductDependencies = (
2F4E7E772BDF21E200DF2ACD /* CordovaPluginsSPM */,
);
productName = "__PROJECT_NAME__";
productReference = 1D6058910D05DD3D006BFB54 /* __PROJECT_NAME__.app */;
productType = "com.apple.product-type.application";
Expand Down Expand Up @@ -252,6 +257,9 @@
Base,
);
mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */;
packageReferences = (
2F4E7E762BDF21E200DF2ACD /* XCLocalSwiftPackageReference "CordovaPluginsSPM" */,
);
projectDirPath = "";
projectReferences = (
{
Expand Down Expand Up @@ -483,6 +491,20 @@
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */

/* Begin XCLocalSwiftPackageReference section */
2F4E7E762BDF21E200DF2ACD /* XCLocalSwiftPackageReference "CordovaPluginsSPM" */ = {
isa = XCLocalSwiftPackageReference;
relativePath = CordovaPluginsSPM;
};
/* End XCLocalSwiftPackageReference section */

/* Begin XCSwiftPackageProductDependency section */
2F4E7E772BDF21E200DF2ACD /* CordovaPluginsSPM */ = {
isa = XCSwiftPackageProductDependency;
productName = CordovaPluginsSPM;
};
/* End XCSwiftPackageProductDependency section */
};
rootObject = 29B97313FDCFA39411CA2CEA /* Project object */;
}