静态存档中的C符号可见性

时间:2016-10-11 15:52:43

标签: c gcc linker visibility symbols

我有文件foo.c bar.c和baz.c,以及包装代码myfn.c,它定义了一个函数myfn(),它使用来自其他文件的代码和数据。

我想创建像目标文件或存档,myfn.o或libmyfn.a这样的东西,这样myfn()就可以用于其他项目,而不会从{foo,bar,baz导出一堆符号.o以及。

在Linux / gcc中,正确的方法是什么?感谢。

更新:我找到了一种方法。我原本应该强调这是关于静态档案,而不是DSO。无论如何,食谱:

  1. #define PUBLIC __attribute__ ((visibility("default")))然后在myfn()中将PUBLIC标记为myfn.c。不要标记任何其他内容PUBLIC

  2. 使用gcc -c foo.c bar.c baz.c myfn.c -fvisibility=hidden编译对象,除了myfn()之外,它将所有内容标记为隐藏。

  3. 使用ld的部分链接切换创建便利归档:ld -r foo.o bar.o baz.o myfn.o -o libmyfn.a

  4. 将所有不是PUBLIC的内容本地化:objcopy --localize-hidden libmyfn.a

  5. 现在nmmyfnlibmyfn.a中唯一的全局符号,后续链接到其他程序的工作正常:gcc -o main main.c -L. -lmyfn(此处,程序调用myfn();如果它试图调用foo(),则编译将失败。

  6. 如果我在步骤3中使用ar而不是ld -r,则在步骤5中编译失败:我猜ar没有将foo等链接到{{ 1}},并且一旦这些函数被本地化,就不再可以了,而myfn在它被本地化之前解析链接。

    我欢迎任何回复确认这是"权利"方式,或描述一种实现相同目的的光滑方式。

3 个答案:

答案 0 :(得分:0)

从此开始构建静态库

gcc -c -O2 foo.c bar.c baz.c myfn.c
ar av libmyfunctions.a foo.o bar.o baz.o myfn.o

编译并链接其他程序,例如:

gcc -O2 program.c -lmyfunctions -o myprogram

现在你的libmyfunctions.a最终将从源代码中获得myfn.c中代码不需要的额外内容。但是链接器在创建最终程序时应该合理地删除它。

答案 1 :(得分:0)

不幸的是,全局变量的C链接是全有或全无的,因为所有模块的全局变量都可以在libmyfn.a的最终外部符号列表中使用。

gcc工具链提供了一个扩展程序,可让您隐藏外部用户的符号,同时将其提供给库中的其他翻译单元:

foo.h中:

void foo();

foo.c的:

void foo() __attribute__ ((visibility ("hidden")));

myfn.h:

void myfn();

myfn.c:

#include <stdio.h>
#include "foo.h"

void myfn() {
    printf("calling foo...\n");
    foo();
    printf("calling foo again...\n");
    foo();
}

为了便于移植,您可能会为__attribute__ ((visibility ("hidden")))创建一个宏,并将其置于以gcc为条件的条件编译块中。

此外,Linux提供了utility called strip,它允许您从编译的目标文件中删除一些符号。通过选项-N-K,您可以识别要保留或删除的各个符号。

答案 2 :(得分:-1)

假设myfn.c有函数myfun(),你想在其他三个文件中使用foo.c,bar.c&amp; baz.c

现在从myfn.c中的代码创建一个共享库viz libmyf.a

在其他三个文件中使用此函数调用myfun()。在这些文件中将函数声明为extern。现在,您可以创建这些文件的目标代码,并在链接阶段链接libmyf.a。

有关使用共享库的信息,请参阅以下链接。

http://www.cprogramming.com/tutorial/shared-libraries-linux-gcc.html