静态档案中的 C 符号可见性
C symbol visibility in static archives
我有文件 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.c
中将 myfn()
标记为 PUBLIC
。不要标记其他任何东西 PUBLIC
.
使用 gcc -c foo.c bar.c baz.c myfn.c -fvisibility=hidden
编译对象,这会将除 myfn()
.
之外的所有内容标记为隐藏
使用 ld
的 partial-linking 开关创建方便的存档:ld -r foo.o bar.o baz.o myfn.o -o libmyfn.a
本地化不是 PUBLIC
的所有内容,像这样:objcopy --localize-hidden libmyfn.a
现在 nm
说 myfn
是 libmyfn.a
中唯一的全局符号,随后 linking 到其他程序中工作得很好:gcc -o main main.c -L. -lmyfn
(这里,程序调用 myfn()
;如果它试图调用 foo()
,那么编译将失败)。
如果我在第 3 步中使用 ar
而不是 ld -r
,那么在第 5 步中编译会失败:我猜 ar
还没有 linked foo
等到 myfn
,一旦这些函数被本地化就不再可以,而 ld -r
在它被本地化之前解析 link。
我欢迎任何确认这是 "right" 方式或描述实现相同方式的更巧妙方式的回复。
假设 myfn.c 有函数 myfun(),你想在其他三个文件 foo.c、bar.c & baz.c
中使用它
现在从 myfn.c 中的代码创建一个共享库,即 libmyf.a
在其他三个文件中使用此函数调用myfun()。在这些文件中将函数声明为 extern。现在您可以在 linking 阶段创建这些文件和 link libmyf.a 的目标代码。
参考以下link使用共享库。
http://www.cprogramming.com/tutorial/shared-libraries-linux-gcc.html
从这里开始构建静态库
gcc -c -O2 foo.c bar.c baz.c myfn.c
ar av libmyfunctions.a foo.o bar.o baz.o myfn.o
编译并link使用其他程序,例如:
gcc -O2 program.c -lmyfunctions -o myprogram
现在你的 libmyfunctions.a
最终会从源代码中获得额外的东西,而 myfn.c 中的代码不需要这些东西但是 link 开发者应该合理地删除它当它创建最终程序时。
不幸的是,全局变量的 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
可让您识别要保留或删除的单个符号。
我有文件 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.c
中将myfn()
标记为PUBLIC
。不要标记其他任何东西PUBLIC
.使用
gcc -c foo.c bar.c baz.c myfn.c -fvisibility=hidden
编译对象,这会将除myfn()
. 之外的所有内容标记为隐藏
使用
ld
的 partial-linking 开关创建方便的存档:ld -r foo.o bar.o baz.o myfn.o -o libmyfn.a
本地化不是
PUBLIC
的所有内容,像这样:objcopy --localize-hidden libmyfn.a
现在
nm
说myfn
是libmyfn.a
中唯一的全局符号,随后 linking 到其他程序中工作得很好:gcc -o main main.c -L. -lmyfn
(这里,程序调用myfn()
;如果它试图调用foo()
,那么编译将失败)。
如果我在第 3 步中使用 ar
而不是 ld -r
,那么在第 5 步中编译会失败:我猜 ar
还没有 linked foo
等到 myfn
,一旦这些函数被本地化就不再可以,而 ld -r
在它被本地化之前解析 link。
我欢迎任何确认这是 "right" 方式或描述实现相同方式的更巧妙方式的回复。
假设 myfn.c 有函数 myfun(),你想在其他三个文件 foo.c、bar.c & baz.c
中使用它现在从 myfn.c 中的代码创建一个共享库,即 libmyf.a
在其他三个文件中使用此函数调用myfun()。在这些文件中将函数声明为 extern。现在您可以在 linking 阶段创建这些文件和 link libmyf.a 的目标代码。
参考以下link使用共享库。
http://www.cprogramming.com/tutorial/shared-libraries-linux-gcc.html
从这里开始构建静态库
gcc -c -O2 foo.c bar.c baz.c myfn.c
ar av libmyfunctions.a foo.o bar.o baz.o myfn.o
编译并link使用其他程序,例如:
gcc -O2 program.c -lmyfunctions -o myprogram
现在你的 libmyfunctions.a
最终会从源代码中获得额外的东西,而 myfn.c 中的代码不需要这些东西但是 link 开发者应该合理地删除它当它创建最终程序时。
不幸的是,全局变量的 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
可让您识别要保留或删除的单个符号。