我有foo.c bar.c和baz.c文件,还有包装器代码myfn.c,它定义了一个函数myfn(),该函数使用其他文件中的代码和数据。
我想创建一个类似于对象文件或归档文件myfn.o或libmyfn.a的文件,这样myfn()就可以用于其他项目,而不必从{foo,bar,baz}.o导出大量符号。
在Linux/gcc中,正确的方法是什么?谢谢。
更新:我找到了一种方法我本来应该强调的是,这是关于静态存档,而不是dso。不管怎样,食谱是:#define PUBLIC __attribute__ ((visibility("default")))
然后在myfn()
中将PUBLIC
标记为myfn.c
不要标记任何其他PUBLIC
。
使用gcc -c foo.c bar.c baz.c myfn.c -fvisibility=hidden
编译对象,这会将除myfn()
之外的所有内容标记为隐藏。
使用ld
的部分链接开关创建一个方便的存档文件:ld -r foo.o bar.o baz.o myfn.o -o libmyfn.a
定位所有不PUBLIC
的内容,就像这样:objcopy --localize-hidden libmyfn.a
现在nm
表示myfn
是libmyfn.a
中唯一的全局符号,随后链接到其他程序的工作正常:gcc -o main main.c -L. -lmyfn
(这里,程序调用myfn()
;如果它试图调用foo()
,则编译将失败)。
如果我在步骤3中使用ar
而不是ld -r
,那么在步骤5中编译将失败:我猜ar
没有将foo
等链接到myfn
,一旦这些函数被本地化,就不能再进行编译,而ld -r
在链接被本地化之前将其解析。
我欢迎任何确认这是“正确的”方法,或者描述一种更巧妙的实现方法的回复。
最佳答案
不幸的是,globals的C链接是all或nothing,因为所有模块的globals都可以在libmyfn.a
的最终外部符号列表中找到。gcc
工具链提供了一个扩展,允许您对外部用户隐藏符号,同时使它们可用于库中的其他翻译单元:
食物:
void foo();
食品c:
void foo() __attribute__ ((visibility ("hidden")));
我的名字:
void myfn();
我的名字:
#include <stdio.h>
#include "foo.h"
void myfn() {
printf("calling foo...\n");
foo();
printf("calling foo again...\n");
foo();
}
为了便于移植,您可能会受益于为
__attribute__ ((visibility ("hidden")))
生成宏,并将其放置在条件编译块中。此外,Linux提供了一个utility called
gcc
,它允许您从编译的对象文件中删除一些符号选项strip
和-N
允许您标识要保留或删除的单个符号。关于c - 静态文件中的C符号可见性,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39981491/