3

我正在构建 .so 库并且想知道 - b/w -h 和 -o cc 编译器选项(使用 Sun Studio C++)有什么区别?

他们不是指的是同一个东西 - 输出文件的名称吗?

4

3 回答 3

5

-o是编译器将写入磁盘的文件名

-h是将记录在链接到此文件的 ELF 二进制文件中的名称。

一种常见用途是提供库次要版本号。例如,如果您正在创建共享库 libfoo,您可能会这样做:

cc -o libfoo.so.1.0 -h libfoo.so.1 *.o
ln -s libfoo.so.1.0 libfoo.so.1
ln -s libfoo.so libfoo.so.1

然后,如果您编译您的 hello world 应用程序并使用

cc -o hello -lfoo

hello 的 elf 二进制文件将记录一个NEEDED条目libfoo.so.1(您可以通过运行来查看elfdump -d hello)。

然后,当您稍后需要添加新功能时,您可以将-o值更改为 libfoo.so.1.1但保留 -h libfoo.so.1- 您已经使用 1.0 构建的所有程序仍会尝试libfoo.so.1在运行时加载,因此无需重新构建即可继续工作,但您会通过 ls 看到它是 1.1。

如果您没有单独的安装目录或通过打包系统安装,则有时也会在它们在运行时使用的同一目录中构建库时使用。为了避免覆盖库二进制文件时正在运行的程序崩溃,并避免在构建过程中程序无法启动,一些 Makefile 会这样做:

cc -o libfoo.so.1.new -h libfoo.so.1 *.o
rm libfoo.so.1 ; mv libfoo.so.1.new libfoo.so.1

(由 X 中的旧 Imake makefile 生成器构建的 Makefile 通常会这样做。)

于 2009-12-10T01:20:40.890 回答
2

他们指的是不同的名字。具体来说,该-o选项是文件的实际名称 - 文件系统上的名称。该-h选项在最终目标文件中设置内部。 DT_SONAME这是其他模块在内部引用共享对象的名称。ldd我相信这是您在链接到它的对象上运行时也会看到的名称。

于 2009-12-10T01:17:36.840 回答
1

-o 选项将命名输出文件,而 -h 选项将在库中设置一个内在名称。当动态加载器使用这个内在名称时,它优先于文件名,并允许它使用预定义的规则来查看正确的库。

您可以使用该命令查看给定库中记录的内在名称:

elfdump -d xxx.so | grep SONAME

在这里查看详细信息:

http://docs.oracle.com/cd/E23824_01/html/819-0690/chapter4-97194.html

于 2009-12-10T02:04:52.273 回答