静态存档中的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。无论如何,配方:
$ b $ ol #define PUBLIC __attribute__((visibility(default)))
然后在 myfn.c中将
。不要标记任何东西 myfn()
标记为 PUBLIC
PUBLIC
。
编译对象gcc - c foo.c bar.c baz.c myfn.c -fvisibility = hidden
,除了 myfn()
以外, / p> 使用 ld
的部分链接开关创建一个便捷存档: ld -r foo.o bar.o baz.o myfn.o -o libmyfn.a
本地化所有不是 PUBLIC
就像这样: objcopy --localize-hidden libmyfn.a
nm
表示 myfn
是 libmyfn中唯一的全局符号.a
并且随后链接到其他程序中工作得很好: gcc -o main main.c -L。 -lmyfn
(这里,程序调用 myfn()
;如果它试图调用 foo()$ c
如果我使用 ar $ c,那么编译就会失败)。
$ c>代替 ld -r
在步骤3中,那么编译在步骤5中失败:我猜想 ar
没有将 foo
等链接到 myfn
,并且不再能够一旦这些函数被本地化,而 ld
我欢迎任何回应,证实这是正确的的方式,或描述一种实现相同的方式。 解决方案
- 或者什么都没有,因为所有模块的全局变量都可以在 libmyfn.a
的外部符号的最终列表中找到。
gcc
工具链提供了一个扩展,可让您从外部用户中隐藏符号,同时使其可用到您图书馆的其他翻译单元:
foo.h:
void foo();
foo.c:
void foo()__attribute__((visibility(hidden)));
myfn.h:
void myfn();
myfn.c:
#include< stdio.h>
#includefoo.h
void myfn(){
printf(calling foo ... \\\
);
foo();
printf(再次调用foo ... \\\
);
foo();
}
为便于携带,您可能会从为 __ attribute__((visibility(hidden)))
,并将它放在一个以 gcc
为条件的条件编译块中。
另外,Linux提供了一个实用程序称为 strip
,它可以让你从编译目标文件中删除一些符号。选项 -N
和 -K
可让您识别要保留或移除的单个符号。
I have files foo.c bar.c and baz.c, plus wrapper code myfn.c defining a function myfn() that uses code and data from those other files.
I would like to create something like an object file or archive, myfn.o or libmyfn.a, so that myfn() can be made available to other projects without also exporting a load of symbols from {foo,bar,baz}.o as well.
What's the right way to do that in Linux/gcc? Thanks.
Update: I've found one way of doing it. I should've emphasised originally that this was about static archives, not DSOs. Anyway, the recipe:
#define PUBLIC __attribute__ ((visibility("default")))
then markmyfn()
asPUBLIC
inmyfn.c
. Don't mark anything elsePUBLIC
.Compile objects with
gcc -c foo.c bar.c baz.c myfn.c -fvisibility=hidden
, which marks everything as hidden except formyfn()
.Create a convenience archive using
ld
's partial-linking switch:ld -r foo.o bar.o baz.o myfn.o -o libmyfn.a
Localise everything that wasn't
PUBLIC
like so:objcopy --localize-hidden libmyfn.a
Now
nm
saysmyfn
is the only global symbol inlibmyfn.a
and subsequent linking into other programs works just fine:gcc -o main main.c -L. -lmyfn
(here, the program callsmyfn()
; if it tried to callfoo()
then compilation would fail).
If I use ar
instead of ld -r
in step 3 then compilation fails in step 5: I guess ar
hasn't linked foo
etc to myfn
, and no longer can once those functions are localised, whereas ld -r
resolves the link before it gets localised-away.
I'd welcome any response that confirms this is the "right" way, or describes a slicker way of achieving the same.
Unfortunately, C linkage for globals is all-or-nothing, in the sense that the globals of all modules would be available in libmyfn.a
's final list of external symbols.
gcc
tool chain offers an extension that lets you hide symbols from outside users, while making them available to other translation units in your library:
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();
}
For portability, you would probably benefit from making a macro for __attribute__ ((visibility ("hidden")))
, and placing it in a conditional compilation block conditioned on gcc
.
In addition, Linux offers a utility called strip
, which lets you remove some of the symbols from compiled object files. Options -N
and -K
let you identify individual symbols that you want to keep or remove.
这篇关于静态存档中的C符号可见性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!