我有一个目录,其中包含一小部分业余爱好 OpenGL 程序的标头和源代码。我的目标是创建两个主要头文件:“toolbox.h”和“geometry.h”。第二个
#include
是第一个。为了方便起见,我还希望将与这两个标头相关的来源集中为两个档案。当我 make 01_Planet-Geom
时,尽管我将其存档作为 make 规则的一部分,但没有找到“toolbox.h”中的任何符号。 make 00_Dyn-6D
效果很好。
我需要改变什么才能
make 01_Planet-Geom
?
01_Planet-Geom: 01_Planet-Geom.o toolbox.a geometry.a
gcc $(CFLG) -o [email protected] $^ $(LIBS)
make 01_Planet-Geom
。我得到以下输出:
gcc -c -O3 -Wall -std=gnu17 01_Planet-Geom.c
gcc -c -O3 -Wall -std=gnu17 TriNet.c
ar -rcs geometry.a toolbox.a TriNet.o
gcc -O3 -Wall -std=gnu17 -o 01_Planet-Geom.out 01_Planet-Geom.o toolbox.a geometry.a -lglut -lGLU -lGL -lm
/usr/bin/ld: geometry.a(TriNet.o): in function `N_from_VF':
TriNet.c:(.text+0x151): undefined reference to `get_CCW_tri_norm'
...还有很多人喜欢它。这些都是“vector-f_ops.c”中定义的函数...
/usr/bin/ld: TriNet.c:(.text+0x1abd): undefined reference to `dot_vec4f'
collect2: error: ld returned 1 exit status
make: *** [makefile:50: 01_Planet-Geom] Error 1
我在“makefile”中有以下内容:
########## COMPILATION SETTINGS ##################
CFLG=-O3 -Wall -std=gnu17
LIBS=-lglut -lGLU -lGL -lm
CLEAN=rm -f *.out *.o *.a
########## DEPENDENCIES ##########################
### Prog Dependencies ###
00_Dyn-6D.o: 00_Dyn-6D.c toolbox.h
01_Planet-Geom.o: 01_Planet-Geom.c toolbox.h geometry.h
### Float Matrix Math ###
matrix4x4f.o: matrix4x4f.c matrix4x4f.h
### OpenGL Toolbox ###
OGL_utils.o: OGL_utils.c toolbox.h
load_assets.o: load_assets.c toolbox.h
vector-f_ops.o: vector-f_ops.c toolbox.h
### Geometry Construction ###
TriNet.o: TriNet.c toolbox.h geometry.h
########## ARCHIVES & GENERAL RULES ##############
toolbox.a: OGL_utils.o load_assets.o vector-f_ops.o
ar -rcs $@ $^
geometry.a: toolbox.a TriNet.o
ar -rcs $@ $^
# Compile rules
.c.o:
gcc -c $(CFLG) $<
########## PROGRAM & CLEAN RULES #################
##### Program Rules ##############################
00_Dyn-6D: 00_Dyn-6D.o toolbox.a
gcc $(CFLG) -o [email protected] $^ $(LIBS)
01_Planet-Geom: 01_Planet-Geom.o toolbox.a geometry.a
gcc $(CFLG) -o [email protected] $^ $(LIBS)
##### Clean Rule #################################
# Clean
clean:
$(CLEAN)
我仔细检查了所有源文件
#include
适当的标题。
“TriNet.c”已在不同的上下文中成功编译。 我确认在添加
make 00_Dyn-6D
和 01_Planet-Geom
的规则后,geometry.a
仍然有效。
您的链接由于两个原因而失败。
第一个
是这个:
ar -rcs geometry.a toolbox.a TriNet.o
由 Makefile 规则得出:
geometry.a: toolbox.a TriNet.o
ar -rcs $@ $^
你可能会相信
ar -rcs geometry.a toolbox.a TriNet.o
提取的效果
存档中的所有目标文件 toolbox.a
并将它们添加到
目标存档 geometry.a
,以及目标文件 TriNet.o
。
事实上,它只是将 files
toolbox.a
和 TriNet.o
归档到
geometry.a
,结果是 geometry.a
是一个包含
另一个存档 toolbox.a
和一个目标文件 TriNet.o
。
当诸如
geometry.a
之类的存档输入到链接器时,它仅考虑
目标文件是存档的成员,如ar t geometry.a
列出。
它将从存档中仅提取那些成员对象文件
提供输出文件中先前未定义符号的定义并静态
将它们链接到输出文件中,迭代执行此操作,直到存档产生
不再需要定义。
链接器将不会考虑属于以下成员的目标文件 属于
geometry.a
成员的档案。因此 geometry.a
可以
对您的联系做出贡献只是TriNet.o
,这当然不是
够了。
如果您希望
geometry.a
将 toolbox.a
中的所有目标文件作为成员
以及 TriNet.o
那么你需要从 相同的目标文件制作
geometry.a
您放入 toolbox.a
,加上 TriNet.o
。
如果
ar -rcs geometry.a toolbox.a TriNet.o
如您所期望的那样工作
到,那么就没有必要将 geometry.a
和 toolbox.a
都链接到
需要 geometry.a
的程序,并且您需要一些其他原因 toolbox.a
存在(看来你确实如此)。
但是显然你还是认为有必要在联动中将两者都输入 您的计划的
01_Planet-Geom.out
。
gcc -O3 -Wall -std=gnu17 -o 01_Planet-Geom.out 01_Planet-Geom.o toolbox.a geometry.a -lglut -lGLU -lGL -lm
谁的联动失败:
/usr/bin/ld: geometry.a(TriNet.o): in function `N_from_VF':
TriNet.c:(.text+0x151): undefined reference to `get_CCW_tri_norm'
这让我们想到:
第二个
geometry.a
仅包含链接器可以看到的目标文件 TriNet.o
。但是TriNet.o
包含对 get_CCW_tri_norm
的未定义引用,(我打赌)它是在 toolbox.a
的成员中定义的。
您已在链接中输入
toolbox.a
,但您已在 geometry.a
之前输入了它。所以当 链接器检查了
toolbox.a
它知道没有对
get_CCW_tri_norm
的未定义引用并且 因此没有从
toolbox.a
中寻找、提取或链接任何提供定义的目标文件
get_CCW_tri_norm
。没有“随后”输入的文件文件提供该定义, 因此符号在链接末尾保持未定义状态。将未定义符号引入链接的文件必须 提供给提供其定义的链接器before库。链接器将检查库 只查找手中已有的未定义符号的定义,而不向后看。