Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
Username: Password: oppure
C/C++ - Problema linking
Forum - C/C++ - Problema linking

Pagine: [ 1 2 ] Precedente | Prossimo
Avatar
Bonnox (Member)
Pro


Messaggi: 85
Iscritto: 23/08/2014

Segnala al moderatore
Postato alle 10:00
Mercoledì, 03/08/2016
Buongiorno ancora, mi spiace postare un sacco di domande ma non mi hanno mai preparato a dovere su questi argomenti...

volevo testare un semplice makefile, compilando un programma di 2 file (per stare sul semplice).

I file sono main.c , libreria.c, libreria.h e makefile. Sono tutti nella stessa cartella, diversa da quella del compilatore.

Codice sorgente - presumibilmente C++

  1. #include <stdio.h>
  2. #include "libreria.h"
  3.  
  4. int main()
  5. {
  6.         mio();
  7.         return 0;
  8. }



Codice sorgente - presumibilmente C/C++

  1. #include "libreria.h"
  2. #include <stdio.h>
  3.  
  4. void mio()
  5. {
  6.     printf("ciao make!");
  7. }



Codice sorgente - presumibilmente C++

  1. #ifndef LIBRERIA_H_INCLUDED
  2. #define LIBRERIA_H_INCLUDED
  3.  
  4. void mio ();
  5.  
  6. #endif // LIBRERIA_H_INCLUDED



ho usato codeblocks per scriverli, e di suo gestisce automaticamente i programmi con più file. ho guardato il build log e i comandi erano come me li aspettavo dopo aver letto il libro di King.
Ho provato dunque a fare da me:

Codice sorgente - presumibilmente Plain Text

  1. hellomake: hellomake.o libreria.o
  2.         D:\Sviluppo\mingw\bin\gcc -o "D:\programmazione\cose C\testmake\hellomake.o" "D:\programmazione\cose C\testmake\libreria.o"
  3. hellomake.o: hellomake.c libreria.h
  4.         D:\Sviluppo\mingw\bin\gcc -c "D:\programmazione\cose C\testmake\hellomake.c" -o "D:\programmazione\cose C\testmake\hellomake.o"
  5. libreria.o: libreria.c libreria.h
  6.         D:\Sviluppo\mingw\bin\gcc -c "D:\programmazione\cose C\testmake\libreria.c" -o "D:\programmazione\cose C\testmake\libreria.o"



se vado nella cartella dei sorgenti e invoco mingw32-make (è nel path) mi da questo (non uso il tag code perchè ho visto che lo colora in un modo che non si capisce niente):

D:\Sviluppo\mingw\bin\gcc -c "D:\programmazione\cose C\testmake\hellomake.c" -o "D:\programmazione\cose C\testmake\hellomake.o"
D:\Sviluppo\mingw\bin\gcc -o "D:\programmazione\cose C\testmake\hellomake.o" "D:\programmazione\cose C\testmake\libreria.o"
d:/sviluppo/mingw/bin/../lib/gcc/mingw32/4.9.3/../../../libmingw32.a(main.o):(.text.startup+0xa0): undefined reference to `WinMain@16'
collect2.exe: error: ld returned 1 exit status
makefile:2: recipe for target 'hellomake' failed
mingw32-make: *** [hellomake] Error 1

parla di un winmain, ma io sto facendo una console application :S

poi provo a fare prima i singoli o e a metterli insieme... anche lì nessun risultato.

poi mi accorgo che il nome del primo target era diverso dai nomi del file main, così rinomino tutti i "main" nel file con "hellomake", per giungere al code che ho scritto, ma che comunque non funziona.

non riesco a capire dove sta l'errore... :d

EDIT: ho provato a mettere i percorsi assoluti anche sulle dipendenze, ma mi becco un bell'errore "multiple target patterns".

Ultima modifica effettuata da Bonnox il 03/08/2016 alle 10:32
PM Quote
Avatar
lumo (Member)
Expert


Messaggi: 449
Iscritto: 18/04/2010

Segnala al moderatore
Postato alle 10:47
Mercoledì, 03/08/2016
Per qualche motivo sembra che il tuo progetto sia impostato come win32 application, è l'unico motivo per cui il linker può richiedere WinMain.
Controlla bene, magari crea di nuovo il progetto.

PM Quote
Avatar
Bonnox (Member)
Pro


Messaggi: 85
Iscritto: 23/08/2014

Segnala al moderatore
Postato alle 21:56
Mercoledì, 03/08/2016
ti ringrazio per avermi dedicato del tempo!


nella mia mente malata avevo pensato che "se lo rifaccio con linux funzionerà sicuramente, il gcc è già incluso" e altre robe che farebbero rivoltare stallman.

e invece continuavo a ottenere gli stessi, e nuovi, errori, ma stavolta in italiano (che bello!!)

poi ho avuto un lampo di genio: sbagliavo il primo comando. dopo -o ci va il nome dell'eseguibile, che io dimenticavo, mentre pensavo fosse una cosa come "guarda che devi trasformare questi -oggetti in un eseguibile" lol :rofl:
e infatti ora va.
non so se sentirmi entusiasta o idiota.

scusate per il post inutile :_doubt:

Ultima modifica effettuata da Bonnox il 03/08/2016 alle 21:58
PM Quote
Avatar
Roby94 (Member)
Guru


Messaggi: 1170
Iscritto: 28/12/2009

Segnala al moderatore
Postato alle 11:15
Giovedì, 04/08/2016
Beh allora diamo un senso al topic, potresti migliorare il valore del tuo makefile. Primo tra tutti avere percorsi assoluti in un makefile non ha molto senso, un vantaggio non indifferente del make è di poter ricompilare su sistemi diversi con modifiche minime al make, senza dover essere legato ad un progetto di qualche IDE.

Una regola clean raramente manca.
Codice sorgente - presumibilmente Plain Text

  1. clean:
  2.         rm -f "Release/*.o" || true


Il classico "pulisci la soluzione".

è comodo dichiarare una regola fittizia che dipende dai file finali che vorrai vedere come output
Codice sorgente - presumibilmente Plain Text

  1. release: Release\hellomake.exe


Che non presenta altro che dipendenze, nessuna regola di compilazione.

Un altra precisazione è di dichiarare come phony tutte le regole che non si riferiscono direttamente a file.
Codice sorgente - presumibilmente Plain Text

  1. .PHONY: release clean


Questo evita problemi in caso siano presenti erroneamente file con questi nomi nella directory di riferimento.

Ora indipendentemente dal progetto per compilare è sufficiente un "make release", e per pulire "make clean".

PM Quote
Avatar
Bonnox (Member)
Pro


Messaggi: 85
Iscritto: 23/08/2014

Segnala al moderatore
Postato alle 17:55
Giovedì, 04/08/2016
Testo quotato

Postato originariamente da Roby94:

Beh allora diamo un senso al topic, potresti migliorare il valore del tuo makefile. Primo tra tutti avere percorsi assoluti in un makefile non ha molto senso, un vantaggio non indifferente del make è di poter ricompilare su sistemi diversi con modifiche minime al make, senza dover essere legato ad un progetto di qualche IDE.




Sì esatto, infatti ho visto su internet alcuni semplici makefile e ho imparato le variabili CC e CFLAGS!
Praticamente qualuque parola in maiuscolo seguita da = diventa una variabile stringa che puoi espandere con $(), ho capito bene?

Testo quotato



Una regola clean raramente manca.
Codice sorgente - presumibilmente Plain Text

  1. clean:
  2.         rm -f "Release/*.o" || true


Il classico "pulisci la soluzione".




Ok il clean l'ho già visto, tuttavia non mi sono chiari dei punti:
cosa significa " || true " ? or true? che effetto ha sul terminale?
e cosa si intende con soluzione?
(scusa la mia nabbezza)

Testo quotato




Un altra precisazione è di dichiarare come phony tutte le regole che non si riferiscono direttamente a file.
Codice sorgente - presumibilmente Plain Text

  1. .PHONY: release clean


Questo evita problemi in caso siano presenti erroneamente file con questi nomi nella directory di riferimento.


Ora indipendentemente dal progetto per compilare è sufficiente un "make release", e per pulire "make clean".



quindi qualunque regola che non crea file oggetto deve essere dichiarata dopo questo phony? o solo alcune regole? e poi dicendo make seguito dal nome posso eseguirla.

che tipo di problemi possono sorgere?

tuttavia non capisco a cosa serva la regola "release". se il faccio il make è perchè voglio compilare il programma, non mi importa se per la release o per il debug. anzi, quello lo regolerò con un #define, no?

grazie anche a te per l'intervento, credo che leggerò il manuale del make (o anche del gcc, nella prossima vita aha) :k:

PM Quote
Avatar
Roby94 (Member)
Guru


Messaggi: 1170
Iscritto: 28/12/2009

Segnala al moderatore
Postato alle 20:51
Venerdì, 05/08/2016
Testo quotato

Postato originariamente da Bonnox:
Sì esatto, infatti ho visto su internet alcuni semplici makefile e ho imparato le variabili CC e CFLAGS!
Praticamente qualuque parola in maiuscolo seguita da = diventa una variabile stringa che puoi espandere con $(), ho capito bene?


Non per forza maiuscolo.
Testo quotato


Ok il clean l'ho già visto, tuttavia non mi sono chiari dei punti:
cosa significa " || true " ? or true? che effetto ha sul terminale?
e cosa si intende con soluzione?
(scusa la mia nabbezza)


Alcuni IDE a un return false associano un errore, in caso non vi siano file da cancellare rm restituisce false, con || true evito possibili errori di questo genere.
Testo quotato


quindi qualunque regola che non crea file oggetto deve essere dichiarata dopo questo phony? o solo alcune regole? e poi dicendo make seguito dal nome posso eseguirla.


Si, ogni regola che non genera direttamente un file andrebbe dichiarata come PHONY per evitare ambiguità, quello che è dichiarato come PHONY è SEMPRE una regola che non si riferisce ad un file, quindi il make non andrà a ricercarlo come file nella directory.
Testo quotato


tuttavia non capisco a cosa serva la regola "release". se il faccio il make è perchè voglio compilare il programma, non mi importa se per la release o per il debug. anzi, quello lo regolerò con un #define, no?


Non vi è uno standard per make, se no avrebbe poco senso permettere cosi tanta libertà, io lo uso per la getsione sia di debug che release, e sono abbastanza contrario all'uso della define DEBUG, uso make in ambito AVR dove il debug RT è eseguibile solo con codici non ottimizzati, quindi mi fa comodo poter compilare librerie anche in modalità debug senza modificare il codice C.
Ti mostro un esempio
Codice sorgente - presumibilmente C/C++

  1. ATMEGA_INCLUDE="C:\Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.0.91\include"
  2. MCU_INCLUDE="C:\Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.0.91\gcc\dev\atmega328p"
  3. MCU="atmega328p"
  4.  
  5. STANDARD_OPTIONS=-x c -std=gnu99 -I $(ATMEGA_INCLUDE) -mmcu=$(MCU) -B $(MCU_INCLUDE)
  6. ADDITIONAL_OPTIONS=-ffunction-sections -fdata-sections -fpack-struct -fshort-enums
  7. DEBUG=-DDEBUG -O1
  8. RELEASE=-DNDEBUG -Os
  9. OPTIONS=$(STANDARD_OPTIONS) $(ADDITIONAL_OPTIONS)
  10.  
  11. .PHONY: all debug release clean
  12.  
  13. all: debug release
  14.  
  15. debug: Debug\libI2C.a
  16.  
  17. release: Release\libI2C.a
  18.  
  19.  
  20. Debug\I2C.o: I2C.h I2C.c
  21.         test -d "Debug" || mkdir "Debug"
  22.         avr-gcc.exe -c $(OPTIONS) $(DEBUG) -o "Debug\I2C.o" "I2C.c"
  23.  
  24. Debug\libI2C.a: Debug\I2C.o
  25.         avr-ar.exe -r -o "Debug\libI2C.a" "Debug\I2C.o"
  26.  
  27. Release\I2C.o: I2C.h I2C.c
  28.         test -d "Release" || mkdir "Release"
  29.         avr-gcc.exe -c $(OPTIONS) $(RELEASE) -o "Release\I2C.o" "I2C.c"
  30.  
  31. Release\libI2C.a: Release\I2C.o
  32.         avr-ar.exe -r -o "Release\libI2C.a" "Release\I2C.o"
  33.  
  34.  
  35. clean:
  36.         rm -f "Debug/*.o" || true
  37.         rm -f "Release/*.o" || true


Testo quotato

credo che leggerò il manuale del make (o anche del gcc, nella prossima vita aha) :k:


Il make file hanno molte potenzialità ma è la classica situazione dove il 90% delle casistiche le risolvi con il 10% del linguaggio.

PM Quote
Avatar
Bonnox (Member)
Pro


Messaggi: 85
Iscritto: 23/08/2014

Segnala al moderatore
Postato alle 23:30
Sabato, 06/08/2016
:k:

perdonami una sola domanda...

Che significa AVR? :_doubt:

comunque io di solito quando faccio il debug mi definisco una variabile booleana e se è vera stampo a console (anche se magari il programma è grafico) le informazioni di debug... tu invece come fai? ma lavori su sistemi embedded? blocchi run time l'esecuzione con dispositivi di dump?

e per finire, cosa succederebbe se non dichiarassi phony le regole?

grazie e buonasera

PM Quote
Avatar
nessuno (Normal User)
Guru^2


Messaggi: 6367
Iscritto: 03/01/2010

Segnala al moderatore
Postato alle 0:42
Domenica, 07/08/2016
Testo quotato

Postato originariamente da Bonnox:

Che significa AVR? :_doubt:



Ricorda che nessuno è obbligato a risponderti e che nessuno è perfetto ...
---
Il grande studioso italiano Bruno de Finetti (uno dei padri fondatori del moderno Calcolo delle probabilità) chiamava il gioco del Lotto Tassa sulla stupidità.
PM Quote
Avatar
Roby94 (Member)
Guru


Messaggi: 1170
Iscritto: 28/12/2009

Segnala al moderatore
Postato alle 0:55
Domenica, 07/08/2016
Testo quotato


Che significa AVR? :_doubt:


http://www.atmel.com/products/microcontrollers/avr/
Testo quotato


comunque io di solito quando faccio il debug mi definisco una variabile booleana e se è vera stampo a console (anche se magari il programma è grafico) le informazioni di debug...


Evito il metodo della definizione di DEBUG, in quanto alla pubblicazione tendo ad eliminare ogni singolo elemento di debug per rendere il codice più pulito.
Testo quotato


tu invece come fai? ma lavori su sistemi embedded? blocchi run time l'esecuzione con dispositivi di dump?


Si, principalmente uso C su microcontrollori, dove il metodo di debug più semplice ed immediato è il debug RT con interrupt.
Testo quotato


e per finire, cosa succederebbe se non dichiarassi phony le regole?


Mettiamo che voglio dichiarare la regola "all", se non viene dichiarato come phony e per caso è presente un file che si chiama "all" nella cartella, piu recente dei file di dipendenza, non verranno eseguite le regole relative a questi file. Se dichiaro una regola non vincolata ad un file la mia intenzione è che venga eseguita sempre quando la invoco, e non debba dipendere dalle informazioni temporali del file.

Codice sorgente - presumibilmente Plain Text

  1. all: file.txt
  2.    test -d "abc" || mkdir "abc"


erroneamente non dichiaro all come phony, ed è presente un file all nella directory di riferimento con data di ultima modifica piu recente di file.txt, se eseguo all questa regola verrà ignorata.
è un caso raro, ma phony è pensato per evitare anche questo.

PM Quote
Pagine: [ 1 2 ] Precedente | Prossimo