Allegro5 makefile 错误

Allegro5 makefile error

注意:这是 Head First C 书中的最后一个练习。

我有以下问题。我正在尝试使用 allegro5.2 库制作游戏。我想使用多个 .c 文件来整齐地组织所有内容。但是,我在使用 makefile 编译我的程序时遇到了问题。我正在尝试编译这个简单的程序:

#include <stdio.h>
#include <allegro5/allegro.h>

const int disp_h = 640;
const int disp_w = 480;

int main(int argc, char **argv) {

ALLEGRO_DISPLAY *display;

if(!al_init()) {
    fprintf(stderr, "failed to initialize allegro!\n");
    return -1;
}

display = al_create_display(disp_h,disp_w);
if(!display) {
    fprintf(stderr, "failed to create display!\n");
    return -1;
}

al_rest(0.4);
al_destroy_display(display);

printf("bye bye!!!\n");

return 0;
}

生成文件是:

Blasteroids.o: allegro.h Blasteroids.c
    gcc -Wall -c Blasteroids.c

Blasteroids: Blasteroids.o allegro.h
    gcc -Wall -I/usr/include/allegro5 -L/usr/lib -lallegro -lallegro_main Blasteroids.o -o Blasteroids

现在,当我使用终端时编译正常,但现在我似乎遇到了问题。终端给出的错误(使用命令make Blassteroids)是:

cc   Blasteroids.o   -o Blasteroids
Undefined symbols for architecture x86_64:
  "_al_create_display", referenced from:
      __al_mangled_main in Blasteroids.o
  "_al_destroy_display", referenced from:
      __al_mangled_main in Blasteroids.o
  "_al_install_system", referenced from:
      __al_mangled_main in Blasteroids.o
  "_al_rest", referenced from:
      __al_mangled_main in Blasteroids.o
  "_main", referenced from:
     implicit entry/start for main executable
     (maybe you meant: __al_mangled_main)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [Blasteroids] Error 1

我不知道我做错了什么,而且我对这些东西很陌生。我在 makefile 中搜索了示例,但它们给我的代码就像我现在正在使用的那样。 我现在可以只为上面的程序使用一行,但我的想法是我想制作自己的 .c 文件,将它们制作成 .o 文件,然后 link 将它们放在一起。因此生成文件。

像下面的 makefile 内容应该可以完成工作

备注:

  1. 仅在编译阶段需要头文件
  2. 仅在 link 步骤
  3. 期间需要库文件
  4. 最好让第一个 'target' 成为 'all' 这样 makefile 可以成功执行而不必包含 'Blasteroids' 参数
  5. 拥有 'target' 'clean' 可以轻松清除将要重建的项目
  6. 任何不生成同名文件的'target' 都应列在“.PSEUDO”运算符中
  7. linker 按照命令行中列出的顺序处理 linker 命令行项。因此,列出对象,然后是目录,然后是库 'short' names
  8. 在编译命令行末尾列出头文件
  9. 使用包含可执行文件完整路径的宏(如 CC 和 RM),以便使用正确的可执行文件,否则将使用在 $PATH 中找到的与名称匹配的第一项。
  10. $^ 是一个扩展到配方依赖项的内置宏
  11. $< 是扩展到第一个依赖项的内置宏
  12. $@ 是一个扩展到食谱 'target'
  13. 的内置宏
  14. $(SRC:.c=?) 语句对 $(SRC)
  15. 中包含的文件扩展名进行字符替换
  16. %.o:%.c 秘诀说对于每个要编译成目标文件的源文件,使用这个秘诀
  17. '-ggdb' 是为了让 'gdb' 调试器可以获得最大的调试信息。
  18. 这种 'makefile' 的模式可以广泛用于其他项目,只需稍作改动。为了获得更大的灵活性,还可以插入一个自动生成头文件依赖项的配方,因此不需要在编译配方中单独列出它们,但现在,以下 makefile 内容将执行您当前尝试执行的操作

现在是 makefile

CC := /bin/gcc
RM := /bin/rm

CFLAGS := -Wall -Wextra -pedantic -std=gnu99 -ggdb -c
LFLAGS := -L/usr/lib -lallegro -lallegro_main

SRC    := Blasteroids.c
#OBJ    := $(SRC:.c=.0)
OBJ    := $(SRC:.c=.o)
NAME   := $(SRC:.c=)

.PSEUDO: all clean

all: $(NAME)

%.o:%.c
    #$(CC) $(CFLAGS) $^ -o $@ -I/usr/include/allegro5
    $(CC) $(CFLAGS) $< -o $@ -I/usr/include/allegro5

$(NAME): $(OBJ)
    $(CC) -ggdb  $^ -o $@  $(LFLAGS)

.clean:
    $(RM) -f $(NAME) $(OBJ)

make 程序查找名为 makefileMakefile 的文件,不带扩展名。如果您将 makefile 命名为其他名称,例如 makefile.txt,那么 make 将无法找到它,它只会使用自己的 built-in 规则,该规则对额外标志 ro 一无所知可能需要的库。

因此,要么将您的 makefile 重命名为 makefileMakefile,要么在 运行 make 时在命令行中明确指定您的 makefile 的名称,例如 make -f makefile.txt Blasteroids.

其次,如果您没有在命令行中指定目标,那么 make 将始终构建第一个目标。所以,如果你 re-order 你的目标,那么你通常想要构建的目标(在本例中 Blasteroids)是第一个,那么你可以 运行 make 没有参数它将构建该目标。

与编程语言不同,目标定义的顺序无关紧要:例如,您不必在 link 行之前先为所有目标文件定义规则。 Make读取整个文件并构造一个前提关系的内部图,这个图中的节点和边可以按任意顺序添加。