mirror of
https://github.com/microsoft/vscode.git
synced 2025-12-11 10:13:36 -06:00
154 lines
6.3 KiB
TypeScript
154 lines
6.3 KiB
TypeScript
/*---------------------------------------------------------------------------------------------
|
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
*--------------------------------------------------------------------------------------------*/
|
|
import assert from 'assert';
|
|
import * as cp from 'child_process';
|
|
import * as fs from 'fs';
|
|
import gulp from 'gulp';
|
|
import * as path from 'path';
|
|
import rcedit from 'rcedit';
|
|
import vfs from 'vinyl-fs';
|
|
import pkg from '../package.json' with { type: 'json' };
|
|
import product from '../product.json' with { type: 'json' };
|
|
import { getVersion } from './lib/getVersion.ts';
|
|
import * as task from './lib/task.ts';
|
|
import * as util from './lib/util.ts';
|
|
|
|
import { createRequire } from 'module';
|
|
const require = createRequire(import.meta.url);
|
|
|
|
const repoPath = path.dirname(import.meta.dirname);
|
|
const commit = getVersion(repoPath);
|
|
const buildPath = (arch: string) => path.join(path.dirname(repoPath), `VSCode-win32-${arch}`);
|
|
const setupDir = (arch: string, target: string) => path.join(repoPath, '.build', `win32-${arch}`, `${target}-setup`);
|
|
const innoSetupPath = path.join(path.dirname(path.dirname(require.resolve('innosetup'))), 'bin', 'ISCC.exe');
|
|
const signWin32Path = path.join(repoPath, 'build', 'azure-pipelines', 'common', 'sign-win32.ts');
|
|
|
|
function packageInnoSetup(iss: string, options: { definitions?: Record<string, unknown> }, cb: (err?: Error | null) => void) {
|
|
const definitions = options.definitions || {};
|
|
|
|
if (process.argv.some(arg => arg === '--debug-inno')) {
|
|
definitions['Debug'] = 'true';
|
|
}
|
|
|
|
if (process.argv.some(arg => arg === '--sign')) {
|
|
definitions['Sign'] = 'true';
|
|
}
|
|
|
|
const keys = Object.keys(definitions);
|
|
|
|
keys.forEach(key => assert(typeof definitions[key] === 'string', `Missing value for '${key}' in Inno Setup package step`));
|
|
|
|
const defs = keys.map(key => `/d${key}=${definitions[key]}`);
|
|
const args = [
|
|
iss,
|
|
...defs,
|
|
`/sesrp=node ${signWin32Path} $f`
|
|
];
|
|
|
|
cp.spawn(innoSetupPath, args, { stdio: ['ignore', 'inherit', 'inherit'] })
|
|
.on('error', cb)
|
|
.on('exit', code => {
|
|
if (code === 0) {
|
|
cb(null);
|
|
} else {
|
|
cb(new Error(`InnoSetup returned exit code: ${code}`));
|
|
}
|
|
});
|
|
}
|
|
|
|
function buildWin32Setup(arch: string, target: string): task.CallbackTask {
|
|
if (target !== 'system' && target !== 'user') {
|
|
throw new Error('Invalid setup target');
|
|
}
|
|
|
|
return (cb) => {
|
|
const x64AppId = target === 'system' ? product.win32x64AppId : product.win32x64UserAppId;
|
|
const arm64AppId = target === 'system' ? product.win32arm64AppId : product.win32arm64UserAppId;
|
|
|
|
const sourcePath = buildPath(arch);
|
|
const outputPath = setupDir(arch, target);
|
|
fs.mkdirSync(outputPath, { recursive: true });
|
|
|
|
const quality = (product as typeof product & { quality?: string }).quality || 'dev';
|
|
let versionedResourcesFolder = '';
|
|
let issPath = path.join(import.meta.dirname, 'win32', 'code.iss');
|
|
if (quality && quality === 'insider') {
|
|
versionedResourcesFolder = commit!.substring(0, 10);
|
|
issPath = path.join(import.meta.dirname, 'win32', 'code-insider.iss');
|
|
}
|
|
const originalProductJsonPath = path.join(sourcePath, versionedResourcesFolder, 'resources/app/product.json');
|
|
const productJsonPath = path.join(outputPath, 'product.json');
|
|
const productJson = JSON.parse(fs.readFileSync(originalProductJsonPath, 'utf8'));
|
|
productJson['target'] = target;
|
|
fs.writeFileSync(productJsonPath, JSON.stringify(productJson, undefined, '\t'));
|
|
|
|
const definitions: Record<string, unknown> = {
|
|
NameLong: product.nameLong,
|
|
NameShort: product.nameShort,
|
|
DirName: product.win32DirName,
|
|
Version: pkg.version,
|
|
RawVersion: pkg.version.replace(/-\w+$/, ''),
|
|
Commit: commit,
|
|
NameVersion: product.win32NameVersion + (target === 'user' ? ' (User)' : ''),
|
|
ExeBasename: product.nameShort,
|
|
RegValueName: product.win32RegValueName,
|
|
ShellNameShort: product.win32ShellNameShort,
|
|
AppMutex: product.win32MutexName,
|
|
TunnelMutex: product.win32TunnelMutex,
|
|
TunnelServiceMutex: product.win32TunnelServiceMutex,
|
|
TunnelApplicationName: product.tunnelApplicationName,
|
|
ApplicationName: product.applicationName,
|
|
Arch: arch,
|
|
AppId: { 'x64': x64AppId, 'arm64': arm64AppId }[arch],
|
|
IncompatibleTargetAppId: { 'x64': product.win32x64AppId, 'arm64': product.win32arm64AppId }[arch],
|
|
AppUserId: product.win32AppUserModelId,
|
|
ArchitecturesAllowed: { 'x64': 'x64', 'arm64': 'arm64' }[arch],
|
|
ArchitecturesInstallIn64BitMode: { 'x64': 'x64', 'arm64': 'arm64' }[arch],
|
|
SourceDir: sourcePath,
|
|
RepoDir: repoPath,
|
|
OutputDir: outputPath,
|
|
InstallTarget: target,
|
|
ProductJsonPath: productJsonPath,
|
|
VersionedResourcesFolder: versionedResourcesFolder,
|
|
Quality: quality
|
|
};
|
|
|
|
if (quality === 'stable' || quality === 'insider') {
|
|
definitions['AppxPackage'] = `${quality === 'stable' ? 'code' : 'code_insider'}_${arch}.appx`;
|
|
definitions['AppxPackageDll'] = `${quality === 'stable' ? 'code' : 'code_insider'}_explorer_command_${arch}.dll`;
|
|
definitions['AppxPackageName'] = `${product.win32AppUserModelId}`;
|
|
}
|
|
|
|
packageInnoSetup(issPath, { definitions }, cb as (err?: Error | null) => void);
|
|
};
|
|
}
|
|
|
|
function defineWin32SetupTasks(arch: string, target: string) {
|
|
const cleanTask = util.rimraf(setupDir(arch, target));
|
|
gulp.task(task.define(`vscode-win32-${arch}-${target}-setup`, task.series(cleanTask, buildWin32Setup(arch, target))));
|
|
}
|
|
|
|
defineWin32SetupTasks('x64', 'system');
|
|
defineWin32SetupTasks('arm64', 'system');
|
|
defineWin32SetupTasks('x64', 'user');
|
|
defineWin32SetupTasks('arm64', 'user');
|
|
|
|
function copyInnoUpdater(arch: string) {
|
|
return () => {
|
|
return gulp.src('build/win32/{inno_updater.exe,vcruntime140.dll}', { base: 'build/win32' })
|
|
.pipe(vfs.dest(path.join(buildPath(arch), 'tools')));
|
|
};
|
|
}
|
|
|
|
function updateIcon(executablePath: string): task.CallbackTask {
|
|
return cb => {
|
|
const icon = path.join(repoPath, 'resources', 'win32', 'code.ico');
|
|
rcedit(executablePath, { icon }, cb);
|
|
};
|
|
}
|
|
|
|
gulp.task(task.define('vscode-win32-x64-inno-updater', task.series(copyInnoUpdater('x64'), updateIcon(path.join(buildPath('x64'), 'tools', 'inno_updater.exe')))));
|
|
gulp.task(task.define('vscode-win32-arm64-inno-updater', task.series(copyInnoUpdater('arm64'), updateIcon(path.join(buildPath('arm64'), 'tools', 'inno_updater.exe')))));
|