sunjob 0 30 апреля, 2018 Опубликовано 30 апреля, 2018 (изменено) · Жалоба AVR mixing c/cpp, makefile, build shell, atmega328 - trouble добрый день linux, avr-gcc, mixing c/cpp codes, makefile, build on shell, atmega-328p, NO ARDUINO, NO IDE/AVR-Studio/Eclipse/etc, NO_WINDOWS проект простой "шаблон", изучаю "топик", в частности "c/cpp mixing" - два модуля, один си, другой си++, оба имеют хедеры (func.c/h func.cpp/h), в хедерах описание функции и массива - главный модуль main, в "процессе" меняется расширение, c/cpp (main.*) - итого: имеем два модуля си/си++ и главный модуль тоже "меняет" свой окрас :о) - сборка: makefile & bash - собираем, смотрим как ведет себя "смешанный код" итого: если главный модуль си / main.c - ни каких проблем, проект собирается нормально если главный модуль си++ / main.cpp - ошибка линковки: множ.определение массива в си++ модуле makefile & bash выдают одинаковый результат модификатор 'extern "C"' - в данном случае, естественно, не помогает ошибка: multiple definition of mass_cpp[] ... проанализировал выхлоп makefile, все, вроде, идеально выкусы команд скинул в файл build_cmd.txt команды идут парами, первая строка "сценарий с ошибкой", вторая "нормальна" единственное отличие - последовательность сборки, пробывал мануально собирать и менять последовательность, на конечный результат не влияет ... (тему изучил но ...:о) итак, высказываемся, предполагаем, просто философствуем ... linux x32 avr-binutils-2.25 avr-gcc-4.9.2 avr-gdb-7.8.1 avr-libc-1.8.1 option: avr-gcc-toolchain-3.4.2 avr-gcc-toolchain-3.5.4 ... содержание проекта (не нашел спойлер) /////////////////////////////////////////////////////////////////////////////// // main.* /////////////////////////////////////////////////////////////////////////////// #include <avr/io.h> #include <util/delay.h> #include <stdint.h> #include "src/func_c.h" #include "src/func_cpp.h" int main(void) { func_c(); func_cpp(); } /////////////////////////////////////////////////////////////////////////////// // func_c.h /////////////////////////////////////////////////////////////////////////////// #ifndef _FUNC_C_H_ #define _FUNC_C_H_ #ifdef __cplusplus extern "C" { #endif int mass_c[8]; void func_c(void); #ifdef __cplusplus } #endif #endif /////////////////////////////////////////////////////////////////////////////// // func_c.c /////////////////////////////////////////////////////////////////////////////// #include "func_c.h" void func_c(void) {;} /////////////////////////////////////////////////////////////////////////////// // func_cpp.h /////////////////////////////////////////////////////////////////////////////// #ifndef _FUNC_CPP_H_ #define _FUNC_CPP_H_ #ifdef __cplusplus extern "C" { #endif int mass_cpp[8]; void func_cpp(void); #ifdef __cplusplus } #endif #endif /////////////////////////////////////////////////////////////////////////////// // func_cpp.cpp /////////////////////////////////////////////////////////////////////////////// #include "func_cpp.h" void func_cpp(void) {;} /////////////////////////////////////////////////////////////////////////////// // содержание баш-скрипта /////////////////////////////////////////////////////////////////////////////// #!/bin/sh set -e; clear CLK=16000000 MAIN=main.cpp FUNC1=func_c.c FUNC2=func_cpp.cpp OUT=out CPU=atmega328p rm -fr $OUT; mkdir -p $OUT echo "===> gcc $FUNC1" avr-gcc -mmcu=$CPU -Wall -Os -DF_CPU=$CLK -c -o $OUT/$FUNC1.elf src/$FUNC1 echo "===> gcc $FUNC2" avr-gcc -mmcu=$CPU -Wall -Os -DF_CPU=$CLK -c -o $OUT/$FUNC2.elf src/$FUNC2 echo "===> gcc $MAIN" avr-gcc -mmcu=$CPU -Wall -Os -DF_CPU=$CLK -c -o $OUT/$MAIN.elf $MAIN echo "===> gcc links" # var.1 avr-gcc -mmcu=$CPU -Wall -DF_CPU=$CLK -o $OUT/x.elf $OUT/$MAIN.elf $OUT/$FUNC1.elf $OUT/$FUNC2.elf # var.2 - выкус эха makefile #avr-gcc -mmcu=$CPU -g -DF_CPU=$CLK -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wundef \ #-Wa,-adhlns=out/func_c.o -std=gnu99 \ #out/func_c.c.elf out/func_cpp.cpp.elf out/main.cpp.elf --output out/main.elf -Wl,-Map=out/main.map,--cref -lm echo "===> objcopy" cd $OUT #avr-objcopy -O ihex $MAIN.elf $MAIN.hex # --> avr-objcopy -O ihex x.elf $MAIN.hex cd - echo "### OK $0 ###"; sleep 1 tag: linux, avr-gcc, mixing c/cpp codes, makefile, build on shell, atmega-328p, NO ARDUINO, NO IDE/AVR-Studio/Eclipse/etc, NO_WINDOWS Изменено 2 мая, 2018 пользователем IgorKossak [codebox] для длинного кода. [code]-для короткого!!! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 30 апреля, 2018 Опубликовано 30 апреля, 2018 · Жалоба Перенесите определение вашего массива в main.cpp. В заголовочном файле оставьте объявление вашего массива extern int mass_c[8]; Почитайте о правиле единственного определения (one definition rule). extern "C" относится к функциям и служит для отключения декорирования имен (name mangling), которое для переменных смысла не имеет. Совет: не злоупотребляйте жирным шрифтом и метки (tags) на этом форуме тоже не работают. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sunjob 0 30 апреля, 2018 Опубликовано 30 апреля, 2018 (изменено) · Жалоба Перенесите определение вашего массива в main.cpp разобрался уже :rolleyes: а так, массиву в главном модуле делать нечего... в тело своего модуля его надо вставлять... метки (tags) на этом форуме тоже не работают это не для форума :) а для людей one definition rule в данном случае это не проблема а последствие :) спасибо Изменено 30 апреля, 2018 пользователем sunjob Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 30 апреля, 2018 Опубликовано 30 апреля, 2018 · Жалоба это не для форума :) а для людейКак человек, не вижу никакой пользы в бессмысленном наборе слов. в данном случае это не проблема а последствие :)Внезапно. Линковщик ругался на нарушение именно этого правила. Впрочем, считайте как хотите. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sunjob 0 30 апреля, 2018 Опубликовано 30 апреля, 2018 (изменено) · Жалоба не вижу никакой пользы до тех пор пока не посоветовали "набить код в ардуине", вставить его в avr-studio или еще какой эклипс... сразу и смысл и польза проявится :rolleyes: Внезапно. Линковщик ругался на нарушение именно этого правила как последствие -fno-common ... ### UPDATE ### - сборка в 3х вариантах с миксами, вроде как разобрался, продолжаю исследования в разрезе вариантов сборки - makefile - avr-gcc shell - avr-gcc shell, single mode первый вариант - сборка с пом-ю makefile второй - с пом-ю шелл-скрипта (компиляция по отдельности файлов, потом сборка "все в кучу") третий - попытаться инклудами в главном модуле собрать "общий код" в одном месте (надеюсь понятно?), так, что-бы достаточно было компилировать только один главный модуль, плюс ко всему прочему добавил флаг сборки BUILD_SINGLE и условиями препроцессора переношу определение массива из тела C/C++ в хедер файл, (и для эмуляции более логичного и понятного для меня понимания что-где должно лежать :) как итог - сборка и тест всех трех вариантов - без ошибок, для отладки использую вывод на терминал - размеры hex-файла: 6486 - makefile 3540 - avr-gcc shell (md5-отличается) вопросы по ходу: - почему у makefile - чуть ли не в два раза больше? оптимизация во всех случаях -Os, могу предположить, что makefile что-то дополнилтельно пихает (ну... что сказали, то и пихает) - подводные камни третьего варианта? (для меня он наиболее понятен и прозрачен, и хотелось бы уточнить тонкости, особенности) и как обычно - высказываемся, предполагаем, просто философствуем Изменено 30 апреля, 2018 пользователем sunjob Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться