我正在创建一个用于线程池的静态库,它依赖于其他两个自制静态库(一个自制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
我该如何解决我的错误?
答案 0 :(得分:1)
由于ftpool
库中的代码使用了ft
和ftprintf
中的代码,因此(几乎可以肯定)您需要以相反的顺序列出这些库:
cc .objs/test.o -o test -L./libft -L./printf -L./thpool -lthpool -lftprintf -lft -lpthread
扫描静态库时,链接器将查找当前未定义的符号的定义。如果您的测试代码仅从thpool
调用函数,则在扫描ft
库时,不会引用ft
中的任何符号,因此库中不包含任何符号;如果在扫描ftprintf
库时未引用ftprintf
的任何符号,则ftprintf
也不包含任何符号。当遇到thpool
中引用ft
或ftprintf
中事物的符号时,为时已晚。链接器不会重新扫描库。因此,您需要按顺序列出库,以便通过在(B)之前链接(A)来找到从一个库(A)到另一个(B)的所有引用。如果测试代码引用了ft
或ftprintf
中的某些函数,您可能会很幸运,或者有些幸运;可能会链接一些符号。但是,如果thpool
中有一些函数首次引用了ft
中的函数,则按问题的顺序进行操作,您将失去链接所有内容的机会。因此,建议重新排序。
另一种(非常肮脏,但仍然有效)的技术是通过在命令行上多次列出静态库来重新扫描静态库。
对于共享库,链接规则是不同的。如果共享库满足任何符号,则整个库将可用,因此链接器会记住所有定义的符号,并且您很可能会摆脱原来的链接顺序。
您可能需要查找“拓扑排序”。您当然应该设计静态库,以使依赖项中没有循环;导致依赖关系的循环,唯一可靠的解决方案是重新扫描库或合并库。