Bir .ino Arduino Sketch doğrudan GCC-AVR'da derlenecek mi?


10

Tamam, hepimiz bu soruları Web'de Arduino vs C ++ veya diğer benzer sorular gibi gördük. Ve cevapların büyük bir çoğunluğu soyutlanmış bilgilerden başka derleme farklılıklarına bile dokunmuyor.

Benim sorum, bir .ino dosyasının bir .cpp dosyasına veya c ++ için benzer bir dosya uzantısına yeniden adlandırıldığı GCC-AVR kullanarak nasıl derleneceğindeki gerçek farklılıkları (tercihleri ​​değil) çözmeyi amaçlıyor. En azından Arduino başlık dosyasını dahil etmek zorunda olduğunuzu biliyorum, ancak bunun ötesinde, örneğin GCC-AVR'yi kullanarak, .ino dosyasını .cpp dosyasına derlerken bir derleme hatasına neden olur. Basitlik adına, farklılıkların ne olduğunu açıklamak için klasik göz kırpma örneğini kullanalım. Veya daha iyi bir kod snippet'iniz varsa, lütfen elbette, snippet'i cevabınıza ekleyin ve farkları iyice açıklayın.

Lütfen hangisini kullanmanın daha iyi bir yol veya araç olduğuna dair görüş belirtmeyin.

Bilginize. Geliştirme için Platformio kullanıyorum ve derleme sırasında perde arkasında gerçekleşen bir dönüşüm süreci fark ediyorum. Ben orada gerçekten ne olduğunu anlamaya çalışıyorum, bu yüzden Arduino kod zaman, ben de "saf" C ++ sürümünü anlıyorum.

Soruma önceden cevap verdiğiniz için teşekkür ederiz.


Özellikle gccmasaüstünüzde mi yoksa AVR için AVR derleyicisinde avr-gccmi soruyorsunuz ? orada bir .inove bir .cppdosya arasında olduğundan çok daha büyük bir fark vardır .
BrettAM

@BrettAM Arduino UNO olarak GCC-AVR araç kiti hedef tahtasıdır ve bildiğiniz gibi bir Atmel AVR yongası kullanır. Sorumdaki belirsizliğe çağrı yaptığınız için teşekkürler. Ve evet, çok daha büyük bir fark olduğunu biliyorum. Bu yüzden bu soruyu soruyorum. Bu farklılıkların ne olduğunu öğrenmek için!
RedDogAlpha

Yanıtlar:


14

Cevabımı burada görebilirsiniz: Sınıflar ve nesneler: bunları kullanmak için kaç tane ve hangi dosya türüne ihtiyacım var? - özellikle: IDE'nin işleri nasıl organize ettiği .

En azından Arduino başlık dosyasını eklemeniz gerektiğini biliyorum

Evet, yapmanız gerekecek.

ancak bunun ötesinde, örneğin .CCP dosyasını, örneğin GCC-AVR kullanarak derleyerek .cpp dosyasına derlerseniz derleme hatasına neden olur.

IDE sizin için işlev prototipleri üretir. Bir .ino dosyasındaki kod buna ihtiyaç duyabilir veya gerekmeyebilir (yazar her zamanki C ++ yolunda kod yazacak ve bunları kendileri yapacak kadar disiplinli değilse, muhtemelen gerekecektir).


"Çizim" başka dosyalar (örn. Diğer .ino, .c veya .cpp dosyaları) içeriyorsa, bunların yukarıda belirtilen cevabımda açıkladığım gibi derleme işlemine dahil edilmesi gerekir.

Ayrıca çizim tarafından kullanılan herhangi bir kütüphanede bağlantı kurmanız (derlemeniz ve) gerekir.


Nesnelerin bağlantı tarafını sormadınız, ancak doğal olarak derlenen çeşitli dosyaların birbirine bağlanması ve daha sonra yükleme amacıyla bir .elf ve .hex dosyasına dönüştürülmesi gerekiyor. Aşağıya bakınız.


Örnek makefile

IDE çıkışına dayanarak bir süre önce basit bir makefile yaptım :

#
# 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 

Bu durumda, .ino dosyası Blink.cpp olarak yeniden adlandırıldıktan ve şu satırı ekledikten sonra sorunsuz bir şekilde derlendi :

#include <Arduino.h>

Özlü cevabınız için Nick'e teşekkür ederim, bulunduğunuz seviyeye yakın değilim ve bir yapım dosyası bile düşünmedim. Yani temel olarak sözdizimi aynı, sadece nesneleri bağlamakla ilgili, değil mi? İncelemek için make dosyanızı paylaştığınız için teşekkür ederiz. Bundan daha fazla soru geleceğinden eminim! Tekrar teşekkürler!
RedDogAlpha

Yukarıdaki dosyam yayınladığımda çalıştı, ancak daha sonraki IDE'ler için ayarlanmaya ihtiyaç duyabileceğine inanıyorum (çünkü hareket ediyorlar veya kütüphane dosyalarını yeniden adlandırıyorlar). Yine de, ayrıntılı bir derleme yapmak, IDE'nin şu anda ne ürettiğini gösterir, bu da sizi başlatmalıdır.
Nick Gammon

10

Nick Gammon'un cevabına birkaç puan eklemek istiyorum:

  • Derlemek için bir .ino dosyasını yeniden adlandırmanız gerekmez: derleyiciye C ++ (seçenek -x c++) olduğunu açıkça belirtirseniz , olağandışı dosya uzantısını yoksayar ve C ++ olarak derler.
  • #include <Arduino.h>.İno dosyasına eklemenize gerek yoktur : derleyiciye bunu sizin için yapmasını söyleyebilirsiniz ( -include Arduino.h).

Bu hileleri kullanarak , sadece uygun komut satırı seçenekleriyle avr-g ++ 'ı çağırarak, hiçbir değişiklik yapmadan Blink.ino'yu derleyebilirim :

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

Yukarıdaki komut satırında birkaç not:

  • /usr/local/lib/arduino/uno/libcore.aderlediğim Arduino çekirdeğini kurtardım. Aynı şeyleri tekrar tekrar derlemekten nefret ediyorum.
  • -x nonederleyiciye dosya uzantılarını tekrar hatırlatmasını söylemek için gereklidir. Bu olmadan, libcore.a'nın bir C ++ dosyası olduğunu varsayar.

Bu hileleri Sudar Muthu'nun Arduino-Makefile'sinden öğrendim . Bu, birçok kurul ve kütüphane ile çalışan çok genel bir Makefile'dir. Arduino IDE'ye göre eksik olan tek şey ileri bildirimlerdir.


Çok güzel, Edgar! Benim çözümüm temelde IDE'nin yaptıklarını taklit ediyor, sizinki asıl problemi çok daha temiz bir şekilde çözüyor. Tabii ki libcore.adosyayı önceden yapmak zorunda kalacaksınız . Cevabımdaki yapının core.aönceden yapılabileceğini düşünüyorum, bu yüzden her yapının bir parçası olmak zorunda değiller. Deneyimler, daha karmaşık eskizlerin (ör. Wire veya SPI kullanımı) eklenecek daha fazla dosyaya ihtiyaç duyduğunu göstermiştir core.a.
Nick Gammon

@NickGammon: Doğru, Muthu'nun Makefile (ve sanırım, Arduino IDE) libcore.a'da kullandığınız kütüphaneleri koyma eğilimindedir. Bu yaklaşımı gerçekten sevmiyorum çünkü sözde “çekirdek kütüphane” yi derlediğiniz programa bağımlı kılıyor. Wire veya SPI gibi tek dosya kitaplıkları için, kitaplık C ++ dosyasını ana programla aynı derleme komutuna koymayı tercih ederim. Bu komut satırı oldukça uzun sürüyor, bu yüzden bir Makefile kullanıyorum.
Edgar Bonet

1
IDE hakkında sevdiğim şeylerden biri, etrafta dolaşmak zorunda olmamanız. Zaten basit projeler için, "sadece çalışır".
Nick Gammon
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.