我有文件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()
中将PUBLIC
标记为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
现在nm
说myfn
是libmyfn.a
中唯一的全局符号,后续链接到其他程序的工作正常:gcc -o main main.c -L. -lmyfn
(此处,程序调用myfn()
;如果它试图调用foo()
,则编译将失败。
如果我在步骤3中使用ar
而不是ld -r
,则在步骤5中编译失败:我猜ar
没有将foo
等链接到{{ 1}},并且一旦这些函数被本地化,就不再可以了,而myfn
在它被本地化之前解析链接。
我欢迎任何回复确认这是"权利"方式,或描述一种实现相同目的的光滑方式。
答案 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