in lib/build.js [150:321]
module.exports.run = function (buildOpts) {
try {
buildOpts = parseOptions(buildOpts);
} catch (e) {
return Promise.reject(e);
}
const projectPath = this.root;
let emulatorTarget = 'iOS Device';
if (buildOpts.target && buildOpts.target.match(/mac/i)) {
buildOpts.catalyst = true;
buildOpts.device = true;
buildOpts.emulator = false;
emulatorTarget = 'macOS Catalyst';
}
return Promise.resolve()
.then(() => {
if (!buildOpts.emulator && !buildOpts.catalyst) {
return require('./listDevices').run().then(devices => {
if (devices.length > 0) {
// we explicitly set device flag in options
buildOpts.device = true;
}
});
}
})
.then(() => {
// CB-12287: Determine the device we should target when building for a simulator
if (!buildOpts.device) {
let newTarget = buildOpts.target || '';
if (newTarget) {
// only grab the device name, not the runtime specifier
newTarget = newTarget.split(',')[0];
}
// a target was given to us, find the matching Xcode destination name
const promise = require('./listEmulatorBuildTargets').targetForSimIdentifier(newTarget);
return promise.then(theTarget => {
if (!theTarget) {
return getDefaultSimulatorTarget().then(defaultTarget => {
emulatorTarget = defaultTarget.name;
events.emit('warn', `No simulator found for "${newTarget}. Falling back to the default target.`);
events.emit('log', `Building for "${emulatorTarget}" Simulator (${defaultTarget.identifier}, ${defaultTarget.simIdentifier}).`);
return emulatorTarget;
});
} else {
emulatorTarget = theTarget.name;
events.emit('log', `Building for "${emulatorTarget}" Simulator (${theTarget.identifier}, ${theTarget.simIdentifier}).`);
return emulatorTarget;
}
});
}
})
.then(() => check_reqs.run())
.then(() => {
let extraConfig = '';
if (buildOpts.codeSignIdentity) {
extraConfig += `CODE_SIGN_IDENTITY = ${buildOpts.codeSignIdentity}\n`;
}
if (buildOpts.provisioningProfile) {
if (typeof buildOpts.provisioningProfile === 'string') {
extraConfig += `PROVISIONING_PROFILE_SPECIFIER = ${buildOpts.provisioningProfile}\n`;
} else {
const keys = Object.keys(buildOpts.provisioningProfile);
extraConfig += `PROVISIONING_PROFILE_SPECIFIER = ${buildOpts.provisioningProfile[keys[0]]}\n`;
}
}
if (buildOpts.developmentTeam) {
extraConfig += `DEVELOPMENT_TEAM = ${buildOpts.developmentTeam}\n`;
}
function writeCodeSignStyle (value) {
const project = createProjectObject(projectPath);
events.emit('verbose', `Set CODE_SIGN_STYLE Build Property to ${value}.`);
project.xcode.updateBuildProperty('CODE_SIGN_STYLE', value);
events.emit('verbose', `Set ProvisioningStyle Target Attribute to ${value}.`);
project.xcode.addTargetAttribute('ProvisioningStyle', value);
project.write();
}
if (buildOpts.provisioningProfile) {
events.emit('verbose', 'ProvisioningProfile build option set, changing project settings to Manual.');
writeCodeSignStyle('Manual');
} else if (buildOpts.automaticProvisioning) {
events.emit('verbose', 'ProvisioningProfile build option NOT set, changing project settings to Automatic.');
writeCodeSignStyle('Automatic');
}
return fs.promises.writeFile(path.join(projectPath, 'cordova', 'build-extras.xcconfig'), extraConfig, 'utf-8');
}).then(() => {
const configuration = buildOpts.release ? 'Release' : 'Debug';
events.emit('log', `Building project: ${path.join(projectPath, 'App.xcworkspace')}`);
events.emit('log', `\tConfiguration: ${configuration}`);
events.emit('log', `\tPlatform: ${buildOpts.device ? 'device' : 'emulator'}`);
events.emit('log', `\tTarget: ${emulatorTarget}`);
const buildOutputDir = path.join(projectPath, 'build', `${configuration}-${(buildOpts.device ? 'iphoneos' : 'iphonesimulator')}`);
// remove the build output folder before building
fs.rmSync(buildOutputDir, { recursive: true, force: true });
const xcodebuildArgs = getXcodeBuildArgs(projectPath, configuration, emulatorTarget, buildOpts);
return execa('xcodebuild', xcodebuildArgs, { cwd: projectPath, stdio: 'inherit' });
}).then(() => {
if (!buildOpts.device || buildOpts.catalyst || buildOpts.noSign) {
return;
}
const project = createProjectObject(projectPath);
const bundleIdentifier = project.getPackageName();
const exportOptions = { ...buildOpts.exportOptions, compileBitcode: false, method: 'development' };
if (buildOpts.packageType) {
exportOptions.method = buildOpts.packageType;
}
if (buildOpts.iCloudContainerEnvironment) {
exportOptions.iCloudContainerEnvironment = buildOpts.iCloudContainerEnvironment;
}
if (buildOpts.developmentTeam) {
exportOptions.teamID = buildOpts.developmentTeam;
}
if (buildOpts.provisioningProfile && bundleIdentifier) {
if (typeof buildOpts.provisioningProfile === 'string') {
exportOptions.provisioningProfiles = { [bundleIdentifier]: String(buildOpts.provisioningProfile) };
} else {
events.emit('log', 'Setting multiple provisioning profiles for signing');
exportOptions.provisioningProfiles = buildOpts.provisioningProfile;
}
exportOptions.signingStyle = 'manual';
}
if (buildOpts.codeSignIdentity) {
exportOptions.signingCertificate = buildOpts.codeSignIdentity;
}
const exportOptionsPlist = plist.build(exportOptions);
const exportOptionsPath = path.join(projectPath, 'exportOptions.plist');
const configuration = buildOpts.release ? 'Release' : 'Debug';
const buildOutputDir = path.join(projectPath, 'build', `${configuration}-iphoneos`);
function checkSystemRuby () {
const ruby_cmd = which.sync('ruby', { nothrow: true });
if (ruby_cmd !== '/usr/bin/ruby') {
events.emit('warn', 'Non-system Ruby in use. This may cause packaging to fail.\n' +
'If you use RVM, please run `rvm use system`.\n' +
'If you use chruby, please run `chruby system`.');
}
}
function packageArchive () {
const xcodearchiveArgs = getXcodeArchiveArgs(projectPath, buildOutputDir, exportOptionsPath, buildOpts);
return execa('xcodebuild', xcodearchiveArgs, { cwd: projectPath, stdio: 'inherit' });
}
return fs.promises.writeFile(exportOptionsPath, exportOptionsPlist, 'utf-8')
.then(checkSystemRuby)
.then(packageArchive);
})
.then(() => {}); // resolve to undefined
};