Перейти к содержанию

AVR mixing c/cpp, makefile, build shell, atmega328 - trouble

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

...

содержание проекта (не нашел спойлер)
CODE
///////////////////////////////////////////////////////////////////////////////
// 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
Изменено пользователем IgorKossak
[codebox] для длинного кода. [code]-для короткого!!!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
Перенесите определение вашего массива в main.cpp. В заголовочном файле оставьте объявление вашего массива extern int mass_c[8]; Почитайте о правиле единственного определения (one definition rule).

extern "C" относится к функциям и служит для отключения декорирования имен (name mangling), которое для переменных смысла не имеет.

Совет: не злоупотребляйте жирным шрифтом и метки (tags) на этом форуме тоже не работают.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
Цитата
Перенесите определение вашего массива в main.cpp

разобрался уже rolleyes.gif
а так, массиву в главном модуле делать нечего... в тело своего модуля его надо вставлять...

Цитата
метки (tags) на этом форуме тоже не работают

это не для форума sm.gif а для людей

Цитата
one definition rule

в данном случае это не проблема а последствие sm.gif

спасибо
Изменено пользователем sunjob

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
QUOTE (sunjob @ Apr 30 2018, 10:44) <{POST_SNAPBACK}>
это не для форума sm.gif а для людей
Как человек, не вижу никакой пользы в бессмысленном наборе слов.

QUOTE (sunjob @ Apr 30 2018, 10:44) <{POST_SNAPBACK}>
в данном случае это не проблема а последствие sm.gif
Внезапно. Линковщик ругался на нарушение именно этого правила. Впрочем, считайте как хотите.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
Цитата
не вижу никакой пользы

до тех пор пока не посоветовали "набить код в ардуине", вставить его в avr-studio или еще какой эклипс...
сразу и смысл и польза проявится rolleyes.gif

Цитата
Внезапно. Линковщик ругался на нарушение именно этого правила

как последствие -fno-common

...

### UPDATE ### - сборка в 3х вариантах

с миксами, вроде как разобрался, продолжаю исследования в разрезе вариантов сборки
- makefile
- avr-gcc shell
- avr-gcc shell, single mode


первый вариант - сборка с пом-ю makefile
второй - с пом-ю шелл-скрипта (компиляция по отдельности файлов, потом сборка "все в кучу")
третий - попытаться инклудами в главном модуле собрать "общий код" в одном месте (надеюсь понятно?), так, что-бы достаточно было компилировать только один главный модуль, плюс ко всему прочему добавил флаг сборки BUILD_SINGLE и условиями препроцессора переношу определение массива из тела C/C++ в хедер файл, (и для эмуляции более логичного и понятного для меня понимания что-где должно лежать sm.gif

как итог
- сборка и тест всех трех вариантов - без ошибок, для отладки использую вывод на терминал
- размеры hex-файла:
6486 - makefile
3540 - avr-gcc shell (md5-отличается)

вопросы по ходу:
- почему у makefile - чуть ли не в два раза больше? оптимизация во всех случаях -Os, могу предположить, что makefile что-то дополнилтельно пихает (ну... что сказали, то и пихает)
- подводные камни третьего варианта? (для меня он наиболее понятен и прозрачен, и хотелось бы уточнить тонкости, особенности)

и как обычно - высказываемся, предполагаем, просто философствуем
Изменено пользователем sunjob

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для публикации сообщений создайте учётную запись или авторизуйтесь

Вы должны быть пользователем, чтобы оставить комментарий

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти
Авторизация