@@ -25,6 +25,8 @@ import { Readable } from 'stream';
2525import * as nls from 'vscode-nls' ;
2626import { CppBuildTaskProvider } from './cppBuildTaskProvider' ;
2727import { UpdateInsidersAccess } from '../main' ;
28+ import { PlatformInformation } from '../platform' ;
29+ import * as semver from 'semver' ;
2830
2931nls . config ( { messageFormat : nls . MessageFormat . bundle , bundleFormat : nls . BundleFormat . standalone } ) ( ) ;
3032const 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 ( / T a r g e t P l a t f o r m = " (?< 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 */
161235export 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