From 9e6c839be0fbd36d6728dac688c86d705c144d79 Mon Sep 17 00:00:00 2001 From: fatme Date: Wed, 5 Dec 2018 16:13:05 +0200 Subject: [PATCH 1/5] fix: don't pass VALID_ARCHS and ARCHS to xcodebuild command Don't pass VALID_ARCHS and ARCHS to xcodebuild command in order to allow user to specify them from `build.xcconfig` file --- lib/definitions/platform.d.ts | 16 +++++++ lib/definitions/project.d.ts | 21 +++++++++ lib/services/android-project-service.ts | 2 + lib/services/ios-project-service.ts | 54 +++++++++++++++++------ lib/services/livesync/livesync-service.ts | 1 + lib/services/platform-service.ts | 23 +++++++++- 6 files changed, 102 insertions(+), 15 deletions(-) diff --git a/lib/definitions/platform.d.ts b/lib/definitions/platform.d.ts index cd6dd4a31e..2e6ecf8362 100644 --- a/lib/definitions/platform.d.ts +++ b/lib/definitions/platform.d.ts @@ -83,6 +83,15 @@ interface IPlatformService extends IBuildPlatformAction, NodeJS.EventEmitter { */ shouldInstall(device: Mobile.IDevice, projectData: IProjectData, release: IRelease, outputPath?: string): Promise; + /** + * + * @param {Mobile.IDevice} device The device where the application should be installed. + * @param {IProjectData} projectData DTO with information about the project. + * @param {string} @optional outputPath Directory containing build information and artifacts. + * @returns {Promise} true indicates that the application should be installed. + */ + validateInstall(device: Mobile.IDevice, projectData: IProjectData, release: IRelease, outputPath?: string): Promise; + /** * Determines whether the project should undergo the prepare process. * @param {IShouldPrepareInfo} shouldPrepareInfo Options needed to decide whether to prepare. @@ -307,6 +316,13 @@ interface INodeModulesDependenciesBuilder { interface IBuildInfo { prepareTime: string; buildTime: string; + /** + * Currently it is used only for iOS. + * As `xcrun` command does not throw an error when IPHONEOS_DEPLOYMENT_TARGET is provided in `xcconfig` file and + * the simulator's version does not match IPHONEOS_DEPLOYMENT_TARGET's value, we need to save it to buildInfo file + * in order check it on livesync and throw an error to the user. + */ + deploymentTarget?: string; } interface IPlatformDataComposition { diff --git a/lib/definitions/project.d.ts b/lib/definitions/project.d.ts index d7a2aac13d..48a5ac7176 100644 --- a/lib/definitions/project.d.ts +++ b/lib/definitions/project.d.ts @@ -444,6 +444,27 @@ interface IPlatformProjectService extends NodeJS.EventEmitter, IPlatformProjectS * Traverse through the production dependencies and find plugins that need build/rebuild */ checkIfPluginsNeedBuild(projectData: IProjectData): Promise>; + + /** + * Get the deployment target's version + * Currently implemented only for iOS -> returns the value of IPHONEOS_DEPLOYMENT_TARGET property from xcconfig file + */ + getDeploymentTarget(projectData: IProjectData): IDeploymentTargetData; +} + +interface IDeploymentTargetData { + /** + * The whole version's value + */ + version: string; + /** + * The major's version + */ + majorVersion: number; + /** + * The minor's version + */ + minorVersion: number; } interface IValidatePlatformOutput { diff --git a/lib/services/android-project-service.ts b/lib/services/android-project-service.ts index 5c7a3f1ea3..e6aa935fab 100644 --- a/lib/services/android-project-service.ts +++ b/lib/services/android-project-service.ts @@ -665,6 +665,8 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject // Nothing android specific to check yet. } + public getDeploymentTarget(projectData: IProjectData): IDeploymentTargetData { return; } + private copy(projectRoot: string, frameworkDir: string, files: string, cpArg: string): void { const paths = files.split(' ').map(p => path.join(frameworkDir, p)); shell.cp(cpArg, paths, projectRoot); diff --git a/lib/services/ios-project-service.ts b/lib/services/ios-project-service.ts index 2335342b8e..a1079f6080 100644 --- a/lib/services/ios-project-service.ts +++ b/lib/services/ios-project-service.ts @@ -384,12 +384,6 @@ export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServ } private async buildForDevice(projectRoot: string, args: string[], buildConfig: IBuildConfig, projectData: IProjectData): Promise { - const defaultArchitectures = [ - 'ARCHS=armv7 arm64', - 'VALID_ARCHS=armv7 arm64' - ]; - - // build only for device specific architecture if (!buildConfig.release && !buildConfig.architectures) { await this.$devicesService.initialize({ platform: this.$devicePlatformsConstants.iOS.toLowerCase(), deviceId: buildConfig.device, @@ -402,10 +396,7 @@ export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServ .uniq() .value(); if (devicesArchitectures.length > 0) { - const architectures = [ - `ARCHS=${devicesArchitectures.join(" ")}`, - `VALID_ARCHS=${devicesArchitectures.join(" ")}` - ]; + const architectures = this.getBuildArchitectures(projectData, buildConfig, devicesArchitectures); if (devicesArchitectures.length > 1) { architectures.push('ONLY_ACTIVE_ARCH=NO'); } @@ -413,7 +404,7 @@ export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServ } } - args = args.concat((buildConfig && buildConfig.architectures) || defaultArchitectures); + args = args.concat((buildConfig && buildConfig.architectures) || this.getBuildArchitectures(projectData, buildConfig, ["armv7", "arm64"])); args = args.concat([ "-sdk", "iphoneos", @@ -457,6 +448,28 @@ export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServ return commandResult; } + private getBuildArchitectures(projectData: IProjectData, buildConfig: IBuildConfig, architectures: string[]): string[] { + let result: string[] = []; + + const frameworkVersion = this.getFrameworkVersion(projectData); + if (semver.valid(frameworkVersion) && semver.validRange(frameworkVersion) && semver.lt(semver.coerce(frameworkVersion), "5.1.0")) { + const target = this.getDeploymentTarget(projectData); + if (target && target.majorVersion >= 11) { + // We need to strip 32bit architectures as of deployment target >= 11 it is not allowed to have such + architectures = _.filter(architectures, arch => { + const is64BitArchitecture = arch === "x86_64" || arch === "arm64"; + if (!is64BitArchitecture) { + this.$logger.warn(`The architecture ${arch} will be stripped as it is not supported for deployment target ${target.version}.`); + } + return is64BitArchitecture; + }); + } + result = [`ARCHS=${architectures.join(" ")}`, `VALID_ARCHS=${architectures.join(" ")}`]; + } + + return result; + } + private async setupSigningFromTeam(projectRoot: string, projectData: IProjectData, teamId: string) { const xcode = this.$pbxprojDomXcode.Xcode.open(this.getPbxProjPath(projectData)); const signing = xcode.getSigning(projectData.projectName); @@ -555,13 +568,14 @@ export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServ } private async buildForSimulator(projectRoot: string, args: string[], projectData: IProjectData, buildConfig?: IBuildConfig): Promise { + const architectures = this.getBuildArchitectures(projectData, buildConfig, ["i386", "x86_64"]); + args = args + .concat(architectures) .concat([ "build", "-configuration", buildConfig.release ? "Release" : "Debug", "-sdk", "iphonesimulator", - "ARCHS=i386 x86_64", - "VALID_ARCHS=i386 x86_64", "ONLY_ACTIVE_ARCH=NO", "CONFIGURATION_BUILD_DIR=" + path.join(projectRoot, "build", "emulator"), "CODE_SIGN_IDENTITY=", @@ -1031,6 +1045,20 @@ We will now place an empty obsolete compatability white screen LauncScreen.xib f return []; } + public getDeploymentTarget(projectData: IProjectData): IDeploymentTargetData { + const target = this.$xCConfigService.readPropertyValue(this.getBuildXCConfigFilePath(projectData), "IPHONEOS_DEPLOYMENT_TARGET"); + if (!target) { + return null; + } + + const parts = target.split("."); + return { + version: target, + majorVersion: parseInt(parts[0]), + minorVersion: parseInt(parts[1]) + }; + } + private getAllLibsForPluginWithFileExtension(pluginData: IPluginData, fileExtension: string): string[] { const filterCallback = (fileName: string, pluginPlatformsFolderPath: string) => path.extname(fileName) === fileExtension; return this.getAllNativeLibrariesForPlugin(pluginData, IOSProjectService.IOS_PLATFORM_NAME, filterCallback); diff --git a/lib/services/livesync/livesync-service.ts b/lib/services/livesync/livesync-service.ts index 7ee71b5947..9a0768dff5 100644 --- a/lib/services/livesync/livesync-service.ts +++ b/lib/services/livesync/livesync-service.ts @@ -463,6 +463,7 @@ export class LiveSyncService extends EventEmitter implements IDebugLiveSyncServi }); } + await this.$platformService.validateInstall(options.device, options.projectData, options, options.deviceBuildInfoDescriptor.outputPath); const shouldInstall = await this.$platformService.shouldInstall(options.device, options.projectData, options, options.deviceBuildInfoDescriptor.outputPath); if (shouldInstall) { await this.$platformService.installApplication(options.device, { release: false }, options.projectData, pathToBuildItem, options.deviceBuildInfoDescriptor.outputPath); diff --git a/lib/services/platform-service.ts b/lib/services/platform-service.ts index d46fc27e6f..2a433e55c0 100644 --- a/lib/services/platform-service.ts +++ b/lib/services/platform-service.ts @@ -436,13 +436,20 @@ export class PlatformService extends EventEmitter implements IPlatformService { public saveBuildInfoFile(platform: string, projectDir: string, buildInfoFileDirname: string): void { const buildInfoFile = path.join(buildInfoFileDirname, buildInfoFileName); + const projectData = this.$projectDataService.getProjectData(projectDir); + const platformData = this.$platformsData.getPlatformData(platform, projectData); - const prepareInfo = this.$projectChangesService.getPrepareInfo(platform, this.$projectDataService.getProjectData(projectDir)); - const buildInfo = { + const prepareInfo = this.$projectChangesService.getPrepareInfo(platform, projectData); + const buildInfo: IBuildInfo = { prepareTime: prepareInfo.changesRequireBuildTime, buildTime: new Date().toString() }; + const deploymentTarget = platformData.platformProjectService.getDeploymentTarget(projectData); + if (deploymentTarget) { + buildInfo.deploymentTarget = deploymentTarget.version; + } + this.$fs.writeJson(buildInfoFile, buildInfo); } @@ -455,9 +462,21 @@ export class PlatformService extends EventEmitter implements IPlatformService { const platformData = this.$platformsData.getPlatformData(platform, projectData); const deviceBuildInfo: IBuildInfo = await this.getDeviceBuildInfo(device, projectData); const localBuildInfo = this.getBuildInfo(platform, platformData, { buildForDevice: !device.isEmulator, release: release.release }, outputPath); + return !localBuildInfo || !deviceBuildInfo || deviceBuildInfo.buildTime !== localBuildInfo.buildTime; } + public async validateInstall(device: Mobile.IDevice, projectData: IProjectData, release: IRelease, outputPath?: string): Promise { + const platform = device.deviceInfo.platform; + const platformData = this.$platformsData.getPlatformData(platform, projectData); + const localBuildInfo = this.getBuildInfo(device.deviceInfo.platform, platformData, { buildForDevice: !device.isEmulator, release: release.release }, outputPath); + if (localBuildInfo.deploymentTarget) { + if (semver.lt(semver.coerce(device.deviceInfo.version), semver.coerce(localBuildInfo.deploymentTarget))) { + this.$errors.fail(`Unable to install on device with version ${device.deviceInfo.version} as deployment target is ${localBuildInfo.deploymentTarget}`); + } + } + } + public async installApplication(device: Mobile.IDevice, buildConfig: IBuildConfig, projectData: IProjectData, packageFile?: string, outputFilePath?: string): Promise { this.$logger.out(`Installing on device ${device.deviceInfo.identifier}...`); From 13cad6ac070c533c250c907155c50004c09d83fe Mon Sep 17 00:00:00 2001 From: fatme Date: Wed, 5 Dec 2018 16:13:47 +0200 Subject: [PATCH 2/5] fix: add unit tests --- test/ios-project-service.ts | 125 ++++++++++++++++++++++++++++++++++++ test/stubs.ts | 7 ++ 2 files changed, 132 insertions(+) diff --git a/test/ios-project-service.ts b/test/ios-project-service.ts index f6431d517a..452dd22edb 100644 --- a/test/ios-project-service.ts +++ b/test/ios-project-service.ts @@ -1055,3 +1055,128 @@ describe("Merge Project XCConfig files", () => { } }); }); + +describe("buildProject", () => { + let xcodeBuildCommandArgs: string[] = []; + + function setup(data: { frameworkVersion: string, deploymentTarget: string, devices?: Mobile.IDevice[] }): IInjector { + const projectPath = "myTestProjectPath"; + const projectName = "myTestProjectName"; + const testInjector = createTestInjector(projectPath, projectName); + + const childProcess = testInjector.resolve("childProcess"); + childProcess.spawnFromEvent = (command: string, args: string[]) => { + if (command === "xcodebuild" && args[0] !== "-exportArchive") { + xcodeBuildCommandArgs = args; + } + }; + + const projectDataService = testInjector.resolve("projectDataService"); + projectDataService.getNSValue = (projectDir: string, propertyName: string) => { + if (propertyName === "tns-ios") { + return { + name: "tns-ios", + version: data.frameworkVersion + }; + } + }; + + const projectData = testInjector.resolve("projectData"); + projectData.appResourcesDirectoryPath = path.join(projectPath, "app", "App_Resources"); + + const devicesService = testInjector.resolve("devicesService"); + devicesService.initialize = () => ({}); + devicesService.getDeviceInstances = () => data.devices || []; + + const xCConfigService = testInjector.resolve("xCConfigService"); + xCConfigService.readPropertyValue = (projectDir: string, propertyName: string) => { + if (propertyName === "IPHONEOS_DEPLOYMENT_TARGET") { + return data.deploymentTarget; + } + }; + + const pbxprojDomXcode = testInjector.resolve("pbxprojDomXcode"); + pbxprojDomXcode.Xcode = { + open: () => ({ + getSigning: () => ({}), + setAutomaticSigningStyle: () => ({}), + save: () => ({}) + }) + }; + + const iOSProvisionService = testInjector.resolve("iOSProvisionService"); + iOSProvisionService.getDevelopmentTeams = () => ({}); + iOSProvisionService.getTeamIdsWithName = () => ({}); + + return testInjector; + } + + function executeTests(testCases: any[], data: { buildForDevice: boolean }) { + _.each(testCases, testCase => { + it(`${testCase.name}`, async () => { + const testInjector = setup({ frameworkVersion: testCase.frameworkVersion, deploymentTarget: testCase.deploymentTarget }); + const projectData: IProjectData = testInjector.resolve("projectData"); + + const iOSProjectService = testInjector.resolve("iOSProjectService"); + (iOSProjectService).getExportOptionsMethod = () => ({}); + await iOSProjectService.buildProject("myProjectRoot", projectData, { buildForDevice: data.buildForDevice }); + + const archsItem = xcodeBuildCommandArgs.find(item => item.startsWith("ARCHS=")); + if (testCase.expectedArchs) { + const archsValue = archsItem.split("=")[1]; + assert.deepEqual(archsValue, testCase.expectedArchs); + } else { + assert.deepEqual(undefined, archsItem); + } + }); + }); + } + + describe("for device", () => { + afterEach(() => { + xcodeBuildCommandArgs = []; + }); + + const testCases = [{ + name: "shouldn't exclude armv7 architecture when deployment target 10", + frameworkVersion: "5.0.0", + deploymentTarget: "10.0", + expectedArchs: "armv7 arm64" + }, { + name: "should exclude armv7 architecture when deployment target is 11", + frameworkVersion: "5.0.0", + deploymentTarget: "11.0", + expectedArchs: "arm64" + }, { + name: "shouldn't pass architecture to xcodebuild command when frameworkVersion is 5.1.0", + frameworkVersion: "5.1.0", + deploymentTarget: "11.0" + }]; + + executeTests(testCases, { buildForDevice: true }); + }); + + describe("for simulator", () => { + afterEach(() => { + xcodeBuildCommandArgs = []; + }); + + const testCases = [{ + name: "shouldn't exclude i386 architecture when deployment target is 10", + frameworkVersion: "5.0.0", + deploymentTarget: "10.0", + expectedArchs: "i386 x86_64" + }, { + name: "should exclude i386 architecture when deployment target is 11", + frameworkVersion: "5.0.0", + deploymentTarget: "11.0", + expectedArchs: "x86_64" + }, { + name: "shouldn't pass architecture to xcodebuild command when frameworkVersion is 5.1.0", + frameworkVersion: "5.1.0", + deploymentTarget: "11.0" + }]; + + executeTests(testCases, { buildForDevice: false }); + }); +}); diff --git a/test/stubs.ts b/test/stubs.ts index 851431106f..f09c8fc6f2 100644 --- a/test/stubs.ts +++ b/test/stubs.ts @@ -467,6 +467,9 @@ export class PlatformProjectServiceStub extends EventEmitter implements IPlatfor getPluginPlatformsFolderPath(pluginData: IPluginData, platform: string): string { return ""; } + getDeploymentTarget(projectData: IProjectData): IDeploymentTargetData { + return; + } } export class PlatformsDataStub extends EventEmitter implements IPlatformsData { @@ -828,6 +831,10 @@ export class PlatformServiceStub extends EventEmitter implements IPlatformServic return true; } + public async validateInstall(device: Mobile.IDevice): Promise { + return; + } + public installApplication(device: Mobile.IDevice, options: IRelease): Promise { return Promise.resolve(); } From f2c72758daed7aa8a7471ed41d5388d61e8ff063 Mon Sep 17 00:00:00 2001 From: fatme Date: Wed, 5 Dec 2018 16:18:03 +0200 Subject: [PATCH 3/5] chore: fix the comment --- lib/definitions/platform.d.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/definitions/platform.d.ts b/lib/definitions/platform.d.ts index 2e6ecf8362..2fe9bdd2f9 100644 --- a/lib/definitions/platform.d.ts +++ b/lib/definitions/platform.d.ts @@ -88,7 +88,6 @@ interface IPlatformService extends IBuildPlatformAction, NodeJS.EventEmitter { * @param {Mobile.IDevice} device The device where the application should be installed. * @param {IProjectData} projectData DTO with information about the project. * @param {string} @optional outputPath Directory containing build information and artifacts. - * @returns {Promise} true indicates that the application should be installed. */ validateInstall(device: Mobile.IDevice, projectData: IProjectData, release: IRelease, outputPath?: string): Promise; From 5574fc502c0e3cca456b7bdd7718110c27a36a8d Mon Sep 17 00:00:00 2001 From: fatme Date: Thu, 6 Dec 2018 08:26:24 +0200 Subject: [PATCH 4/5] chore: add more unit tests --- test/ios-project-service.ts | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/test/ios-project-service.ts b/test/ios-project-service.ts index 452dd22edb..93c9ab6a5c 100644 --- a/test/ios-project-service.ts +++ b/test/ios-project-service.ts @@ -1151,6 +1151,21 @@ describe("buildProject", () => { name: "shouldn't pass architecture to xcodebuild command when frameworkVersion is 5.1.0", frameworkVersion: "5.1.0", deploymentTarget: "11.0" + }, { + name: "should pass only 64bit architecture to xcodebuild command when frameworkVersion is 5.0.0 and deployment target is 11.0", + frameworkVersion: "5.0.0", + deploymentTarget: "11.0", + expectedArchs: "arm64" + }, { + name: "should pass both architectures to xcodebuild command when frameworkVersion is 5.0.0 and deployment target is 10.0", + frameworkVersion: "5.0.0", + deploymentTarget: "10.0", + expectedArchs: "armv7 arm64" + }, { + name: "should pass both architectures to xcodebuild command when frameworkVersion is 5.0.0 and no deployment target", + frameworkVersion: "5.0.0", + deploymentTarget: null, + expectedArchs: "armv7 arm64" }]; executeTests(testCases, { buildForDevice: true }); @@ -1175,6 +1190,21 @@ describe("buildProject", () => { name: "shouldn't pass architecture to xcodebuild command when frameworkVersion is 5.1.0", frameworkVersion: "5.1.0", deploymentTarget: "11.0" + }, { + name: "should pass only 64bit architecture to xcodebuild command when frameworkVersion is 5.0.0 and deployment target is 11.0", + frameworkVersion: "5.0.0", + deploymentTarget: "11.0", + expectedArchs: "x86_64" + }, { + name: "should pass both architectures to xcodebuild command when frameworkVersion is 5.0.0 and deployment target is 10.0", + frameworkVersion: "5.0.0", + deploymentTarget: "10.0", + expectedArchs: "i386 x86_64" + }, { + name: "should pass both architectures to xcodebuild command when frameworkVersion is 5.0.0 and no deployment target", + frameworkVersion: "5.0.0", + deploymentTarget: null, + expectedArchs: "i386 x86_64" }]; executeTests(testCases, { buildForDevice: false }); From a2a235cd5b5b9bee452a19b8687005f0089056b1 Mon Sep 17 00:00:00 2001 From: fatme Date: Thu, 6 Dec 2018 13:35:48 +0200 Subject: [PATCH 5/5] chore: remove IDeploymentTarget interface --- lib/definitions/project.d.ts | 17 +---------------- lib/services/android-project-service.ts | 2 +- lib/services/ios-project-service.ts | 11 +++-------- test/stubs.ts | 2 +- 4 files changed, 6 insertions(+), 26 deletions(-) diff --git a/lib/definitions/project.d.ts b/lib/definitions/project.d.ts index 48a5ac7176..bfd818b754 100644 --- a/lib/definitions/project.d.ts +++ b/lib/definitions/project.d.ts @@ -449,22 +449,7 @@ interface IPlatformProjectService extends NodeJS.EventEmitter, IPlatformProjectS * Get the deployment target's version * Currently implemented only for iOS -> returns the value of IPHONEOS_DEPLOYMENT_TARGET property from xcconfig file */ - getDeploymentTarget(projectData: IProjectData): IDeploymentTargetData; -} - -interface IDeploymentTargetData { - /** - * The whole version's value - */ - version: string; - /** - * The major's version - */ - majorVersion: number; - /** - * The minor's version - */ - minorVersion: number; + getDeploymentTarget(projectData: IProjectData): any; } interface IValidatePlatformOutput { diff --git a/lib/services/android-project-service.ts b/lib/services/android-project-service.ts index e6aa935fab..c8cfd0062a 100644 --- a/lib/services/android-project-service.ts +++ b/lib/services/android-project-service.ts @@ -665,7 +665,7 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject // Nothing android specific to check yet. } - public getDeploymentTarget(projectData: IProjectData): IDeploymentTargetData { return; } + public getDeploymentTarget(projectData: IProjectData): semver.SemVer { return; } private copy(projectRoot: string, frameworkDir: string, files: string, cpArg: string): void { const paths = files.split(' ').map(p => path.join(frameworkDir, p)); diff --git a/lib/services/ios-project-service.ts b/lib/services/ios-project-service.ts index a1079f6080..f78022d11e 100644 --- a/lib/services/ios-project-service.ts +++ b/lib/services/ios-project-service.ts @@ -454,7 +454,7 @@ export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServ const frameworkVersion = this.getFrameworkVersion(projectData); if (semver.valid(frameworkVersion) && semver.validRange(frameworkVersion) && semver.lt(semver.coerce(frameworkVersion), "5.1.0")) { const target = this.getDeploymentTarget(projectData); - if (target && target.majorVersion >= 11) { + if (target && target.major >= 11) { // We need to strip 32bit architectures as of deployment target >= 11 it is not allowed to have such architectures = _.filter(architectures, arch => { const is64BitArchitecture = arch === "x86_64" || arch === "arm64"; @@ -1045,18 +1045,13 @@ We will now place an empty obsolete compatability white screen LauncScreen.xib f return []; } - public getDeploymentTarget(projectData: IProjectData): IDeploymentTargetData { + public getDeploymentTarget(projectData: IProjectData): semver.SemVer { const target = this.$xCConfigService.readPropertyValue(this.getBuildXCConfigFilePath(projectData), "IPHONEOS_DEPLOYMENT_TARGET"); if (!target) { return null; } - const parts = target.split("."); - return { - version: target, - majorVersion: parseInt(parts[0]), - minorVersion: parseInt(parts[1]) - }; + return semver.coerce(target); } private getAllLibsForPluginWithFileExtension(pluginData: IPluginData, fileExtension: string): string[] { diff --git a/test/stubs.ts b/test/stubs.ts index f09c8fc6f2..f52e4769e9 100644 --- a/test/stubs.ts +++ b/test/stubs.ts @@ -467,7 +467,7 @@ export class PlatformProjectServiceStub extends EventEmitter implements IPlatfor getPluginPlatformsFolderPath(pluginData: IPluginData, platform: string): string { return ""; } - getDeploymentTarget(projectData: IProjectData): IDeploymentTargetData { + getDeploymentTarget(projectData: IProjectData): any { return; } }