我有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表示myfnlibmyfn.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/

10-10 06:47