Скетч не компилируется: словарь сообщений компилятора Arduino IDE
Скетч с форума обещал работающий термометр за вечер. Код скопирован, вставлен в чистое окно Arduino IDE, нажата кнопка с галочкой — и внизу, под редактором, вырастает столбик красного текста, а в самом конце притулилась лаконичная подпись exit status 1. Именно так выглядит первое знакомство большинства новичков с компилятором. Хорошая новость: красный столбик — не приговор, а протокол с адресами. Почти каждая строка в нём называет файл, строку и причину; загвоздка в том, что пишет компилятор по-английски и буквально, а новичок ищет в этом тексте магию.
Ниже — словарь из десяти самых частых сообщений: что компилятор хочет сказать формулами вроде expected ; или was not declared in this scope, почему IDE красит не ту строку и как за две минуты добраться до виновника. Куда копать глубже — анатомия строки лога и каскады сообщений — разобраны в отдельном уроке про чтение лога компиляции; эта страница — про быстрое лечение.
Как читать панель сообщений: суть — внизу, причина — выше
Панель сообщений в IDE 2 — вкладка «Вывод» внизу окна. Читать её стоит сверху вниз, а не снизу: последняя строка — почти всегда exit status 1, пустая подпись о том, что сборка закончилась провалом, без единого намёка на причину. Причина живёт выше — в первой красной строке. Клик по ней прыгает курсором на место в скетче: файл, строка и столбец указаны прямо в сообщении. В классической IDE 1.8 красный текст вываливается в то же нижнее окно, логика та же — первая красная строка главнее последней.
Таблица: сообщение компилятора → причина → лечение
Перед разбором столбика сделайте одну вещь: убедитесь, что среда вообще знает, для чего собирать. В меню Инструменты → Плата должно стоять настоящее имя железа, а не серое «не выбрана» — без платы сборка падает на первых же шагах, и красный текст будет про настройку, а не про код. Если список пуст или имя перепутано, начните с урока про выбор платы и порта. Дальше — таблица: слева фраза из лога, в середине перевод на человеческий, справа действие.
| Что пишет компилятор | Что это значит | Что делать |
|---|---|---|
| expected ; before X | Пропущена точка с запятой — в строке выше той, что покраснела: компилятор замечает пропуск, когда началась следующая инструкция | Дописать ; в конец предыдущей строки и глянуть на соседние |
| X was not declared in this scope | Имя компилятору незнакомо: опечатка, другой регистр, не подключена библиотека — либо переменная объявлена внутри setup() и в loop() её нет | Сверить имя и регистр с объявлением, проверить include, вынести переменную в начало файла |
| expected unqualified-id before X | Конструкция сломалась строкой выше: незакрытая скобка, точка с запятой после заголовка функции или код, вынесенный за пределы setup() и loop() | Проверить баланс скобок в строках выше; осиротевший код вернуть внутрь функций |
| expected } at end of input | Не хватает закрывающей фигурной скобки: компилятор дошёл до конца файла, так и не закрыв блок | Прогнать автоформатирование и посчитать пары скобок |
| fatal error: имя.h: No such file or directory | Библиотека из строки include не установлена — либо имя написано не точно, вплоть до регистра букв | Поставить библиотеку через Менеджер и скопировать название из его карточки буква в букву |
| fatal error: WProgram.h: No such file or directory | Библиотека выпущена до Arduino 1.0: главный файл среды тогда назывался WProgram.h, с 2011 года — Arduino.h | Заменить в include WProgram.h на Arduino.h или поискать свежую версию библиотеки |
| stray 342 in program | В коде байт вне ASCII: длинное тире вместо минуса, фигурные кавычки или русская буква, прилетевшие из буфера обмена | Перепечатать отмеченную строку с клавиатуры; русский текст оставить в комментариях и строках печати |
| exit status 1 | Итоговая строка протокола: сборка закончилась провалом, причина выше — само сообщение ничего не называет | Листать панель сообщений вверх до первой красной строки |
| too few arguments to function | Функция вызвана с меньшим числом аргументов, чем в её объявлении: например, attach() без номера пина | Открыть объявление функции и повторить полный список аргументов |
| X has no member named Y | У класса нет такого метода: версия библиотеки другая или перепутана похожая библиотека | Сверить имя метода с примером из карточки библиотеки; обновить или сменить библиотеку |
Скопированный скетч: тире вместо минуса и потерянная скобка
Два самых массовых виновника в коде вообще не видны — они прилетают из буфера обмена. Первый: форумы и текстовые процессоры тихо меняют минус на длинное тире, а прямые кавычки на фигурные — глаз читает, компилятор видит байты вне ASCII и отказывается работать. Второй: потерянная скобка, фигурная или круглая, — компилятор спотыкается несколькими строками ниже и красит безупречную строку, поэтому скобки ищут парами, а не взглядом в красную строку. Русский текст при этом разрешён, но только в комментариях и внутри строк печати; в самом коде — латиница и ничего кроме. Ниже один и тот же скетч до правки (закомментирован) и после двух минут работы руками:
/* С ФОРУМА ПРИЕХАЛО ТАК — сборка падает:void setup() { Serial.begin(9600) // точка с запятой потерялась int t = analogRead(A0) — 200; // тире вместо минуса: в логе stray 342 if (t > 0) { Serial.println(t);} // скобка блока if так и не закрылась}*/ // ПОСЛЕ ПРАВКИ — соберётся с первого раза:void setup() { Serial.begin(9600); // точка с запятой вернулась int t = analogRead(A0) - 200; // минус набран с клавиатуры if (t > 0) { Serial.println(t); } // каждой { досталась своя }}void loop() {}Если красная строка начинается с No such file — дело в библиотеке. Ставится она в два клика через встроенный Менеджер: Скетч → Подключить библиотеку → Управлять библиотеками; как устроен этот каталог и чем он лучше ручного копирования в папку libraries, рассказано в уроке про библиотеки в IDE и пошаговом разборе Менеджера. Живой пример — дисплей LCD1602 с переходником I2C: без установленной LiquidCrystal_I2C сборка падает с No such file ещё до первой строки логики, а после установки упирается в регистр букв в имени класса — полный маршрут такого подключения собран в лендинге про LCD1602 по I2C. Отдельная история — скетчи десятилетней давности: библиотеки, выпущенные до Arduino 1.0, начинаются со строки include WProgram.h, которой в современных версиях среды нет, — замена на Arduino.h оживляет половину старых находок.
После каждой правки жмите проверку снова и смотрите на первую красную строку: компилятор идёт по тексту сверху вниз, и один честный фикс гасит половину столбика — остальное было каскадом. Не пугайтесь, если после правки сообщение сменится на другое: это движение вперёд, компилятор добрался до следующего тупика. Когда сборка наконец прошла, а на этапе загрузки начались странности с портом и зависания на syncing — причина уже не в тексте скетча, а в связи с платой, и лог там другой.