什么是;链接器输入文件未使用,因为链接未完成;什么意思?(C makefile)

什么是;链接器输入文件未使用,因为链接未完成;什么意思?(C makefile),c,compilation,makefile,linker,C,Compilation,Makefile,Linker,我已经创建了一个makefile来编译和链接我的程序,但是,我不明白为什么会出现这个错误。这和SDL有关吗 GCC = gcc CFLAGS = -c -std=c99 -lm -Wall -Wextra -pedantic -O3 -Wfloat-equal -g SDL = -lSDL2 -lSDL2_ttf -lSDL2_image -lSDL2_mixer all: ./game game: global.o display.o player.o entities.o control

我已经创建了一个makefile来编译和链接我的程序,但是,我不明白为什么会出现这个错误。这和SDL有关吗

GCC = gcc
CFLAGS = -c -std=c99 -lm -Wall -Wextra -pedantic -O3 -Wfloat-equal -g
SDL = -lSDL2 -lSDL2_ttf -lSDL2_image -lSDL2_mixer

all: ./game

game: global.o display.o player.o entities.o controls.o sound.o menu.o
    $(GCC) $(CFLAGS) global.o display.o player.o entities.o controls.o sound.o menu.o -o game

global.o: global.c
    $(GCC) $(CFLAGS) $(SDL) global.c

display.o: display.c
    $(GCC) $(CFLAGS) $(SDL) display.c

player.o: player.c
    $(GCC) $(CFLAGS) $(SDL) player.c

entities.o: entities.c
    $(GCC) $(CFLAGS) $(SDL) entities.c

controls.o: controls.c
    $(GCC) $(CFLAGS) $(SDL) controls.c

sound.o: sound.c
    $(GCC) $(CFLAGS) $(SDL) sound.c

menu.o: menu.c
    $(GCC) $(CFLAGS) $(SDL) menu.c

clean:
    rm *o game

不要将
-lm
或SDL库放入
CFLAGS
中,库操作数位于命令行末尾。相反,使用一个额外的变量
LDLIBS
,修改游戏规则如下:

game: global.o display.o player.o entities.o controls.o sound.o menu.o
    $(GCC) $(CFLAGS) -o $@ global.o display.o player.o entities.o controls.o sound.o menu.o $(LDLIBS)

-lm
操作数(它不是一个选项)和SDL的操作数仅在链接时适用,因此它不应该是
CFLAGS
的一部分,也不应该在没有链接的情况下编译时指定(即提供了
-c
时)。

链接命令扩展为:

gcc -c -std=c99 -lm -Wall -Wextra -pedantic -O3 -Wfloat-equal -g global.o display.o player.o entities.o controls.o sound.o menu.o -o game
如您所见,其中包含
-c
标志。
-c
标志告诉gcc不要进行链接。所以它实际上没有什么关系。(
.o
文件只能用于链接,您已禁用链接,这就是您收到该消息的原因)


您不希望在编译和链接时使用相同的标志。对于编译,您可能需要
-c-std=c99-Wall-Wextra-pedantic-O3-Wfloat equal-g
,对于链接,您可能需要
-lm-lSDL2-lSDL2_ttf-lSDL2_image-lSDL2_mixer-g

在发布的makefile中有几个小疏忽

其中:

  • 库名称仅在链接步骤中使用,而不是在编译步骤中使用
  • 建议使用“通配符”make运算符获取源文件列表。然后使用patterm替换操作符获取对象文件的列表:
  • 例如:

    SRC := $(wildcard *.c)
    OBJ := $(SRC:.c=.o)
    
  • 当目标(全部、清除)无法生成同名文件时,请在生成文件的早期插入
    .PHONY:
    语句:
  • 类似于:

    .PHONY : all clean
    
  • 发布的make文件没有处理相关头文件的工具,有几种方法可以处理。这遵循OPs规则,不处理头文件,因此更改头文件不会重新编译/重新链接受影响的源文件

  • 此行:
    rm*o game
    不会删除name.o文件,因为它在根名称和“o”扩展名之间缺少“.”。此外,'-f'标志应与'rm'命令一起使用

  • 建议:

    rm -f *.o game 
    
    all: game
    
  • 这一行:
    all:./game
    会产生问题
  • 建议:

    rm -f *.o game 
    
    all: game
    
  • 创建对象文件列表后(如上所述),可以减少编译规则:
  • 通过使用make操作符:

    %.o: %.c
        $(CC) $(CFLAGS) -c $< -o $@ -I.
    

    您的
    CFLAGS
    中有
    -c
    。这意味着编译但不链接。并且您正在规则中使用那些标志来链接
    游戏
    目标。编译对象文件时,您不需要
    $(SDL)
    宏;它只指定库。在链接命令的命令行中确实需要
    $(SDL)
    宏。您需要一个宏,例如
    OBJECTS=global.o display.o player.o entities.o controls.o sound.o menu.o
    ,您可以在链接依赖项和链接命令中使用它,该命令可能应该是
    $(CC)-o$@$(CFLAGS)$(OBJECTS)$(LDFLAGS)$(LDLIBS)
    其中
    LDFLAGS
    可能指定
    -L/usr/local/sdl/lib
    LDLIBS
    将包括
    $(sdl)
    -lm
    选项。CFLAGS宏不应包含
    -c
    。最好创建一个宏
    OBJECTS=global.o display.o player.o entities.o controls.o sound.o menu.o
    ,然后在依赖项行和链接命令行中使用。谢谢。我试着跟随教程,有几件事我不明白。您已经清除了它们的错误消息OP接收到的错误消息表示未执行链接步骤。由于OPs发布的makefile中存在多个“oop”,因此未执行该操作。由于最终生成的makefile存在多个错误做法,因此进行向下投票:硬编码RM和CC,不使用make的内置规则,以硬编码方式传递一些链接标志,其他通过SDL,包括“.”是不需要的,始终附加到CFLAGS,以便可以在命令行上指定其他CFLAGS,使用“LFLAGS”作为第二组CFLAGS(没有警告)。@user318904,您对makefile内容的“最佳实践”的理解与我的理解有很大不同。请在网页上发布链接,列出makefiles的“最佳实践”