静态lib中的链接错误,除非在主项目中使用

时间:2018-07-29 15:25:40

标签: c makefile static-libraries ld

我正在创建一个用于线程池的静态库,它依赖于其他两个自制静态库(一个自制printf和一个自制迷你libc)。

但是像ft_bzero这样的子功能在项目中没有链接,除非我在需要使用线程池库的根项目上使用它们。所以我的链接错误来自我的thpool库。

样品:

cc -Wall -Werror -Wextra -MD -I ./ -I ./jqueue -I ../libft/incs -I 
../printf/incs -o .objs/thpool_create.o -c ./thpool_create.c

ar rc libthpool.a ./.objs/thpool_create.o etcetc

在库中,我编译每个.o并使用ar rc libthpool.a *.o。然后我从主项目(实际上是一个.o)编译test.c,然后

cc .objs/test.o -o test -L./libft -L./printf -L./thpool -lft -lftprintf -lthpool -lpthread

我该如何解决我的错误?

1 个答案:

答案 0 :(得分:1)

由于ftpool库中的代码使用了ftftprintf中的代码,因此(几乎可以肯定)您需要以相反的顺序列出这些库:

cc .objs/test.o -o test -L./libft -L./printf -L./thpool -lthpool -lftprintf  -lft -lpthread

扫描静态库时,链接器将查找当前未定义的符号的定义。如果您的测试代码仅从thpool调用函数,则在扫描ft库时,不会引用ft中的任何符号,因此库中不包含任何符号;如果在扫描ftprintf库时未引用ftprintf的任何符号,则ftprintf也不包含任何符号。当遇到thpool中引用ftftprintf中事物的符号时,为时已晚。链接器不会重新扫描库。因此,您需要按顺序列出库,以便通过在(B)之前链接(A)来找到从一个库(A)到另一个(B)的所有引用。如果测试代码引用了ftftprintf中的某些函数,您可能会很幸运,或者有些幸运;可能会链接一些符号。但是,如果thpool中有一些函数首次引用了ft中的函数,则按问题的顺序进行操作,您将失去链接所有内容的机会。因此,建议重新排序。

另一种(非常肮脏,但仍然有效)的技术是通过在命令行上多次列出静态库来重新扫描静态库。

对于共享库,链接规则是不同的。如果共享库满足任何符号,则整个库将可用,因此链接器会记住所有定义的符号,并且您很可能会摆脱原来的链接顺序。

您可能需要查找“拓扑排序”。您当然应该设计静态库,以使依赖项中没有循环;导致依赖关系的循环,唯一可靠的解决方案是重新扫描库或合并库。