我是Linux OS新手。我正在尝试使用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
(请注意,当我最后明确地使用gcc
运行-lm
时,它会正常运行。
答案 0 :(得分:61)
您的链接器(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)的顺序。
答案 1 :(得分:50)
在更复杂的构建场景中,通常将编译分解为阶段,首先进行编译和汇编(输出到目标文件),然后将目标文件链接到最终的可执行文件或库中 - 这可以防止必须重新编译所有目标文件的源文件未更改。这就是为什么当你将-lm
放入CFLAGS
时,包含链接标志CFLAGS
不起作用的原因(编译阶段使用LOADLIBES
)。
要链接的库的惯例是将它们放在LDLIBS
或LDLIBS=-lm
中(GNU make包含两者,但您的里程可能会有所不同):
-p
这应该允许您继续使用内置规则,而不必编写自己的链接规则。对于其他品牌,应该有一个标志来输出内置规则(对于GNU make,这是-l
)。如果您的make版本没有用于链接的内置规则(或者如果它没有client.o: client.c
$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c -o $@ $<
client: client.o
$(CC) $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@
指令的占位符),那么您需要编写自己的:
{{1}}
答案 2 :(得分:1)
似乎链接标志的顺序在旧版本的gcc中不是问题。例如gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-16)
在输入文件之前附带Centos-6.7满意的链接器选项;但gcc与ubuntu 16.04 gcc (Ubuntu 5.3.1-14ubuntu2.1) 5.3.1 20160413
不允许。
它不仅仅是gcc版本,我对发行版有所了解