Ошибка компиляции при использовании #ifdef`а
- Войдите на сайт для отправки комментариев
Пт, 20/11/2015 - 18:54
Приветствую уважаемых форумчан!
Столкнулся с непонятным мне поведением компилятора при использовании #ifdef`а...
Посмотрите первый скетч:
void setup(){ } void loop() { }
Как и ожидалось скетч успешно скомпилировался:
Sketch uses 450 bytes (1%) of program storage space. Maximum is 30 720 bytes.
Global variables use 9 bytes (0%) of dynamic memory, leaving 2 039 bytes for local variables. Maximum is 2 048 bytes.
Усложним наш скетч:
int a; void setup(){ } void loop() { }
Скетч опять успешно скомпилировался:
Sketch uses 450 bytes (1%) of program storage space. Maximum is 30 720 bytes.
Global variables use 9 bytes (0%) of dynamic memory, leaving 2 039 bytes for local variables. Maximum is 2 048 bytes.
Обложим теперь объявленную переменную #ifdef`ом:
#ifdef A int a; #endif void setup(){ } void loop() { }
Компиляция этого скетча приводит к ошибке:
Изменена опция сборки, пересобираем все
C:\Users\vlad\AppData\Local\Temp\build582594788212757414.tmp/core.a(main.cpp.o): In function `main':
C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino/main.cpp:40: undefined reference to `setup'
C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino/main.cpp:43: undefined reference to `loop'
collect2.exe: error: ld returned 1 exit status
Ошибка компиляции.
Удивляемся и продолжаем эксперементировать. Определим теперь A что бы задействовать в программе содержимое #ifdef`а:
#define A #ifdef A int a; #endif void setup(){ } void loop() { }
Компиляция успешна:
Изменена опция сборки, пересобираем все
Sketch uses 450 bytes (1%) of program storage space. Maximum is 30 720 bytes.
Global variables use 9 bytes (0%) of dynamic memory, leaving 2 039 bytes for local variables. Maximum is 2 048 bytes.
Закоментируем теперь #define A:
//#define A #ifdef A int a; #endif void setup(){ } void loop() { }
Компиляция вновь с ошибкой:
Изменена опция сборки, пересобираем все
C:\Users\vlad\AppData\Local\Temp\build582594788212757414.tmp/core.a(main.cpp.o): In function `main':
C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino/main.cpp:40: undefined reference to `setup'
C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino/main.cpp:43: undefined reference to `loop'
collect2.exe: error: ld returned 1 exit status
Ошибка компиляции.
Ну и еще один скетч, закоментируем переменную:
//#define A #ifdef A // int a; #endif void setup(){ } void loop() { }
Компиляция успешна:
Изменена опция сборки, пересобираем все
Sketch uses 450 bytes (1%) of program storage space. Maximum is 30 720 bytes.
Global variables use 9 bytes (0%) of dynamic memory, leaving 2 039 bytes for local variables. Maximum is 2 048 bytes.
Как можно объяснить такое поведение компилятора?
Как переменная внутри #ifdef`а, содержимое которого итак не должно в итоге попасть в скопилированный код, влияет на функции setup и loop?
Версия Arduino IDE 1.6.5.
PS: Не подумайте что я просто извращаюсь... Я написал код в котором активно использую #ifdef`ы для управления конфигурациями разных сборок и при тестировании натолкнулся на эту ошибку. Теперь пытаюсь понять в чем тут дело...
Влад, я уже не в первый раз здесь пишу об этом ...
Эти
мчудаки - авторы IDE решили облегчить жизнь новичкам ... серия непечатных слов ... Ради этой этой благородной цели они решили своим препроцессором вручную собирать по коду все заголовки функций и помещать вначале их (функций) предварительные объявления. Мол, типа, при таком подходе новичок может не париться, что у него функция используется до объявления - мы мол ему поможем ... серия непечатных слов ...В результате возникают ошибки типа Вашей. Вот смотрите, у Вас было:
а вот, что эти
казлынехорошие люди передают настоящему компилятору gcc после своего грёбанного препроцессора:Понятно теперь почему не компилируется? Спасибо авторам IDE ... серия непечатных слов, переходящая в понос словесный и не только ...
В Вашем случае бороться с этим несложно - достаточно, чтобы #ifdef не был первым в программе. Например, вот так вполне сработает:
Если интересно, могу привести ещё один код, который "необъяснимо" не компилируется, благодаря всё той же дурацкой инициативе - собирать в начало все объявления.
Смотрите, сначала я объявляю класс, а потом его использую, как делают все нормальные люди! Но из-за того, что эти
казлынехорошие люди перетащили в самое начало объявление функции, всё летит к чертям и компилятор ругается (и правильно делает). Вот пример:Ух-ты .. не я один авторов "добрым словом" помянул .. :)
Да, это феноменальное решение. Пошукайте, в сети есть настройки к Эклипсу для компиляции и прошивок БЕЗ использования ИДЕ. Помогает. :)
Евгений, спасибо большое за объяснение!
Да, действительно еще одна переменная вне #ifdef`а спасает...
Остается только один вопрос - зачем они засунули свои объявления в МОЙ #ifdef? Разве не могли поднять свои объявления на самый верх?
И еще... Евгений а как вы дошли до этой мысли? :) Где то можно увидить результат работы препроцессора?
PS: Предварительно искал поиском темы с такой ошибкой, но там были темы с явными ошибками разработчика, а не компилятора. Возможно был не внимателен, пропустил...
Все, понял... В темпе нашел файлик (результат Вашего примера):
Забавно...
И еще... Евгений а как вы дошли до этой мысли? :) Где то можно увидить результат работы препроцессора?
Дошел случайно. Заметил. что я ошибся (использовал функцию до объявления), а компилятор "схавал". Дальше по Гоголю "Э-э-э сказали мы с Петром Ивановичем" ... и полез смотреть
Посмотреть легко.
1. В файле настроек IDE preferences.txt недалеко от начало есть строка "build.verbose=false". Замените false на true.
2. В том же файле пониже есть "preproc.save_build_files=true" - убедитесь, что true.
(ВНИМАНИЕ! Этот файл можно редактировать только при полностью закрытом IDE - все окна закрыть).
После этого запускайте IDE - он при компиляции станет ОЧЕНЬ болтливым. Среди всей болтовни найдёте назвние файла типа <имя Вашего скетча>.ino.cpp - там он будет с полным путём (путь весьма извилистый). Вот это он самый и есть - файл, который уходит настоящему компилятору после всех IDE'шных извращений. Именно его я Вам и процитировал выше.
Все, понял... В темпе нашел файлик (результат Вашего примера):
Во-во! Видите, использование класса Kaka оказалось выше его определения. Понятно, что компилятор ругается на меня, а я на авторов IDE.
Эту же настройку можно поправить в меню Файл \ Настройки и там "Показывать подробный вывод".
Похоже это одно и то же... Тоже стал "болтливый".
ЕвгенийП, хотелось бы попросить Вас зайти в тему http://arduino.ru/forum/programmirovanie/arduino-kak-konechnyi-avtomat-z...
Там у человека проблема с компиляцией из под винды в версии ИДЕ 1.5.2 моей либы.. но только вот не понимаю что там вообще происходит, а проверить нет возможности.. заранее, спасибо.
А ещё, если в preference.txt определить build.path=build и создать в каталоге, где установлена ArduinoIDE подкаталог build, то можно в нём после компиляции найти интересные файлы. Это удобней, нежели рыться в тэмпе.
Опять же удобно оттуда подтягивать hex файл в Proteus, например.
Спасибо, добрый человек! Будем знать. :)
Разрабатываю контроллер для своей муфельной печи.
Натолкнулся на "бред какой-то"...
Создал пустую функцию void Mbut4(void){
}
и пустую переменную knopki[4];
Попытался компильнуть...
Пишет:
collect2.exe: error: ld returned 5 exit status
Ошибка компиляции.
... и вываливаектся!
Посмотрел файлы (как описано выше) - там все нормально...
При закомментировании функции или переменной все начинает работать.
(всего лишь добавилась аналогичная функция и переменная)
Правил preferences.txt - ничего не изменилось
закомментировал "все новое" - "бздец"! Перестал скетч работать! ( предыдущая версия компилируется и грузится и работает)
Я 25-20 лет назад, писал на С и С++ . Может подскажите попроще редактор-компилятор, что б вспомнить, работать и не "материться"... версия 1.6.4... попробую поставить завтра 1.6.7... )
Разработка встала мертво! (
Сейчас "нарыл" Code::Blocks c поддержкой arduino...
Тестовую программу прогнал... Пойду дальше разбираться... Вроде все просто )))
P.S. Прошло 20 мин и я уже разобрался и перегрузил проект "Контроллера Муфельной печи" из CodeBlocks без ошибок и вываливаний... Ура!!! )))