... vorrei scrivere un singolo programma che, nel caso venga compilato per ATtiny85 includa la libreria "TinyWireM", mentre, nel caso venga compilato per ATmega328p includa la libreria "Wire" ... così da compilare senza errori in funzione del target dove deve essere eseguito ...
Devo cercarti i particolari o posso risponderti in generale?
Esiste una variabile di sistema che determina il Controller in uso.
#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__)
codice per ATmega328...
#else
Codice per gli altri Controller
#endif
Controlla un po la libreria fastSPI.
Non so come si chiama la variabile per il ATtiny85 ma se Ti serve solo l' uno o l' altro basta controllare se non é un ATmega328p
... è ovviamente quella che uno da d'impulso, ma ... metti la libreria TinyWireM nella tua cartella delle librerie, scrivi un semplice programmino, che non fa nulla (setup e loop anche vuoti), ma che in testa contiene quel "#if defined", e prova a compilarlo per Arduino UNO ... avrai una bella sorpresa !!! ] ] ]
Ecco ... ti risparmi la fatica di scriverlo, compila questo per Arduino UNO ...
In questo momento non posso fare prove perché non ho nessuna board definita con un ATtiny85 e non ho tempo di farlo.
In questo momento nella compilazione la libreria mi da un sacco di errori di registri non definite indipendentemente si includo la libreria in modo non condizionato o condizionato.
Da quel poco che so dedurre é che sembra che la libreria venga inclusa indipendentemente dalla condizione #if.
prendendo come esempio la libreria FastSPI_LED dovrebbe funzionare:
uwefed:
Ciao Guglielmo
In questo momento non posso fare prove perché non ho nessuna board definita con un ATtiny85 e non ho tempo di farlo.
In questo momento nella compilazione la libreria mi da un sacco di errori di registri non definite indipendentemente si includo la libreria in modo non condizionato o condizionato.
NON ti serve l'ATtiny85 ... sei già caduto sul problema, tanto è vero che mi dici "... mi da un sacco di errori di registri non definite indipendentemente se includo la libreria in modo non condizionato o condizionato" ...
E' proprio questo il punto ...
... come vedi anche se la "#if defined", ma anche la "#ifdef", escludono una certa condizione, questa ... viene comunque compilata ... con i casini che ne conseguono e, con il fatto che quindi ... NON riesci a compilare il codice !!!
Guglielmo
P.S. : E' ovvio che dia un sacco di errori ... quelli sono registri del ATtiny85 che non esistono su Arduino UNO ... e difatti, NON essendo definito AVR_ATtiny85 non dovrebbe compilare quella lib ... invece ...
No Nid ... non compila correttamente, ma credo che tu non te ne accorgi perché probabilmente hai il "verbose" non attivo ... mettilo attivo in compilazione e vedrai ...
La strada che indichi si chiama "Computed Includes" ... ed è la seconda strada che ho provato anche io subito dopo aver visto il problema con la include normale, ma ... purtroppo non va neanche quella ...
Non da errore, ma da warning perché ... non trova il file da includere ...
Il problema del "#ifdef" in realtà, secondo me, deriva da questo ...
"Even if a conditional fails, the controlled text inside it is still run through initial transformations and tokenization. Therefore, it must all be lexically valid C."
... che, secondo me, va letto come : "Anche se la condizione è falsa, il testo in essa contenuto (cioè quello che uno mette dentro al #ifdef) viene comunque trattato, per cui deve essere sintatticamente valido per il C."
Chiaramente, la libreria TiniWireM.h contiene cose che in C sono sintatticamente valide se il processore è il ATtiny85, ma non più valide se il processore è un altro e ... li casca l'asino.
Guglielmo
Edit : la cosa è indipendente dalla versione del IDE che si usa e ... anche dalla Toolchain (provato anche con la 3.4.3)
gpb01:
"Even if a conditional fails, the controlled text inside it is still run through initial transformations and tokenization. Therefore, it must all be lexically valid C."
Mi sembra una cosa stupida. Se non la voglio includere c'e' un motivo. Perchè analizzarla comunque?
Un conto è una define per una macro o una costante per debug, ma comunque non mi interessa ne faccia l'analisi.
Alquanto strana come "decisione" del gcc.
nid69ita:
Mi sembra una cosa stupida. Se non la voglio includere c'e' un motivo. Perchè analizzarla comunque?
...
Nid, concordo con te, e purtroppo questa cosa crea dei bei casini che, credo vadano ad aggiungersi a quelli che già crea di perse l'IDE.
Ad esempio ... il fatto che nei "Computed Includes" non trova i files (... perché non sa seguire più le path) ... ho idea che sia qualche cosa introdotto dall' IDE e non da gcc
il problema è probabilmente quello che fa l'ide qunado tagliuzza le cose per crare il file main in cpp a partire dall'INO.
Attivate le scritte di debug e controllate in che cartella temporanea compila, entrate nella cartella e cercate il main() (nomesckecth.cpp se ricordo bene) e verificate cosa è successo alle ifdef.
Se sono scomparse, e trovate entrambe le include, alloa aprite un bug (se state usando l'ultima versione di ide, si intende! se no aggiornate)
credo che intenda sintatticamente, non che viene elaborato. la #ifdef usata così è normale, ed è usata anche nelle librerie arduino. potrebbe essere che il fatto che Arduino.h sia incluso DOPO sia il problema?
Ho riletto, ma non ho capito qual'è l'intento. Per un compilatore C il preprocessore si limita a includere o meno del codice limitatamente al codice testato con #if, ciò non influisce sulle altre compile unit che se non hanno #if vengono compilate e questo è corretto.
Normalmente quando si ha un sorgente compatibile con più di una libreria si deve creare un configure parametrizzato che permetta di configurare il build per compilare la libreria da cui dipende e per fare la fase di collegamento. Questo è possibile farlo con IDE che offrono strumenti di configurazione esterni che possono essere configurati dal file di progetto.
Nel mio caso con qtcreator ho queste righe nel file di progetto:
Includo il path di ricerca header lib/tc, abilito la dipendenza nei confronti di /lib/tc, includo il path di ricerca header locale, LIBS +=..... mi permette di specificare delle librerie da linkare al codice compilato.
Potrei mettere LIBS +=... in una condizione simile a if elseif che in base al valore di una variabile sceglie cosa linkare, in realtà posso usare strutture condizionali ovunque rendendo il codice configurabile attraverso una o più
variabili o anche una sola, es contains(WhatBuilt, ALL) { } else { contains(WhatBuild, DEMO} ecc.
Mentre credo che l'ide di Arduino abiliti o meno la compilazione di librerie aggiuntive grazie al preprocessore
interno che però non è in grado di fare il lavoro che svolge il preprocessore C++, quindi include la libreria per compilarla e linkarla ma il preprocessore C non include l'header.
Comunque, se il problema c'è di sicuro non riguarda GCC in quanto il comportamento è standard.
MauroTec:
...
Comunque, se il problema c'è di sicuro non riguarda GCC in quanto il comportamento è standard.
Non sembrerebbe Mauro, anche dalla documentazione gnu che ho postato ...
"Even if a conditional fails, the controlled text inside it is still run through initial transformations and tokenization. Therefore, it must all be lexically valid C."
... e difatti è proprio quello che fa ... solo che facendolo, la cosa crea problemi !
Questo è il codice che mi interessa, visto che sto scrivendo del codice che vorrei poter compilare sia per ATtiny85 che per ATmega328p e che usa il protocollo I2C :
#if defined( __AVR_ATtiny85__ )
#include <TinyWireM.h>
#else
#include <Wire.h>
#endif
void setup() {
// non ha importanza
}
void loop() {
// non ha importanza
}
... ora provate voi a compilarlo senza errori né warning
Guglielmo
@Lesto : E non puoi mica girartela come ti pare ... certo che ti funziona, in quel modo non sei grado di produrre l'errore. Usa la libreria e l'include che ho messo io (che su 328p crea errore) e allora vedrai ...
L'IDE prende il codice sopra scritto, c'aggiunge qualche riga e lo trasforma così (sketch_jan28a.cpp) :
#line 1 "sketch_jan28a.ino"
#if defined( __AVR_ATtiny85__ )
#include <TinyWireM.h>
#else
#include <Wire.h>
#endif
#include "Arduino.h"
void setup();
void loop();
#line 7
void setup() {
// non ha importanza
}
void loop() {
// non ha importanza
}
A questo punto lancia avr-g++ ... e salta fuori il problema perché, nonostante la "#if defined" comunque ".... the controlled text inside it is still run through initial transformations and tokenization" :
Quando una caratteristica viene confusa per bug, di questo si tratta.
"Even if a conditional fails, the controlled text inside it is still run through initial transformations and tokenization. Therefore, it must all be lexically valid C"
Questo significa che anche se il test fallisce il parser e il tokenizer e quindi il controllo degli errori è attivo e questa è una caratteristica. Diversamente scopriresti di aver scritto includ "stoca> solo quando la ifdef da esito positivo.
Quindi se ci sono errori di scrittura o di altra natura sia che il test dia o meno validità il parser ecc fa il suo lavoro e questo è utile o no.
Il problema che si presenta e proprio quello che ho descritto, cioè il codice sorgente della libreria viene comunque incluso in quanto il preprocessore di Arduino non è in grado di valutare l'espressione #ifdef ....
Ricorda che il preprocessore di arduino viene eseguito sul codice prima che il preprocessore C++ possa operare.
Uso spesso Gcc è ti posso garantire che non si tratta di un bug.