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
2 changes: 2 additions & 0 deletions docs_espressif/en/commands.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ All commands start with ``ESP-IDF:``.
- Open a window with a setup wizard to install ESP-IDF, IDF Tools and Python virtual environment.
* - Configure Project SDKConfig for Coverage
- Set required values in your project SDKConfig to enable code coverage analysis.
* - Configure project for ESP-Clang
- Configure the current ESP-IDF project to use esp-clang as toolchain to use and configure LLVM Clang extension in settings.json.
* - Create Project from Extension Template
- Create an ESP-IDF project using one of the extension template projects.
* - Create New ESP-IDF Component
Expand Down
19 changes: 18 additions & 1 deletion docs_espressif/en/configureproject.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,24 @@ For code navigation and C/C++ syntax highlighting, you can use `Microsoft C/C++

Usually C/C++ language extensions rely on a file called ``compile_commands.json``, which is located in your project build directory. You can generate this file using the ``ESP-IDF: Run idf.py reconfigure task``.

For LLVM clangd extension, only ``compile_commands.json`` is needed. For Microsoft C/C++ extension, a configuration file is located at ``{PROJECT_DIRECTORY_PATH}/.vscode/c_cpp_properties.json``. This file can be generated by creating a project using ``ESP-IDF: New Project``, ``ESP-IDF: Show Example Projects`` command, or by using the ``ESP-IDF: Add .vscode Configuration Folder`` command on an existing ESP-IDF projects.
For `LLVM clangd extension <https://marketplace.visualstudio.com/items?itemName=llvm-vs-code-extensions.vscode-clangd>`_, the user can use the ``ESP-IDF: Configure project for ESP-Clang`` to configure this extension argument.
The command will search for ``esp-clang`` in the configured ESP-IDF setup, the build directory from ``idf.buildPath`` (``idf.buildPathWin`` in Windows) and the GCC toolchain path from current ``IDF_TARGET`` and configured ESP-IDF setup and use these paths to configure clang path and arguments.

The result looks like this:

.. code-block:: JSON

{
"clangd.path": "/Users/user/.espressif/tools/esp-clang/esp-18.1.2_20240912/esp-clang/bin/clangd",
"clangd.arguments": [
"--background-index",
"--query-driver=/Users/user/.espressif/tools/xtensa-esp-elf/esp-14.2.0_20241119/xtensa-esp-elf/bin/xtensa-esp32-elf-gcc",
"--compile-commands-dir=/path/to/esp-idf-project/build"
]
}


For `Microsoft C/C++ extension <https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools>`_, a configuration file is located at ``{PROJECT_DIRECTORY_PATH}/.vscode/c_cpp_properties.json``. This file can be generated by creating a project using ``ESP-IDF: New Project``, ``ESP-IDF: Show Example Projects`` command, or by using the ``ESP-IDF: Add .vscode Configuration Folder`` command on an existing ESP-IDF projects.

The file structure is as follows:

Expand Down
5 changes: 2 additions & 3 deletions l10n/bundle.l10n.es.json
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@
"Launch Websocket server and IDF Monitor": "Inicie el servidor Websocket y el monitor IDF",
"Start/Stop QEMU Server": "Iniciar/detener el servidor QEMU",
"Configure ESP-IDF Extension": "Configurar la extensión ESP-IDF",
"esp-clang not found in PATH. Make sure esp-clang is installed.": "No se ha encontrado a esp-clang en PATH. Verifique la instalación de esp-clang.",
"Select current ESP-IDF version": "Seleccione la versión actual de ESP-IDF",
"Show Examples": "Mostrar ejemplos",
"New Project Wizard": "Asistente para nuevos proyectos",
Expand Down Expand Up @@ -203,9 +204,7 @@
"Yes": "Sí",
"No": "No",
"Starting ESP-IDF settings cleanup...": "Iniciando limpieza de configuraciones ESP-IDF...",
"Removed global setting: {0}": "Configuración global eliminada: {0}",
"Removed workspace setting: {0}": "Configuración del espacio de trabajo eliminada: {0}",
"Removed workspace folder setting: {0}": "Configuración de la carpeta del espacio de trabajo eliminada: {0}",
"Removed {0} setting: {1}": "Configuración {0} eliminada: {1}",
"Warning: Could not fully remove setting {0}: {1}": "Advertencia: No se pudo eliminar completamente la configuración {0}: {1}",
"ESP-IDF settings removed successfully.": "Configuraciones de ESP-IDF eliminadas exitosamente.",
"Failed to remove settings: {0}": "Error al eliminar las configuraciones: {0}",
Expand Down
5 changes: 2 additions & 3 deletions l10n/bundle.l10n.pt.json
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@
"Flash with DFU": "Flash com DFU",
"Launch Websocket server and IDF Monitor": "Inicie o servidor Websocket e o IDF Monitor",
"Start/Stop QEMU Server": "Iniciar/parar servidor QEMU",
"esp-clang not found in PATH. Make sure esp-clang is installed.": "esp-clang não encontrado em PATH. Certifique-se de que o esp-clang está instalado.",
"Configure ESP-IDF Extension": "Configurar extensão ESP-IDF",
"Select current ESP-IDF version": "Selecione a versão atual do ESP-IDF",
"Show Examples": "Mostrar exemplos",
Expand Down Expand Up @@ -203,9 +204,7 @@
"Yes": "Sim",
"No": "Não",
"Starting ESP-IDF settings cleanup...": "Iniciando limpeza das configurações ESP-IDF...",
"Removed global setting: {0}": "Configuração global removida: {0}",
"Removed workspace setting: {0}": "Configuração do espaço de trabalho removida: {0}",
"Removed workspace folder setting: {0}": "Configuração da pasta do espaço de trabalho removida: {0}",
"Removed {0} setting: {1}": "Configuração ${0} removida: {1}",
"Warning: Could not fully remove setting {0}: {1}": "Aviso: Não foi possível remover completamente a configuração {0}: {1}",
"ESP-IDF settings removed successfully.": "Configurações ESP-IDF removidas com sucesso.",
"Failed to remove settings: {0}": "Falha ao remover configurações: {0}",
Expand Down
5 changes: 2 additions & 3 deletions l10n/bundle.l10n.ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@
"Flash with DFU": "Прошивка через DFU",
"Launch Websocket server and IDF Monitor": "Запуск сервера Websocket и монитора IDF",
"Start/Stop QEMU Server": "Запуск/остановка сервера QEMU",
"esp-clang not found in PATH. Make sure esp-clang is installed.": "esp-clang не найден в PATH. Убедитесь, что esp-clang установлен.",
"Configure ESP-IDF Extension": "Настройка расширения ESP-IDF",
"Select current ESP-IDF version": "Выбор текущей версии ESP-IDF",
"Show Examples": "Показать примеры",
Expand Down Expand Up @@ -203,9 +204,7 @@
"Yes": "Да",
"No": "Нет",
"Starting ESP-IDF settings cleanup...": "Начинается очистка настроек ESP-IDF...",
"Removed global setting: {0}": "Удалена глобальная настройка: {0}",
"Removed workspace setting: {0}": "Удалена настройка рабочего пространства: {0}",
"Removed workspace folder setting: {0}": "Удалена настройка папки рабочего пространства: {0}",
"Removed {0} setting: {1}": "Удалена {0} настройка: {1}",
"Warning: Could not fully remove setting {0}: {1}": "Предупреждение: Не удалось полностью удалить настройку {0}: {1}",
"ESP-IDF settings removed successfully.": "Настройки ESP-IDF успешно удалены.",
"Failed to remove settings: {0}": "Не удалось удалить настройки: {0}",
Expand Down
5 changes: 2 additions & 3 deletions l10n/bundle.l10n.zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@
"Flash with DFU": "通过 DFU 接口烧录项目",
"Launch Websocket server and IDF Monitor": "启动 WebSocket 服务器和 IDF 监视器",
"Start/Stop QEMU Server": "启动/停止 QEMU 服务器",
"esp-clang not found in PATH. Make sure esp-clang is installed.": "在 PATH 中未找到 esp-clang。请确保已安装 esp-clang。",
"Configure ESP-IDF Extension": "配置 ESP-IDF 扩展",
"Select current ESP-IDF version": "选择当前的 ESP-IDF 版本",
"Show Examples": "展示示例项目",
Expand Down Expand Up @@ -203,9 +204,7 @@
"Yes": "是",
"No": "否",
"Starting ESP-IDF settings cleanup...": "正在开始清理ESP-IDF设置...",
"Removed global setting: {0}": "已删除全局设置:{0}",
"Removed workspace setting: {0}": "已删除工作区设置:{0}",
"Removed workspace folder setting: {0}": "已删除工作区文件夹设置:{0}",
"Removed {0} setting: {1}": "已删除 {0} 设置:{1}",
"Warning: Could not fully remove setting {0}: {1}": "警告:无法完全删除设置 {0}:{1}",
"ESP-IDF settings removed successfully.": "ESP-IDF设置已成功删除。",
"Failed to remove settings: {0}": "删除设置失败:{0}",
Expand Down
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -1756,6 +1756,11 @@
"title": "%espIdf.hexView.deleteElement.title%",
"category": "ESP-IDF",
"icon": "$(trash)"
},
{
"command": "espIdf.setClangSettings",
"title": "%espIdf.setClangSettings.title%",
"category": "ESP-IDF"
}
],
"breakpoints": [
Expand Down
1 change: 1 addition & 0 deletions package.nls.es.json
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@
"espIdf.selectNotificationMode.title": "Seleccionar modo de notificación y salida",
"espIdf.selectOpenOcdConfigFiles.title": "Seleccionar archivos de configuración de placa OpenOCD",
"espIdf.selectPort.title": "Seleccionar puerto a usar (COM, tty, usbserial)",
"espIdf.setClangSettings.title": "Configurar el proyecto para usar ESP-Clang",
"espIdf.setGcovConfig.title": "Configurar SDKConfig del proyecto para cobertura",
"espIdf.setMatterDevicePath.title": "Establecer Ruta del Dispositivo ESP-MATTER (ESP_MATTER_DEVICE_PATH)",
"espIdf.setTarget.title": "Establecer Objetivo del Dispositivo Espressif",
Expand Down
1 change: 1 addition & 0 deletions package.nls.json
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@
"espIdf.selectNotificationMode.title": "Select Output and Notification Mode",
"espIdf.selectOpenOcdConfigFiles.title": "Select OpenOCD Board Configuration",
"espIdf.selectPort.title": "Select Port to Use (COM, tty, usbserial)",
"espIdf.setClangSettings.title": "Configure project for ESP-Clang",
"espIdf.setGcovConfig.title": "Configure Project SDKConfig for Coverage",
"espIdf.setMatterDevicePath.title": "Set ESP-MATTER Device Path (ESP_MATTER_DEVICE_PATH)",
"espIdf.setTarget.title": "Set Espressif Device Target",
Expand Down
1 change: 1 addition & 0 deletions package.nls.pt.json
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@
"espIdf.selectNotificationMode.title": "Selecione o modo de saída e notificação",
"espIdf.selectOpenOcdConfigFiles.title": "Selecione a configuração da placa OpenOCD",
"espIdf.selectPort.title": "Selecione a porta a ser usada (COM, tty, usbserial)",
"espIdf.setClangSettings.title": "Configurar o projeto para ESP-Clang",
"espIdf.setGcovConfig.title": "Configurar o projeto SDKConfig para cobertura",
"espIdf.setMatterDevicePath.title": "Definir caminho do dispositivo ESP-MATTER (ESP_MATTER_DEVICE_PATH)",
"espIdf.setTarget.title": "Definir destino do dispositivo Espressif",
Expand Down
1 change: 1 addition & 0 deletions package.nls.ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@
"espIdf.selectNotificationMode.title": "Выбор режима вывода и уведомлений",
"espIdf.selectOpenOcdConfigFiles.title": "Выбор конфигурации платы OpenOCD",
"espIdf.selectPort.title": "Выбор порта (COM, tty, usbserial)",
"espIdf.setClangSettings.title": "Настроить проект для ESP-Clang",
"espIdf.setGcovConfig.title": "Конфигурация Project SDKConfig для покрытия",
"espIdf.setMatterDevicePath.title": "Установка пути к устройству ESP-MATTER (ESP_MATTER_DEVICE_PATH)",
"espIdf.setTarget.title": "Установка целевого устройства Espressif",
Expand Down
1 change: 1 addition & 0 deletions package.nls.zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@
"espIdf.selectNotificationMode.title": "选择输出和通知模式",
"espIdf.selectOpenOcdConfigFiles.title": "选择 OpenOCD 开发板配置",
"espIdf.selectPort.title": "选择要使用的端口 (COM、tty、usbserial)",
"espIdf.setClangSettings.title": "为 ESP-Clang 配置项目",
"espIdf.setGcovConfig.title": "配置 SDKConfig 文件以启用代码覆盖率",
"espIdf.setMatterDevicePath.title": "设置 ESP-MATTER 设备路径 (ESP_MATTER_DEVICE_PATH)",
"espIdf.setTarget.title": "设置乐鑫设备目标",
Expand Down
120 changes: 120 additions & 0 deletions src/clang/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/*
* Project: ESP-IDF VSCode Extension
* File Created: Thursday, 27th March 2025 3:04:59 pm
* Copyright 2025 Espressif Systems (Shanghai) CO LTD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { l10n, Uri, workspace } from "vscode";
import {
appendIdfAndToolsToPath,
getToolchainPath,
isBinInPath,
} from "../utils";
import { pathExists, writeJSON, writeFile } from "fs-extra";
import { readParameter } from "../idfConfiguration";
import { join } from "path";
import { Logger } from "../logger/logger";
import { parse } from "jsonc-parser";

export async function validateEspClangExists(workspaceFolder: Uri) {
const modifiedEnv = await appendIdfAndToolsToPath(workspaceFolder);

const espClangdPath = await isBinInPath(
"clangd",
workspaceFolder.fsPath,
modifiedEnv
);
return espClangdPath;
}

export async function setClangSettings(
settingsJson: any,
workspaceFolder: Uri
) {
const espClangPath = await validateEspClangExists(workspaceFolder);
if (!espClangPath) {
const error = new Error(
l10n.t("esp-clang not found in PATH. Make sure esp-clang is installed.")
);
Logger.errorNotify(
error.message,
error,
"clang index configureClangSettings"
);
return;
}
const buildPath = readParameter("idf.buildPath", workspaceFolder);
const gccPath = await getToolchainPath(workspaceFolder, "gcc");
settingsJson["clangd.path"] = espClangPath;
settingsJson["clangd.arguments"] = [
"--background-index",
`--query-driver=${gccPath}`,
`--compile-commands-dir=${buildPath}`,
];
}

export async function configureClangSettings(workspaceFolder: Uri) {
const settingsJsonPath = join(
workspaceFolder.fsPath,
".vscode",
"settings.json"
);
const settingsPathExists = await pathExists(settingsJsonPath);
if (!settingsPathExists) {
const err = new Error("settings.json not found in .vscode folder");
Logger.errorNotify(err.message, err, "clang index configureClangSettings");
return;
}
let settingsJson: any;
try {
const settingsContent = await workspace.fs.readFile(
Uri.file(settingsJsonPath)
);
settingsJson = parse(settingsContent.toString());
} catch (error) {
Logger.errorNotify(
"Failed to parse settings.json. Ensure it has valid JSON syntax.",
error,
"clang index configureClangSettings"
);
return;
}

await setClangSettings(settingsJson, workspaceFolder);

await writeJSON(settingsJsonPath, settingsJson, {
spaces: workspace.getConfiguration().get("editor.tabSize") || 2,
});

await createClangdFile(workspaceFolder);
}

export async function createClangdFile(workspaceFolder: Uri) {
const clangdFilePath = join(workspaceFolder.fsPath, ".clangd");
const clangdContent = `CompileFlags:
Remove: [-f*, -m*]
`;

try {
await writeFile(clangdFilePath, clangdContent, { encoding: "utf8" });
Logger.infoNotify(".clangd file created successfully.");
} catch (error) {
Logger.errorNotify(
"Failed to create .clangd file.",
error,
"clang index createClangdFile"
);
}
}
16 changes: 15 additions & 1 deletion src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ import {
HexTreeItem,
HexViewProvider,
} from "./cdtDebugAdapter/hexViewProvider";
import { configureClangSettings } from "./clang";

// Global variables shared by commands
let workspaceRoot: vscode.Uri;
Expand Down Expand Up @@ -1235,10 +1236,12 @@ export async function activate(context: vscode.ExtensionContext) {
commandDictionary[CommandKeys.SelectFlashType].iconId
}) ${flashType}`;
}
} else if (e.affectsConfiguration("idf.buildPath")) {
} else if (e.affectsConfiguration("idf.buildPath" + winFlag)) {
updateIdfComponentsTree(workspaceRoot);
await configureClangSettings(workspaceRoot);
} else if (e.affectsConfiguration("idf.customExtraVars")) {
await getIdfTargetFromSdkconfig(workspaceRoot, statusBarItems["target"]);
await configureClangSettings(workspaceRoot);
}
});

Expand Down Expand Up @@ -2521,6 +2524,17 @@ export async function activate(context: vscode.ExtensionContext) {
});
});

registerIDFCommand("espIdf.setClangSettings", async () => {
PreCheck.perform([openFolderCheck], async () => {
await configureClangSettings(workspaceRoot);
vscode.window.showInformationMessage(
vscode.l10n.t(
"ESP-IDF: Clang settings have been configured for the project."
)
);
});
});

registerIDFCommand("espIdf.apptrace", () => {
PreCheck.perform([webIdeCheck, openFolderCheck], async () => {
const appTraceLabel =
Expand Down
1 change: 1 addition & 0 deletions src/idfToolsManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ export class IdfToolsManager {
const packagesToInstall = this.allPackages.filter((pkg) => {
return (
pkg.install === "always" ||
pkg.name === "esp-clang" ||
(onReqPkgs &&
pkg.install === "on_request" &&
onReqPkgs.indexOf(pkg.name) > -1)
Expand Down
2 changes: 2 additions & 0 deletions src/newProject/newProjectPanel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { IExample } from "../examples/Example";
import { setCurrentSettingsInTemplate } from "./utils";
import { NotificationMode, readParameter } from "../idfConfiguration";
import { IdfSetup } from "../views/setup/types";
import { createClangdFile } from "../clang";

export class NewProjectPanel {
public static currentPanel: NewProjectPanel | undefined;
Expand Down Expand Up @@ -301,6 +302,7 @@ export class NewProjectPanel {
openOcdConfigs,
workspaceFolder
);
await createClangdFile(vscode.Uri.file(newProjectPath));
await writeJSON(settingsJsonPath, settingsJson, {
spaces: 2,
});
Expand Down
2 changes: 2 additions & 0 deletions src/newProject/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { readJSON } from "fs-extra";
import { Uri } from "vscode";
import { IdfSetup } from "../views/setup/types";
import { getSystemPythonFromSettings } from "../pythonManager";
import { setClangSettings } from "../clang/index";

export async function setCurrentSettingsInTemplate(
settingsJsonPath: string,
Expand Down Expand Up @@ -68,5 +69,6 @@ export async function setCurrentSettingsInTemplate(
settingsJson["idf.customExtraVars"] = settingsJson["idf.customExtraVars"] || {};
settingsJson["idf.customExtraVars"]["IDF_TARGET"] = selectedIdfTarget;
}
await setClangSettings(settingsJson, workspace);
return settingsJson;
}
2 changes: 2 additions & 0 deletions src/project-conf/ProjectConfigurationManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { createStatusBarItem } from "../statusBar";
import { getIdfTargetFromSdkconfig } from "../workspaceConfig";
import { Logger } from "../logger/logger";
import { getProjectConfigurationElements } from "./index";
import { configureClangSettings } from "../clang";

export class ProjectConfigurationManager {
private readonly configFilePath: string;
Expand Down Expand Up @@ -359,6 +360,7 @@ export class ProjectConfigurationManager {
this.statusBarItems["target"]
);
await setCCppPropertiesJsonCompileCommands(this.workspaceUri);
await configureClangSettings(this.workspaceUri);
ConfserverProcess.dispose();
}

Expand Down
Loading