如何在Makefile中使用LDFLAGS


72

我是Linux操作系统的新手。我正在尝试.c使用Makefile编译文件。数学库必须链接。我的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

(请注意,当我在末尾gcc显式运行with-lm时,它可以工作)。

Answers:


68

您的链接器(ld)显然不喜欢make排列GCC参数的顺序,因此您必须稍微更改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)

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


58
LDLIBS用于库,LDFLAGS应用于标记/搜索路径(-L)
falstaff 2014年

3
我还认为-lm应该在LDFLAGS中,但事实证明(请参见laindir的答案和gnu.org/software/make/manual/html_node/Catalogue-of-Rules.html),它应该位于LOADLIBES中,然后一切都是开箱即用的(即,无需定义明确的规则)!
Emil Vatai 2015年

2
您在规则中的哪里使用源代码?它已定义,但未使用。很难理解这一点。
MrPickles

@MrPickles:是的,SOURCE实际上没有使用,可以删除。
Makkes's

9
@EmilVatai据gnu.org/software/make/manual/make.html#index-LDLIBS LOADLIBES已被废弃,LDLIBS应改为使用。
海星

52

在更复杂的构建方案中,通常将编译分为多个阶段,首先进行编译和汇编(输出到目标文件),然后再将目标文件链接到最终的可执行文件或库中,这避免了在需要时重新编译所有目标文件的情况。他们的源文件没有改变。这就是为什么-lm当您将链接标记放入CFLAGSCFLAGS在编译阶段使用)时,包含链接标记不起作用的原因。

链接库的约定是将它们放在LOADLIBES或中LDLIBS(GNU make包含两者,但您的里程可能会有所不同):

LDLIBS=-lm

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

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

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

1

似乎链接标志的顺序在旧版gcc中不是问题。例如gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-16),Centos-6.7自带了输入文件之前的链接器选项;但是带有ubuntu 16.04的gccgcc (Ubuntu 5.3.1-14ubuntu2.1) 5.3.1 20160413不允许。

它不只是gcc版本,我与发行版有关

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.