Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
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++
#include <stdio.h>
#include "libreria.h"
int main()
{
mio();
return0;
}
Codice sorgente - presumibilmente C/C++
#include "libreria.h"
#include <stdio.h>
void mio()
{
printf("ciao make!");
}
Codice sorgente - presumibilmente C++
#ifndef LIBRERIA_H_INCLUDED
#define LIBRERIA_H_INCLUDED
void mio ();
#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:
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...
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
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.
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
e infatti ora va.
non so se sentirmi entusiasta o idiota.
scusate per il post inutile
Ultima modifica effettuata da Bonnox il 03/08/2016 alle 21:58
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
clean:
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
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
.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".
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
clean:
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
.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)
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
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?
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à.
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
all: file.txt
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.