具有多个存档的 C makefile

问题描述 投票:0回答:1

我有一个目录,其中包含一小部分业余爱好 OpenGL 程序的标头和源代码。我的目标是创建两个主要头文件:“toolbox.h”和“geometry.h”。第二个

#include
是第一个。为了方便起见,我还希望将与这两个标头相关的来源集中为两个档案。当我
make 01_Planet-Geom
时,尽管我将其存档作为 make 规则的一部分,但没有找到“toolbox.h”中的任何符号。
make 00_Dyn-6D
效果很好。

我需要改变什么才能

make 01_Planet-Geom

  • 相关的make规则是
    01_Planet-Geom: 01_Planet-Geom.o toolbox.a geometry.a

    gcc $(CFLG) -o [email protected] $^ $(LIBS)
  • 我从项目目录运行
    make 01_Planet-Geom
  • gcc版本9.4.0
  • GNU Make 4.2.1

我得到以下输出:

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
仍然有效。

c gcc opengl makefile archive
1个回答
0
投票

您的链接由于两个原因而失败。

第一个

是这个:

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

库。链接器将检查库 只查找手中已有的未定义符号的定义,而不向后看。

© www.soinside.com 2019 - 2024. All rights reserved.