2012-12-01 15 views
8

Mam pytanie dotyczące kompilacji i łączenia w Makefile (i być może w ogóle).Makefile, kompilowanie i łączenie

Mam plik server.c, który składa się z programu głównego, który ma funkcję main(). server.c zawiera rio.c. Mam moduł o nazwie rio, który składa się z rio.c i rio.h. Nie ma funkcji main().

Mam dwa pytania, jak faktycznie napisać plik Makefile i najlepszą praktykę do robienia czegoś takiego.

Q1: Jak napisać Makefile

Mam następujący Makefile:

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 

Mam łącząc problemy z tym. Mówi, że mam wiele definicji wszystkich funkcji używanych w C. Nie jestem pewien jak to jest możliwe, ponieważ serwer.c jest skompilowany z flagą -c, więc nic nie jest faktycznie połączone. Powinien wiedzieć, że niektóre funkcje istnieją, ale nie łączą się z nimi, dopóki reguła all nie skompiluje obu plików obiektów razem i nie tworzy jednego pliku obiektowego, który ma wszystko połączone.

Na czym polega problem?

Q2: Najlepsza praktyka Ponieważ mam moduł, a następnie inny plik, który zawiera program główny, należy skompilować program główny, server.c, jako osobny moduł, a następnie skompilować razem w all lub skompilować serwer .c we wszystkich i dodać tam moduł rio.o? Zauważ, że to nadal powoduje ten sam problem z linkami, który mam powyżej, więc jestem pewien, że mój problem leży gdzieś indziej.

+0

Czy używasz żadnych zewnętrznych bibliotek? – zeboidlund

+0

Tak. Ale to wywołuje błędy w moich własnych funkcjach, mówiąc, że serwer.c je zdefiniował jako pierwszy. server.c i rio.h oba importują: stdio.h, stdlib.h, unistd.h i errno.h – darksky

+3

Kiedy mówisz, "server.c zawiera rio.c", masz na myśli to w pliku 'server.c', masz linię typu '#include" rio.c "'? Jeśli tak, to jest to niewłaściwe podejście i prawdopodobne źródło błędu; powinieneś zamiast tego wpisać 'rio.h'. –

Odpowiedz

13

Należy zmienić strukturę trochę:

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 

Różnica polega na tym, że fałszywy reguła all zależy sysstatd bycie na bieżąco, a sysstatd jest aktualne, gdy jest to aktualne wrt obiektu akta.

Teraz jest po prostu dość gadatliwy, pisząc wyraźnie działania kompilacyjne. Byłoby wystarczy użyć:

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 

Można też dyskutować: czy server.c nie używać rio.h? Jeśli tak, należy wymienić zależność. Jeśli nie, dlaczego istnieje rio.h? make zakłada, że ​​server.o zależy od server.c, więc nie musisz tego określać (ale nie będzie przyjmować założeń dotyczących nagłówków). Można również użyć makra, aby zapobiec powtórzeniu się nazwa programu:

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 

Jeśli potrzebne innych bibliotek, a następnie można użyć:

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

Niezwykle korzystny widok, który poprawił się krok po kroku w ten sposób. Dziękuję Ci. –