2012-12-01 18 views
8

Ich habe eine Frage zum Kompilieren und Verknüpfen in Makefile (und vielleicht im Allgemeinen).Makefile, Kompilieren und Verknüpfen

Ich habe eine server.c Datei, die aus dem Hauptprogramm besteht, das eine main() Funktion hat. server.c enthält rio.c. Ich habe ein Modul namens rio, das aus rio.c und rio.h besteht. Es hat keine main() Funktion.

Ich habe zwei Fragen, wie man das Makefile tatsächlich schreibt, und die beste Vorgehensweise, um so etwas zu tun.

Q1: Wie das Makefile

Ich habe folgendes Makefile schreiben:

CC = gcc 
CFLAGS = -Wall -Werror -Wmissing-prototypes 
OBJS = server.o rio.o 

all: $(OBJS) 
    $(CC) $(CFLAGS) $(OBJS) -o sysstatd 

server.o: server.c 
    $(CC) $(CFLAGS) -c server.c 

rio.o: rio.c rio.h 
    $(CC) $(CFLAGS) -c rio.c 

clean: 
    rm -f *~ *.o sysstatd 

Ich habe Probleme mit diesem zu verbinden. Es sagt, dass ich mehrere Definitionen aller Funktionen habe, die in C verwendet werden. Ich bin nicht sicher, wie das möglich ist, da server.c mit dem -c Flag kompiliert wird, so dass nichts tatsächlich verknüpft ist. Es sollte wissen, dass einige Funktionen existieren, aber nicht wirklich verknüpfen, bis die all Regel beide Objektdateien zusammenstellt und eine einzelne Objektdatei erzeugt, die alles verknüpft hat.

Was ist das Problem hier?

Q2: Best practice Da ich ein Modul und dann eine andere Datei, die das Hauptprogramm enthält, sollte ich kompilieren das Hauptprogramm, server.c, als separates Modul und dann beide zusammen in all kompilieren oder Server kompilieren .c in allem und fügen Sie das rio.o Modul dort hinzu? Beachten Sie, dass dies immer noch das gleiche Linkproblem erzeugt, das ich oben habe, daher bin ich mir ziemlich sicher, dass mein Problem woanders liegt.

+0

Sind Sie externe Bibliotheken verwenden? – zeboidlund

+0

Ja. Aber es ruft Fehler in meinen eigenen Funktionen auf und sagt, dass server.c sie zuerst definiert hat. server.c und rio.h beide importieren: stdio.h, stdlib.h, unistd.h und errno.h – darksky

+3

Wenn Sie sagen, "server.c includes rio.c", meinen Sie das in der Datei 'server.c', du hast eine Zeile wie '#include" rio.c "'? Wenn dies der Fall ist, ist dies der falsche Ansatz und die wahrscheinliche Fehlerquelle. Sie sollten stattdessen 'rio.h' einschließen. –

Antwort

13

Sie sollten die Struktur überarbeiten ein wenig:

CC = gcc 
CFLAGS = -Wall -Werror -Wmissing-prototypes 
OBJS = server.o rio.o 

all: sysstatd 

sysstatd: $(OBJS) 
    $(CC) $(CFLAGS) $(OBJS) -o sysstatd 

server.o: server.c 
    $(CC) $(CFLAGS) -c server.c 

rio.o: rio.c rio.h 
    $(CC) $(CFLAGS) -c rio.c 

clean: 
    rm -f *~ *.o sysstatd 

Der Unterschied besteht darin, dass die phoney Regel all hängt von sysstatd zu Aktualität, und sysstatd ist auf dem neuesten Stand, wenn es auf dem neuesten Stand WRT ist das Objekt Dateien.

Jetzt ist es nur ziemlich ausführlich, die Compilierungsaktionen explizit zu schreiben. Es würde ausreichen, um zu verwenden:

CC = gcc 
CFLAGS = -Wall -Werror -Wmissing-prototypes 
OBJS = server.o rio.o 

all: sysstatd 

sysstatd: $(OBJS) 
    $(CC) $(CFLAGS) $(OBJS) -o sysstatd 

server.o: server.c 
rio.o: rio.c rio.h 

clean: 
    rm -f *~ *.o sysstatd 

Sie könnten Debatte auch: nicht server.c nicht rio.h benutzen? Wenn dies der Fall ist, sollte die Abhängigkeit aufgelistet werden. Wenn nicht, warum existiert rio.h? make wird davon ausgehen, dass server.o von server.c abhängt, also müssen Sie das nicht angeben (aber es werden keine Annahmen über die Header gemacht). Sie könnten auch ein Makro verwenden Wiederholung des Programmnamens zu verhindern:

CC = gcc 
CFLAGS = -Wall -Werror -Wmissing-prototypes 
OBJS = server.o rio.o 
PROG = sysstatd 

all: $(PROG) 

$(PROG): $(OBJS) 
    $(CC) $(CFLAGS) $(OBJS) -o [email protected] 

server.o: rio.h 
rio.o: rio.h 

clean: 
    rm -f *~ *.o $(PROG) core a.out 

Wenn Sie andere Bibliotheken benötigt, dann könnten Sie verwenden:

CC = gcc 
CFLAGS = -Wall -Werror -Wmissing-prototypes 
OBJS = server.o rio.o 
PROG = sysstatd 
LOCALLIBDIR = /usr/local/lib 
LDFLAGS = -L$(LOCALLIBDIR) 
LDLIBS = -lone -ltwo 

all: $(PROG) 

$(PROG): $(OBJS) 
    $(CC) $(CFLAGS) $(OBJS) -o [email protected] $(LDFLAGS) $(LDLIBS) 

server.o: rio.h 
rio.o: rio.h 

clean: 
    rm -f *~ *.o $(PROG) core a.out 
+1

Sehr vorteilhaft, da es Schritt für Schritt so verbessert wurde. Vielen Dank. –

Verwandte Themen