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

时间:2015-12-22 23:44:45

标签: 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 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

3 个答案:

答案 0 :(得分:6)

您的关联命令扩展为:

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

答案 1 :(得分:4)

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

其中:

  1. 库名称仅在链接步骤中使用,而不是在编译步骤
  2. 中使用
  3. 建议使用'通配符' make operator获取源文件列表。然后使用patterm替换运算符获取目标文件列表:
  4. 例如:

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

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

      2. 此行:rm *o game不会删除name.o文件,因为它缺少'。'在根名称与' o'之间延期。而且,' -f'标志应该与'rm'一起使用。命令。

      3. 建议:

        rm -f *.o game 
        
        1. 此行:all: ./game可能会产生问题
        2. 建议:

          all: game
          
          1. 一旦创建了目标文件列表(如上所述),就可以减少编译规则:
          2. 使用make运算符:

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

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

            3. 如果您希望game可执行,请插入chmod命令作为&#39;链接中的最后一行。规则

            4. 建议阅读有关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
              

答案 2 :(得分:0)

不要将-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时)。