diff --git a/lib/Api.js b/lib/Api.js index c131f1b83..407cd7fe2 100644 --- a/lib/Api.js +++ b/lib/Api.js @@ -107,8 +107,6 @@ class Api { * @param {Object} [options] An options object. The most common options are: * @param {String} [options.customTemplate] A path to custom template, that * should override the default one from platform. - * @param {Boolean} [options.link] Flag that indicates that platform's - * sources will be linked to installed platform instead of copying. * @param {EventEmitter} [events] An EventEmitter instance that will be used for * logging purposes. If no EventEmitter provided, all events will be logged to * console diff --git a/lib/create.js b/lib/create.js index 2c4ea38d3..f3f9936c3 100755 --- a/lib/create.js +++ b/lib/create.js @@ -19,7 +19,7 @@ const path = require('node:path'); const fs = require('node:fs'); -const { CordovaError, events } = require('cordova-common'); +const { ConfigParser, CordovaError, events, xmlHelpers } = require('cordova-common'); const xcode = require('xcode'); const pkg = require('../package'); @@ -31,10 +31,11 @@ const ROOT = path.join(__dirname, '..'); * @param {string} project_path Path to your new Cordova iOS project * @param {string} package_name Package name, following reverse-domain style convention * @param {string} project_name Project name - * @param {{ link: boolean, customTemplate: string }} opts Project creation options + * @param {{ customTemplate: string }} opts Project creation options + * @param {ConfigParser} root_config The application config.xml * @returns {Promise} resolves when the project has been created */ -exports.createProject = async (project_path, package_name, project_name, opts) => { +exports.createProject = async (project_path, package_name, project_name, opts, root_config) => { package_name = package_name || 'my.cordova.project'; project_name = project_name || 'CordovaExample'; @@ -56,7 +57,7 @@ exports.createProject = async (project_path, package_name, project_name, opts) = }, options: { templatePath: opts.customTemplate || path.join(ROOT, 'templates', 'project'), - linkLib: !!opts.link + rootConfig: root_config } }).create(); @@ -73,6 +74,7 @@ class ProjectCreator { this.provideCordovaJs(); this.provideBuildScripts(); this.updateProjectSettings(); + this.updatePlatformConfigFile(); } provideProjectTemplate () { @@ -97,6 +99,17 @@ class ProjectCreator { fs.cpSync(srcScriptsDir, destScriptsDir, { recursive: true }); } + updatePlatformConfigFile () { + const defaultXmlPath = this.projectPath('cordova', 'defaults.xml'); + const configXmlPath = this.projectPath('App', 'config.xml'); + + fs.cpSync(defaultXmlPath, configXmlPath); + + const config = new ConfigParser(configXmlPath); + xmlHelpers.mergeXml(this.options.rootConfig.doc.getroot(), config.doc.getroot(), 'ios', /* clobber= */true); + config.write(); + } + updateProjectSettings () { const projectPath = this.projectPath('App.xcodeproj', 'project.pbxproj'); const xcodeproj = xcode.project(projectPath); @@ -105,6 +118,11 @@ class ProjectCreator { xcodeproj.updateBuildProperty('PRODUCT_NAME', `"${this.project.name}"`, null, 'App'); xcodeproj.updateBuildProperty('PRODUCT_BUNDLE_IDENTIFIER', `"${this.project.id}"`, null, 'App'); + const deploymentTarget = this.options.rootConfig.getPreference('deployment-target', 'ios'); + if (deploymentTarget) { + xcodeproj.updateBuildProperty('IPHONEOS_DEPLOYMENT_TARGET', deploymentTarget); + } + // Update the CordovaLib Swift package reference path const pkgRefs = xcodeproj.hash.project.objects.XCLocalSwiftPackageReference; if (pkgRefs) { diff --git a/tests/spec/createAndBuild.spec.js b/tests/spec/createAndBuild.spec.js index 2f6fe5172..54cb0ccb6 100644 --- a/tests/spec/createAndBuild.spec.js +++ b/tests/spec/createAndBuild.spec.js @@ -21,6 +21,7 @@ const fs = require('node:fs'); const os = require('node:os'); const path = require('node:path'); const xcode = require('xcode'); +const { ConfigParser } = require('cordova-common'); const create = require('../../lib/create'); const makeTempDir = () => path.join( @@ -28,6 +29,8 @@ const makeTempDir = () => path.join( `cordova-ios-create-test-${Date.now()}` ); +const defaultConfigXmlPath = path.join(__dirname, '..', '..', 'templates', 'project', 'App', 'config.xml'); + /** * Verifies that some of the project file exists. Not all will be tested. * E.g. App's resource directory, xcodeproj, xcworkspace, and CordovaLib. @@ -90,7 +93,9 @@ function verifyBuild (tmpDir) { * @returns {Promise} */ async function verifyCreateAndBuild (tmpDir, packageName, projectName) { - await create.createProject(tmpDir, packageName, projectName, {}, undefined) + const configXml = new ConfigParser(defaultConfigXmlPath); + + await create.createProject(tmpDir, packageName, projectName, {}, configXml) .then(() => verifyProjectFiles(tmpDir, projectName)) .then(() => verifyProjectBundleIdentifier(tmpDir, projectName, packageName)) .then(() => verifyBuild(tmpDir)); diff --git a/tests/spec/unit/create.spec.js b/tests/spec/unit/create.spec.js index f07c4bbe5..8bef5dbf7 100644 --- a/tests/spec/unit/create.spec.js +++ b/tests/spec/unit/create.spec.js @@ -21,6 +21,7 @@ const fs = require('node:fs'); const os = require('node:os'); const path = require('node:path'); const xcode = require('xcode'); +const { ConfigParser } = require('cordova-common'); const create = require('../../../lib/create'); const makeTempDir = () => path.join( @@ -28,6 +29,8 @@ const makeTempDir = () => path.join( `cordova-ios-create-test-${Date.now()}` ); +const defaultConfigXmlPath = path.join(__dirname, '..', '..', '..', 'templates', 'project', 'App', 'config.xml'); + /** * Verifies that some of the project file exists. Not all will be tested. * E.g. App's resource directory, xcodeproj, xcworkspace, and CordovaLib. @@ -82,6 +85,15 @@ function verifyProjectBundleIdentifier (tmpDir, projectName, expectedBundleIdent expect(actualBundleName).toBe(`"${projectName}"`); } +function verifyProjectDeploymentTarget (tmpDir, expectedTarget) { + const pbxproj = path.join(tmpDir, 'App.xcodeproj', 'project.pbxproj'); + const xcodeproj = xcode.project(pbxproj); + xcodeproj.parseSync(); + + const actualDeploymentTarget = xcodeproj.getBuildProperty('IPHONEOS_DEPLOYMENT_TARGET'); + expect(actualDeploymentTarget).toBe(expectedTarget); +} + /** * Runs various project creation checks. * @@ -90,8 +102,10 @@ function verifyProjectBundleIdentifier (tmpDir, projectName, expectedBundleIdent * @param {String} projectName * @returns {Promise} */ -async function verifyCreatedProject (tmpDir, packageName, projectName) { - await create.createProject(tmpDir, packageName, projectName, {}, undefined) +async function verifyCreatedProject (tmpDir, packageName, projectName, configFile = defaultConfigXmlPath) { + const configXml = new ConfigParser(configFile); + + await create.createProject(tmpDir, packageName, projectName, {}, configXml) .then(() => verifyProjectFiles(tmpDir, projectName)) .then(() => verifyProjectBundleIdentifier(tmpDir, projectName, packageName)); } @@ -118,4 +132,13 @@ describe('create', () => { const projectName = '応応応応 hello & إثرا 用用用用'; return verifyCreatedProject(tmpDir, packageName, projectName); }); + + it('should copy config.xml into the newly created project', () => { + const configPath = path.join(__dirname, 'fixtures', 'test-config-3.xml'); + const packageName = 'io.cordova.hellocordova.ios'; + const projectName = 'Hello Cordova'; + + return verifyCreatedProject(tmpDir, packageName, projectName, configPath) + .then(() => verifyProjectDeploymentTarget(tmpDir, '15.0')); + }); }); diff --git a/tests/spec/unit/fixtures/test-config-3.xml b/tests/spec/unit/fixtures/test-config-3.xml index ac7f73061..dae557f8d 100644 --- a/tests/spec/unit/fixtures/test-config-3.xml +++ b/tests/spec/unit/fixtures/test-config-3.xml @@ -12,7 +12,7 @@ - +