Чи збиратиметься .ino Arduino Sketch безпосередньо на GCC-AVR?


10

Гаразд, ми всі бачили ці питання в Інтернеті, такі як Arduino vs C ++ або інші подібні запитання. І переважна більшість відповідей навіть не торкаються відмінностей у складанні, окрім як абстрагованої інформації.

Моє запитання має на меті вирішити фактичні відмінності (а не уподобання) у тому, як .ino файл, перейменований у .cpp-файл чи інше подібне розширення файлу для c ++, компілюватиметься за допомогою GCC-AVR. Я знаю, що як мінімум ви повинні включити заголовок Arduino, але крім цього, що може спричинити помилку компіляції, якщо компілювати згаданий .ino в .cpp-файл, використовуючи, скажімо, GCC-AVR. Для простоти давайте скористаємося класичним прикладом моргання, щоб пояснити, у чому полягають відмінності. Або якщо у вас є кращий фрагмент коду для використання, будь-ласка, будь-ласка, включіть фрагмент у свою відповідь та ретельно поясніть відмінності.

Будь ласка, не майте думок щодо того, який є кращим способом чи інструментом для використання.

FYI. Я використовую Platformio для розробки і помічаю процес перетворення, який відбувається за кадром під час компіляції. Я намагаюся зрозуміти, що насправді там відбувається, тому коли я кодую в Arduino, я також розумію "чисту" версію C ++.

Дякуємо за заздалегідь продумані відповіді на моє запитання.


Ви питаєте конкретно про gccсвій робочий стіл чи компілятор GCC для AVR avr-gcc? там набагато більша різниця, ніж між файлом .inoі a .cpp.
BrettAM

@BrettAM Інструментарій GCC-AVR як Arduino UNO є цільовою платою і використовує чіп Atmel AVR, як я впевнений, що ви знаєте. Дякую за заклик до неоднозначності мого запитання. І так, я знаю, що є набагато більша різниця. Ось чому я задаю це питання. Щоб дізнатися, які ці відмінності!
RedDogAlpha

Відповіді:


14

Дивіться мою відповідь тут: Класи та об’єкти: скільки та які типи файлів мені потрібно фактично їх використовувати? - конкретно: як IDE впорядковує речі .

Я знаю, що як мінімум потрібно включити файл заголовка Arduino

Так, вам потрібно було б це зробити.

але крім цього, що може спричинити помилку компіляції, якщо компілювати згаданий файл .ino в .cpp-файл, використовуючи, скажімо, наприклад, GCC-AVR.

IDE генерує прототипи функцій для вас. Код у файлі .ino може не потребувати цього (можливо, це буде, якщо автор не буде досить дисциплінований, щоб кодувати звичайним способом C ++ і зробити їх самостійно).


Якщо "ескіз" містить інші файли (наприклад, інші файли .ino, .c або .cpp), то їх потрібно буде включити в процес компіляції, як я описав у своїй відповіді, згаданій вище.

Також вам потрібно буде (компілювати та) посилання в будь-яких бібліотеках, які використовуються ескізом.


Ви не запитували про зв'язувальну сторону речей, але, природно, різні файли, зібрані, потрібно зв'язати разом, а потім перетворити на файл .elf та .hex для завантаження. Дивись нижче.


Приклад makefile

На основі виводу IDE я зробив простий makefile за часом :

#
# Simple Arduino Makefile
#
# Author: Nick Gammon
# Date: 18th March 2015

# where you installed the Arduino app
ARDUINO_DIR = C:/Documents and Settings/Nick/Desktop/arduino-1.0.6/

# various programs
CC = "$(ARDUINO_DIR)hardware/tools/avr/bin/avr-gcc"
CPP = "$(ARDUINO_DIR)hardware/tools/avr/bin/avr-g++"
AR = "$(ARDUINO_DIR)hardware/tools/avr/bin/avr-ar"
OBJ_COPY = "$(ARDUINO_DIR)hardware/tools/avr/bin/avr-objcopy"

MAIN_SKETCH = Blink.cpp

# compile flags for g++ and gcc

# may need to change these
F_CPU = 16000000
MCU = atmega328p

# compile flags
GENERAL_FLAGS = -c -g -Os -Wall -ffunction-sections -fdata-sections -mmcu=$(MCU) -DF_CPU=$(F_CPU)L -MMD -DUSB_VID=null -DUSB_PID=null -DARDUINO=106
CPP_FLAGS = $(GENERAL_FLAGS) -fno-exceptions
CC_FLAGS  = $(GENERAL_FLAGS)

# location of include files
INCLUDE_FILES = "-I$(ARDUINO_DIR)hardware/arduino/cores/arduino" "-I$(ARDUINO_DIR)hardware/arduino/variants/standard"

# library sources
LIBRARY_DIR = "$(ARDUINO_DIR)hardware/arduino/cores/arduino/"

build:

    $(CPP) $(CPP_FLAGS) $(INCLUDE_FILES) $(MAIN_SKETCH) -o $(MAIN_SKETCH).o
    $(CC) $(CC_FLAGS) $(INCLUDE_FILES) $(LIBRARY_DIR)avr-libc/malloc.c -o malloc.c.o 
    $(CC) $(CC_FLAGS) $(INCLUDE_FILES) $(LIBRARY_DIR)avr-libc/realloc.c -o realloc.c.o 
    $(CC) $(CC_FLAGS) $(INCLUDE_FILES) $(LIBRARY_DIR)WInterrupts.c -o WInterrupts.c.o 
    $(CC) $(CC_FLAGS) $(INCLUDE_FILES) $(LIBRARY_DIR)wiring.c -o wiring.c.o 
    $(CC) $(CC_FLAGS) $(INCLUDE_FILES) $(LIBRARY_DIR)wiring_analog.c -o wiring_analog.c.o 
    $(CC) $(CC_FLAGS) $(INCLUDE_FILES) $(LIBRARY_DIR)wiring_digital.c -o wiring_digital.c.o 
    $(CC) $(CC_FLAGS) $(INCLUDE_FILES) $(LIBRARY_DIR)wiring_pulse.c -o wiring_pulse.c.o 
    $(CC) $(CC_FLAGS) $(INCLUDE_FILES) $(LIBRARY_DIR)wiring_shift.c -o wiring_shift.c.o 
    $(CPP) $(CPP_FLAGS) $(INCLUDE_FILES) $(LIBRARY_DIR)CDC.cpp -o CDC.cpp.o 
    $(CPP) $(CPP_FLAGS) $(INCLUDE_FILES) $(LIBRARY_DIR)HardwareSerial.cpp -o HardwareSerial.cpp.o 
    $(CPP) $(CPP_FLAGS) $(INCLUDE_FILES) $(LIBRARY_DIR)HID.cpp -o HID.cpp.o 
    $(CPP) $(CPP_FLAGS) $(INCLUDE_FILES) $(LIBRARY_DIR)IPAddress.cpp -o IPAddress.cpp.o 
    $(CPP) $(CPP_FLAGS) $(INCLUDE_FILES) $(LIBRARY_DIR)main.cpp -o main.cpp.o 
    $(CPP) $(CPP_FLAGS) $(INCLUDE_FILES) $(LIBRARY_DIR)new.cpp -o new.cpp.o 
    $(CPP) $(CPP_FLAGS) $(INCLUDE_FILES) $(LIBRARY_DIR)Print.cpp -o Print.cpp.o 
    $(CPP) $(CPP_FLAGS) $(INCLUDE_FILES) $(LIBRARY_DIR)Stream.cpp -o Stream.cpp.o 
    $(CPP) $(CPP_FLAGS) $(INCLUDE_FILES) $(LIBRARY_DIR)Tone.cpp -o Tone.cpp.o 
    $(CPP) $(CPP_FLAGS) $(INCLUDE_FILES) $(LIBRARY_DIR)USBCore.cpp -o USBCore.cpp.o 
    $(CPP) $(CPP_FLAGS) $(INCLUDE_FILES) $(LIBRARY_DIR)WMath.cpp -o WMath.cpp.o 
    $(CPP) $(CPP_FLAGS) $(INCLUDE_FILES) $(LIBRARY_DIR)WString.cpp -o WString.cpp.o 
    rm core.a
    $(AR) rcs core.a malloc.c.o 
    $(AR) rcs core.a realloc.c.o 
    $(AR) rcs core.a WInterrupts.c.o 
    $(AR) rcs core.a wiring.c.o 
    $(AR) rcs core.a wiring_analog.c.o 
    $(AR) rcs core.a wiring_digital.c.o 
    $(AR) rcs core.a wiring_pulse.c.o 
    $(AR) rcs core.a wiring_shift.c.o 
    $(AR) rcs core.a CDC.cpp.o 
    $(AR) rcs core.a HardwareSerial.cpp.o 
    $(AR) rcs core.a HID.cpp.o 
    $(AR) rcs core.a IPAddress.cpp.o 
    $(AR) rcs core.a main.cpp.o 
    $(AR) rcs core.a new.cpp.o 
    $(AR) rcs core.a Print.cpp.o 
    $(AR) rcs core.a Stream.cpp.o 
    $(AR) rcs core.a Tone.cpp.o 
    $(AR) rcs core.a USBCore.cpp.o 
    $(AR) rcs core.a WMath.cpp.o 
    $(AR) rcs core.a WString.cpp.o 
    $(CC) -Os -Wl,--gc-sections -mmcu=$(MCU) -o $(MAIN_SKETCH).elf $(MAIN_SKETCH).o core.a -lm 
    $(OBJ_COPY) -O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 $(MAIN_SKETCH).elf $(MAIN_SKETCH).eep 
    $(OBJ_COPY) -O ihex -R .eeprom $(MAIN_SKETCH).elf $(MAIN_SKETCH).hex 

У цьому конкретному випадку .ino файл без проблем зібрався після перейменування його на Blink.cpp та додавання цього рядка:

#include <Arduino.h>

Дякую Ніку за лаконічну відповідь, я ніде не знаходиться на рівні, на якому ти є, і навіть не думав про створення файлу. Так що в основному синтаксис є однаковим, він просто пов'язаний з об'єктами, правда? Дякую, що поділився вашим файлом make для мене, щоб розібрати. Я впевнений, що з цього питання виникне більше! Знову дякую!
RedDogAlpha

Мій файл працював вище, коли я його розміщував, але я вважаю, що може знадобитися налаштування для пізніших IDE (тому що вони переміщуються або перейменують файли бібліотеки). Все-таки виконання багатослівної компіляції показує, що IDE наразі генерує, з чого слід почати.
Нік Гаммон

10

Я хотів би лише додати кілька пунктів до відповіді Ніка Гаммона:

  • Вам не потрібно перейменовувати .ino-файл, щоб скомпілювати його: якщо ви прямо скажете компілятору, що це C ++ (опція -x c++), він ігнорує незвичне розширення файлу і компілює його як C ++.
  • Вам не потрібно додавати #include <Arduino.h>у файл .ino: ви можете сказати компілятору зробити це для вас ( -include Arduino.h).

Використовуючи ці хитрощі, я можу компілювати Blink.ino без будь-яких модифікацій , просто викликаючи avr-g ++ з відповідними параметрами командного рядка:

avr-g++ -mmcu=atmega328p -DARDUINO=105 -DF_CPU=16000000L \
    -I/usr/share/arduino/hardware/arduino/cores/arduino \
    -I/usr/share/arduino/hardware/arduino/variants/standard \
    -Os -fno-exceptions -ffunction-sections -fdata-sections \
    -Wl,--gc-sections -g -Wall -Wextra \
    -x c++ -include Arduino.h \
    /usr/share/arduino/examples/01.Basics/Blink/Blink.ino \
    -x none /usr/local/lib/arduino/uno/libcore.a -lm \
    -o Blink.elf

Кілька приміток до вищевказаного командного рядка:

  • /usr/local/lib/arduino/uno/libcore.aсаме там я зберег складене ядро ​​Arduino. Я ненавиджу знову і знову переробляти ті самі речі.
  • -x noneпотрібно сказати компілятору знову пам’ятати про розширення файлів. Без цього, припустимо, libcore.a - це файл C ++.

Я навчився цих хитрощів із ардуїно-макіяжу Судара Муту . Це дуже загальний Makefile, який працює з багатьма дошками та з бібліотеками. Єдине, чого не вистачає відносно Arduino IDE, - це прямі декларації.


Дуже приємно, Едгар! Моє рішення, в основному, імітує те, що робить IDE, ваше вирішує справжню проблему в набагато більш акуратному вигляді. Звичайно, вам доведеться зробити libcore.aфайл заздалегідь. Я припускаю, що рядки в моїй відповіді про те, які збірки core.aможна зробити заздалегідь, тому вони не повинні бути частиною кожної збірки. Досвід показує, що до складніших ескізів (наприклад, за допомогою Wire або SPI) потрібно додати більше файлів core.a.
Нік Гаммон

@ NickGammon: Правильно, Makefile Muthu (і, я припускаю, Arduino IDE) прагне розміщувати всі бібліотеки, які ви використовуєте в libcore.a. Мені не дуже подобається такий підхід, оскільки він робить нібито «основну бібліотеку» залежною від конкретної програми, яку ви складаєте. Для однофайлових бібліотек, таких як Wire або SPI, я віддаю перевагу просто помістити файл C ++ бібліотеки в ту саму команду компіляції, що і основна програма. Цей командний рядок стає досить довгим, тому я використовую Makefile.
Едгар Боне

1
Одна з речей, що мені подобається в IDE, це те, що вам не доведеться гнатися. Для простих проектів у будь-якому випадку це "просто працює".
Нік Гаммон
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.