Skip to content

Commit 9e6c839

Browse files
committed
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
1 parent e8e126a commit 9e6c839

File tree

6 files changed

+102
-15
lines changed

6 files changed

+102
-15
lines changed

lib/definitions/platform.d.ts

+16
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,15 @@ interface IPlatformService extends IBuildPlatformAction, NodeJS.EventEmitter {
8383
*/
8484
shouldInstall(device: Mobile.IDevice, projectData: IProjectData, release: IRelease, outputPath?: string): Promise<boolean>;
8585

86+
/**
87+
*
88+
* @param {Mobile.IDevice} device The device where the application should be installed.
89+
* @param {IProjectData} projectData DTO with information about the project.
90+
* @param {string} @optional outputPath Directory containing build information and artifacts.
91+
* @returns {Promise<boolean>} true indicates that the application should be installed.
92+
*/
93+
validateInstall(device: Mobile.IDevice, projectData: IProjectData, release: IRelease, outputPath?: string): Promise<void>;
94+
8695
/**
8796
* Determines whether the project should undergo the prepare process.
8897
* @param {IShouldPrepareInfo} shouldPrepareInfo Options needed to decide whether to prepare.
@@ -307,6 +316,13 @@ interface INodeModulesDependenciesBuilder {
307316
interface IBuildInfo {
308317
prepareTime: string;
309318
buildTime: string;
319+
/**
320+
* Currently it is used only for iOS.
321+
* As `xcrun` command does not throw an error when IPHONEOS_DEPLOYMENT_TARGET is provided in `xcconfig` file and
322+
* the simulator's version does not match IPHONEOS_DEPLOYMENT_TARGET's value, we need to save it to buildInfo file
323+
* in order check it on livesync and throw an error to the user.
324+
*/
325+
deploymentTarget?: string;
310326
}
311327

312328
interface IPlatformDataComposition {

lib/definitions/project.d.ts

+21
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,27 @@ interface IPlatformProjectService extends NodeJS.EventEmitter, IPlatformProjectS
444444
* Traverse through the production dependencies and find plugins that need build/rebuild
445445
*/
446446
checkIfPluginsNeedBuild(projectData: IProjectData): Promise<Array<any>>;
447+
448+
/**
449+
* Get the deployment target's version
450+
* Currently implemented only for iOS -> returns the value of IPHONEOS_DEPLOYMENT_TARGET property from xcconfig file
451+
*/
452+
getDeploymentTarget(projectData: IProjectData): IDeploymentTargetData;
453+
}
454+
455+
interface IDeploymentTargetData {
456+
/**
457+
* The whole version's value
458+
*/
459+
version: string;
460+
/**
461+
* The major's version
462+
*/
463+
majorVersion: number;
464+
/**
465+
* The minor's version
466+
*/
467+
minorVersion: number;
447468
}
448469

449470
interface IValidatePlatformOutput {

lib/services/android-project-service.ts

+2
Original file line numberDiff line numberDiff line change
@@ -665,6 +665,8 @@ export class AndroidProjectService extends projectServiceBaseLib.PlatformProject
665665
// Nothing android specific to check yet.
666666
}
667667

668+
public getDeploymentTarget(projectData: IProjectData): IDeploymentTargetData { return; }
669+
668670
private copy(projectRoot: string, frameworkDir: string, files: string, cpArg: string): void {
669671
const paths = files.split(' ').map(p => path.join(frameworkDir, p));
670672
shell.cp(cpArg, paths, projectRoot);

lib/services/ios-project-service.ts

+41-13
Original file line numberDiff line numberDiff line change
@@ -384,12 +384,6 @@ export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServ
384384
}
385385

386386
private async buildForDevice(projectRoot: string, args: string[], buildConfig: IBuildConfig, projectData: IProjectData): Promise<void> {
387-
const defaultArchitectures = [
388-
'ARCHS=armv7 arm64',
389-
'VALID_ARCHS=armv7 arm64'
390-
];
391-
392-
// build only for device specific architecture
393387
if (!buildConfig.release && !buildConfig.architectures) {
394388
await this.$devicesService.initialize({
395389
platform: this.$devicePlatformsConstants.iOS.toLowerCase(), deviceId: buildConfig.device,
@@ -402,18 +396,15 @@ export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServ
402396
.uniq()
403397
.value();
404398
if (devicesArchitectures.length > 0) {
405-
const architectures = [
406-
`ARCHS=${devicesArchitectures.join(" ")}`,
407-
`VALID_ARCHS=${devicesArchitectures.join(" ")}`
408-
];
399+
const architectures = this.getBuildArchitectures(projectData, buildConfig, devicesArchitectures);
409400
if (devicesArchitectures.length > 1) {
410401
architectures.push('ONLY_ACTIVE_ARCH=NO');
411402
}
412403
buildConfig.architectures = architectures;
413404
}
414405
}
415406

416-
args = args.concat((buildConfig && buildConfig.architectures) || defaultArchitectures);
407+
args = args.concat((buildConfig && buildConfig.architectures) || this.getBuildArchitectures(projectData, buildConfig, ["armv7", "arm64"]));
417408

418409
args = args.concat([
419410
"-sdk", "iphoneos",
@@ -457,6 +448,28 @@ export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServ
457448
return commandResult;
458449
}
459450

451+
private getBuildArchitectures(projectData: IProjectData, buildConfig: IBuildConfig, architectures: string[]): string[] {
452+
let result: string[] = [];
453+
454+
const frameworkVersion = this.getFrameworkVersion(projectData);
455+
if (semver.valid(frameworkVersion) && semver.validRange(frameworkVersion) && semver.lt(semver.coerce(frameworkVersion), "5.1.0")) {
456+
const target = this.getDeploymentTarget(projectData);
457+
if (target && target.majorVersion >= 11) {
458+
// We need to strip 32bit architectures as of deployment target >= 11 it is not allowed to have such
459+
architectures = _.filter(architectures, arch => {
460+
const is64BitArchitecture = arch === "x86_64" || arch === "arm64";
461+
if (!is64BitArchitecture) {
462+
this.$logger.warn(`The architecture ${arch} will be stripped as it is not supported for deployment target ${target.version}.`);
463+
}
464+
return is64BitArchitecture;
465+
});
466+
}
467+
result = [`ARCHS=${architectures.join(" ")}`, `VALID_ARCHS=${architectures.join(" ")}`];
468+
}
469+
470+
return result;
471+
}
472+
460473
private async setupSigningFromTeam(projectRoot: string, projectData: IProjectData, teamId: string) {
461474
const xcode = this.$pbxprojDomXcode.Xcode.open(this.getPbxProjPath(projectData));
462475
const signing = xcode.getSigning(projectData.projectName);
@@ -555,13 +568,14 @@ export class IOSProjectService extends projectServiceBaseLib.PlatformProjectServ
555568
}
556569

557570
private async buildForSimulator(projectRoot: string, args: string[], projectData: IProjectData, buildConfig?: IBuildConfig): Promise<void> {
571+
const architectures = this.getBuildArchitectures(projectData, buildConfig, ["i386", "x86_64"]);
572+
558573
args = args
574+
.concat(architectures)
559575
.concat([
560576
"build",
561577
"-configuration", buildConfig.release ? "Release" : "Debug",
562578
"-sdk", "iphonesimulator",
563-
"ARCHS=i386 x86_64",
564-
"VALID_ARCHS=i386 x86_64",
565579
"ONLY_ACTIVE_ARCH=NO",
566580
"CONFIGURATION_BUILD_DIR=" + path.join(projectRoot, "build", "emulator"),
567581
"CODE_SIGN_IDENTITY=",
@@ -1031,6 +1045,20 @@ We will now place an empty obsolete compatability white screen LauncScreen.xib f
10311045
return [];
10321046
}
10331047

1048+
public getDeploymentTarget(projectData: IProjectData): IDeploymentTargetData {
1049+
const target = this.$xCConfigService.readPropertyValue(this.getBuildXCConfigFilePath(projectData), "IPHONEOS_DEPLOYMENT_TARGET");
1050+
if (!target) {
1051+
return null;
1052+
}
1053+
1054+
const parts = target.split(".");
1055+
return {
1056+
version: target,
1057+
majorVersion: parseInt(parts[0]),
1058+
minorVersion: parseInt(parts[1])
1059+
};
1060+
}
1061+
10341062
private getAllLibsForPluginWithFileExtension(pluginData: IPluginData, fileExtension: string): string[] {
10351063
const filterCallback = (fileName: string, pluginPlatformsFolderPath: string) => path.extname(fileName) === fileExtension;
10361064
return this.getAllNativeLibrariesForPlugin(pluginData, IOSProjectService.IOS_PLATFORM_NAME, filterCallback);

lib/services/livesync/livesync-service.ts

+1
Original file line numberDiff line numberDiff line change
@@ -463,6 +463,7 @@ export class LiveSyncService extends EventEmitter implements IDebugLiveSyncServi
463463
});
464464
}
465465

466+
await this.$platformService.validateInstall(options.device, options.projectData, options, options.deviceBuildInfoDescriptor.outputPath);
466467
const shouldInstall = await this.$platformService.shouldInstall(options.device, options.projectData, options, options.deviceBuildInfoDescriptor.outputPath);
467468
if (shouldInstall) {
468469
await this.$platformService.installApplication(options.device, { release: false }, options.projectData, pathToBuildItem, options.deviceBuildInfoDescriptor.outputPath);

lib/services/platform-service.ts

+21-2
Original file line numberDiff line numberDiff line change
@@ -436,13 +436,20 @@ export class PlatformService extends EventEmitter implements IPlatformService {
436436

437437
public saveBuildInfoFile(platform: string, projectDir: string, buildInfoFileDirname: string): void {
438438
const buildInfoFile = path.join(buildInfoFileDirname, buildInfoFileName);
439+
const projectData = this.$projectDataService.getProjectData(projectDir);
440+
const platformData = this.$platformsData.getPlatformData(platform, projectData);
439441

440-
const prepareInfo = this.$projectChangesService.getPrepareInfo(platform, this.$projectDataService.getProjectData(projectDir));
441-
const buildInfo = {
442+
const prepareInfo = this.$projectChangesService.getPrepareInfo(platform, projectData);
443+
const buildInfo: IBuildInfo = {
442444
prepareTime: prepareInfo.changesRequireBuildTime,
443445
buildTime: new Date().toString()
444446
};
445447

448+
const deploymentTarget = platformData.platformProjectService.getDeploymentTarget(projectData);
449+
if (deploymentTarget) {
450+
buildInfo.deploymentTarget = deploymentTarget.version;
451+
}
452+
446453
this.$fs.writeJson(buildInfoFile, buildInfo);
447454
}
448455

@@ -455,9 +462,21 @@ export class PlatformService extends EventEmitter implements IPlatformService {
455462
const platformData = this.$platformsData.getPlatformData(platform, projectData);
456463
const deviceBuildInfo: IBuildInfo = await this.getDeviceBuildInfo(device, projectData);
457464
const localBuildInfo = this.getBuildInfo(platform, platformData, { buildForDevice: !device.isEmulator, release: release.release }, outputPath);
465+
458466
return !localBuildInfo || !deviceBuildInfo || deviceBuildInfo.buildTime !== localBuildInfo.buildTime;
459467
}
460468

469+
public async validateInstall(device: Mobile.IDevice, projectData: IProjectData, release: IRelease, outputPath?: string): Promise<void> {
470+
const platform = device.deviceInfo.platform;
471+
const platformData = this.$platformsData.getPlatformData(platform, projectData);
472+
const localBuildInfo = this.getBuildInfo(device.deviceInfo.platform, platformData, { buildForDevice: !device.isEmulator, release: release.release }, outputPath);
473+
if (localBuildInfo.deploymentTarget) {
474+
if (semver.lt(semver.coerce(device.deviceInfo.version), semver.coerce(localBuildInfo.deploymentTarget))) {
475+
this.$errors.fail(`Unable to install on device with version ${device.deviceInfo.version} as deployment target is ${localBuildInfo.deploymentTarget}`);
476+
}
477+
}
478+
}
479+
461480
public async installApplication(device: Mobile.IDevice, buildConfig: IBuildConfig, projectData: IProjectData, packageFile?: string, outputFilePath?: string): Promise<void> {
462481
this.$logger.out(`Installing on device ${device.deviceInfo.identifier}...`);
463482

0 commit comments

Comments
 (0)