Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Прозрачность программы для компилятора
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Cредства разработки для МК > IAR
Waso
Насколько я понимаю, инклюд, обьявленный в начале файла должен быть виден во всех последующих инклюдах программы. Согласно Кернигану и Риччи, предпроцессор заменяет директиву #include на содержимое файла, на который она указывает. Однако в ИАРе для успешной компиляции некоторые инклюды приходится втыкать чуть ли не в каждый файл проекта. Плюс к тому, с-шные файлы вообще не участвуют в инклюдах, а обращение к их функциям происходит через прототипы функций одноименных хедеров. Нестыковочка.

Подскажите пожалуйста, как можно избавиться от сабжевой проблемы, в чем могут быть ее причины? Общие ответы типа "в кривости кода" - не в счет.


PS Пользую IAR EWARM 4.40A
Сергей Борщ
Цитата(Waso @ Oct 30 2007, 14:43) *
Однако в ИАРе для успешной компиляции некоторые инклюды приходится втыкать чуть ли не в каждый файл проекта.
Каждый .c -файл, входящий в проект, компилируется отдельно (и называется единицей компиляции). При этом компилятор понятия не имеет о других файлах (единицах компиляции) и, следовательно, о включенных в них инклюдах. Все инклюды, которые вам могут понадобиться в этом .c надо в него включить.
Цитата(Waso @ Oct 30 2007, 14:43) *
Плюс к тому, с-шные файлы вообще не участвуют в инклюдах, а обращение к их функциям происходит через прототипы функций одноименных хедеров. Нестыковочка.
Стыковочка. На этапе компиляции из заголовочных файлов берутся прототипы (описания) функций, благодаря которым компилятор знает, что существует функция с таким именем, знает с какими параметрами функция должна вызываться и значение какого типа должна возвращать. За соблюдением этих типов и следит компилятор. А уже линкер в места вызова функций подставляет конкретные адреса. При этом тело и место вызова могут находиться в разных единицах компиляции. Можете поискать в гугле по ключевым словам "раздельная компиляция".
IgorKossak
Проблема не в кривости кода а в недопонимании.
Во первых, как Вы правильно сказали
Цитата
предпроцессор заменяет директиву #include на содержимое файла
, но это в том файле, где этот include стоИт. С какой стати он должен быть виден в других файлах проекта, где Вы его ставить не желаете?
Компилятор в каждый момент времени работает только с одним С/С++ файлом проекта и учитывает только входящие в него include. Нестыковки здесь нет.
Во вторых, если в файле несколько include, то каждый последующий видит содержимое предыдущих, но не наоборот, и это логично. Таким образом получается возможная зависимость от порядка. Чтобы её избежать применяются различные ходы вроде включения include в хедеры (и это тоже логично, поскольку есть некоторые зависимости), при этом все хедеры должны иметь охранные директивы, о чём многократно писалось на форуме.

PS Как всегда, не успел за Сергеем Борщом wink.gif
alexander55
Цитата(Waso @ Oct 30 2007, 14:43) *

Кроме выше сказанного, могу предложить вариант создания файла all.h
со всеми включениями, а потом включать только его.
Waso
Благодарю.
Начинает доходить. smile.gif

Значит любой с-файл включенный в проект будет компилироваться и отгрызать место даже если я закоментирую инклюд с его хедером??

Насчет охранных директив и порядка следования я в курсе. Тем больше удивлялся когда повторное включение хедера с охранной директивой изменяло результат компиляции. Но теперь ясно.

alexander55 отличная идея! На первый взгляд. Почему тогда такой прием широко не используется? Врядли для того чтобы сократить время компиляции.
dxp
Цитата(Waso @ Oct 30 2007, 18:36) *
Значит любой с-файл включенный в проект будет компилироваться и отгрызать место даже если я закоментирую инклюд с его хедером??

Компилироваться будет в любом случае. Но линкер потом включит только то, что реально используется. Ничего лишнего в выходной прошивке не будет.
alexander55
Цитата(Waso @ Oct 30 2007, 15:36) *
alexander55 отличная идея! На первый взгляд. Почему тогда такой прием широко не используется? Врядли для того чтобы сократить время компиляции.

Используется широко.
Файл all.h
#ifndef allH
#define allH
...
#endif
ig_z
Цитата(Waso @ Oct 30 2007, 16:36) *
alexander55 отличная идея! На первый взгляд. Почему тогда такой прием широко не используется? Врядли для того чтобы сократить время компиляции.

Отличную идею нужно довести до конца!
1 склеим все хедеры в один
2 склеим все сишники в один
3 склеим склееное в один супер сишник
4 выкинем лишнее, оставшееся от хедеров
Получаем удовольствие 08.gif
alexander55
Цитата(ig_z @ Oct 30 2007, 16:37) *
Отличную идею нужно довести до конца!
1 склеим все хедеры в один
2 склеим все сишники в один
3 склеим склееное в один супер сишник
4 выкинем лишнее, оставшееся от хедеров
Получаем удовольствие 08.gif

Давайте без фанатизма и экстремизма. biggrin.gif
Но все мечтают видеть все, сразу, вместе и чтобы было все ясно и наглядно !
PS. И хорошо бы, чтобы и работало без вопросов. 07.gif
scifi
Цитата(Waso @ Oct 30 2007, 15:36) *
отличная идея! На первый взгляд. Почему тогда такой прием широко не используется? Врядли для того чтобы сократить время компиляции.

Полезно объявлять только то, что реально используется в данном *.с файле. Это поможет понять, что происходит, тому бедолаге, который когда-нибудь будет вынужден разбираться в этом коде.
alexander55
Цитата(scifi @ Oct 30 2007, 17:21) *
Полезно объявлять только то, что реально используется в данном *.с файле. Это поможет понять, что происходит, тому бедолаге, который когда-нибудь будет вынужден разбираться в этом коде.

Это желательно, но не обязательно (но стремиться к этому надо).
Andy Mozzhevilov
Цитата(alexander55 @ Oct 30 2007, 17:16) *
Кроме выше сказанного, могу предложить вариант создания файла all.h
со всеми включениями, а потом включать только его.


Мне эта идея раньше нравилась тоже, но сейчас уже нет, после того, как я некоторое время поработал по такой системе.
Если проект достаточно большой, содержит несколько десятков исходников, начинает напрягать пересборка всего при малейшей правке в любом хедере.
Например, последние проекты на Fujitsu FFMC, которые я делал, выливались где-то в 100 кБ бинарного кода. Время компиляции всех файлов проекта занимает порядка минуты. Это уже существенно, чтобы такой подход начал напрягать.
Непомнящий Евгений
Полностью присоединяюсь к Andy Mozzhevilov - избыточные включения - перекомпиляция всего при любом изменении.
Кроме того, если вы явно включаете только то, что нужно - вы четко знаете зависимости. Если вы включаете все - у вас все зависит от всего, ни о каких зависимостях говорить не получается. А в сколь-нибудь больших проектах без инкапсуляции очень сложно...
alexander55
Цитата(Andy Mozzhevilov @ Oct 31 2007, 07:50) *

Я согласен. Не может быть все со знаком плюс, чем то приходится поступиться.
Главное - не принципами ! biggrin.gif
Waso
Линкер выдает такую ошибку:
Код
Error[e27]: Entry "AT91F_ADC_CfgModeReg" in module BasicWEB ( ..\BasicWEB.r79 ) redefined in module SAM7_EMAC ( ..\SAM7_EMAC.r79 )
В обоих указан инклюд, в котором находится конфликтующая ф-я. Причом она инлайновая.
#include <lib_AT91SAM7X256.h>
С АЦП я вообще не работаю. Охранные директивы в этом хедере есть. В чем проблема?
Сергей Борщ
Цитата(Waso @ Nov 2 2007, 12:28) *
В обоих указан инклюд, в котором находится конфликтующая ф-я. Причом она инлайновая.
Похоже этот заголовочник отлаживался в С++ режиме, а вы его пытаетесь в С использовать. Допишите перед определением функции static.

Цитата(ig_z @ Oct 30 2007, 16:37) *
1 склеим все хедеры в один
2 склеим все сишники в один
3 склеим склееное в один супер сишник
4 выкинем лишнее, оставшееся от хедеров
Получаем удовольствие 08.gif
Получаем CodeVisionAVR lol.gif
VladislavS
Цитата(Waso @ Nov 2 2007, 12:28) *
Охранные директивы в этом хедере есть. В чем проблема?


А причем тут охранные директивы? Они нужны только чтобы при компиляции хидер только один раз включался, если вдруг хидер по каким-то причинам несколько раз подключен. В вашем случае имеется два тела инлайновой (это кстати не главное в данном случае) функции в разных модулях. Вот линкер и не может разобраться. Надо бы ограничить зону видимости этой функции. Наверное static поможет.
Николай Z
Цитата(Waso @ Nov 2 2007, 12:28) *
Линкер выдает такую ошибку:
Код
Error[e27]: Entry "AT91F_ADC_CfgModeReg" in module BasicWEB ( ..\BasicWEB.r79 ) redefined in module SAM7_EMAC ( ..\SAM7_EMAC.r79 )
В обоих указан инклюд, в котором находится конфликтующая ф-я. Причом она инлайновая.
#include <lib_AT91SAM7X256.h>
С АЦП я вообще не работаю. Охранные директивы в этом хедере есть. В чем проблема?


Это уже линкер обругал Ваши объектные файлы... АЦП тут вовсе непричем.

Просто у Вас скорее всего в сишных файлах и/или инклюдниках есть два объявления функции AT91F_ADC_CfgModeReg, а именно в файлах
BasicWEB.с ( или в асмовском)
и в файле:
SAM7_EMAC.c ( или в асмовском)

Да Вы и сами причину написали:
Цитата
В обоих указан инклюд, в котором находится конфликтующая ф-я. Причом она инлайновая.


вот не должно так быть... Охранные директивы - охраняют только в пределах одного *.c файла, между ними - охранные директивы не работают. Вот Вы и получили - в разных модулях - одну и ту же функцию, а линкер это обнаружил... Все правильно...

Цитата(VladislavS @ Nov 2 2007, 20:41) *
Наверное static поможет.


либо попробовать ее в одном из файлов как extern объявить, но если она не inline-естествоенно...
мне вообще странно что inline-функция вылезла аж до линкера. biggrin.gif
Вроде бы ее тело должно просто быть подставлено в текст программы в каждой точке ее вызова и она не должна вылазить в распоряжение линкера?
Waso
Видимо проблема в том что компилятор умничает и игнорирует директиву inline, и поскольку эти функции описаны внутри хедера (а не с-шного файла) то получается конфликт. Этот хедер писали сами атмеловцы и не предусмотрели почемуто отключение эвристики компилятора. Хотя они заботливо подменили через дефайн слово inline строкой __inline. Небольшое исправление этого дефайна устранило проблему:

Было:
#define __inline inline

Стало:
#define __inline _Pragma("inline = forced")

================================================
Еще маленький вопросик - как в редакторе ИАР табом сдвинуть сразу несколько строк?
Сергей Борщ
Цитата(Waso @ Nov 8 2007, 13:45) *
Еще маленький вопросик - как в редакторе ИАР табом сдвинуть сразу несколько строк?
Как и в большинстве редакторов - выделить несколько строк и нажать таб для сдвига вправо или шифт-таб для сдвига влево.
Waso
Спасибо. Просто у меня после паскалевских Ctrl-Shift-K и -N (кажется) не рождается таких простых ассоциаций насчет таба. =)))

Еще вопрос - можно ли в ИАР 4.40A при пользовании J-Link запускать отладку не прошивая кристалл? Тоесть прошил я один раз и отлаживаю. Смотрю по шагам прогу. День рабочий закончился или нечаянно вышел из дебаггера, если программу не менял - не хочется зря тратить ресурс флеша при новом запуске дебаггера...
Сергей Борщ
Цитата(Waso @ Nov 13 2007, 13:08) *
Еще вопрос - можно ли в ИАР 4.40A при пользовании J-Link запускать отладку не прошивая кристалл?
Project->Options->Debugger->Download поставить галочку Suppress Download. Автоматически выключится галочка Use flash loader. Когда захотите прошить снова и будете снимать Suppress Dowload - не забудьте поставить Use flash loader. А можно создать вде конфигурации - одну с прошивкой, другую без. Создавать проще всего в текстовом редакторе, скопровав и переименовав соответствующие секции в *.ewd и *.ewp
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.