Skip to content

Commit 125b657

Browse files
authored
Add compatibility check of VSIX TargetPlatform (#8910)
1 parent 67669b4 commit 125b657

File tree

1 file changed

+76
-0
lines changed

1 file changed

+76
-0
lines changed

Extension/src/LanguageServer/extension.ts

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ import { Readable } from 'stream';
2525
import * as nls from 'vscode-nls';
2626
import { CppBuildTaskProvider } from './cppBuildTaskProvider';
2727
import { UpdateInsidersAccess } from '../main';
28+
import { PlatformInformation } from '../platform';
29+
import * as semver from 'semver';
2830

2931
nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })();
3032
const localize: nls.LocalizeFunc = nls.loadMessageBundle();
@@ -155,11 +157,85 @@ function sendActivationTelemetry(): void {
155157
telemetry.logLanguageServerEvent("Activate", activateEvent);
156158
}
157159

160+
async function checkVsixCompatibility(): Promise<void> {
161+
// Check to ensure the correct platform-specific VSIX was installed.
162+
const vsixManifestPath: string = path.join(util.extensionPath, ".vsixmanifest");
163+
// Skip the check if the file does not exist, such as when debugging cpptools.
164+
if (await util.checkFileExists(vsixManifestPath)) {
165+
const content: string = await util.readFileText(vsixManifestPath);
166+
const matches: RegExpMatchArray | null = content.match(/TargetPlatform="(?<platform>[^"]*)"/);
167+
if (matches && matches.length > 0 && matches.groups) {
168+
const vsixTargetPlatform: string = matches.groups['platform'];
169+
const platformInfo: PlatformInformation = await PlatformInformation.GetPlatformInformation();
170+
let isPlatformCompatible: boolean = true;
171+
let isPlatformMatching: boolean = true;
172+
switch (vsixTargetPlatform) {
173+
case "win32-x64":
174+
isPlatformMatching = platformInfo.platform === "win32" && platformInfo.architecture === "x64";
175+
// x64 binaries can also be run on arm64 Windows 11.
176+
isPlatformCompatible = platformInfo.platform === "win32" && (platformInfo.architecture === "x64" || (platformInfo.architecture === "arm64" && semver.gte(os.release(), "10.0.22000")));
177+
break;
178+
case "win32-ia32":
179+
isPlatformMatching = platformInfo.platform === "win32" && platformInfo.architecture === "x86";
180+
// x86 binaries can also be run on x64 and arm64 Windows.
181+
isPlatformCompatible = platformInfo.platform === "win32" && (platformInfo.architecture === "x86" || platformInfo.architecture === "x64" || platformInfo.architecture === "arm64");
182+
break;
183+
case "win32-arm64":
184+
isPlatformMatching = platformInfo.platform === "win32" && platformInfo.architecture === "arm64";
185+
isPlatformCompatible = isPlatformMatching;
186+
break;
187+
case "linux-x64":
188+
isPlatformMatching = platformInfo.platform === "linux" && platformInfo.architecture === "x64" && platformInfo.distribution?.name !== "alpine";
189+
isPlatformCompatible = isPlatformMatching;
190+
break;
191+
case "linux-arm64":
192+
isPlatformMatching = platformInfo.platform === "linux" && platformInfo.architecture === "arm64" && platformInfo.distribution?.name !== "alpine";
193+
isPlatformCompatible = isPlatformMatching;
194+
break;
195+
case "linux-armhf":
196+
isPlatformMatching = platformInfo.platform === "linux" && platformInfo.architecture === "arm" && platformInfo.distribution?.name !== "alpine";
197+
// armhf binaries can also be run on aarch64 linux.
198+
isPlatformCompatible = platformInfo.platform === "linux" && (platformInfo.architecture === "arm" || platformInfo.architecture === "arm64") && platformInfo.distribution?.name !== "alpine";
199+
break;
200+
case "alpine-x64":
201+
isPlatformMatching = platformInfo.platform === "linux" && platformInfo.architecture === "x64" && platformInfo.distribution?.name === "alpine";
202+
isPlatformCompatible = isPlatformMatching;
203+
break;
204+
case "alpine-arm64":
205+
isPlatformMatching = platformInfo.platform === "linux" && platformInfo.architecture === "arm64" && platformInfo.distribution?.name === "alpine";
206+
isPlatformCompatible = isPlatformMatching;
207+
break;
208+
case "darwin-x64":
209+
isPlatformMatching = platformInfo.platform === "darwin" && platformInfo.architecture === "x64";
210+
isPlatformCompatible = isPlatformMatching;
211+
break;
212+
case "darwin-arm64":
213+
isPlatformMatching = platformInfo.platform === "darwin" && platformInfo.architecture === "arm64";
214+
// x64 binaries can also be run on arm64 macOS.
215+
isPlatformCompatible = platformInfo.platform === "darwin" && (platformInfo.architecture === "x64" || platformInfo.architecture === "arm64");
216+
break;
217+
default:
218+
console.log("Unrecognized TargetPlatform in .vsixmanifest");
219+
break;
220+
}
221+
if (!isPlatformCompatible) {
222+
vscode.window.showErrorMessage(localize("vsix.platform.incompatible", "The target platform {0} specifed in the C/C++ Extension VSIX is not compatible with your system.", vsixTargetPlatform));
223+
} else if (!isPlatformMatching) {
224+
vscode.window.showWarningMessage(localize("vsix.platform.mismatching", "The target platform {0} specifed in the C/C++ Extension VSIX does not match VS Code.", vsixTargetPlatform));
225+
}
226+
} else {
227+
console.log("Unable to find TargetPlatform in .vsixmanifest");
228+
}
229+
}
230+
}
231+
158232
/**
159233
* activate: set up the extension for language services
160234
*/
161235
export async function activate(): Promise<void> {
162236

237+
await checkVsixCompatibility();
238+
163239
if (vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders.length > 0) {
164240
for (let i: number = 0; i < vscode.workspace.workspaceFolders.length; ++i) {
165241
const config: string = path.join(vscode.workspace.workspaceFolders[i].uri.fsPath, ".vscode/c_cpp_properties.json");

0 commit comments

Comments
 (0)