Подключение компилятора к VS Code и CLion на примере Microchip XC8

Дисклеймер.

Это статья всего лишь нагромождение моего опыта и попыток подключения малоизвестного компилятора к IDE общего назначения, она не является руководством КАК СДЕЛАТЬ, скорее для помощи и экономии времени тех, кто имеет схожие цели.
Описываемый процесс написан чайником и предназначен для совсем чайников, может иметь имеет неточности, ошибки, использование магии и прямое вранье во имя упрощения. Если вам интересно как это действительно правильно работает и что под капотом — перепроверяйте и читайте официальные гайды.
Тут будет много «не знаю как это работает, но я так сделал и оно заработало».

Настройка CLion в отдельной статье, имеющей зависимости от этой.

Интро или «Нахрена?»

Я за время своего ковыряния с различными микроконтроллерами, не уставал удивляться насколько дефолтные IDE ужасные и отсталые при работе с кодом. Базовая подсветка и топорное автодополнение уже являются счастьем. А если они еще и работают, а подсветка ошибок не заливает пол экрана ввиду битых референсов — так вообще праздник.
И это все в то время как в Visual Studio 2019 и прочих, программисты C# объедаются вкуснейшими code snippet'ами и автодополнением, которое позволяет писать код водя бананом по клавиатуре.

К тому же многие IDE любят использовать собственную неведомую генерацию makefile и при желании хоть как то автоматизировать сборку дают 2 варианта: поддерживать 2 независимых (для IDE и внешнюю) описания сборки, либо прирастать к мейкфалу генерируемому самой IDE. Про сборку через CMake обычно даже слышать не приходиться.

Последней каплей наверно стало, когда выкупивший Atmel Microchip отказался от поддержки Atmel Studio 7, являющийся наверно самой адекватной из всего зоопарка «микроконтроллерных IDE» и стал переводить все на свою богомерзкую MPLABX полную багов, тормозов и прочего говна.

Было решено перемочь и изучить CMake хотя бы на базовом уровне, после чего совершить переезд на вменяемую студию.
Требования были следующие:
  • Восприятие внешней системы сборки без костылей и ее полная интеграция.
  • Отображение ошибок синтаксиса и сборки с свистелками и перделками.
  • Рабочая и не тормозящая проверка синтаксиса.
  • Рабочее и не тормозящее автодополнение, с зайчатками разума.
  • Отсутствие битых зависимостей и заголовочников.
  • Хотя бы какой-то контроль стиля кода.


Кандидаты

Я к своему стыду являюсь заядлым виндузятником и не могу без боли и отвращения братского понимания воспринимать линуксовские GUI, а потому, когда Eclipse отказался перемещать текстовый курсор при ПКМ, я его удалил, закончив свое знакомство на 5й минуте.

После быстрого поиска, стало ясно, что само сообщество С\С++ программистов судя по всему не особо нуждается в чем то подобном, а мои требования скорее «изнеженный каприз» презираемый опытным боевыми кодерами, хреначащими 3 каста массива указателей функций с вызовом в одну строку.

Человек не смог выйти из VIM, узнай что с ним стало...


В итоге, исключая IDE с морально устаревшими, либо не подходящими мне интерфейсами, получился очень не густой список (со спойлерами):
  • Visual Studio — лучший вариант и моя мечта. Не осилил, CMake проект завелся и собрался, но с кучей ошибок и потерянных зависимостей в самом редакторе. Добиться чего-либо от офф поддержки невозможно. Обещают в 2022 качественный завоз поддержки эмбеддед, но пока все очень не понятно и криво. Гуглятся какие-то официальные стать, где для VCPKG, VCPKG И ГОТОВО!
  • VisualGDB for Visual Studio — плагин, который хочет денег, магически делает все хорошо, но завязывает вас на себе и на собственной структуре проекта с разбиением *.h и *.с файлов в разных папках, делает полную реконфигурацию проекта по каждому чиху, что на проекте из 100-200 файлов может занимать минуты, дико тормозит и любит ломаться. Пробовал еще давно — ну нахрен.
  • Visual Studio Code — успех, но ввиду жабс родословной, отказался ввиду того, что не умеет искать ошибки в закрытых файлах, не умеет в вменяемый docking и самое важное — не умеет refactoring-rename между файлам, что и поставило жирный крест.
  • CLion — успех, но просит денех. Несмотря на платность, имеет на мой взгляд кучу недостатков, например так же не умеет в полноценное второе окно и docking всяких радостей в него.
  • QT Creator — так и не заставил себя попробовать. ПТСР от эклипса еще очень свежо.


Пререквизиты

То, что я имел в начале.
  • Установленные и работающие из под консольки система автоматизации сборки CMake и собственно система сборки Ninja
  • Ваш компилятор, который успешно вызывается в консольки без указания пути, а значит внесенный в системную переменную PATH
    
    PS C:\> xc8
    G:\Toolchains\XC8\2.35\pic\bin\picc
    Microchip MPLAB XC8 C Compiler V2.35
    Build date: Dec  6 2021
    Part Support Version: 2.35
    Copyright (C) 2021 Microchip Technology Inc.
    (880) invalid number of parameters. Use "XC8 --HELP" for help
    (908) exit status = 1
    

  • Toolchain.cmake файл вашего компилятора для кросс компиляции — я делал свои, но они получались очень кривенькие и косые, в итоге, нашел проект, которым и воспользовался. CMake XC8 Toolchain. Скорее всего для вашего компилятора есть что то похожее. Иначе — придется разобраться самому, к сожалению, вменяемой инфы для быстрого старта очень не густо.
  • Проект, использующий этот Toolchain.cmake и собираемый CMake из консоли.

Проект содержит простейший цикл, который задействует заголовочные файлы процессора и т.н. системные заголовочные файлы.
Этот код не предназначен для работы в железе, прерывание никогда не выстрелит, только для демонстрации работы IDE.
gpio.h вынесен не просто так, позже на его примере будет показана проблема и ее решение.


main.c

#include <xc.h>        	/* PIC MCU headers */

#include <stdint.h>		/* System lib headers */
#include <stdbool.h>     

#include "gpio.h"

volatile uint8_t i = 0;

void __interrupt(low_priority)  LowISR(void)
{
   i = 0;
}

void main(void)
{	
    while(1) {
      i++;
      bool is_some_condition = (i == 0);
		
      if(is_some_condition ) { SetGPIO(true); }
      else { SetGPIO(false); }
   }
}

gpio.c\h

#include <xc.h>
#include <stdbool.h>

void SetGPIO(bool new_state)
{
   LATCbits.LATC2 = new_state;
}



И CMake файл, с простейшими указаниями.
cmake_minimum_required(VERSION 3.20)
set(CMAKE_TOOLCHAIN_FILE external/cmake-microchip/toolchain.cmake)
set(MICROCHIP_MCU PIC18F97J60)
project(xc8-cmake C)
set(TARGET_NAME "XC8_CMake_project")
add_executable(${TARGET_NAME} main.c gpio.c gpio.h)


Внимание к cmake_minimum_required(VERSION 3.20), у меня при версии выше 3.21 выдавались очень не понятные ошибки, слабо указывающие на зависимость от этого параметра. Может «шарящим» людям ясно из-за чего, но для меня это магия, в которую я пока не погружался.

set(CMAKE_TOOLCHAIN_FILE external/cmake-microchip/toolchain.cmake)
Это магическая переменная CMake, куда загружен относительный путь к моему Toolchain файлу.

set(MICROCHIP_MCU PIC18F97J60) Определение процессора, для которого производится сборка. Это требует конкретно мой тулчейн.

Все это дело, я собираю из консоли простейшими командами.
cd C:/path/to/my/project/folder
cmake -S ./ -B ./build -G "Ninja"
ninja -C ./build


Где:
  • cmake -S ./ -B ./build -G «Ninja» инициализация CMake (не спрашиваете, что это, я не знаю)
  • "-S ./" относительный путь к файлу CMakeLists.txt, который в моем случае находится в корне проекта.
  • "-B ./build" относительный путь к директории, куда будет произведена инициализация CMake.
  • "-G «Ninja» указание генератора, модные хипстеры говорят мейкфайл говно, а ninja круто, так что выберем этот симплдимпл.
  • «ninja -C ./build» запуск сборки, где "-C ./build" путь к директории с сгенерированными файлами.

И собственно как итог всего действа:

PS H:\Learn\XC8_Cmake> cmake -S ./ -B ./build -G "Ninja"
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: G:/Toolchains/XC8/2.35/bin/xc8-cc.exe - skipped
-- Configuring done
-- Generating done
-- Build files have been written to: H:/Learn/XC8_Cmake/build
PS H:\Learn\XC8_Cmake> ninja -C ./build
ninja: Entering directory `./build'
[3/3] Linking C executable XC8_CMake_project.elf

Memory Summary:
    Program space        used    86h (   134) of 1FFF8h bytes   (  0.1%)
    Data space           used     7h (     7) of   EE0h bytes   (  0.2%)
    Configuration bits   used     0h (     0) of     3h words   (  0.0%)

PS H:\Learn\XC8_Cmake>


На этом мы имеем проект, собирающийся из консоли. Который будет использован как базовый, для подключения к различным IDE.

Visual Studio Code

Помимо самой студии, потребуется установить минимум 2 расширения.
  • C/C++ for Visual Studio Code от Microsoft
  • CMake Tools от Microsoft

Сама студия имеет несколько дополнительных сущностей.
*.code-workspace файл, который фактически является файлом проекта и содержит настройки «всей фигни» для работы в VS Code.
.vscode директорию, где в отдельных *.json хранятся настройки конкретных плагинов или куски настроек выдранные из *.workspace
Вроде! Все можно вписывать и в файл воркспейса, предварительно создав map'ы с именами аналогичные именам файлов в .vscode, но это не точно. Другие причины, кроме удобства подобного разбиения, мне не известны.

И так, первым делом, надо Open folder... корень проекта, после чего Save workspace as ..., что создаст файл воркспейса.
Во время открытия, студия будет спамить всплывающими окнами, в том числе предлагая сконфигурировать проект под CMake — отказывается или игнорим. У меня такая штука сломала все труды и я так не разобрался почему, потратив несколько часов, закончившиеся очищением того, что оно добавило в конфиг.

После чего можно оглядеть проект из IDE.

Глядя в окно output, можно увидеть, что CMakeLists.txt автоматически подцепился и сконфигурировался.
А ПКМ по CMakeLists.txt -> Build All Projects даже запустит и успешно завершит сборку. Казалось бы успех…

Но если чуточку поковыряться, можно заметить:
  • xc.h не найден, а значит никакого автокомплита по регистрам и макросам компилятора и самого МК.
  • Синтаксические ошибки не будут подсвечены, кроме ошибок поиска заголовочных файлов. И это проблема. VS Code не будет задействовать intellisense пока не будут разрешены ошибки заголовочников. (но даже если вы их разрешите — см. ниже)
  • Прагмы, дефайны и спецсимволы компилятора аля __interrupt(low_priority) будут неизвестны и в лучшем случае светится ошибкой, в худшем рушить синтаксические конструкции и вызывать кучи ошибок в самых неожиданных местах.
  • Системные заголовочники будут видимы, но при CTRL+ЛКМП по ним, вы попадете в папку какого-нибудь MSVC. В принципе с этим нет проблем, интерфейс стандартных библиотек везде одинаковый, а их использование IDE, не значит их использование компилятором, как и наоборот, вот этот момент надо всегда держать в уме. Но проблема в том, что там могут быть не только системные, но и другие заголовочные файлы, у меня это был gpio.h Что вызывало невидимость void SetGPIO(bool new_state)
    для IDE и ошибку отсутствия определения. У вас похожая проблема может не возникнуть или возникнуть не сразу.

Ок. Пытаемся решить.
ВНИМАНИЕ: Студия жабсовая и дурная, она может менять настройки при сохранении файла, а может хотеть рестарта, а может вообще их применять спустя несколько десятков секунд, потому что пошел на хрен.
Благо перезапускается она за секунды.

Для начала надо в файле воркспейса вписать строку, включающую отображение ошибок C++, что бы получилось так:
{
	"folders": [
		{
			"path": "."
		}
	],
	"settings": {
		"C_Cpp.errorSquiggles": "Enabled",	// Включить отображение ошибок???? 
		"C_Cpp.intelliSenseUpdateDelay": 500,	// Задержка после редактирования файла, перед началом парсинга intellisense.
		"C_Cpp.intelliSenseEngineFallback": "Enabled",	// Не знаешь - не трожь!
		"C_Cpp.autocompleteAddParentheses": true, // Описание при наведении
	}
}

В отдельности это ничего не изменит, но потребуется для дальнейшего. (а может не потребуется, черт знает)

Далее, в корне проекта, в папке .vscode надо создать файл c_cpp_properties.json. Если папки не появилось, это норма, ее надо создать руками.
И копируем туда следующий жабсон код
{
    "version": 4, // Версия жабсон, спросите у фронтендеров зачем она

    "configurations": [
        { 
            "name": "Win32",    // Указание платформы компилятора, хз на что влияет. Не знаешь - не трогай!
            "includePath": [    // Пути где Intellisense будет искать заголовочники (** значит рекурсивно всю внутрянку)
                "${workspaceFolder}/**",                // Корень нашего проекта
                "G:/Toolchains/XC8/2.35/pic/include/**" // Заголовочники компилятора
            ],

            // Файлы которые будут считаться заинклуженными поверх всех остальных.
            // Исправляем зависимость от MSVCшного gpio.h
            "forcedInclude": [
                "${workspaceFolder}/gpio.h"
            ],
            
            // Определенные символы, которые будут включены по принципу
            //  #define ${string}
            // Причем просто имя задефайнит его единицей, для пустого дефайна надо поставить "="
            "defines": [
                "_DEBUG",       // #define _DEBUG 1
                "__XC",         // #define __XC 1
                "__XC8",
                "__XC8_VERSION=2000",   // #define __XC8_VERSION 2000
                "_18F97J60",
                "__PICC18__",
                "high_priority=",       // #define high_priority
                "low_priority=",
                "__interrupt(x)=",      // #define __interrupt(x)
                "_XTAL_FREQ=41666666",  // #define _XTAL_FREQ 41666666
                "__bit=",               // #define __bit
                "__near="
            ],
            // Путь до exe компилятора, вообще он не очень то здесь и нужен. (вроде)
            "compilerPath": "G:/Toolchains/XC8/2.35/bin/xc8-cc.exe",
            "cStandard": "c99",
            "cppStandard": "c++98",
             // Как-то влияет на режимы intellisense, при наличии 
             // дурных ошибок подсвеченных в IDE, которые однако без проблем съедает компилятор, стоит попробовать поиграться этим значением.
             // Варианты должно быть можно вызвать через CTRL+SPACE
            "intelliSenseMode": "clang-x86",

            // Путь к файлам, которые подвергаются парсингу intellisens'ом
            "browse": {
                "path": [
                    "${workspaceFolder}/**",
                    "G:/Toolchains/XC8/2.35/pic/include/**" // Заголовочники компилятора, почему 2 раза? Иначе не работает!
                ]
            }
        }
    ]
}


После этого основные мои проблемы с VS Code закончились. Скорее всего у вас буду ваши, свои собственные, возможно описанное выше не решит их, но пусть оно будет хотя бы дополнительной информацией.

«Ментальные вызовы» VS Code

Помимо основных проблем, были еще мелкие:

1. Intellisense ТОРМОЗИЛЛЛллллллл, между изменением файла и окончанием парсинга проходили десятки секунд. Увы нормально не лечится, на гите вскода тикеты висят годами, после чего ехидный модер их закрывает с пометкой «наверно само вылечилось уже», но их позже переоткрывают энжой йор жабс. У меня была проблема, что заголовочники компилятора обильны и велики числом, особенно заголовки самих МК. В итоге, специально для IDE, я вынес их в папку с проектом, обрезал там все, что не требовалось моему процу и перенаправил пути инклудов IDE в жабсон туда.
2. Отображение ошибок лишь в открытых файлах. Не лечится. На гите вскода сказали, что и не будет в ближайшем будущем. энжой йор жабс
3. Отсутствие Refactor -> Rename по всему проекту. См. пункт 2. энжой йор жабс

Аутро

После микропроблемы пункта 3, была в ярости удалена, а ярость перенаправлена в русло борьбы с CLion, которое вроде завершилось успехом и будет описано позднее.
А вот и она.

Примерно с этого момента можно начать наслаждаться удобной IDE, платить подписку и делать уже что то полезное.

Мне согласился помочь доброжелатель описав настройку под QT Creator, так что думаю в скором времени будет дополнение.
Если есть желание и возможность уточнить технические, орфографические и пунктуационные моменты или описать дополнительные проблемы, решения, тонкости — буду очень рад.

Благодарности

Спасибо множеству людей из t.me/supapro и t.me/probuildsystems слушавшим мое нытье и глупые вопросы, не скупившимся на объяснение и помощь, на протяжении нескольких месяцев, пока я осиливал несколько этих строчек конфигурации IDE.
  • +1
  • 03 февраля 2022, 19:27
  • ReasonX

Комментарии (2)

RSS свернуть / развернуть
Проверил файл c_cpp_properties.json с помощью 'online' JSON отладчика JSON Formatter & Validator, посыпались ошибки. Почему так?
0
Насколько мне известно, базовое соглашение о JSON не подразумевает наличие комментариев. Но большинство парсеров их есть, среди них парсер VS Code.

PS там действительно была 1 ошибка с запятой, поправил.
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.