mirror of
https://github.com/microsoft/vscode.git
synced 2026-05-31 00:10:04 +08:00
Add Win32 metadata all executable binaries (#296710)
This commit is contained in:
@@ -25,6 +25,8 @@ import { untar } from './lib/util.ts';
|
||||
import File from 'vinyl';
|
||||
import * as fs from 'fs';
|
||||
import glob from 'glob';
|
||||
import { promisify } from 'util';
|
||||
import rceditCallback from 'rcedit';
|
||||
import { compileBuildWithManglingTask } from './gulpfile.compile.ts';
|
||||
import { cleanExtensionsBuildTask, compileNonNativeExtensionsBuildTask, compileNativeExtensionsBuildTask, compileExtensionMediaBuildTask } from './gulpfile.extensions.ts';
|
||||
import { vscodeWebResourceIncludes, createVSCodeWebFileContentMapper } from './gulpfile.vscode.web.ts';
|
||||
@@ -35,6 +37,8 @@ import { fetchUrls, fetchGithub } from './lib/fetch.ts';
|
||||
import jsonEditor from 'gulp-json-editor';
|
||||
|
||||
|
||||
const rcedit = promisify(rceditCallback);
|
||||
|
||||
const REPO_ROOT = path.dirname(import.meta.dirname);
|
||||
const commit = getVersion(REPO_ROOT);
|
||||
const BUILD_ROOT = path.dirname(REPO_ROOT);
|
||||
@@ -422,6 +426,40 @@ function packageTask(type: string, platform: string, arch: string, sourceFolderN
|
||||
};
|
||||
}
|
||||
|
||||
function patchWin32DependenciesTask(destinationFolderName: string) {
|
||||
const cwd = path.join(BUILD_ROOT, destinationFolderName);
|
||||
|
||||
return async () => {
|
||||
const deps = (await Promise.all([
|
||||
promisify(glob)('**/*.node', { cwd }),
|
||||
promisify(glob)('**/rg.exe', { cwd }),
|
||||
])).flatMap(o => o);
|
||||
const packageJsonContents = JSON.parse(await fs.promises.readFile(path.join(cwd, 'package.json'), 'utf8'));
|
||||
const productContents = JSON.parse(await fs.promises.readFile(path.join(cwd, 'product.json'), 'utf8'));
|
||||
const baseVersion = packageJsonContents.version.replace(/-.*$/, '');
|
||||
|
||||
const patchPromises = deps.map<Promise<unknown>>(async dep => {
|
||||
const basename = path.basename(dep);
|
||||
|
||||
await rcedit(path.join(cwd, dep), {
|
||||
'file-version': baseVersion,
|
||||
'version-string': {
|
||||
'CompanyName': 'Microsoft Corporation',
|
||||
'FileDescription': productContents.nameLong,
|
||||
'FileVersion': packageJsonContents.version,
|
||||
'InternalName': basename,
|
||||
'LegalCopyright': 'Copyright (C) 2026 Microsoft. All rights reserved',
|
||||
'OriginalFilename': basename,
|
||||
'ProductName': productContents.nameLong,
|
||||
'ProductVersion': packageJsonContents.version,
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
await Promise.all(patchPromises);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param product The parsed product.json file contents
|
||||
*/
|
||||
@@ -466,12 +504,18 @@ function tweakProductForServerWeb(product: typeof import('../product.json')) {
|
||||
const sourceFolderName = `out-vscode-${type}${dashed(minified)}`;
|
||||
const destinationFolderName = `vscode-${type}${dashed(platform)}${dashed(arch)}`;
|
||||
|
||||
const serverTaskCI = task.define(`vscode-${type}${dashed(platform)}${dashed(arch)}${dashed(minified)}-ci`, task.series(
|
||||
const packageTasks: task.Task[] = [
|
||||
compileNativeExtensionsBuildTask,
|
||||
gulp.task(`node-${platform}-${arch}`) as task.Task,
|
||||
util.rimraf(path.join(BUILD_ROOT, destinationFolderName)),
|
||||
packageTask(type, platform, arch, sourceFolderName, destinationFolderName)
|
||||
));
|
||||
];
|
||||
|
||||
if (platform === 'win32') {
|
||||
packageTasks.push(patchWin32DependenciesTask(destinationFolderName));
|
||||
}
|
||||
|
||||
const serverTaskCI = task.define(`vscode-${type}${dashed(platform)}${dashed(arch)}${dashed(minified)}-ci`, task.series(...packageTasks));
|
||||
gulp.task(serverTaskCI);
|
||||
|
||||
const serverTask = task.define(`vscode-${type}${dashed(platform)}${dashed(arch)}${dashed(minified)}`, task.series(
|
||||
|
||||
@@ -623,12 +623,16 @@ function patchWin32DependenciesTask(destinationFolderName: string) {
|
||||
const cwd = path.join(path.dirname(root), destinationFolderName);
|
||||
|
||||
return async () => {
|
||||
const deps = await glob('**/*.node', { cwd, ignore: 'extensions/node_modules/@parcel/watcher/**' });
|
||||
const deps = (await Promise.all([
|
||||
glob('**/*.node', { cwd, ignore: 'extensions/node_modules/@parcel/watcher/**' }),
|
||||
glob('**/rg.exe', { cwd }),
|
||||
glob('**/*explorer_command*.dll', { cwd }),
|
||||
])).flatMap(o => o);
|
||||
const packageJson = JSON.parse(await fs.promises.readFile(path.join(cwd, versionedResourcesFolder, 'resources', 'app', 'package.json'), 'utf8'));
|
||||
const product = JSON.parse(await fs.promises.readFile(path.join(cwd, versionedResourcesFolder, 'resources', 'app', 'product.json'), 'utf8'));
|
||||
const baseVersion = packageJson.version.replace(/-.*$/, '');
|
||||
|
||||
await Promise.all(deps.map(async dep => {
|
||||
const patchPromises = deps.map<Promise<unknown>>(async dep => {
|
||||
const basename = path.basename(dep);
|
||||
|
||||
await rcedit(path.join(cwd, dep), {
|
||||
@@ -638,13 +642,15 @@ function patchWin32DependenciesTask(destinationFolderName: string) {
|
||||
'FileDescription': product.nameLong,
|
||||
'FileVersion': packageJson.version,
|
||||
'InternalName': basename,
|
||||
'LegalCopyright': 'Copyright (C) 2022 Microsoft. All rights reserved',
|
||||
'LegalCopyright': 'Copyright (C) 2026 Microsoft. All rights reserved',
|
||||
'OriginalFilename': basename,
|
||||
'ProductName': product.nameLong,
|
||||
'ProductVersion': packageJson.version,
|
||||
}
|
||||
});
|
||||
}));
|
||||
});
|
||||
|
||||
await Promise.all(patchPromises);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@ tar = "0.4.38"
|
||||
[build-dependencies]
|
||||
serde = { version="1.0.163", features = ["derive"] }
|
||||
serde_json = "1.0.96"
|
||||
winresource = "0.1"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
winreg = "0.50.0"
|
||||
|
||||
51
cli/build.rs
51
cli/build.rs
@@ -20,6 +20,7 @@ fn main() {
|
||||
let files = enumerate_source_files().expect("expected to enumerate files");
|
||||
ensure_file_headers(&files).expect("expected to ensure file headers");
|
||||
apply_build_environment_variables();
|
||||
apply_win32_version_resources();
|
||||
}
|
||||
|
||||
fn camel_case_to_constant_case(key: &str) -> String {
|
||||
@@ -148,6 +149,56 @@ fn apply_build_environment_variables() {
|
||||
};
|
||||
}
|
||||
|
||||
fn apply_win32_version_resources() {
|
||||
if env::var("CARGO_CFG_TARGET_OS").as_deref() != Ok("windows") {
|
||||
return;
|
||||
}
|
||||
|
||||
let repo_dir = env::current_dir().unwrap().join("..");
|
||||
let package_json = read_json_from_path::<PackageJson>(&repo_dir.join("package.json"));
|
||||
|
||||
let product_json_path = match env::var("VSCODE_CLI_PRODUCT_JSON") {
|
||||
Ok(v) => {
|
||||
if cfg!(windows) {
|
||||
PathBuf::from_str(&v.replace('/', "\\")).unwrap()
|
||||
} else {
|
||||
PathBuf::from_str(&v).unwrap()
|
||||
}
|
||||
}
|
||||
Err(_) => repo_dir.join("product.json"),
|
||||
};
|
||||
|
||||
let product: HashMap<String, Value> = read_json_from_path(&product_json_path);
|
||||
let name_long = product
|
||||
.get("nameLong")
|
||||
.and_then(|v| v.as_str())
|
||||
.unwrap_or("Code - OSS");
|
||||
let application_name = product
|
||||
.get("applicationName")
|
||||
.and_then(|v| v.as_str())
|
||||
.unwrap_or("code");
|
||||
let exe_name = format!("{application_name}.exe");
|
||||
|
||||
let base_version = package_json.version.split('-').next().unwrap_or("0.0.0");
|
||||
let version_parts: Vec<&str> = base_version.split('.').collect();
|
||||
let major: u64 = version_parts.first().and_then(|v| v.parse().ok()).unwrap_or(0);
|
||||
let minor: u64 = version_parts.get(1).and_then(|v| v.parse().ok()).unwrap_or(0);
|
||||
let patch: u64 = version_parts.get(2).and_then(|v| v.parse().ok()).unwrap_or(0);
|
||||
|
||||
let mut res = winresource::WindowsResource::new();
|
||||
res.set("ProductName", name_long);
|
||||
res.set("FileDescription", name_long);
|
||||
res.set("CompanyName", "Microsoft Corporation");
|
||||
res.set("LegalCopyright", "Copyright (C) 2026 Microsoft. All rights reserved");
|
||||
res.set("FileVersion", &package_json.version);
|
||||
res.set("ProductVersion", &package_json.version);
|
||||
res.set("InternalName", &exe_name);
|
||||
res.set("OriginalFilename", &exe_name);
|
||||
res.set_version_info(winresource::VersionInfo::FILEVERSION, (major << 48) | (minor << 16) | patch);
|
||||
res.set_version_info(winresource::VersionInfo::PRODUCTVERSION, (major << 48) | (minor << 16) | patch);
|
||||
res.compile().expect("failed to compile Windows resources");
|
||||
}
|
||||
|
||||
fn ensure_file_headers(files: &[PathBuf]) -> Result<(), io::Error> {
|
||||
let mut ok = true;
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ interface ITargetMetadata {
|
||||
export class TestContext {
|
||||
private static readonly authenticodeInclude = /^.+\.(exe|dll|sys|cab|cat|msi|jar|ocx|ps1|psm1|psd1|ps1xml|pssc1)$/i;
|
||||
private static readonly versionInfoInclude = /^.+\.(exe|dll|node|msi)$/i;
|
||||
private static readonly versionInfoExclude = /^(dxil\.dll|ffmpeg\.dll|msalruntime\.dll)$/i;
|
||||
|
||||
private readonly tempDirs = new Set<string>();
|
||||
private readonly wslTempDirs = new Set<string>();
|
||||
@@ -404,7 +405,11 @@ export class TestContext {
|
||||
if (entry.isDirectory()) {
|
||||
this.collectVersionInfoFiles(filePath, files);
|
||||
} else if (TestContext.versionInfoInclude.test(entry.name)) {
|
||||
files.push(filePath);
|
||||
if (TestContext.versionInfoExclude.test(entry.name)) {
|
||||
this.log(`Skipping excluded file from VersionInfo validation: ${filePath}`);
|
||||
} else {
|
||||
files.push(filePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user