Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion build/darwin/create-universal-app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,23 @@ function crossCopyPlatformDir(x64AppPath: string, arm64AppPath: string, relative
}
}

/**
* Like {@link crossCopyPlatformDir} but for a single file. Copies the file from whichever build
* has it into the one that does not, creating the parent directory if needed.
*/
function crossCopyFile(x64AppPath: string, arm64AppPath: string, relativePath: string): void {
const inX64 = path.join(x64AppPath, relativePath);
const inArm64 = path.join(arm64AppPath, relativePath);

if (fs.existsSync(inX64) && !fs.existsSync(inArm64)) {
fs.mkdirSync(path.dirname(inArm64), { recursive: true });
fs.cpSync(inX64, inArm64);
} else if (fs.existsSync(inArm64) && !fs.existsSync(inX64)) {
fs.mkdirSync(path.dirname(inX64), { recursive: true });
fs.cpSync(inArm64, inX64);
}
}

async function main(buildDir?: string) {
const arch = process.env['VSCODE_ARCH'];

Expand Down Expand Up @@ -80,6 +97,14 @@ async function main(buildDir?: string) {
crossCopyPlatformDir(x64AppPath, arm64AppPath, path.join(copilotExtensionNodeModules, '@github', 'copilot', 'tgrep', 'bin', plat));
}

// MSAL ships arch-suffixed native broker dylibs (libmsalruntime_x64.dylib / libmsalruntime_arm64.dylib),
// each present only in its own arch's build. The universal merger requires both builds to have identical
// file trees, so cross-copy each dylib into the other build. They are then kept as single-arch files
// (x64ArchFiles below) and excluded from Mach-O arch verification (verify-macho.ts).
const msalDistDir = path.join('Contents', 'Resources', 'app', 'extensions', 'microsoft-authentication', 'dist');
crossCopyFile(x64AppPath, arm64AppPath, path.join(msalDistDir, 'libmsalruntime_x64.dylib'));
crossCopyFile(x64AppPath, arm64AppPath, path.join(msalDistDir, 'libmsalruntime_arm64.dylib'));

const filesToSkip = [
'**/CodeResources',
'**/Credits.rtf',
Expand Down Expand Up @@ -121,7 +146,7 @@ async function main(buildDir?: string) {
outAppPath,
force: true,
mergeASARs: true,
x64ArchFiles: '{*/kerberos.node,**/extensions/microsoft-authentication/dist/libmsalruntime.dylib,**/extensions/microsoft-authentication/dist/msal-node-runtime.node,**/node_modules/@github/copilot-darwin-*/**,**/node_modules/@github/copilot/prebuilds/darwin-*/*,**/node_modules/@github/copilot/tgrep/bin/darwin-*/*,**/node_modules/@github/copilot/sdk/tgrep/bin/darwin-*/*,**/node_modules.asar.unpacked/@github/copilot-darwin-*/**,**/node_modules.asar.unpacked/@github/copilot/prebuilds/darwin-*/*,**/node_modules.asar.unpacked/@github/copilot/tgrep/bin/darwin-*/*,**/node_modules.asar.unpacked/@github/copilot/sdk/tgrep/bin/darwin-*/*,**/extensions/copilot/node_modules/@github/copilot/sdk/prebuilds/darwin-*/*,**/extensions/copilot/node_modules/@github/copilot/sdk/ripgrep/bin/darwin-*/*,**/extensions/copilot/node_modules/@github/copilot/sdk/tgrep/bin/darwin-*/*,**/extensions/copilot/node_modules/@github/copilot/tgrep/bin/darwin-*/*,**/node_modules/@vscode/ripgrep-universal/bin/darwin-*/*,**/node_modules.asar.unpacked/@vscode/ripgrep-universal/bin/darwin-*/*,**/node_modules/@microsoft/mxc-sdk/bin/**,**/node_modules.asar.unpacked/@microsoft/mxc-sdk/bin/**}',
x64ArchFiles: '{*/kerberos.node,**/extensions/microsoft-authentication/dist/libmsalruntime_x64.dylib,**/extensions/microsoft-authentication/dist/libmsalruntime_arm64.dylib,**/extensions/microsoft-authentication/dist/msal-node-runtime.node,**/node_modules/@github/copilot-darwin-*/**,**/node_modules/@github/copilot/prebuilds/darwin-*/*,**/node_modules/@github/copilot/tgrep/bin/darwin-*/*,**/node_modules/@github/copilot/sdk/tgrep/bin/darwin-*/*,**/node_modules.asar.unpacked/@github/copilot-darwin-*/**,**/node_modules.asar.unpacked/@github/copilot/prebuilds/darwin-*/*,**/node_modules.asar.unpacked/@github/copilot/tgrep/bin/darwin-*/*,**/node_modules.asar.unpacked/@github/copilot/sdk/tgrep/bin/darwin-*/*,**/extensions/copilot/node_modules/@github/copilot/sdk/prebuilds/darwin-*/*,**/extensions/copilot/node_modules/@github/copilot/sdk/ripgrep/bin/darwin-*/*,**/extensions/copilot/node_modules/@github/copilot/sdk/tgrep/bin/darwin-*/*,**/extensions/copilot/node_modules/@github/copilot/tgrep/bin/darwin-*/*,**/node_modules/@vscode/ripgrep-universal/bin/darwin-*/*,**/node_modules.asar.unpacked/@vscode/ripgrep-universal/bin/darwin-*/*,**/node_modules/@microsoft/mxc-sdk/bin/**,**/node_modules.asar.unpacked/@microsoft/mxc-sdk/bin/**}',
filesToSkipComparison: (file: string) => {
for (const expected of filesToSkip) {
if (minimatch(file, expected)) {
Expand Down
6 changes: 4 additions & 2 deletions build/darwin/verify-macho.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@ const MACHO_X86_64_CPU_TYPE = new Set([

// Files to skip during architecture validation
const FILES_TO_SKIP = [
// MSAL runtime files are only present in ARM64 builds
'**/extensions/microsoft-authentication/dist/libmsalruntime.dylib',
// MSAL runtime dylibs are arch-suffixed and intentionally shipped as single-arch files in the
// universal app (see create-universal-app.ts), so exclude them from the universal arch check.
Comment on lines +26 to +27
'**/extensions/microsoft-authentication/dist/libmsalruntime_x64.dylib',
'**/extensions/microsoft-authentication/dist/libmsalruntime_arm64.dylib',
'**/extensions/microsoft-authentication/dist/msal-node-runtime.node',
// Copilot SDK: universal app has both x64 and arm64 platform packages
'**/node_modules/@github/copilot-darwin-x64/**',
Expand Down
61 changes: 35 additions & 26 deletions extensions/microsoft-authentication/esbuild.mts
Original file line number Diff line number Diff line change
Expand Up @@ -13,41 +13,50 @@ const isWindows = process.platform === 'win32';
const isMacOS = process.platform === 'darwin';
const isLinux = !isWindows && !isMacOS;

const windowsArches = ['x64'];
const windowsArches = ['x64', 'arm64'];
const linuxArches = ['x64'];

let platformFolder: string;
switch (process.platform) {
case 'win32': platformFolder = 'windows'; break;
case 'darwin': platformFolder = 'macos'; break;
case 'linux': platformFolder = 'linux'; break;
default: throw new Error(`Unsupported platform: ${process.platform}`);
}

const arch = process.env.VSCODE_ARCH || process.arch;

const msalRuntimeDistDir = path.join(import.meta.dirname, 'node_modules', '@azure', 'msal-node-runtime', 'dist');
const isMsalBinary = (file: string) => /^(lib)?msal.*\.(node|dll|dylib|so)$/.test(file);

/**
* Copy native MSAL runtime binaries to the output directory.
* Copy every MSAL native binary from `srcDir` into `destDir` (created if needed).
* No-op if `srcDir` does not exist (unsupported platform/arch).
*/
async function copyNativeMsalFiles(outDir: string): Promise<void> {
if (
!(isWindows && windowsArches.includes(arch)) &&
!isMacOS &&
!(isLinux && linuxArches.includes(arch))
) {
async function copyMsalBinaries(srcDir: string, destDir: string): Promise<void> {
let files: string[];
try {
files = await fs.promises.readdir(srcDir);
} catch {
return;
}

const msalRuntimeDir = path.join(import.meta.dirname, 'node_modules', '@azure', 'msal-node-runtime', 'dist', platformFolder, arch);
try {
const files = await fs.promises.readdir(msalRuntimeDir);
for (const file of files) {
if (/^(lib)?msal.*\.(node|dll|dylib|so)$/.test(file)) {
await fs.promises.copyFile(path.join(msalRuntimeDir, file), path.join(outDir, file));
}
await fs.promises.mkdir(destDir, { recursive: true });
for (const file of files) {
if (isMsalBinary(file)) {
await fs.promises.copyFile(path.join(srcDir, file), path.join(destDir, file));
}
} catch {
// Skip if directory doesn't exist (unsupported platform/arch)
}
}

/**
* Copy the native MSAL runtime broker binaries into the extension output directory, where MSAL's
* `require('./msal-node-runtime')` resolves them.
*
* For Windows and macOS the target arch can differ from the build host (cross-arch / universal builds),
* so we copy the binaries for the specific target arch out of the package's `dist/<platform>/<arch>/`.
* Linux binaries are distro-specific, and `@azure/msal-node-runtime`'s own install script
* (`copyBinaries.js`) already selects and flattens the correct binary for the build machine into the
* package's `dist/` root — so we use the package as-is and copy those flattened binaries.
*/
async function copyNativeMsalFiles(outDir: string): Promise<void> {
if (isWindows && windowsArches.includes(arch)) {
await copyMsalBinaries(path.join(msalRuntimeDistDir, 'windows', arch), outDir);
} else if (isMacOS) {
await copyMsalBinaries(path.join(msalRuntimeDistDir, 'macos', arch), outDir);
} else if (isLinux && linuxArches.includes(arch)) {
await copyMsalBinaries(msalRuntimeDistDir, outDir);
}
}

Expand Down
6 changes: 3 additions & 3 deletions extensions/microsoft-authentication/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions extensions/microsoft-authentication/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,9 @@
"keytar": "file:./packageMocks/keytar",
"vscode-tas-client": "^0.1.84"
},
"overrides": {
"@azure/msal-node-runtime": "0.20.5"
},
"repository": {
"type": "git",
"url": "https://github.com/microsoft/vscode.git"
Expand Down
2 changes: 1 addition & 1 deletion test/sanity/src/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export class TestContext {
// MXC SDK ships per-arch SPDX catalog manifests that Get-AuthenticodeSignature reports as UnknownError.
private static readonly authenticodeExclude = /[\\/]node_modules[\\/]@microsoft[\\/]mxc-sdk[\\/]bin[\\/][^\\/]+[\\/]_manifest[\\/][^\\/]+[\\/]manifest\.cat$/i;
private static readonly versionInfoInclude = /^.+\.(exe|dll|node|msi)$/i;
private static readonly versionInfoFileExclude = /^(dxil\.dll|ffmpeg\.dll|msalruntime\.dll)$/i;
private static readonly versionInfoFileExclude = /^(dxil\.dll|ffmpeg\.dll|msalruntime(_arm64)?\.dll)$/i;
// MXC SDK binaries under bin are signed, but they do not carry a ProductName VersionInfo resource.
private static readonly versionInfoPathExclude = /(?:^|[\\/])node_modules(?:\.asar\.unpacked)?[\\/]@microsoft[\\/]mxc-sdk[\\/]bin[\\/]/i;
private static readonly dpkgLockError = /dpkg frontend lock was locked by another process|unable to acquire the dpkg frontend lock|could not get lock \/var\/lib\/dpkg\/lock-frontend/i;
Expand Down
Loading