GCC fråga (KPIT GNU)
Re: GCC fråga (KPIT GNU)
Är du helt säker på att du har skrivit rätt i #ifndef-villkoren då? behövs bara ett tecken fel där så funkar det ju inte som tänkt.
Re: GCC fråga (KPIT GNU)
Har du "wrappen" i själva .h filerna?
Eller i .c filerna (och wrappar #include direktivet)?
Alltså:
I .h filen:
#ifndet denna-h
#define denna-h
...
...
#endif
I .c filen gör man bara en #include som vanligt (utan "wrapp").
Istället för att i *varje* .c fil göra:
#ifndef denna-h
#include denna.h
#endif
Det är enklare att lägga det på ett ställe, alltså i .h filen.
Eller i .c filerna (och wrappar #include direktivet)?
Alltså:
I .h filen:
#ifndet denna-h
#define denna-h
...
...
#endif
I .c filen gör man bara en #include som vanligt (utan "wrapp").
Istället för att i *varje* .c fil göra:
#ifndef denna-h
#include denna.h
#endif
Det är enklare att lägga det på ett ställe, alltså i .h filen.
Re: GCC fråga (KPIT GNU)
Nerre: jag kopierar när det gäller wrap-strängen...
Men just nu har jag renset lite och nu innehåller One_Wire.h uteslutande typedef och lite #define - och det verkar vara på väg att kanske fungera.
Jag är alltså helt enkelt slarvig som tusan...

Men just nu har jag renset lite och nu innehåller One_Wire.h uteslutande typedef och lite #define - och det verkar vara på väg att kanske fungera.
Jag är alltså helt enkelt slarvig som tusan...


Re: GCC fråga (KPIT GNU)
Det är nästan så jag börjar tro att Icecap trollar! 
Icecap skrev:

Icecap skrev:
Nerre skrev:I båda RTC och EEPROM-filen har jag sedan:
#ifndef __CONTROLLER_UNIT_200_IIC_100__
#include "\Workspace\Functions\Controller_Unit_200_IIC_100.c"
#endif // __CONTROLLER_UNIT_200_IIC_100__
Icecap, förstår du vad Nerre förklarar här?Det är där du gör fel, du kan inte inkludera samma .c-fil i två andra .c-filer. Då kommer att du dubletter av koden och då är det klart länkaren klagar på att det är dubletter. Samma kod kommer att kompileras två gånger, i två olika objektfiler.
Re: GCC fråga (KPIT GNU)
mri: jag förstår mycket väl - och likaväl fungerar det!
I "Controller_Unit_200_IIC_100.c":
#define __CONTROLLER_UNIT_200_IIC_100__
I "Controller_Unit_200_DS3232.c":
#ifndef __CONTROLLER_UNIT_200_IIC_100__
#include "\Workspace\Functions\Controller_Unit_200_IIC_100.c"
#endif // __CONTROLLER_UNIT_200_IIC_100__
I "Controller_Unit_200_24FC256.c":
#ifndef __CONTROLLER_UNIT_200_IIC_100__
#include "\Workspace\Functions\Controller_Unit_200_IIC_100.c"
#endif // __CONTROLLER_UNIT_200_IIC_100__
Konklusion:
Så länge jag gör en #include "\Workspace\Functions\Controller_Unit_200_DS3232.c" i main-filen till projektet kommer den att inkludera TEXTEN som programmet består av som hade det varit en del av main-filen.
Alltså kommer IIC-delen att inkluderas "per automatik" innan endera RTC eller EEPROM-delen inkluderas och då kommer __CONTROLLER_UNIT_200_IIC_100__ att vara definierat varför en "ny" inkludering inte sker från nästa av RTC/EEPROM-filen.
Så nej, jag trollar inte, jag får det att fungera istället.
EDIT: för tillfället har jag båda RTC och EEPROM med i form av #include "blabla" medan de 3 seriella portar har fått "grundfilerna" kopierade till projektbiblioteket (de ska ju anpassas till kommunikationsprotokollen) och de är tillfogad projektet som en källkodsfil på linje med main-filen.
Resultat: noll fel och noll problem. Men det ska jag snart få ordning på!
I "Controller_Unit_200_IIC_100.c":
#define __CONTROLLER_UNIT_200_IIC_100__
I "Controller_Unit_200_DS3232.c":
#ifndef __CONTROLLER_UNIT_200_IIC_100__
#include "\Workspace\Functions\Controller_Unit_200_IIC_100.c"
#endif // __CONTROLLER_UNIT_200_IIC_100__
I "Controller_Unit_200_24FC256.c":
#ifndef __CONTROLLER_UNIT_200_IIC_100__
#include "\Workspace\Functions\Controller_Unit_200_IIC_100.c"
#endif // __CONTROLLER_UNIT_200_IIC_100__
Konklusion:
Så länge jag gör en #include "\Workspace\Functions\Controller_Unit_200_DS3232.c" i main-filen till projektet kommer den att inkludera TEXTEN som programmet består av som hade det varit en del av main-filen.
Alltså kommer IIC-delen att inkluderas "per automatik" innan endera RTC eller EEPROM-delen inkluderas och då kommer __CONTROLLER_UNIT_200_IIC_100__ att vara definierat varför en "ny" inkludering inte sker från nästa av RTC/EEPROM-filen.
Så nej, jag trollar inte, jag får det att fungera istället.
EDIT: för tillfället har jag båda RTC och EEPROM med i form av #include "blabla" medan de 3 seriella portar har fått "grundfilerna" kopierade till projektbiblioteket (de ska ju anpassas till kommunikationsprotokollen) och de är tillfogad projektet som en källkodsfil på linje med main-filen.
Resultat: noll fel och noll problem. Men det ska jag snart få ordning på!

Senast redigerad av Icecap 27 maj 2014, 13:48:21, redigerad totalt 1 gång.
Re: GCC fråga (KPIT GNU)
BEEEPAlltså kommer IIC-delen att inkluderas "per automatik" innan endera RTC eller EEPROM-delen inkluderas och då kommer __CONTROLLER_UNIT_200_IIC_100__ att vara definierat varför en "ny" inkludering inte sker från nästa av RTC/EEPROM-filen.
Där är felet. Sista delen av den där meningen är helt felaktig.
VARJE c-fil i projektet kommer att kompileras separat.
Först kompileras alltså RTC-filen. Den inkluderar IIC-delen, eftersom de delarna inte är definierade, och så kompileras IIC-koden och hamnar i objektfilen för RTC.
Sen kompilera EEPROM-filen. Den inkluderar IIC-delen, eftersom de delarna inte är definierade (vid den kompileringen), och så kompileras IIC-koden och hamnar i objektfilen för EEPROM.
Sen när länkaren ska länka ihop RTC och EEPROM-filerna så finns IIC-koden i bägge => dublett!!!
Jag har skrivit det två gånger tidigare: varje C-fil som är inlagd i "projektet" kommer att pre-processas och kompileras separat, till en objektfil.
Re: GCC fråga (KPIT GNU)
*Lite* rörigt här... 
> du kan inte inkludera samma .c-fil i två andra .c-filer.
Det *kan* visst gå! Det beror helt på vad .c filen innehåller!
Det kan vara kod som enbart kompileras "local" i varje överordnad
c-fil och då uppstår inga problem alls. Däremot är det väldigt ovanligt
att man bygger sin kod på det sättet idag! Det är vanligare att
strukturera koden annorlunda och använda funktionsanrop.
Och i det aktuella fallet så misstänker jag att Controller_Unit_200_IIC_100.c *INTE*
ska inkluderas! Den borde separatkompileras och Controller_Unit_200_IIC_100.o
borde länkas till det övriga "at link-time".
I ifndef/include/endif exemplet borde det vara en .h fil som inkluderas!
Och som sagt, det är snyggare/enklare att lägga ifndef/endif *i* .h filen
istället för i alla .c filer. Visst, .h filen kommer att öppnas "i onödan" ett
par gånger, men det märks sannolikt inte.
Jag tar en annan sak i ett nytt inlägg...

> du kan inte inkludera samma .c-fil i två andra .c-filer.
Det *kan* visst gå! Det beror helt på vad .c filen innehåller!
Det kan vara kod som enbart kompileras "local" i varje överordnad
c-fil och då uppstår inga problem alls. Däremot är det väldigt ovanligt
att man bygger sin kod på det sättet idag! Det är vanligare att
strukturera koden annorlunda och använda funktionsanrop.
Och i det aktuella fallet så misstänker jag att Controller_Unit_200_IIC_100.c *INTE*
ska inkluderas! Den borde separatkompileras och Controller_Unit_200_IIC_100.o
borde länkas till det övriga "at link-time".
I ifndef/include/endif exemplet borde det vara en .h fil som inkluderas!
Och som sagt, det är snyggare/enklare att lägga ifndef/endif *i* .h filen
istället för i alla .c filer. Visst, .h filen kommer att öppnas "i onödan" ett
par gånger, men det märks sannolikt inte.
Jag tar en annan sak i ett nytt inlägg...
Re: GCC fråga (KPIT GNU)
OK, jag *tror* att jag börjar förstå grundproblemet... 
Du har rutiner som *inte* tillhör själva projektet, eller hur?
T.ex IIC, RTC och EEPROM. De är generella rutiner och kan
(åter-) användas i flera olika applikationer?
De ligger i (ett?) separata bibliotek t.ex "\Workspace\Functions\" ?
Helt OK, då ska dessa rutiner *inte* kompileras med projektet varje gång!
Dessa rutiner är *egna projekt* och byggs helt separat från din applikation.
Det skapar en .o fil någonstans (kanske också i "\Workspace\Functions\")
och du har .h filer som beskriver "interfacet" till dessa rutiner. När det är
gjort så är det inte mer med det, de är "black boxes". De ska normalt *inte*
kompileras om igen för varje applikation. D.v.s om du har skrivit dom så.
Sedan, i ditt applikation-projekt, så får du lägga till "\Workspace\Functions\"
till de sökvägar där *länkaren* letar efter .o (eller .lib) filer. Då kommer den
(d.v.s länkaren) att kunna bygga en komplett applikation.
På samma sätt behöver du sannolikt lägga till "\Workspace\Functions\" till de
ställen där kompilatorn letar efter .h filer när du gör #include...
Det ända som din applikation behöver "se" är en .h fil (kompilatorn) och
en .o fil (länkaren).
Ofta samlar man alla .h och .c (och eventeuellt .lib) filer i några generella
kataloger som "\Workspace\Include\" och "\Workspace\Object\" eller liknande.
Då blir det samma setup i alla appliktioner som använder dessa och du kan
ha egna kataloger for IIC, RTC, EEPROM o.s.v. Lättare att underhålla.
Men om alla generella rutiner ändå ligger i \Workspace\Functions\" så fungerar
ju även det...
Att du måste includera .c filer för att få det att "bygga" en en tydlig signal
om att något är ganska fel. Det är väldigt ovanligt att man gör så med C.
Om dessa (IIC, RTC o.s.v) filer *måste* kompileras om för att "anpassas"
till varje projekt, ja då är de ju inte generella och kan lika gärna kopieras
till varje projektkatalog och kompileras där. Och då ligger dom ju med
i "projektet" och miljön lägger automatiskt till dom vid "build".

Du har rutiner som *inte* tillhör själva projektet, eller hur?
T.ex IIC, RTC och EEPROM. De är generella rutiner och kan
(åter-) användas i flera olika applikationer?
De ligger i (ett?) separata bibliotek t.ex "\Workspace\Functions\" ?
Helt OK, då ska dessa rutiner *inte* kompileras med projektet varje gång!
Dessa rutiner är *egna projekt* och byggs helt separat från din applikation.
Det skapar en .o fil någonstans (kanske också i "\Workspace\Functions\")
och du har .h filer som beskriver "interfacet" till dessa rutiner. När det är
gjort så är det inte mer med det, de är "black boxes". De ska normalt *inte*
kompileras om igen för varje applikation. D.v.s om du har skrivit dom så.
Sedan, i ditt applikation-projekt, så får du lägga till "\Workspace\Functions\"
till de sökvägar där *länkaren* letar efter .o (eller .lib) filer. Då kommer den
(d.v.s länkaren) att kunna bygga en komplett applikation.
På samma sätt behöver du sannolikt lägga till "\Workspace\Functions\" till de
ställen där kompilatorn letar efter .h filer när du gör #include...
Det ända som din applikation behöver "se" är en .h fil (kompilatorn) och
en .o fil (länkaren).
Ofta samlar man alla .h och .c (och eventeuellt .lib) filer i några generella
kataloger som "\Workspace\Include\" och "\Workspace\Object\" eller liknande.
Då blir det samma setup i alla appliktioner som använder dessa och du kan
ha egna kataloger for IIC, RTC, EEPROM o.s.v. Lättare att underhålla.
Men om alla generella rutiner ändå ligger i \Workspace\Functions\" så fungerar
ju även det...

Att du måste includera .c filer för att få det att "bygga" en en tydlig signal
om att något är ganska fel. Det är väldigt ovanligt att man gör så med C.
Om dessa (IIC, RTC o.s.v) filer *måste* kompileras om för att "anpassas"
till varje projekt, ja då är de ju inte generella och kan lika gärna kopieras
till varje projektkatalog och kompileras där. Och då ligger dom ju med
i "projektet" och miljön lägger automatiskt till dom vid "build".
Re: GCC fråga (KPIT GNU)
Problemet som jag fattat det är att dessa gemensamma filer inte enkelt kan byggas till bibliotek
då de är avhängiga compile-time direktiv för t.ex. hur många UART:ar, hur många 1-wire sensorer et.c.
Ett alternativ som framhållits är ju att i förväg bygga alla tänkbara kombinationer till egna lib:ar och sedan
bara välja att länka till rätt lib för resp. projekt, typ 1-wire-2sensors.o, 1-wire-1sensor.o et.c.
Ett annat vore att "inkludera" .c-filerna, från sin gemensamma plats, via makefile:n istället för som #include i koden.
Ett tredje är att låta lib:arna dynamiskt allokera det minne de behöver i någon form av init() metod.
Vilket sätt som smakar bäst vet bara Icecap.
/johan
då de är avhängiga compile-time direktiv för t.ex. hur många UART:ar, hur många 1-wire sensorer et.c.
Ett alternativ som framhållits är ju att i förväg bygga alla tänkbara kombinationer till egna lib:ar och sedan
bara välja att länka till rätt lib för resp. projekt, typ 1-wire-2sensors.o, 1-wire-1sensor.o et.c.
Ett annat vore att "inkludera" .c-filerna, från sin gemensamma plats, via makefile:n istället för som #include i koden.
Ett tredje är att låta lib:arna dynamiskt allokera det minne de behöver i någon form av init() metod.
Vilket sätt som smakar bäst vet bara Icecap.
/johan
Re: GCC fråga (KPIT GNU)
En liten justering...
Man behöver nog specifikt peka ut de .o filer som ska vara med vid länkningen,
det räcker inte med att peka ut en katalog, om jag läser docs till LD rätt.
Alternativt laddar man alla .o filer till en .lib och pekar då enbart ut den.
Det är väl det normala sättet att hantera det...
Man behöver nog specifikt peka ut de .o filer som ska vara med vid länkningen,
det räcker inte med att peka ut en katalog, om jag läser docs till LD rätt.
Alternativt laddar man alla .o filer till en .lib och pekar då enbart ut den.
Det är väl det normala sättet att hantera det...
Re: GCC fråga (KPIT GNU)
> Problemet som jag fattat det är att dessa gemensamma filer inte enkelt kan byggas till bibliotek
> då de är avhängiga compile-time direktiv för t.ex. hur många UART:ar, hur många 1-wire sensorer et.c.
Ja exakt! Om de *måste* anpassas och kompileras till varje projekt så
är de ju inte generella, och då kan de lika gärna kopieras till varje
applikationsprojekt katalog och byggas "som vanligt" tillsammans
med projektet för övrigt. De blir bara en vanlig .c fil i projektet...
Det här är mer ett problem på mindre/snålare plattformar där det oftare
finns anledning till anpassning av koden för varje applikation.
Oavsett detta så är en #include av .c filer i princip alltid fel...
EDIT:
Hm, man skulle kunna ha en liten "placeholder" .c fil i projektet
som *enbart* gör include på t.ex RTC.c. På det sättet så skulle
det se ut som att den tillhör projektet samtidigt som det enbart
finns i kopia av källkoden någon annanstans...
EDIT2:
Kanske två includes, en för en applikations specifik .h fil som sätter
upp t.ex antalet 1-wire linjer och in för själva 1-wire koden...
> då de är avhängiga compile-time direktiv för t.ex. hur många UART:ar, hur många 1-wire sensorer et.c.
Ja exakt! Om de *måste* anpassas och kompileras till varje projekt så
är de ju inte generella, och då kan de lika gärna kopieras till varje
applikationsprojekt katalog och byggas "som vanligt" tillsammans
med projektet för övrigt. De blir bara en vanlig .c fil i projektet...
Det här är mer ett problem på mindre/snålare plattformar där det oftare
finns anledning till anpassning av koden för varje applikation.
Oavsett detta så är en #include av .c filer i princip alltid fel...

EDIT:
Hm, man skulle kunna ha en liten "placeholder" .c fil i projektet
som *enbart* gör include på t.ex RTC.c. På det sättet så skulle
det se ut som att den tillhör projektet samtidigt som det enbart
finns i kopia av källkoden någon annanstans...
EDIT2:
Kanske två includes, en för en applikations specifik .h fil som sätter
upp t.ex antalet 1-wire linjer och in för själva 1-wire koden...
Re: GCC fråga (KPIT GNU)
Fast om man kopierar dem till varje projekt så kan man inte enkelt uppgradera dem med nyare/förbättrade funktioner.
Fast jag skulle nog lösa det då genom att ha en projektspecifik C-fil som inkluderar dessa C-filer och skapar ett funktionsbibliotek för det projektet. (Ungefär som Sodjan är inne på där ser jag, vi skrev samtidigt.)
Så länge källkodsfilerna inte ändras så kommer de inte kompileras om varje gång (MEN, nu insåg jag haken, kompilatorn märker nog inte om #include-erade filer ändras och bygger då inte om objektfilen...).
Det är betydligt enklare om man skriver make-filer. Där anger man ju för varje destinationsfil dels vilka andra filer den beror på och dels vilket kommando som bygger den. Där skulle man då kunna skriva nåt i stil med:
Så om nån av filerna IIC.c, RTC.c, EEPROM.c, project_functions.c eller project_functions.h har ändrats (har senare datum än projekt_functions.o) så kompileras allt om.
(Filen project_functions.c inkluderar alltså dels de projektspecifikat definitionerna i project_functions.h och dels källkodsfilerna IIC.c, RTC.c, EEPROM.c)
(Fast nu har jag kanske rört till det...)
Fast jag skulle nog lösa det då genom att ha en projektspecifik C-fil som inkluderar dessa C-filer och skapar ett funktionsbibliotek för det projektet. (Ungefär som Sodjan är inne på där ser jag, vi skrev samtidigt.)
Så länge källkodsfilerna inte ändras så kommer de inte kompileras om varje gång (MEN, nu insåg jag haken, kompilatorn märker nog inte om #include-erade filer ändras och bygger då inte om objektfilen...).
Det är betydligt enklare om man skriver make-filer. Där anger man ju för varje destinationsfil dels vilka andra filer den beror på och dels vilket kommando som bygger den. Där skulle man då kunna skriva nåt i stil med:
Kod: Markera allt
projekt_functions.o: IIC.c RTC.c EEPROM.c project_functions.c project_functions.h
gcc project_functions.c -o project_functions.o
(Filen project_functions.c inkluderar alltså dels de projektspecifikat definitionerna i project_functions.h och dels källkodsfilerna IIC.c, RTC.c, EEPROM.c)
(Fast nu har jag kanske rört till det...)
Re: GCC fråga (KPIT GNU)
> Fast om man kopierar dem till varje projekt
Det är det man undviker med mina två EDIT's i senaste inlägget.
Som ju är samma sak som du också skrev...
> (MEN, nu insåg jag haken, kompilatorn märker nog inte om #include-erade filer ändras och bygger då inte om objektfilen...).
Men om en .h fil ändras i ett vanligt projekt, så måste väl miljön
fatta det och se till att bygga om allt som inkluderar den filen !?
Det är inte så att miljön själv scannar källkoden efter #include's och
bygger sina egna beroenden? Kanske inte...
> (Fast nu har jag kanske rört till det...)
Nja, det röriga är att ha generella rutiner som i alla fall måste
anpassas till varje projekt...
Då blir det lite rörigt... 
Det är det man undviker med mina två EDIT's i senaste inlägget.
Som ju är samma sak som du också skrev...
> (MEN, nu insåg jag haken, kompilatorn märker nog inte om #include-erade filer ändras och bygger då inte om objektfilen...).
Men om en .h fil ändras i ett vanligt projekt, så måste väl miljön
fatta det och se till att bygga om allt som inkluderar den filen !?
Det är inte så att miljön själv scannar källkoden efter #include's och
bygger sina egna beroenden? Kanske inte...
> (Fast nu har jag kanske rört till det...)
Nja, det röriga är att ha generella rutiner som i alla fall måste
anpassas till varje projekt...


Re: GCC fråga (KPIT GNU)
Det hela går ut på att jag har generella rutiner som INTE ska tillpassas från projekt till projekt!
I min main-fil till projektet finns det nu:
#include "\Workspace\Functions\Controller_Unit_200_24FC256_100.c"
#include "\Workspace\Functions\Controller_Unit_200_DS3232_100.c"
Den första inkluderar EEPROM-funktionen men då __CONTROLLER_UNIT_200_IIC_100__ INTE är definierat kommer följande:
<I båda "Controller_Unit_200_24FC256_100.c" och "Controller_Unit_200_DS323_100.c">
#ifndef __CONTROLLER_UNIT_200_IIC_100__
#include "\Workspace\Functions\Controller_Unit_200_IIC_100.c"
#endif // __CONTROLLER_UNIT_200_IIC_100__
Resultatet är att den - innan annan kod kompileras i respektive fil - inkluderar IIC-koden.
När den sedan kommer till RTC-filen är __CONTROLLER_UNIT_200_IIC_100__ redan definierat varför IIC-delen inte inkluderas igen.
Fungerar smärtfritt och klickfritt numera.
I min main-fil till projektet finns det nu:
#include "\Workspace\Functions\Controller_Unit_200_24FC256_100.c"
#include "\Workspace\Functions\Controller_Unit_200_DS3232_100.c"
Den första inkluderar EEPROM-funktionen men då __CONTROLLER_UNIT_200_IIC_100__ INTE är definierat kommer följande:
<I båda "Controller_Unit_200_24FC256_100.c" och "Controller_Unit_200_DS323_100.c">
#ifndef __CONTROLLER_UNIT_200_IIC_100__
#include "\Workspace\Functions\Controller_Unit_200_IIC_100.c"
#endif // __CONTROLLER_UNIT_200_IIC_100__
Resultatet är att den - innan annan kod kompileras i respektive fil - inkluderar IIC-koden.
När den sedan kommer till RTC-filen är __CONTROLLER_UNIT_200_IIC_100__ redan definierat varför IIC-delen inte inkluderas igen.
Fungerar smärtfritt och klickfritt numera.
Re: GCC fråga (KPIT GNU)
Tja... C kompilatorn ger ju utrymme för ganska mycket kreativtitet, på gott och ont.
Är de inte lite såhär Arduino IDEn gör, dvs slår ihop alla källkodsfiler (sketcher) till en stor fil och sedan skickar den till kompilatorn.
Men Icecap, det du gör kan göras på annat mer "standardiserat" och mer allmänt förekommande sätt, med bibehållna möjligheter till anpassning osv. Men som sagt, C miljön tillåter kreativitet.
Är de inte lite såhär Arduino IDEn gör, dvs slår ihop alla källkodsfiler (sketcher) till en stor fil och sedan skickar den till kompilatorn.
Men Icecap, det du gör kan göras på annat mer "standardiserat" och mer allmänt förekommande sätt, med bibehållna möjligheter till anpassning osv. Men som sagt, C miljön tillåter kreativitet.