Kompilácia programu

Page

Stránky / Arduino / Pod kapotou Arduina /

V tomto texte sa pokúsim popísať, čo sa deje počas kompilácie programu. Je to dôležité na pochopenie toho, prečo si v C++, ktoré používa kompilátor pre Arduino môžeme dovoliť niektoré konštrukcie, ktoré by ináč vyhadzovali chybu. A zase naopak, niektoré bežné konštrukcie v C++ nás môžu v IDE Arduina prekvapiť. Budeme sa držať aktuálneho IDE v čase písania textu 1.0.6.

Nič nerobiaci program

Na skúmanie kompilácie použijeme program, ktorý nerobí nič, iba obsahuje najzákladnejšiu konštrukciu nutnú na to, aby išiel program skompilovať. Arduino IDE použije na reálne kompilovanie dočasný adresár, v ktorom určitým spôsobom modifikuje pôvodný zdrojový text. Ak chceme vidieť, kde sa ten adresár nachádza, je treba spustiť funkciu menu File/Preferences a v zobrazenom dialógu zaškrtnúť položku Show verbose output during compilation.

Originál

// ######
// Header
// ######

void setup() {
}

void loop() {
}

Upravené

#line 1 "compile1.ino"
// ######
// Header
// ######

#include "Arduino.h"
void setup();
void loop();
#line 5
void setup() {
}

void loop() {
}

Vidíme, že IDE urobilo drobné zmeny. Našlo prvý riadok za poznámkami, kde sa reálne začína náš kód a do vzniknutej medzery doplnilo hlavičkový súbor Arduino.h a definície všetkých prototypov funkcií, ktoré sa v súbore nachádzajú.

Prototyp funkcie definovaný pred prvým použitím

Na čo je ale dobré to, čo IDE urobilo. Vysvetlíme si to na nasledovnom príklade. V typickom prekladači C++ by sa nasledovný príklad skončil s chybou, pretože funkcia func() nie je známa na mieste, kde sa prekladá funkcia setup(). Na tom mieste by sa objavila chyba. Arduino IDE preto prehľadá váš kód a doplní na začiatok prototypy funkcií, ktoré nájde v kóde. Robí tak vlastne za vás to, čo by ste mali urobiť sami. Je zrejmé, že autori Arduina mysleli na to, že k jeho vývojovému prostrediu sadajú aj menej skúsení programátori, ktorí by sa na tomto elementárnom probléme zasekli na dlhší čas.

Originál

// ######
// Header
// ######

void setup() {
  func();
}

void loop() {
}

void func() {
}

Upravené

#line 1 "compile2.ino"
// ######
// Header
// ######

#include "Arduino.h"
void setup();
void loop();
void func();
#line 5
void setup() {
  func();
}

void loop() {
}

void func() {
}

Keď tento postup narobí problémy

Obvykle to mnohým problémom pomôže, ale existuje možnosť, kedy sa to celé pokazí a vy nemáte ani potuchy prečo. Nasleduje príklad s enum, kde je to dobre vidno. Enum je definovaný pred prvým použitím a napriek tomu chyba? Zapracovala tu ale logika Arduina, čo bolo v tomto prípade na škodu.

Originál

// ######
// Header
// ######

enum state {statea=1,stateb};

void setup() {
  func(statea);
}

void loop() {
}

void func(state s) {
}

Upravené

#line 1 "compile3.ino"
// ######
// Header
// ######

#include "Arduino.h"
void setup();
void loop();
void func(state s);
#line 5
enum state {statea=1,stateb};

void setup() {
  func(statea);
}

void loop() {
}

void func(state s) {
}

Našťastie je tu ľahká možnosť nápravy. Je treba vo svetlozelenom poli nájsť malé rozbaľovacie menu a v ňom použiť funkciu New tab. IDE si vypýta názov súboru, kam zadajte napríklad definicie.h. Do neho preneste definíciu enum. Na začiatok pôvodného súboru nezabudnite pripísať #include "definicie.h". Potom to už pôjde skompilovať.

IDE opäť prehľadá váš zdrojový kód a urobí to, že do dočasného adresára skopíruje aj súbor definicie.h v nezmenenej podobe a compile3.ino ako compile3.cpp a tam to celé preloží.

compile3.ino

// ######
// Header
// ######

#include "definicie.h"

void setup() {
  func(statea);
}

void loop() {
}

void func(state s) {
}

definicie.h

enum state {statea=1,stateb};

compile3.cpp

#line 1 "compile3.ino"
// ######
// Header
// ######

#include "definicie.h"

#include "Arduino.h"
void setup();
void loop();
void func(state s);
#line 7
void setup() {
  func(statea);
}

void loop() {
}

void func(state s) {
}

Ak by sa hlavičkový súbor mal používať vo viacerých zdrojových súboroch, potom je bezpečnejšie, ak ho obalíte do trojice #ifndef#define a #endif, tak ako je to zaužívané pri bežných hlavičkových súboroch v C++. Príklad si môžete pozrieť napríklad v mojom projekte 1W LED svetla.


05.07.2015


Menu