web-dev-qa-db-fra.com

Comment utiliser LDFLAGS dans un makefile

Je suis nouveau sur Linux OS. J'essaie de compiler un fichier .c à l'aide d'un fichier makefile. La bibliothèque de mathématiques doit être liée. Mon fichier make ressemble à ceci:

CC=gcc
CFLAGS=-Wall -lm

all:client

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

Lorsque je lance make, j'obtiens le message d'erreur suivant:

"undefined reference to rint"

Donc, il n'est pas capable de lier la bibliothèque de mathématiques.

Mais quand je compile explicitement en utilisant

gcc client.c -lm -o client

il compile avec succès.

Alors, comment devrais-je changer mon makefile pour qu'il fonctionne? J'ai déjà essayé d'ajouter LDFLAGS=-lm. Mais je reçois la même erreur.

Je devrais aussi ajouter que lorsque je lance make, il se développe en

gcc -Wall -lm client.c -o client

(remarquez que lorsque je lance gcc explicitement avec -lm à la fin, cela fonctionne).

63
user1802785

Votre éditeur de liens (ld) n'aime évidemment pas l'ordre dans lequel make arrange les arguments de GCC, vous devrez donc changer un peu votre Makefile:

CC=gcc
CFLAGS=-Wall
LDFLAGS=-lm

.PHONY: all
all: client

.PHONY: clean
clean:
    $(RM) *~ *.o client

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

Dans la ligne définissant la cible client, modifiez l'ordre de $ (LDFLAGS) selon vos besoins.

63
Makkes

Dans des scénarios de compilation plus complexes, il est courant de scinder la compilation en étapes, la compilation et l’assemblage se déroulant d’abord (sortie dans des fichiers objet), puis de lier les fichiers objet à un exécutable final ou à une bibliothèque, ce qui évite de recompiler tous les fichiers objet leurs fichiers sources n'ont pas changé. C'est pourquoi l'inclusion de l'indicateur de liaison -lm ne fonctionne pas lorsque vous le mettez dans CFLAGS (CFLAGS est utilisé dans la phase de compilation).

La convention pour les bibliothèques à lier est de les placer dans LOADLIBES ou LDLIBS (GNU make inclut les deux, mais votre kilométrage peut varier):

LDLIBS=-lm

Cela devrait vous permettre de continuer à utiliser les règles intégrées plutôt que de devoir écrire votre propre règle de liaison. Pour les autres marques, il devrait y avoir un drapeau pour sortir les règles intégrées (pour GNU make, il s'agit de -p). Si votre version de make n'a pas de règle intégrée pour les liens (ou si elle n'a pas d'espace réservé pour les directives -l), vous devrez écrire votre propre:

client.o: client.c
    $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_Arch) -c -o $@ $<

client: client.o
    $(CC) $(LDFLAGS) $(TARGET_Arch) $^ $(LOADLIBES) $(LDLIBS) -o $@
50
laindir

On dirait que l'ordre des drapeaux de liaison n'était pas un problème dans les anciennes versions de gcc. Par exemple, gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-16) vient avec Centos-6.7 satisfait de l'option de l'éditeur de liens avant inputfile; mais gcc avec Ubuntu 16.04 gcc (Ubuntu 5.3.1-14ubuntu2.1) 5.3.1 20160413 ne le permet pas.

Ce n'est pas la version gcc seule, j'ai quelque chose à faire avec les distributions

1
J.Greg