diff --git a/Extension/src/common.ts b/Extension/src/common.ts index f32502b91..f906154dc 100644 --- a/Extension/src/common.ts +++ b/Extension/src/common.ts @@ -417,21 +417,18 @@ export function getHttpsProxyAgent(): HttpsProxyAgent | undefined { return new HttpsProxyAgent(proxyOptions); } -/** Creates a file if it doesn't exist */ -function touchFile(file: string): Promise { - return new Promise((resolve, reject) => { - fs.writeFile(file, "", (err) => { - if (err) { - reject(err); - } - - resolve(); - }); - }); -} +export interface InstallLockContents { + platform: string; + architecture: string; +}; -export function touchInstallLockFile(): Promise { - return touchFile(getInstallLockPath()); +export function touchInstallLockFile(info: PlatformInformation): Promise { + const installLockObject: InstallLockContents = { + platform: info.platform, + architecture: info.architecture + }; + const content: string = JSON.stringify(installLockObject); + return writeFileText(getInstallLockPath(), content); } export function touchExtensionFolder(): Promise { @@ -503,20 +500,6 @@ export function checkInstallLockFile(): Promise { return checkFileExists(getInstallLockPath()); } -/** Get the platform that the installed binaries belong to.*/ -export function getInstalledBinaryPlatform(): string | undefined { - // the LLVM/bin folder is utilized to identify the platform - let installedPlatform: string | undefined; - if (checkFileExistsSync(path.join(extensionPath, "LLVM/bin/clang-format.exe"))) { - installedPlatform = "win32"; - } else if (checkFileExistsSync(path.join(extensionPath, "LLVM/bin/clang-format.darwin"))) { - installedPlatform = "darwin"; - } else if (checkFileExistsSync(path.join(extensionPath, "LLVM/bin/clang-format"))) { - installedPlatform = "linux"; - } - return installedPlatform; -} - /** Check if the core binaries exists in extension's installation folder */ export async function checkInstallBinariesExist(): Promise { if (!checkInstallLockFile()) { diff --git a/Extension/src/main.ts b/Extension/src/main.ts index 9512f0f2c..611f98eb5 100644 --- a/Extension/src/main.ts +++ b/Extension/src/main.ts @@ -75,38 +75,71 @@ export async function activate(context: vscode.ExtensionContext): Promise = new PersistentState("CPP.promptForMacArchictureMismatch", true); + + // Read archictures of binaries from install.lock + const fileContents: string = await util.readFileText(util.getInstallLockPath()); + let installedPlatformAndArchitecture: util.InstallLockContents; + // Just in case we're debugging with an existing install.lock that is empty, assume current platform if empty. + if (fileContents.length === 0) { + installedPlatformAndArchitecture = { + platform: process.platform, + architecture: arch + }; + } else { + installedPlatformAndArchitecture = JSON.parse(fileContents); + } // Check the main binaries files to declare if the extension has been installed successfully. - if (installedPlatform && process.platform !== installedPlatform) { + if (process.platform !== installedPlatformAndArchitecture.platform + || (arch !== installedPlatformAndArchitecture.architecture && (arch !== "x64" || installedPlatformAndArchitecture.architecture !== 'x86' || process.platform !== "win32"))) { // Check if the correct offline/insiders vsix is installed on the correct platform. const platformInfo: PlatformInformation = await PlatformInformation.GetPlatformInformation(); const vsixName: string = vsixNameForPlatform(platformInfo); - errMsg = localize("native.binaries.not.supported", "This {0} version of the extension is incompatible with your OS. Please download and install the \"{1}\" version of the extension.", GetOSName(installedPlatform), vsixName); - const downloadLink: string = localize("download.button", "Go to Download Page"); - vscode.window.showErrorMessage(errMsg, downloadLink).then(async (selection) => { - if (selection === downloadLink) { - vscode.env.openExternal(vscode.Uri.parse(releaseDownloadUrl)); - } - }); - } else if (!(await util.checkInstallBinariesExist())) { - errMsg = localize("extension.installation.failed", "The C/C++ extension failed to install successfully. You will need to repair or reinstall the extension for C/C++ language features to function properly."); - const reload: string = localize("remove.extension", "Attempt to Repair"); - vscode.window.showErrorMessage(errMsg, reload).then(async (value?: string) => { - if (value === reload) { - await util.removeInstallLockFile(); - vscode.commands.executeCommand("workbench.action.reloadWindow"); - } - }); - } else if (!(await util.checkInstallJsonsExist())) { - // Check the Json files to declare if the extension has been installed successfully. - errMsg = localize("jason.files.missing", "The C/C++ extension failed to install successfully. You will need to reinstall the extension for C/C++ language features to function properly."); const downloadLink: string = localize("download.button", "Go to Download Page"); - vscode.window.showErrorMessage(errMsg, downloadLink).then(async (selection) => { - if (selection === downloadLink) { - vscode.env.openExternal(vscode.Uri.parse(releaseDownloadUrl)); + if (installedPlatformAndArchitecture.platform === 'darwin' && installedPlatformAndArchitecture.architecture === "x64" && arch === "arm64") { + if (promptForMacArchictureMismatch.Value) { + // Display a message specifically referring the user to the ARM64 Mac build on ARM64 Mac. + errMsg = localize("native.binaries.mismatch.osx", "This Intel version of the extension has been installed. Since you are on an Apple Silicon Mac, we recommend installing the Apple Silicon version of the extension."); + promptForMacArchictureMismatch.Value = false; + vscode.window.showErrorMessage(errMsg, downloadLink).then(async (selection) => { + if (selection === downloadLink) { + vscode.env.openExternal(vscode.Uri.parse(releaseDownloadUrl)); + } + }); } - }); + } else { + // Reset the persistent boolean tracking whether to warn the user of architecture mismatch on OSX. + promptForMacArchictureMismatch.Value = true; + errMsg = localize("native.binaries.not.supported", "This {0} version of the extension is incompatible with your OS. Please download and install the \"{1}\" version of the extension.", GetOSName(installedPlatformAndArchitecture.platform), vsixName); + vscode.window.showErrorMessage(errMsg, downloadLink).then(async (selection) => { + if (selection === downloadLink) { + vscode.env.openExternal(vscode.Uri.parse(releaseDownloadUrl)); + } + }); + } + } else { + // Reset the persistent boolean tracking whether to warn the user of architecture mismatch on OSX. + promptForMacArchictureMismatch.Value = true; + if (!(await util.checkInstallBinariesExist())) { + errMsg = localize("extension.installation.failed", "The C/C++ extension failed to install successfully. You will need to repair or reinstall the extension for C/C++ language features to function properly."); + const reload: string = localize("remove.extension", "Attempt to Repair"); + vscode.window.showErrorMessage(errMsg, reload).then(async (value?: string) => { + if (value === reload) { + await util.removeInstallLockFile(); + vscode.commands.executeCommand("workbench.action.reloadWindow"); + } + }); + } else if (!(await util.checkInstallJsonsExist())) { + // Check the Json files to declare if the extension has been installed successfully. + errMsg = localize("jason.files.missing", "The C/C++ extension failed to install successfully. You will need to reinstall the extension for C/C++ language features to function properly."); + const downloadLink: string = localize("download.button", "Go to Download Page"); + vscode.window.showErrorMessage(errMsg, downloadLink).then(async (selection) => { + if (selection === downloadLink) { + vscode.env.openExternal(vscode.Uri.parse(releaseDownloadUrl)); + } + }); + } } return cppTools; @@ -219,7 +252,7 @@ async function onlineInstallation(info: PlatformInformation): Promise { await rewriteManifest(); setInstallationStage('touchInstallLockFile'); - await touchInstallLockFile(); + await touchInstallLockFile(info); setInstallationStage('postInstall'); await postInstall(info); @@ -311,8 +344,8 @@ function removeUnnecessaryFile(): Promise { return Promise.resolve(); } -function touchInstallLockFile(): Promise { - return util.touchInstallLockFile(); +function touchInstallLockFile(info: PlatformInformation): Promise { + return util.touchInstallLockFile(info); } function handleError(error: any): void {