如何在Makefile中使用LDFLAGS

How to use LDFLAGS in makefile

我是Linux操作系统的新手。我正在尝试使用Makefile编译.c文件。数学库必须链接。我的makefile看起来像这样:

1
2
3
4
5
6
7
8
CC=gcc
CFLAGS=-Wall -lm

all:client

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

运行make时,出现以下错误:

1
"undefined reference to rint"

因此它无法链接数学库。

但是当我使用

进行显式编译时

1
gcc client.c -lm -o client

成功编译。

所以我应该如何更改我的makefile使其起作用。我已经尝试添加LDFLAGS=-lm。但是我得到了同样的错误。

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

1
gcc -Wall -lm client.c -o client

(请注意,当我以-lm结尾时显式运行gcc时,它将起作用)。


您的链接器(ld)显然不喜欢make排列GCC参数的顺序,因此您必须稍微更改Makefile:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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)

在定义客户目标的行中,根据需要更改$(LDFLAGS)的顺序。


在更复杂的构建方案中,通常将编译分为多个阶段,首先进行编译和汇编(输出到目标文件),然后再将目标文件链接到最终的可执行文件或库中,这避免了必须重新编译所有文件。对象文件的源文件未更改时。这就是为什么将链接标志-lm放在CFLAGS中时不起作用的原因(在编译阶段使用CFLAGS)。

要链接的库的惯例是将它们放置在LOADLIBESLDLIBS中(GNU make包括两者,但里程可能会有所不同):

1
LDLIBS=-lm

这应该使您可以继续使用内置规则,而不必编写自己的链接规则。对于其他品牌,应该有一个标记来输出内置规则(对于GNU品牌,这是-p)。如果您的make版本没有链接的内置规则(或者它没有-l指令的占位符),则需要编写自己的:

1
2
3
4
5
client.o: client.c
    $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c -o $@ $<

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

好像链接标志的顺序在旧版gcc中不是问题。例如gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-16)随Centos-6.7一起提供,在输入文件之前对链接器选项感到满意;但是带有ubuntu 16.04 gcc (Ubuntu 5.3.1-14ubuntu2.1) 5.3.1 20160413的gcc不允许。

不仅是gcc版本,发行版也给我带来了帮助