c - 除非在主项目中使用,否则静态库中的链接错误

标签 c makefile static-libraries ld

我正在创建一个用于线程池的小型静态库,它依赖于另外 2 个自制静态库(一个自制的 printf 和一个自制的迷你 libc)。

但是像 ft_bzero 这样的子函数不会在项目中链接,除非我在根项目(需要使用线程池库的项目)上使用它们。所以我的 thpool lib 出现了链接错误。

示例:

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。然后我从主项目(实际上是一个 test.c)编译 .o ,然后

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

如何解决我的错误?

最佳答案

由于 ftpool 库中的代码使用来自 ftftprintf 的代码,因此您(几乎肯定)需要在逆序:

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

扫描静态库时,链接器会查找当前 undefined symbol 的定义。如果您的测试代码仅调用 thpool 中的函数,则扫描 ft 库时不会引用 ft 中的任何符号,因此不会有任何结果从图书馆收录;如果扫描 ftprintf 库时没有引用 ftprintf 中的任何符号,则 ftprintf 中也不会包含任何内容。当它遇到 thpool 中引用 ftftprintf 内容的符号时,为时已晚;链接器不会重新扫描库。因此,您需要按顺序列出库,以便通过在 (B) 之前链接 (A) 来找到从一个库 (A) 到另一个库 (B) 的所有引用。如果测试代码引用了ftftprintf中的一些函数,你可能会很幸运,或者有点幸运;一些符号可能被链接进来。但是,如果 thpool 中的函数首次引用 ft 中的函数,按照问题中的顺序,你就输了连接一切的机会。因此建议重新排序。

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

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

您可能需要查找“拓扑排序”。您当然应该致力于设计静态库,以便在依赖项中不存在循环;这会导致依赖循环,唯一可靠的解决方案是重新扫描库或组合库。

关于c - 除非在主项目中使用,否则静态库中的链接错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51581794/

相关文章:

cocoa - 我有一个 Xcode 静态库项目,如何向其中添加测试目标以便可以在那里运行它? (而不是在链接到它的项目中。)

c++ - Arduino 编译为 C++,而不是 C

c - 是否有 "lseek"要内存?

linux - linux 中的透明惰性 makefile

c - 如何链接linux/gpio.h?

c++ - 将静态 C 库与 C++ 代码链接时出现 "undefined reference to"错误

ios - XCode 创建一半大小的静态库

c - 如何在 Linux 中读取和写入 fifo(命名管道)?

c - 如何使用 scanf 来限制用户输入不大于数组的字符串?

c - Linux/生成文件 : Creating a binary that executes as if it were in a specific directory