2012-11-06 16 views
49

Jestem nowy w systemie operacyjnym Linux. Próbuję skompilować plik .c przy użyciu pliku makefile. Biblioteka matematyczna musi być połączona. Moje makefile wygląda następująco:Jak używać LDFLAGS w makefile

CC=gcc 
CFLAGS=-Wall -lm 

all:client 

.PHONY: clean 
clean: 
    rm *~ *.o client 

Kiedy biegnę make, pojawia się następujący błąd:

"undefined reference to rint" 

więc nie jest w stanie połączyć bibliotekę matematyczną.

Ale kiedy mogę skompilować jawnie przy użyciu

gcc client.c -lm -o client 

powodzeniem kompiluje.

Jak zatem zmienić plik Makefile tak, aby działał? Próbowałem już dodać: LDFLAGS=-lm. Ale pojawia się ten sam błąd.

Należy również dodać, że gdy uruchamiam make, rozszerza się

gcc -Wall -lm client.c -o client 

(Zauważ, że gdy uruchamiam gcc wyraźnie ze -lm na końcu, to działa).

Odpowiedz

52

Twój linker (LD) oczywiście nie lubi kolejność wprowadzania porządkuje argumenty GCC więc będziesz musiał zmienić nieco Makefile:

CC=gcc 
CFLAGS=-Wall 
LDFLAGS=-lm 

OBJECTS=client.o 

client: $(OBJECTS) 
    $(CC) $(CFLAGS) $(OBJECTS) -o client $(LDFLAGS) 

all:client 

.PHONY: clean 
clean: 
    rm -f *~ *.o client 

W linii wyznaczającej klienta cel zmień kolejność $ (LDFLAGS) w razie potrzeby.

+40

LDLIBS jest dla bibliotek, LDFLAGS należy stosować Flagi/ścieżek wyszukiwania (-L) – falstaff

+3

[nie trzeba jawnie zdefiniować 'CC'.] (Http://www.gnu.org/software/make/manual/html_node/Implicit-Variables.html) – 0xcaff

+3

Myślałem również, że -lm powinien być w LDFLAGS, ale jak się okazuje (patrz odpowiedź laindira i https://www.gnu.org/software/make/manual/html_node/Catalogue-of-Rules.html), zamiast tego powinien znajdować się w LOADLIBES, a następnie wszystko działa po wyjęciu z pudełka (tj. bez definiowania jawnych reguł) ! –

41

W bardziej skomplikowanych scenariuszach kompilacji często dochodzi do podziału kompilacji na etapy - najpierw kompilacja i montaż odbywa się (wyjście do plików obiektów), a następnie łączenie plików obiektów do końcowego pliku wykonywalnego lub biblioteki - zapobiega to ponownemu kompilowaniu wszystkie pliki obiektów, gdy ich pliki źródłowe nie uległy zmianie. Dlatego włączenie flagi łączącej -lm nie działa, gdy umieścisz ją w CFLAGS (CFLAGS jest używana w etapie kompilacji).

Konwencja bibliotek być połączone jest, aby umieścić je w jednej LOADLIBES lub LDLIBS (make GNU obejmuje zarówno, ale może się wahać):

LDLIBS=-lm 

To powinno pozwolić na dalsze korzystanie z wbudowanego w regułach, zamiast pisać własną regułę łączenia. Dla innych marek powinna istnieć flaga do wyprowadzania wbudowanych reguł (dla GNU make, to jest -p). Jeśli wersja marki nie posiada wbudowaną regułę powiązanie (lub jeśli nie masz zastępczy -l dyrektyw), musisz napisać własny:

client.o: client.c 
    $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c -o [email protected] $< 

client: client.o 
    $(CC) $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o [email protected] 
1

Wygląda rzędu flagi łączące nie były problemem w starszych wersjach gcc. Np. gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-16) pochodzi z programem Centos-6.7 zadowolonym z opcji linker przed plikiem wejściowym; ale gcc z Ubuntu 16.04 gcc (Ubuntu 5.3.1-14ubuntu2.1) 5.3.1 20160413 nie pozwala.

nie jego samego gcc wersja, że ​​ma coś wspólnego z dystrybucjami