为什么静态库被使用两次才能使编译工作?

时间:2016-04-20 15:46:38

标签: c++ cmake

我正在学习ARToolKit和CMake。我正在尝试创建一个CMake例程来复制ARToolKit在其Makefile文件中所做的事情。我发现了这个:

LIBS= -lARgsub_lite -lARvideo -lAR -lARICP -lAR -lglut -lGLU -lGL -lX11 -lm -lpthread -ljpeg -ldc1394 -lraw1394

$(BIN_DIR)/simpleLite: simpleLite.o $(OBJS)
cc -o $(BIN_DIR)/simpleLite simpleLite.o $(OBJS) $(LDFLAG) $(LIBS)

我注意到-lAR被宣布为两次。我决定在我的CMake文件中复制它,也是两次声明。

set( ART_STATICS libARgsub_lite.a libARvideo.a libAR.a libARICP.a libAR.a)
link_directories(${ART_DIR}/lib)

它的工作原理。但是如果我删除最后一个重复的那个,那么程序会抱怨它无法从libAR库中找到函数。 (确切地说,它是libAR的matrix.h中的矩阵函数)为什么?订单重要吗?或libARICP.a libAR.a中的某些内容可能正在消耗git diff --stat ee28fb0...fdca511中的内容,因此您必须再次声明它?对不起,我不明白链接静态库的内部工作原理......

1 个答案:

答案 0 :(得分:2)

我发现这个比喻对你所询问的问题特别有用([{3}}):

  
      
  • 将存档库想象成一个书架,上面有一些书(单独的.o文件)。
  •   
  • 有些书可能会将您推荐给其他书籍(通过未解决的符号),这些书籍可能位于同一书架上,也可能位于不同的书架上。
  •   
     

图书管理员来到第一个书架(第一个档案库)   你的链接线)有两个列表 - 她仍然需要的东西列表   (未解决的符号),以及她已经拥有的事物清单(符号   已定义)。

     

通常,她已经拥有crt0.o(由链接添加到链接行)   编译器驱动程序),它指的是main。所以她的“需要”列表包含   主要。她经常会有main.o,这意味着她不再   需要main,但可能需要malloc,free,printf等。

     

现在她开始一次扫描一个书架,寻找书籍   定义她需要的符号。如果一本书定义了其中一个符号   “需要”清单,她从书架上取下那本书,刮掉了所有   该书中定义的符号来自“需要”列表,添加了所有已定义的符号   符号到“有”列表,并添加该书使用的所有符号   尚未列入“需要”列表的“有”列表。

     

如果某本书没有定义当前“需要”列表中的任何符号,   她不接受它(即使这本书可能会在以后派上用场)。

     

如果她刚刚拍摄的一本书定义了她已经拥有的符号,那么就有   “多重定义的符号”问题。

     

如果她从当前架子上取下任何书籍,她会重新扫描架子   再次,寻找更多书籍(因为她只是书   可能需要当前货架上的其他书籍。)

     

一旦她现在的架子上没有她需要的书,她就是   完成那个架子,她没有回到它(除非   与之对应的库在命令行中列出了几个   次)。

     

在搜索命令行中列出的所有书架后(如   以及由编译器驱动程序添加的libc,她仍然有   “需要”列表中的条目存在“未定义符号”错误。

     

显然,如果你的许多生物学书籍都提到化学书籍,那么   你有一篇生物学论文要写,你最好开始搜索   化学之前的生物书架。

     

有时,两个归档库是相互依赖的:来自一个的对象   依赖于对方的对象,反之亦然。

     

这意味着没有正确的链接这些库的顺序,   这两个库的结构都很差,为了这个   成功链接可执行文件,您可能需要列出这两个   库多次,如:

 gcc main.o -lfoo -lbar -lfoo -lbar -lfoo
     

在使用GNU ld的系统上,可以使用--start-group和   --end-group命令行选项来解决这种库间依赖关系。