【问题标题】:What does "linker input file unused because linking not done" mean? (C makefile)“链接器输入文件未使用,因为链接未完成”是什么意思? (C 生成文件)
【发布时间】:2016-03-29 08:07:34
【问题描述】:

我创建了一个 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

【问题讨论】:

  • 您的CFLAGS 中有-c。这意味着编译但不链接。而且您在应该链接的game 目标的规则中使用这些标志。
  • 编译目标文件时不需要$(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/libLDLIBS 将包括 $(SDL)还有-lm 选项。 CFLAGS 宏不应包含-c

标签: c compilation makefile linker


【解决方案1】:

您的链接命令扩展为:

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 not 进行链接。所以它与实际无关。 (.o 文件只能用于链接,并且您已禁用链接,这就是您收到该消息的原因)

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

【讨论】:

    【解决方案2】:

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

    其中:

    1. 库名称仅在链接步骤中使用,而不是在编译步骤中使用
    2. 建议使用“通配符”make 运算符来获取源文件列表。然后使用模式替换运算符获取目标文件列表:

    例如:

    SRC := $(wildcard *.c)
    OBJ := $(SRC:.c=.o)
    
    1. 当目标(all、clean)不会生成同名文件时,请在 make 文件的早期插入 .PHONY: 语句:

    类似于:

    .PHONY : all clean
    
    1. 发布的 make 文件没有处理相关头文件的工具,有几种处理方法。这遵循 OP 的引导并且不处理头文件,因此更改头文件不会重新编译/重新链接受影响的源文件。

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

    建议:

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

    建议:

    all: game
    
    1. 一旦创建了目标文件列表(如上),就可以减少编译规则:

    使用 make 操作符:

    %.o: %.c
        $(CC) $(CFLAGS) -c $< -o $@ -I.
    
    1. 编译器和链接器的-g 参数允许使用调试器。如果该调试器是gdb,那么更好的参数是-ggdb

    2. 几乎总是不需要多次评估宏定义,因此不要在宏定义中使用=,而是使用:=

    3. 如果您希望game 可执行,则在“链接”规则的最后一行插入chmod 命令

    建议阅读makefile 中可以使用的特殊运算符,以帮助您理解以下建议的makefile

    通常最好用宏替换对 shell 识别命令的调用。

    CC := /user/bin/gcc
    RM := /usr/bin/rm
    
    CFLAGS := -c -std=c99 -Wall -Wextra -pedantic -O3 -Wfloat-equal -ggdb
    LFLAGS := -std=c99 -O3 -ggdb
    
    SDL := -lSDL2 -lSDL2_ttf -lSDL2_image -lSDL2_mixer
    
    SRC := $(wildcard *.c)
    OBJS := $(SRC:.c=.o)
    
    
    .PHONY : all clean
    all: game
    
    
    game: $(OBJS)
        $(CC) $(LFLAGS)  $(OBJS) -o $@ $(SDL) -lm
    
    %.o: %.c
        $(CC) $(CFLAGS) -c $< -o $@ -I.
    
    
    clean:
        $(RM) -f *.o game
    

    【讨论】:

    • 谢谢。我曾尝试按照教程进行操作,但有几件事我不明白。你已经为我清理了它们
    • OP 收到的错误消息表示未执行链接步骤。由于 OP 发布的 makefile 中有几个“oops”,因此未执行。
    • 投反对票,因为您的最终 Makefile 有几个不好的做法:硬编码 RM 和 CC,不使用 make 的内置规则,硬编码传递一些链接标志,其他通过 SDL,包括“。”不需要,始终附加到 CFLAGS,以便可以在命令行上指定其他的,使用“LFLAGS”作为第二组 cflags(没有警告)。
    • @user318904,您对 makefile 内容的“最佳实践”的理解与我的理解有很大不同。请发布一个指向列出 makefile 的“最佳实践”的网页的链接
    【解决方案3】:

    不要将-lm 或SDL 库放入CFLAGS,库操作数会放在命令行的末尾。相反,使用一个额外的变量 LDLIBS 并像这样修改你的 game 规则:

    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 是提供)。

    【讨论】:

    • 最好还是创建一个宏OBJECTS = global.o display.o player.o entities.o controls.o sound.o menu.o,然后在依赖行和链接命令行中使用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多