Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/tfs/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C .a中的对象文件不包括在.so中_C_Linux_Gcc_Shared Libraries - Fatal编程技术网

C .a中的对象文件不包括在.so中

C .a中的对象文件不包括在.so中,c,linux,gcc,shared-libraries,C,Linux,Gcc,Shared Libraries,我创建了一个.c文件,该文件正在转换为.o文件,以及大约300个其他.c文件,并包含在.a静态库中。这个库和其他许多库一起被用来创建。所以动态库。通过对.a和.so文件进行nm分析,我发现由于某种原因,.c文件中定义的符号存在于.a文件中,而不存在于.so文件中。我想不出发生这种事的理由。谁能帮帮我吗?创建这两个二进制文件的步骤如下: gcc -fvisibility=hidden -c foo.c -o foo.c.o ar cr libbar.a foo.c.o ... gcc -fvisi

我创建了一个
.c
文件,该文件正在转换为
.o
文件,以及大约300个其他
.c
文件,并包含在
.a
静态库中。这个库和其他许多库一起被用来创建
。所以
动态库。通过对
.a
.so
文件进行
nm
分析,我发现由于某种原因,
.c
文件中定义的符号存在于
.a
文件中,而不存在于
.so
文件中。我想不出发生这种事的理由。谁能帮帮我吗?创建这两个二进制文件的步骤如下:

gcc -fvisibility=hidden -c foo.c -o foo.c.o
ar cr libbar.a foo.c.o ...
gcc -fvisibility=hidden -fPIC -o libfinal.so libbar.a x.o y.a ... 
我在这里指定隐藏可见性的原因是我只想公开几个选定的符号。要公开
foo.c
中的符号,我已指定可见性属性,以便标题
foo.h
中的函数签名如下所示:

extern int属性(可见性(“默认”))func()

编辑:命令
nm libbar.a | grep Ctx
给出:

000023c5 T CtxAcquireBitmap
000026e9 T CtxAcquireArray
00001e77 T CtxCallMethod
但是,
nm libfinal.so | grep Ctx
没有显示任何内容

更新:找到另一个讨论
--whole archive
选项用法的文件。此外,还偶然发现了
--export dynamic
选项,该选项显然告诉链接器保留未引用的符号。进一步调查。

尝试使用
--whole archive
链接器选项在链接时将所有对象包含到共享库中

gcc -o libfinal.so -Wl,--whole-archive libbar.a x.o y.a -Wl,--no-whole-archive
手册ld

--整个归档文件
对于命令行中--whole archive选项之后提到的每个归档,请在 链接,而不是在存档中搜索所需的对象文件。这通常用于将存档文件转换为共享文件 库,强制将每个对象包括在生成的共享库中。此选项可多次使用

使用gcc中的此选项时需要注意两个问题:首先,gcc不知道此选项,所以必须使用-Wl,-whole archive。 其次,不要忘记在您的归档列表之后使用-Wl,-no-whole archive,因为gcc会将自己的归档列表添加到您的 链接,您可能不希望此标志也影响这些


据我所知,在对a.a进行编译时,gcc只会提取其他模块引用的对象。如果您的目的是将.a的全部内容包含在.so中,那么简单的“使用libbar.a中的内容将x.c编译/链接到libfinal.so”并不是您想要的。为我的主文件中所需的符号创建虚拟引用并不能解决问题。引用符号出现在二进制转储中(使用
nm
获得),带有
U
(=未定义)标记。我通过在创建
.so
文件时直接链接对象文件,而不是首先将其包含在
.a
库中,成功地解决了这个问题。由于这些函数被标记为
extern
,因此它们被包含在
中。因此
即使它们没有在库中被引用。如果它们没有被标记为
extern
,它们就不会像sylvainulg所说的那样被包括在内


感谢Dmitry指出了
--whole archive
选项。我不知道有这样一个选项。

你能给我们看一下
nm
的一些输出,让我们看清楚区别吗?我们还可以看到这些符号的“类型”消失了。
-fPIC
选项只在编译时生效,而不是在链接时生效。因此,除非在编译时使用
-fPIC
,否则最终将得到一个非PIC共享库。这意味着每个实例将使用更多的内存(大部分页面无法共享),甚至在某些系统(如x86_64)上也无法工作。用信息更新了问题。@sylvainulg给出的答案告诉您出了什么问题。如果您没有在任何地方使用任何可见性属性,您仍然会遇到同样的问题。那么,我如何包括要导出供另一个
。So
或可执行文件使用但未在
中引用的符号。So
?使用导出文件不是一个选项。是的,就是这样。在我的系统上的gcc 4.3.2手册页中,“链接器通过扫描归档文件中定义符号的成员来处理归档文件,这些符号到目前为止已被引用但尚未定义。但是,如果找到的文件是普通对象文件,则以通常的方式链接。”我很想说,生成.a和.so的最常见方法是从.o文件集合中构建它们,而不是从另一个文件中构建一个。说得好。在两个标记中包含这个
.a
,这将非常复杂,尽管我的项目使用
CMake
。必须想办法在项目限制范围内做到这一点。谢谢。我个人会谨慎使用--整个存档(也就是说,使用objdump&nm仔细检查输出),因为我不确定如果试图链接“标准”库,链接器会做什么。只包括--整个存档和--没有整个存档应该是安全的,不需要包括标准库