GCC fråga (KPIT GNU)

C, C++, Pascal, Assembly, Raspberry, Java, Matlab, Python, BASIC, SQL, PHP, etc.
Nerre
Inlägg: 27184
Blev medlem: 19 maj 2008, 07:51:04
Ort: Upplands väsby

Re: GCC fråga (KPIT GNU)

Inlägg av Nerre »

Folk har ju kompilerat program ganska länge, under en massa olika förutsättningar, så det har ju vuxit fram en ganska väl beprövad praxis kring hur man gör för att det ska vara smidigast. Det KAN ju vara idé att snegla lite på den väl beprövade praxisen innan man hittar på egna grejer? :)
sodjan
EF Sponsor
Inlägg: 43247
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: GCC fråga (KPIT GNU)

Inlägg av sodjan »

> Det hela går ut på att jag har generella rutiner som INTE ska tillpassas från projekt till projekt!

OK. Så det finns inget i 24FC256 och DS3232 filen som är beroende på något annat
från filerna där de inkluderas?

Men då förstår jag inte alls varför du inte kompilerar dessa separat (d.v.s i förväg) och
bara länkar det till applikationerna. Nu får du ju ta tiden att kompilera om samma
kod om och om igen (kanske inget större problem, det är mer principen).

Visst, det fungerar rent tekniskt så som du gör nu, men det är inte "normalt". :-)
Användarvisningsbild
mri
Inlägg: 1165
Blev medlem: 15 mars 2007, 13:20:50
Ort: Jakobstad, Finland
Kontakt:

Re: GCC fråga (KPIT GNU)

Inlägg av mri »

Nja sodjan, jag ser inga fördelar med att förkompilera i detta fall. Då måste man underhålla dessa förkompilerade objektfiler/biblioteksfiler separat ifall man ändrar nån väsentlig kompileringsoption eller annan inställning som har global verkan, vilket inte är ovanligt när man utvecklar kod.
Även om det principiellt är "rätt" och för dessa små projekt kanske vinner nån bråkdels sekund vid kompileringen av applikationen, har man också skapat ett underhållsproblem åt sig.
Bättre är då, tycker jag, att inkludera de externa .c filerna direkt i projektet man jobbar med, och med *inkludera* menar jag INTE med #include som Icecap gjort, utan man inkluderar .c filen i Makefilen eller nåt motsvarande projektsystem som moderna IDEn erbjuder. Att kompilera alla källkodsfiler i projektet brukar vanligen också underlätta vid debuggning om man vill stega genom koden. Är koden förkompilerad är det lätt hänt att debuggern tappat kopplingen mellan objektfilen och den ursprungliga källkoden.
Användarvisningsbild
Icecap
Inlägg: 26629
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: GCC fråga (KPIT GNU)

Inlägg av Icecap »

OK, nu har jag flytta om på en hel del (klippa och klistra) och jag kan få till det nu med RTC och EEPROM. Jag inkluderar IIC, RTC och EEPROM .C-filer i projektet, har skapad ett par .H-filer med "extern blablabla" och ytterligare en med typedef för RTC-delen.

Fungerar fint och uppfyller "hur man gör" som jag förstår det.

blabla...

Satt och skrev en lång bit om att jag vill föra "tillbaka" #define under kompileringen - och det går ju inte hur jag än vänder och vrider på det. Om det var möjligt att testa om en viss fil fanns ville det vara enklare men det pre-kompiler direktiv finns inte efter vad jag vet. Annars hade det varit enkelt:
#if file_exist("Projektets_Specialparameter.h")
#include "Projektets_Specialparameter.h"
#else
#define Standard_Parameter 8
#endif

Då kunde man ha default definitioner direkt i filerna men även skriva en fil i projektbiblioteket som overrider dessa. Samtidig kunde man ha "standardfunktionerna" kvar i "orörd" skick.

Nu får jag lösa det vid att flytta "upp" vissa funktioner från funktions-filen och skapa den i main-filen. Tänk: hitta en sensor på 1-wire bussen. Jämför den sensor med den som finns sparad i Config-blocket. Min tanke är att man i vissa projekt kan behöva att kunde addera sensorer med en knapptryckning men även att om exakt en sensor är borta och det har tillkommit exakt en ny, då kan den nyas serienummer ersätta den försvunnade sensorn och man kan alltså ställa in vilka sensorer som hör till vad och även byta dom on-the-fly.

Så istället för att ha en "hitta alla sensorer fast inte fler än X och jämför dom med de sparade i Config" måste jag göra samma sak men ha "intelligensen" i main-filen och sedan låta 1-wire-filen innehålla lägre nivå funktioner. "Find_First", "Find_Next", "Convert_All_Temp" osv. och sedan sy ihop funktionaliteten med dom i main-filen.

Når det fungerar kan jag sannolikt skapa en fil som kan "sno ihop" detta på ett automatisk sätt så i brist på annat kan man använda den funktion.
Användarvisningsbild
arvidb
Inlägg: 4537
Blev medlem: 8 maj 2004, 12:56:24
Ort: Stockholm

Re: GCC fråga (KPIT GNU)

Inlägg av arvidb »

Icecap skrev: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.
Icecap: Nu hann du posta ett till inlägg medan jag skrev, men nedanstående kanske ändå kan vara till nytta

=====

Bra att det fungerar - men vilken röra du får! Du ska i princip aldrig göra '#include "fil.c"'! Endast h-filer inkluderas med #include.

Exempel:

Fil iic.c innehåller funktionsdefinitioner:

Kod: Markera allt

#include <iic.h>

void iic_init(struct iic_periph *peripherals)
{
	while (peripherals->name) {
		iic_periph_init(peripherals);
		peripherals++;
	}
}
Filen iic.h innehåller motsvarande deklarationer samt en "include guard":

Kod: Markera allt

#ifndef IIC_H
#define IIC_H

struct iic_peripheral {
	unsigned char addr;
	char *name;
};

void iic_init(struct iic_periph *peripherals);

#endif /* IIC_H */
Varje funktion i iic.c som inte har en deklaration i iic.h bör definieras som static - t.ex.:

Kod: Markera allt

static void local_function(int param1)
{ 
	...
}

I din main.c gör du sedan följande:

Kod: Markera allt

#include <stdlib.h>
#include <iic.h>

static struct iic_peripheral iic_periphs = {
	{ 0x68, "DS3232" },
	{ 0x50, "24FC256" },
	{ 0x00, NULL },
}

...

int main(void)
{
	iic_init(iic_periphs);

	...
	return EXIT_SUCCESS;
}
Sedan får du instruera din kompileringsmiljö på något sätt så att den vet att både main.c och iic.c ska kompileras och länkas ihop till den slutliga binärfilen. Om du använder '#include <fil.h>' och inte '#include "fil.h"' (alltså med <> istället för "") så måste du också se till så att din kompileringsmiljö håller reda på var .h-filerna finns och talar om det för kompilatorn.

Hoppas det blev klarare av detta...

Edit: glömde include guard i .h-filen. Fixat nu.
ie
EF Sponsor
Inlägg: 1371
Blev medlem: 23 oktober 2006, 13:12:57
Ort: Tyresö

Re: GCC fråga (KPIT GNU)

Inlägg av ie »

Med risk för upprepning...

H-filerna ska man se som interfacet till den modul som är skapad i en C-fil, som alltså talar om vilka funktioner (och ev externa variabler) som finns för denna. Interna deklarationer bör inte ligga i H-filen, då dessa inte ska synas utåt och dessutom ofta är onödiga.

Varje annan modul som behöver använda denna modul ska #include dess H-fil för att få tillgång till interfacet. Eftersom H-filen innehåller #ifndefine-wrappern så gör det inget om samma H-fil inkluderas flera gånger.

När du inkluderar filer i projektet så innebär det att du talar om för utvecklingsmiljön vilka filer resultatet är beroende av, varvid miljön kan bygga en korrekt make-fil.

I AVR-miljön lärde jag mig nyligen hur jag kan ha C-moduler i en gemensam katalog för olika projekt. Det innebär att det bara finns ett original men att samma fil används av flera projekt. (Slipper alltså att kopiera den med risk för att få olika versioner.) Kanske inte alltid rätt att göra så, men passar perfekt för mig då det säkerställer att olika delprojekt alltid använder senaste versionen av koden.

I bifoga fil finns ett stycke ur boken Vägen till C som handlar om just hur H/C-filer bör hanteras.
skanna0001.jpg
Edit: Bilden hamnade lite snett.
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
sodjan
EF Sponsor
Inlägg: 43247
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: GCC fråga (KPIT GNU)

Inlägg av sodjan »

> Nja sodjan, jag ser inga fördelar med att förkompilera i detta fall.

OK, jag talade kanske om ett lite mer generellt fall. :-)
Och det är i alla fall naturligare än att gör #include på c-filer.

> Bättre är då, tycker jag, att inkludera de externa .c filerna direkt i projektet man jobbar med...

Och med "inkludera" menas alltså att lägga till dom i IDE'ts projekt, inte att
flytta någon fil fysiskt mellan kataloger, hoppas jag. Och IDE'ts make-automatik
borde vara tillräckligt smart för att hantera det. Skillnanden mellan det och att
länka till färdiga objekt filer är ju inte så stor, rent tekniskt.
Användarvisningsbild
Icecap
Inlägg: 26629
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: GCC fråga (KPIT GNU)

Inlägg av Icecap »

Det är ju intressant detta...

Och som folk har fel!

Jo, man KAN lägga kod i .H-filer! Jag påstår inte att det är bra eller speciellt vettigt - men man kan! Det är dock många år sedan jag gjorde det senast och kommer jag över några gamla projekt som jag har gjort det i rensar jag upp i det.

static osv. är ju - för mig - gammalt skåpsmat, använder det flitigt för båda variabler och funktioner.

Det som inte verkar till att fatta är att jag vill kunde göra en fil med en funktion i. Filen ska sedan inkluderas i projektet på något vid, helst vid att lägga in det i projektet. MEN - funktionen ska kunde använda en definition om den finns.

Så tag ett exempel. En funktion kan behöva ett värde för att t.ex. allokera plats för en buffer. Och nej, vi pratar INTE om dynamisk minnesallokering! Som standard kanske det är normalt med 10 bytes men i vissa projekt kan 100 bytes vara mer vettigt.

Inget annat ska ändras i funktionsfilen. Och då kommer problemet!
* Rent teknisk behöver man inte att kopiera funktionsfilen till projektbiblioteket - om man bara kunde "överföra" ändringen med en parameter.
* Ändringen kan vara extremt enkel: en definition som är "aktiv" under kompileringen av funktionsfilen men som kommer från projektets definitioner.

Tänk såhär: I funktionsfilen kan man skriva:
#ifndef __FUNCTION_BUFFER_SIZE__
#define __FUNCTION_BUFFER_SIZE__ 10
#endif

unsigned short Buffer[__FUNCTION_BUFFER_SIZE__];

Detta kommer då att göra så att om funktionsfilen kompileras OCH __FUNCTION_BUFFER_SIZE__ är känd när den kompileras kommer bufferstorleken att styras av det värde men är den inte definierat blir den det och då används standardvärdet.

Resultatet vill alltså vara att INGEN editering av funktionsfilen behöver att ske, ingen ändring eller liknande, man kan alltså använda exakt samma fil i många projekt men om det behövs anpassning kan man göra det i projektet.

Och då programmörer är lata människor finns det ganska säker ett sätt att lösa detta på! En programmör tackar ALDRIG nej till en lösning som medger att man kan bygga en funktion och spara den i ett gemensamt funktionsbibliotek där den sedan kan avbuggas och räknas som "säker och stabil"!
Nerre
Inlägg: 27184
Blev medlem: 19 maj 2008, 07:51:04
Ort: Upplands väsby

Re: GCC fråga (KPIT GNU)

Inlägg av Nerre »

Det är klart man KAN lägga kod i .h-filer. Du kan lägga kod i .txt-filer, i .doc-filer eller vad du vill. Vad du kallar filerna bryr sig inte kompilatorn om så länge du säger åt den vad den ska göra med dem.

Men hela poängen med .h-filer är att de ska vara en "header" som bara innehåller deklarationer. De måste inte heta .h heller, du kan kalla dem .inc eller .foo om du vill. Men det blir svårare för andra att förstå vad filerna innehåller om man hittar på egna namn.

http://embeddedgurus.com/barr-code/2010 ... ader-file/


Sen tycker jag att du verkar blanda ihop "återanvända en funktion" och "återanvända källkod".

En funktion som hanterar 10 givare (via en #define) är inte samma funktion som en som hanterar 100 givare (via en #define). I det fallet återanvänder du källkoden, inte funktionen. Funktionerna heter samma sak, men eftersom den kompilerade koden skiljer sig åt är det inte samma funktion.
johano
Inlägg: 1943
Blev medlem: 22 januari 2008, 10:07:45
Ort: Stockholm

Re: GCC fråga (KPIT GNU)

Inlägg av johano »

Icecap:
Du kan använda argumentet -D till GCC för att sätta en projekt-global #define, typ

gcc -D__FUNCTION_BUFFER_SIZE__=100 ...

/johan
Nerre
Inlägg: 27184
Blev medlem: 19 maj 2008, 07:51:04
Ort: Upplands väsby

Re: GCC fråga (KPIT GNU)

Inlägg av Nerre »

Ett annat sätt är väl kanske att .c-filen för de där funktionerna gör include på en .h-fil som ligger i projektet?

Nu minns jag inte till hundra hur det där funkar, man var den letar efter #include-filer styrs ju av om det står "" runt namnet eller <>. Fast lite snabbt googlade visar att den nog där i första hand letar i samma bibliotek som källkodsfilen själv ligger, så det funkar kanske inte. Det där -D verkar vara vettigare.

Men, som jag skrev innan. Det är egentligen inte bra att ha funktioner som kompileras olika beroende på vilket projekt de ligger i, men samtidigt heter exakt samma sak.

Antingen bör man då samtidigt byta namn på funktionerna. Istället för att man har en read_sensors() för 10 givare och en read_sensors() för 100 givare så har man read_sensors10() och read_sensors100().

Eller så använder man nån form av initieringsfunktion (som sätter en static variabel i modulen).

Eller så ser man till att alltid skicka med antalet givare som en parameter till alla funktioner (där kan man faktiskt trixa genom att använda ett projektspecifikt makro, så man slipper skriva parametern varje gång).
Senast redigerad av Nerre 28 maj 2014, 09:18:03, redigerad totalt 1 gång.
sodjan
EF Sponsor
Inlägg: 43247
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: GCC fråga (KPIT GNU)

Inlägg av sodjan »

OK, ja då går de såklart inte att bara länka med förkompilerade objekt filer.

Men fungerar det inte så här:

1. I din projektkatalog, skapa function.h där det (bl.a) finns en rad med "#define __FUNCTION_BUFFER_SIZE__ 20".
2. Skapa en function_stub.c där det bara finns 2 "#include", en för function.h och en för /function_dir/function.c (var den nu ligger).
3. Lägg till function_stub.c till ditt "projekt" så att det kommer att vara med i build-processen.

Detta borde läsa in din egen .h fil och den gemensamma .c filen samt sätta __FUNCTION_BUFFER_SIZE__ rätt.

Ett annat sätt (för att slippa stubb filen) är att säga till kompilatorn att den ska sätta __FUNCTION_BUFFER_SIZE__
innan kompilatorn anropas. Det brukar finnas funktioner i IDE'n för att göra det och den lägger till en switch
på kommandot till kompilatorn.

EDIT: Alltså så som johano skriver, fast det sker genom att fylla i något i IDE't (som sedan
sätter rätt flagga till gcc kommandot).

Notera att varje .c fil kompileras var för sig, det finns igen metod för kompilatorn i sig
att "överföra ändringen med en parameter", varje kompilering är självständig.

Hm, det borde även gå att ha en #include i function.c som pekar mot projekt katalogen (?).
Då behövs bara steg "1" ovan och du lägger till function.c direkt i ditt projekt.

EDIT: Alltså så som Nerre just skrev. Är för långsam idag... :-)
Nerre
Inlägg: 27184
Blev medlem: 19 maj 2008, 07:51:04
Ort: Upplands väsby

Re: GCC fråga (KPIT GNU)

Inlägg av Nerre »

De har blivit så rätt ofta i den här tråden, att vi är flera som skriver nästan samma sak samtidigt (inte blir det bättre av att jag efter att ha postat en grej kommer på ett tillägg och ändrar). Men poängen är ju där att eftersom vi är ganska många som skriver ungefär samma sak så är det ett rätt bra tecken på att det nog är "rätt sätt".
Användarvisningsbild
Icecap
Inlägg: 26629
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: GCC fråga (KPIT GNU)

Inlägg av Icecap »

Nerre: Det må vara att jag anser att en bit källkod är en funktion även om en bufferstorlek ändras och att du anser att det är olika funktioner om en bufferstorlek är olika.

Men nu har jag hittat sättet som uppfyller mitt behov. Tyvärr är det inte lika enkelt som jag hade hoppats på, det hade ju varit enklare att skriva det i en fil med den vanliga editor men OK, lösningen är att i Build lägga in en "fast" definition. Jag gissar på att det är som att lägga in den i starten av make-filen eller liknande.

I HEW är det Build->Toolchain->C/C++. I den flik, under kategori Source kan man visa entries. Där väljer jag "Defines" och där kan jag lägga in en definition och ett värde för den definition, alltså motsvarande till den globala definition jag vill ha inför kompileringen.

Jag har nu testat detta och det fungerar utmärkt, har lagt in i en funktionsfil att default värdet är 8 men i denna inställning har jag angivit 20. När jag sedan använder en utskrift från funktionsinitieringen om detta värde är svaret det värde jag har lagt in i projektet.

Därmed har jag möjlighet att göra "globala defines" som jag har varit målet hela tiden.

===========================
Hoppla, ett par svar innan jag skrev klart:
johano: helt klart, hitta just detta som gör detta - fast på ett annat sätt - fast likadan... Ja, du förstår.

Nerre: jag skulle önska att det fanns ett sätt att låta en fil acceptera att en viss fil inte fanns vid #include. Självklart kan man skapa en fil som alltid ska finnas med i alla projekt och alla funktionsfiler kan sedan inkludera denna, oavsett om den är tom som en ministerhjärna eller inte. Klart en möjlighet jag ska fundera över, jag ska testa när jag får tid.

Sodjan: ja, du ser ju svaren ovan.
Nerre
Inlägg: 27184
Blev medlem: 19 maj 2008, 07:51:04
Ort: Upplands väsby

Re: GCC fråga (KPIT GNU)

Inlägg av Nerre »

Som jag skrev, det är inte samma funktion vara för att de råkar ha olika namn. Samma funktion är det om det kompilerade resultatet ser likadant ut.

Att ha saker som heter samma sak men som gör olika saker är som gjort för att ge oförklarliga buggar.
Skriv svar