Jag har en fråga om hur länkning funkar i C och vore tacksam om nån har lust att upplysa mig.
Jag använder Microchips kompilator C18 och en 18f4550. Till PICen har jag kopplat en LCD som jag försöker köra mha av rutinerna i p18f4550.lib (Microchips lib). För att använda rutinerna länkar jag med lib-filen och inluderar .h-filen. Det funkar ju utan problem.
Men jag får inte LCDn att fungerar riktigt och har därför börjat undersöka koden. För varje ändring jag gör och testar måste jag ju först kompilera om lib:et och sedan programmet som använder lib-filen.
För att förenkla testningen lite drog jag in alla källkodsfilerna(.c-filer) för LCD-rutinerna i projektet och kompilerar.
Det funkar bra ocskå, men nu undrar jag hur det kan funka då samma kod, med samma funktionsnamn finns på två ställen? Funktionerna finns ju dels inkompilerade i lib-filen och sedan tidigare i de inkluderade c-filerna. Vilken kod är det egentligen som komemr att köras? Kompileras bara det som anropas med från ett lib?
Förmodligen så har du inte lyckats med att både kompilera C-koden _och_ länka in den färdigkompilerade lib-filen. Då skulle nämligen länkaren klaga på en massa dubbla deklarationer.
Normalt sett ska inte lib-filen kompileras om, den ska bara länkas in när huvudprogrammet kompilerats. Och så länge du inte någonstans i ditt projekt eller makefil refererar till lib-filens källkod så _kan_ den ju inte (och ska inte) kompileras om heller.
Har du möjlighet att posta make-filen här på forumet?
Ulf: Zäta har nog inte gjort en "#include" på c-filerna utan bara inkluderat dem i själva projektet.
Edit: När du ska felsöka c-koden för LCD:n så föreslår jag att du inkluderar c-koden i ditt projekt och låter bli att länka in lib-filen.
Vissa IDE stödjer att man länkar ett lib och sedan pekar ut C-koden för lib:et när man t.ex. ska "single-steppa" (vad det nu heter på svenska) i koden.
För det första så uttryckte jag mig lite slarvigt, jag inkluderade såklart c-filerna i projektet.
Ulf: Jag ändrar ju i en headerfil för libet och behöver ju därför bygga om libet. Men det var för att slippa det steget som jag drog in c-filerna i projektet.
oJsan: Lib-filen kompileras ju INTE om, den länkas bara med i projektet. Och det är det som förvånar mig att länkaren inte klagar på dubbla deklarationer när jag lägger in c-filerna i projektet. Verkar ju iaf som mina misstankar inte är grundlösa i varje fall.
Jag ska se om jag kan posta make-filen när jag kommer hem.....
Inser nu också att jag måste kolla upp lkr-filen också.
Nu känner jag inte till C18 och det är mycket länge sedan jag pillade med rent grafiska byggmiljöer. Så hur kopplingen mella projekt och byggstöd funkar känner jag inte till. Fick för mig att du använde något modell vanlig make eller cmake. Då skapar man regler för beroenden. Så när du pillat i ett lib så känner make av om det är ändrat i ett lib och bygger om det när det behövs. Googla på make så hittar du massor!
Om du ändå lägger till C-filerna som ingår i LIB'en så behöver du ju inte
ha med LIB'en vid länkningen. Eller finns det annat i LIB'en förrutom
den/de C filer som du har lagt i projektet ?
Får du inte kommendonda till MPLINK i "output" fönstret ?
Sedan kan du ju med MPLINK manualen reda ut vad som åker
med eller inte vid länkningen.
> Så när du pillat i ett lib.....
Notera att detta gäller de standard LIBs som kommer med C18 (om jag
har fattat rätt). Jag är inte helt övertygad om att det är *tänkt* att
man ska pilla i dom. Snarare fixa egna rutiner om de färdiga inte passar.
Det kan ju lätt hända att man kraschar annan exempelkod som bygger
mot de inbyggda LIB'arna...
Sodjan: Jo, det är ju så att jag använder andra funktioner i lib:et.
Jag sitter inte vid datorn som jag kodar på så jag kan inte se vad som kommer i output-fönstret, men minns jag rätt så ser man nog MPLINK-kommandona där.
Men funkar det så vid länkning av ett lib att endast de funktioner som "behövs" länkas med?!?
För övringt tror jag att det är meningen att man ska pilla i källkoden till lib:et. Däremot kan det ju vara smart att göra en kopia och arbeta med....även solen har ju fläckar.
Så här står det t.ex i manualen till "C18 C compiler libraries":
"After these definitions have been made, the user must recompile the XLCD routines and then include the updated files in the project. This can be accomplished by adding the XLCD source files into the project or by recompiling the library files using the provided batch files."
Jag tycker det verkar som om länkaren "känner av" dom dubbla deklarationerna och att dom i c-filerna överrider dom i liben. Studera följande urklipp ur .map-filen.
I det här första fallet har jag bara lib:et med länkat. Här är kommandot som syns i output-fönstret i MPLAB.
(Executing: "C:\MCC18\bin\mplink.exe" /l"C:\MCC18\lib" "D:\PIC\LCDtest\18f4550.lkr" "D:\PIC\LCDtest\main.o" "D:\PIC\LCDtest\p18f4550.lib" /o"LCDtest.cof" /M"LCDtest.map" /W)
Och här är urklippet ur.map-filen.
Symbols - Sorted by Name
Name Address Location Storage File
--------- --------- --------- --------- ---------
BusyXLCD 0x0002fe program extern D:\PIC\my18f4550lib\busyxlcd.c
D1K_1 0x000348 program static C:\MCC18\SRC\TRADIT~1\DELAYS\d1ktcyx.asm
D1Kx 0x000346 program static C:\MCC18\SRC\TRADIT~1\DELAYS\d1ktcyx.asm
Delay1KTCYx 0x00033c program extern C:\MCC18\SRC\TRADIT~1\DELAYS\d1ktcyx.asm
DelayFor18TCY 0x0001a4 program extern D:\PIC\LCDtest\main.c
DelayPORXLCD 0x0001be program extern D:\PIC\LCDtest\main.c
DelayXLCD 0x0001cc program extern D:\PIC\LCDtest\main.c
OpenXLCD 0x00002c program extern D:\PIC\my18f4550lib\openxlcd.c
SetDDRamAddr 0x000210 program extern D:\PIC\my18f4550lib\setddram.c
WriteCmdXLCD 0x0002b0 program extern D:\PIC\my18f4550lib\wcmdxlcd.c
WriteDataXLCD 0x000262 program extern D:\PIC\my18f4550lib\writdata.c
_D1KTCYXCODE_0010 0x00034c program static C:\MCC18\SRC\TRADIT~1\DELAYS\d1ktcyx.asm
Sen inkluderar jag c-filerna och kör samma kompilering+länkning och får då följande.
Symbols - Sorted by Name
Name Address Location Storage File
--------- --------- --------- --------- ---------
BusyXLCD 0x00047c program extern D:\PIC\LCDtest\busyxlcd.c
D1K_1 0x0004c6 program static C:\MCC18\SRC\TRADIT~1\DELAYS\d1ktcyx.asm
D1Kx 0x0004c4 program static C:\MCC18\SRC\TRADIT~1\DELAYS\d1ktcyx.asm
Delay1KTCYx 0x0004ba program extern C:\MCC18\SRC\TRADIT~1\DELAYS\d1ktcyx.asm
DelayFor18TCY 0x0001a4 program extern D:\PIC\LCDtest\main.c
DelayPORXLCD 0x0001be program extern D:\PIC\LCDtest\main.c
DelayXLCD 0x0001cc program extern D:\PIC\LCDtest\main.c
OpenXLCD 0x00002c program extern D:\PIC\LCDtest\openxlcd.c
ReadAddrXLCD 0x000436 program extern D:\PIC\LCDtest\readaddr.c
ReadDataXLCD 0x0003f0 program extern D:\PIC\LCDtest\readdata.c
SetCGRamAddr 0x000262 program extern D:\PIC\LCDtest\setcgram.c
SetDDRamAddr 0x000210 program extern D:\PIC\LCDtest\setddram.c
WriteCmdXLCD 0x000354 program extern D:\PIC\LCDtest\wcmdxlcd.c
WriteDataXLCD 0x000306 program extern D:\PIC\LCDtest\writdata.c
_D1KTCYXCODE_0010 0x0004ca program static C:\MCC18\SRC\TRADIT~1\DELAYS\d1ktcyx.asm
Och här ser man ju att koden kommer från c-filerna. Konstigt tycker jag.......eller kan nån förklara detta?
sodjan: Jag hittar heller inget i manualerna och det var ju nåt fel i stil med det du föreslog som jag hade förväntat mig. Det stör mig när man inte vet hur saker funkar....
speakman: Jag har inte ändrat nåt utan kör med default inställningarna, men jag tycker att en sån här sak borde väl inte bara vara en varning det borde ju vara ett error vid länkningen.
Det borde vara en varning, ett sätt att "välja" rutin är ibland att
välja ordning på C och LIB filer. Första "träffen" vinner, så att säga.
> Jag hittar heller inget i manualerna och det var ju nåt fel i stil
> med det du föreslog som jag hade förväntat mig.
DS33014 sidan 224, "MPASM, MPLINK and MPLIB User Guide".
Vad jag menade med att jag inte hittade något specifikt i manualerna
var *hur* symboler löses upp mellan C och LIB filer. Det står lite om
man har "multiple definisions" i *samma* LIB fil, men inte specifikt för
det fall där en symbol finns med dels i en C fil, dels i en LIB...