如何在makefile中使用LDFLAGS

use*_*785 64 makefile ldflags

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

CC=gcc
CFLAGS=-Wall -lm

all:client

.PHONY: clean
clean:
    rm *~ *.o client
Run Code Online (Sandbox Code Playgroud)

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

"undefined reference to rint"
Run Code Online (Sandbox Code Playgroud)

所以它无法链接数学库.

但是当我使用明确编译时

gcc client.c -lm -o client
Run Code Online (Sandbox Code Playgroud)

它成功编译.

那么我应该如何更改我的makefile以使其正常工作.我已经尝试过添加LDFLAGS=-lm.但我得到了同样的错误.

我还应该补充一点,当我跑步时make,它会扩展到

gcc -Wall -lm client.c -o client
Run Code Online (Sandbox Code Playgroud)

(请注意,当我最后gcc明确地运行-lm时,它的工作原理).

Mak*_*kes 65

您的链接器(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)
Run Code Online (Sandbox Code Playgroud)

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

  • LDLIBS用于库,LDFLAGS应用于标志/搜索路径(-L) (52认同)
  • @EmilVatai根据https://www.gnu.org/software/make/manual/make.html#index-LDLIBS,不推荐使用LOADLIBES,而应使用LDLIBS. (7认同)
  • 我还认为-lm应该在LDFLAGS中,但事实证明(参见laindir的答案和https://www.gnu.org/software/make/manual/html_node/Catalogue-of-Rules.html),它应该是相反,在LOADLIBES中,然后一切都开箱即用(即没有定义明确的规则)! (3认同)
  • 你在哪里使用规则中的来源?它已定义,但未使用.很难理解这一点. (2认同)

lai*_*dir 50

在更复杂的构建场景中,通常将编译分解为阶段,首先进行编译和汇编(输出到目标文件),然后将目标文件链接到最终的可执行文件或库中 - 这可以防止在编译时重新编译所有目标文件他们的源文件没有改变.这就是为什么包含链接标志-lm在你输入时不起作用的原因CFLAGS(CFLAGS在编译阶段使用).

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

LDLIBS=-lm
Run Code Online (Sandbox Code Playgroud)

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

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

client: client.o
    $(CC) $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@
Run Code Online (Sandbox Code Playgroud)


Lui*_*uez 11

根据make此处的当前(2022)文档,当前接受的答案不正确:

\n

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

\n
\n

LDFLAGS:\n当编译器应该调用链接器时提供给编译器的额外标志,\xe2\x80\x98ld\xe2\x80\x99,例如 -L。应将库 (-lfoo) 添加到 LDLIBS 变量中。

\n

LDLIBS:\n当编译器调用链接器时为编译器提供的库标志或名称,\xe2\x80\x98ld\xe2\x80\x99。LOADLIBES 是 LDLIBS 的替代品,已弃用(但仍受支持)。非库链接器标志(例如 -L)应放入 LDFLAGS 变量中。

\n
\n

另外,LOADLIBES上面一些回复中提到的内容早已被弃用,不应再使用。

\n

所以,从前面的定义来看,上面的例子似乎应该这样写更合适:

\n
CC=gcc\nCFLAGS=-Wall\nLDLIBS=-lm\nLDFLAGS=-L/usr/local/include\n\n.PHONY: all\nall: client\n\n.PHONY: clean\nclean:\n    $(RM) *~ *.o client\n\nOBJECTS=client.o\nclient: $(OBJECTS)\n    $(CC) $(CFLAGS) $(OBJECTS) $(LDFLAGS) $(LDLIBS)  -o client\n
Run Code Online (Sandbox Code Playgroud)\n