我有文件 foo.c bar.c 和 baz.c,以及定义函数 myfn() 的包装器代码 myfn.c,该函数使用其他文件中的代码和数据。
我想创建诸如目标文件或存档 myfn.o 或 libmyfn.a 之类的内容,以便 myfn() 可以供其他项目使用,而无需从 {foo,bar,baz}.o 导出大量符号以及。
在 Linux/gcc 中执行此操作的正确方法是什么?谢谢。
更新:我找到了一种方法。我本来应该强调这是关于静态档案,而不是 DSO。无论如何,食谱:
#define PUBLIC __attribute__ ((visibility("default")))
然后标记myfn()
as PUBLIC
in 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
Now nm
says myfn
是唯一的全球符号libmyfn.a
随后链接到其他程序效果很好:gcc -o main main.c -L. -lmyfn
(这里,程序调用myfn()
;如果它试图打电话foo()
那么编译就会失败)。
如果我使用ar
代替ld -r
在步骤 3 中,然后在步骤 5 中编译失败:我猜ar
尚未链接foo
etc to 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
.
此外,Linux 还提供了实用程序称为strip http://www.thegeekstuff.com/2012/09/strip-command-examples/,它允许您从编译的目标文件中删除一些符号。选项-N
and -K
让您识别要保留或删除的各个符号。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)