如何在 makefile 中使用 LDFLAGS

我是 Linux 操作系统的新手。我正在尝试使用 makefile 编译一个 .c文件。数学图书馆必须连接起来。我的 makefile 是这样的:

CC=gcc
CFLAGS=-Wall -lm


all:client


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

当我运行 make时,会得到以下错误:

"undefined reference to rint"

所以它不能链接数学库。

但是当我使用

gcc client.c -lm -o client

它成功地编译了。

因此,我应该如何更改 makefile 以使其工作。我已经试过加入 LDFLAGS=-lm。但我得到了同样的错误。

我还应该补充一点,当我运行 make时,它会展开为

gcc -Wall -lm client.c -o client

(请注意,当我在结尾使用 -lm显式地运行 gcc时,它是有效的)。

295872 次浏览

Your linker (ld) obviously doesn't like the order in which make arranges the GCC arguments so you'll have to change your Makefile a bit:

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)

In the line defining the client target change the order of $(LDFLAGS) as needed.

In more complicated build scenarios, it is common to break compilation into stages, with compilation and assembly happening first (output to object files), and linking object files into a final executable or library afterward--this prevents having to recompile all object files when their source files haven't changed. That's why including the linking flag -lm isn't working when you put it in CFLAGS (CFLAGS is used in the compilation stage).

The convention for libraries to be linked is to place them in either LOADLIBES or LDLIBS (GNU make includes both, but your mileage may vary):

LDLIBS=-lm

This should allow you to continue using the built-in rules rather than having to write your own linking rule. For other makes, there should be a flag to output built-in rules (for GNU make, this is -p). If your version of make does not have a built-in rule for linking (or if it does not have a placeholder for -l directives), you'll need to write your own:

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


client: client.o
$(CC) $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@

Seems like the order of the linking flags was not an issue in older versions of gcc. Eg gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-16) comes with Centos-6.7 happy with linker option before inputfile; but gcc with ubuntu 16.04 gcc (Ubuntu 5.3.1-14ubuntu2.1) 5.3.1 20160413 does not allow.

Its not the gcc version alone, I has got something to with the distros

The currently accepted answer is not correct according to the current (2022) make documentation here:

https://www.gnu.org/software/make/manual/html_node/Implicit-Variables.html

LDFLAGS: Extra flags to give to compilers when they are supposed to invoke the linker, ‘ld’, such as -L. Libraries (-lfoo) should be added to the LDLIBS variable instead.

LDLIBS: Library flags or names given to compilers when they are supposed to invoke the linker, ‘ld’. LOADLIBES is a deprecated (but still supported) alternative to LDLIBS. Non-library linker flags, such as -L, should go in the LDFLAGS variable.

Also the LOADLIBES mentioned in some responses above, has long been deprecated and should not be used anymore.

So, from the previous definitions, it seems the above example should be more properly written like this:

CC=gcc
CFLAGS=-Wall
LDLIBS=-lm
LDFLAGS=-L/usr/local/include


.PHONY: all
all: client


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


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