Skip to content
Merged
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
39 changes: 11 additions & 28 deletions Extension/src/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<void> {
return new Promise<void>((resolve, reject) => {
fs.writeFile(file, "", (err) => {
if (err) {
reject(err);
}

resolve();
});
});
}
export interface InstallLockContents {
platform: string;
architecture: string;
};

export function touchInstallLockFile(): Promise<void> {
return touchFile(getInstallLockPath());
export function touchInstallLockFile(info: PlatformInformation): Promise<void> {
const installLockObject: InstallLockContents = {
platform: info.platform,
architecture: info.architecture
};
const content: string = JSON.stringify(installLockObject);
return writeFileText(getInstallLockPath(), content);
}

export function touchExtensionFolder(): Promise<void> {
Expand Down Expand Up @@ -503,20 +500,6 @@ export function checkInstallLockFile(): Promise<boolean> {
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<boolean> {
if (!checkInstallLockFile()) {
Expand Down
89 changes: 61 additions & 28 deletions Extension/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,38 +75,71 @@ export async function activate(context: vscode.ExtensionContext): Promise<CppToo

await processRuntimeDependencies();

const installedPlatform: string | undefined = util.getInstalledBinaryPlatform();
const promptForMacArchictureMismatch: PersistentState<boolean> = new PersistentState<boolean>("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 = <util.InstallLockContents>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;
Expand Down Expand Up @@ -219,7 +252,7 @@ async function onlineInstallation(info: PlatformInformation): Promise<void> {
await rewriteManifest();

setInstallationStage('touchInstallLockFile');
await touchInstallLockFile();
await touchInstallLockFile(info);

setInstallationStage('postInstall');
await postInstall(info);
Expand Down Expand Up @@ -311,8 +344,8 @@ function removeUnnecessaryFile(): Promise<void> {
return Promise.resolve();
}

function touchInstallLockFile(): Promise<void> {
return util.touchInstallLockFile();
function touchInstallLockFile(info: PlatformInformation): Promise<void> {
return util.touchInstallLockFile(info);
}

function handleError(error: any): void {
Expand Down