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 内容应该可以完成工作
备注:
- 仅在编译阶段需要头文件
- 仅在 link 步骤
期间需要库文件
- 最好让第一个 'target' 成为 'all' 这样 makefile 可以成功执行而不必包含 'Blasteroids' 参数
- 拥有 'target' 'clean' 可以轻松清除将要重建的项目
- 任何不生成同名文件的'target' 都应列在“.PSEUDO”运算符中
- linker 按照命令行中列出的顺序处理 linker 命令行项。因此,列出对象,然后是目录,然后是库 'short' names
- 在编译命令行末尾列出头文件
- 使用包含可执行文件完整路径的宏(如 CC 和 RM),以便使用正确的可执行文件,否则将使用在 $PATH 中找到的与名称匹配的第一项。
- $^ 是一个扩展到配方依赖项的内置宏
- $< 是扩展到第一个依赖项的内置宏
- $@ 是一个扩展到食谱 'target'
的内置宏
$(SRC:.c=?)
语句对 $(SRC)
宏 中包含的文件扩展名进行字符替换
%.o:%.c
秘诀说对于每个要编译成目标文件的源文件,使用这个秘诀
- '-ggdb' 是为了让 'gdb' 调试器可以获得最大的调试信息。
- 这种 '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
程序查找名为 makefile
或 Makefile
的文件,不带扩展名。如果您将 makefile 命名为其他名称,例如 makefile.txt
,那么 make
将无法找到它,它只会使用自己的 built-in 规则,该规则对额外标志 ro 一无所知可能需要的库。
因此,要么将您的 makefile 重命名为 makefile
或 Makefile
,要么在 运行 make 时在命令行中明确指定您的 makefile 的名称,例如 make -f makefile.txt Blasteroids
.
其次,如果您没有在命令行中指定目标,那么 make 将始终构建第一个目标。所以,如果你 re-order 你的目标,那么你通常想要构建的目标(在本例中 Blasteroids
)是第一个,那么你可以 运行 make
没有参数它将构建该目标。
与编程语言不同,目标定义的顺序无关紧要:例如,您不必在 link 行之前先为所有目标文件定义规则。 Make读取整个文件并构造一个前提关系的内部图,这个图中的节点和边可以按任意顺序添加。
注意:这是 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 内容应该可以完成工作
备注:
- 仅在编译阶段需要头文件
- 仅在 link 步骤 期间需要库文件
- 最好让第一个 'target' 成为 'all' 这样 makefile 可以成功执行而不必包含 'Blasteroids' 参数
- 拥有 'target' 'clean' 可以轻松清除将要重建的项目
- 任何不生成同名文件的'target' 都应列在“.PSEUDO”运算符中
- linker 按照命令行中列出的顺序处理 linker 命令行项。因此,列出对象,然后是目录,然后是库 'short' names
- 在编译命令行末尾列出头文件
- 使用包含可执行文件完整路径的宏(如 CC 和 RM),以便使用正确的可执行文件,否则将使用在 $PATH 中找到的与名称匹配的第一项。
- $^ 是一个扩展到配方依赖项的内置宏
- $< 是扩展到第一个依赖项的内置宏
- $@ 是一个扩展到食谱 'target' 的内置宏
$(SRC:.c=?)
语句对$(SRC)
宏 中包含的文件扩展名进行字符替换
%.o:%.c
秘诀说对于每个要编译成目标文件的源文件,使用这个秘诀- '-ggdb' 是为了让 'gdb' 调试器可以获得最大的调试信息。
- 这种 '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
程序查找名为 makefile
或 Makefile
的文件,不带扩展名。如果您将 makefile 命名为其他名称,例如 makefile.txt
,那么 make
将无法找到它,它只会使用自己的 built-in 规则,该规则对额外标志 ro 一无所知可能需要的库。
因此,要么将您的 makefile 重命名为 makefile
或 Makefile
,要么在 运行 make 时在命令行中明确指定您的 makefile 的名称,例如 make -f makefile.txt Blasteroids
.
其次,如果您没有在命令行中指定目标,那么 make 将始终构建第一个目标。所以,如果你 re-order 你的目标,那么你通常想要构建的目标(在本例中 Blasteroids
)是第一个,那么你可以 运行 make
没有参数它将构建该目标。
与编程语言不同,目标定义的顺序无关紧要:例如,您不必在 link 行之前先为所有目标文件定义规则。 Make读取整个文件并构造一个前提关系的内部图,这个图中的节点和边可以按任意顺序添加。