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

    

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

 

...

 

содержание проекта (не нашел спойлер)

///////////////////////////////////////////////////////////////////////////////
// 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:

а так, массиву в главном модуле делать нечего... в тело своего модуля его надо вставлять...

 

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

это не для форума :) а для людей

 

one definition rule

в данном случае это не проблема а последствие :)

 

спасибо

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

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


Ссылка на сообщение
Поделиться на другие сайты
это не для форума :) а для людей
Как человек, не вижу никакой пользы в бессмысленном наборе слов.

 

в данном случае это не проблема а последствие :)
Внезапно. Линковщик ругался на нарушение именно этого правила. Впрочем, считайте как хотите.

 

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


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

до тех пор пока не посоветовали "набить код в ардуине", вставить его в 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 что-то дополнилтельно пихает (ну... что сказали, то и пихает)

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

 

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

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

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


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

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

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

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

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

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

Войти

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

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