Comprensione della sintassi del makefile: problemi comuni e soluzioni (inclusi 'Operatore mancante' e 'Punto di ingresso non trovato')

Comprensione Della Sintassi Del Makefile Problemi Comuni E Soluzioni Inclusi Operatore Mancante E Punto Di Ingresso Non Trovato



Proprio come un file di codice contiene una o più righe di codice come contenuto per renderlo utile, il makefile di base viene costruito utilizzando variabili, regole e obiettivi. Oltre a questo, ci sono anche altri fattori necessari per creare un makefile completo senza problemi. In questa guida discuteremo la sintassi di base del makefile e i problemi comuni durante la scrittura di un makefile e forniremo soluzioni per risolverli.

Comprendere la sintassi di base del Makefile

Per iniziare con la creazione di un makefile, spieghiamo le proprietà di base di un makefile tramite l'esempio di codice makefile. È necessario includere le seguenti proprietà di sintassi nel contenuto del makefile per ottenere un file eseguibile:







Variabile s: dati di base che memorizzano oggetti necessari per essere utilizzati nel makefile. Queste variabili vengono utilizzate per specificare un compilatore, flag, file di origine, file oggetto e file di destinazione. All'interno del seguente makefile di esempio, sono presenti un totale di cinque variabili che sono CXX (per impostare un compilatore C++), CXXFLAGSc (flag del compilatore), TARGET (per impostare un nome di file eseguibile di destinazione), SRCS (per impostare un file di codice sorgente) , OBJS (per contenere i file oggetto generati tramite il file del codice sorgente).



Obiettivi: Un output previsto da creare dall'origine. Può essere un file di destinazione o qualsiasi nome simbolico: 'all' è il target predefinito che deve essere creato tramite la variabile 'TARGET', '$TARGET' dipende dalle variabili 'OBJS' e il target 'clean' rimuove il target e file oggetto dalla directory di lavoro.



Regole e comandi di creazione: Insieme di istruzioni di base da eseguire per creare una destinazione dal file sorgente o dalle dipendenze. Ad esempio, la regola '%.o: %.cpp' indica che il file con estensione 'cpp' viene utilizzato per creare un file oggetto con estensione 'o' mentre entrambi i file contengono lo stesso nome. D'altra parte, il comando build $(CXX) $(CXXFLAGS) -o $(TARGET) $(OBJS) viene utilizzato per collegare insieme un file oggetto e un nuovo file di destinazione. Allo stesso modo, il comando build $(CXX) $(CXXFLAGS) -c $< -o $@ compila il file sorgente in un file oggetto.





Dipendenze: Le dipendenze sono sempre presenti quando vuoi creare un makefile. Ad esempio, il target 'tutti' dipende dalla variabile 'TARGET' mentre il 'TARGET' dipende dalla variabile 'OBJS'. Allo stesso tempo, la variabile “OBJS” dipende dal file sorgente tramite la variabile “SRCS”.

Commenti: Le istruzioni comprensibili dall'uomo vengono solitamente utilizzate per spiegare lo scopo della riga di codice nel caso in cui si utilizzi un file dopo molto tempo. Nel seguente makefile, utilizziamo i commenti che iniziano con il segno '#' per spiegare ogni riga.



CXX = g++
CXXFLAG = -std =c++ undici -Parete
BERSAGLIO = Nuovo
SRCS = main.cpp
OGG = $ ( SRCS:.cpp=.o )
tutto: $ ( BERSAGLIO )
$ ( BERSAGLIO ) : $ ( OBJS )
$ ( CXX ) $ ( CXXFLAG ) -O $ ( BERSAGLIO ) $ ( OBJS )
% .O: % .cpp
$ ( CXX ) $ ( CXXFLAG ) -C $ < -O $ @
pulito:
rm -F $ ( BERSAGLIO ) $ ( OBJS )

Problemi comuni e soluzioni

Durante la scrittura di qualsiasi makefile, è necessario considerare ogni minimo dettaglio per ottenere alla fine l'output desiderato. Alcuni problemi comuni vengono riscontrati frequentemente dagli utenti durante la creazione di un makefile. All'interno di questa sezione discuteremo di tali problemi e suggeriremo le possibili soluzioni come segue:

1: Non utilizzare le variabili

L'uso delle variabili in un makefile è indispensabile poiché è necessario impostare compilatori, destinazione, file sorgente, ecc. Il problema più comune che si può riscontrare è il mancato utilizzo di alcuna variabile in un makefile. Pertanto, assicurati di utilizzare le variabili essenziali come CXX, CXXFLAGSc(flag del compilatore), TARGET, SRCS e OBJS nel makefile di esempio precedente.

2: Problema relativo al separatore mancante

Durante la scrittura di un makefile, è necessario considerare molto attentamente le regole di indentazione perché l'utilizzo degli spazi anziché dei tab ti porterà al problema del “separatore mancante” durante l'esecuzione dell'istruzione “make”. Ad esempio, aggiungiamo lo spazio all'inizio di una regola alla riga 13 e rimuoviamo la tabulazione.

$ ( BERSAGLIO ) : $ ( OBJS )
$ ( CXX ) $ ( CXXFLAG ) -O $ ( BERSAGLIO ) $ ( OBJS )

Dopo l'esecuzione della query 'make', riceviamo un errore 'missing separator' alla riga 13 e il file smette di funzionare. Per evitare questo problema, assicurati di utilizzare 'tab' anziché spazi.

Fare

Per evitare questo problema, assicurati di utilizzare 'tab' anziché gli spazi come illustrato nell'immagine seguente:

$ ( BERSAGLIO ) : $ ( OBJS )
$ ( CXX ) $ ( CXXFLAG ) -O $ ( BERSAGLIO ) $ ( OBJS )

3: Problema 'Punto di ingresso non trovato'.

Questo errore si verifica principalmente a causa del file sorgente e non a causa del makefile, come quando non si utilizza la funzione 'main()' nel file del codice sorgente. Ad esempio, sostituiamo la definizione della funzione main() con una semplice dichiarazione di funzione definita dall'utente.

#include
spettacolo int ( ) {
carattere v;
std::cout << 'Inserisci un valore: ' ;
std::cin >> In;
std::cout << In << std::endl;
ritorno 0 ;
}

Eseguendo l'istruzione “make” sul prompt dei comandi di Windows, incontriamo il “riferimento non definito a 'WinMain'”. Questo perché il compilatore non trova alcun punto di ingresso per avviare l'esecuzione del file C++. Per risolvere questo problema, sostituisci 'mostra' con 'principale'.

4: Utilizzo di estensioni errate

A volte, un utente può utilizzare involontariamente le estensioni sbagliate per un file sorgente da utilizzare nel makefile. L'uso dell'estensione sbagliata porterà a errori di runtime, ovvero nessuna regola per creare un target. Creiamo un makefile per creare il file eseguibile e oggetto per il file C++. Nella settima riga forniamo il file sorgente con l'estensione 'c'.

CXX := g++
CXXFLAG := -std =c++ undici -Parete
BERSAGLIO = nuovo
SRCS = principale.c
OGG = $ ( SRCS:.cpp=.o )
Tutti: $ ( BERSAGLIO )
$ ( BERSAGLIO ) : $ ( OBJS )

L'esecuzione dell'istruzione 'make' ci porta all'errore 'Nessuna regola per rendere target 'main.c''. Per evitare questo problema, assicurati di utilizzare l'estensione del file sorgente corretta.

Fare

5: Dipendenze mancanti

Durante la scrittura di un makefile, dovresti includere tutte le dipendenze di un file sorgente per ottenere l'output desiderato. Ad esempio, il nostro file di codice C++ utilizza il file 'myheader.h' come dipendenza. Pertanto, lo menzioniamo nel file di codice C++ come segue:

#include
#include 'miaintestazione.h'
spettacolo int ( ) {
carattere v;
std::cout << 'Inserisci un valore: ' ;
std::cin >> In;
std::cout << In << std::endl;
ritorno 0 ;
}

All'interno del makefile, ignoriamo intenzionalmente l'uso del file 'myheader.h' all'interno della regola di compilazione scritta alla riga 9.

% .O: % .cpp
$ ( CXX ) $ ( CXXFLAG ) -C $ < -O $ @

Ora, mentre utilizziamo l’istruzione “make”, riscontriamo l’errore “Niente da fare per ‘all’”.

Fare

% .O: % .cpp miaintestazione.h
$ ( CXX ) $ ( CXXFLAG ) -C $ < -O $ @

Per evitare questo problema ed eseguire correttamente il codice sorgente, menziona il nome del file 'myheader.h' nella nona riga del makefile come illustrato di seguito:

Conclusione

All'interno di questa guida, abbiamo spiegato in modo approfondito la sintassi di makefile utilizzando i suoi contenuti necessari come variabili, comandi di compilazione, regole, ecc. L'esempio di codice è incluso per elaborare la sintassi in modo più chiaro. Alla fine, abbiamo discusso alcuni problemi ricorrenti e le relative soluzioni che un utente può incontrare durante la creazione di un makefile.