gpt4 book ai didi

静态文件中的 C 符号可见性

转载 作者:太空宇宙 更新时间:2023-11-04 00:10:43 25 4
gpt4 key购买 nike

我有文件 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() 标记为 PUBLICmyfn.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(),则编译将失败)。

    <

如果我在第 3 步中使用 ar 而不是 ld -r,那么在第 5 步中编译会失败:我猜 ar 还没有链接foo 等到 myfn,一旦这些函数被本地化就不再可以,而 ld -r 在链接被本地化之前解析链接。

我欢迎任何确认这是“正确”方法或描述实现相同方法的更巧妙方法的回复。

最佳答案

不幸的是,全局变量的 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 为条件的条件编译 block 中.

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

关于静态文件中的 C 符号可见性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39981491/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com