具有相同名称的对象文件的静态库(ar)

时间:2011-02-05 13:34:51

标签: c++ linker static-libraries ar

有点背景。假设我有源文件,需要最终在静态库中。假设有两个cpp文件a.cppa.cpp位于两个不同的子目录中。像这样:

foo/a.h
foo/a.cpp
bar/a.h
bar/a.cpp

他们的内容没有冲突,完全不同。文件名是一样的。

现在,在编译时,我最终会得到两个a.o文件。

gcc -c foo/a.cpp -o foo/a.o
gcc -c bar/a.cpp -o bar/a.o

如果我现在用

创建一个静态库
ar rcs libfoobar.a foo/a.o bar/a.o

我可以看到运行nm libfoobar.a的静态库中的两个文件。看起来很好。

问题

我可以看到的问题是,如果我为arfoo/a.o分别运行bar/a.o命令,将它们放在同一个静态库中。现在后一个目标文件将覆盖前者,因此在运行nm libfoobar.a时,我只看到库中的后一个对象。我猜这是因为相同的目标文件名。

使用ar创建静态库时,我是否应该始终将所有对象组合在一起,或者也可以多次运行ar一次收集一部分对象相同的静态库?在这个例子中,我可以看到前者的作品,但不能看到后者。

当一个a.cpp更改并且静态库需要更改时,一切如何运作? ar会在库中找到要更改的a.cpp吗?

这只是一个小例子,但考虑一个包含许多文件的大型项目,其中一些具有相同的名称。如果你现在想要创建一个库,你也可能会遇到这种情况。

一般来说,这只是组织库的组织方式,文件的命名方式或其他方面的内容,以使其有效吗?

4 个答案:

答案 0 :(得分:3)

库只是函数和/或数据的集合,恰好按库中的对象文件进行分组,并且这些对象文件具有名称。除了更新/提取/删除它们之外,这些名称不起任何作用。

因此,为两个或多个目标文件提供两个相同的名称是完全合法的。 更新库时,库管理器用您要替换的名称替换第一个对象,并且不再查看。

但这并不是一件明智的事。

答案 1 :(得分:3)

您必须将ar视为非常旧的文件存档。它甚至不知道有关归档目录的任何信息。 (档案是平的)

(man ar):ar - create, modify, and extract from archives

man ar,选项r

  

r将文件成员...插入存档(替换)。此操作与q的不同之处在于,如果其名称与添加的名称相匹配,则删除任何以前存在的成员

尝试运行ar t libfoobar.a并且您只会看到a.o个文件,因为ar没有在存档中存储目录名称。

因此,如果要使用ar 对库中的某些目标文件进行更新,则必须以不同方式命名所有在ar存档中放置的目标文件(UPD)

ar rcs lib.a foo/a.o bar/a.o替换了lib.a中找到的a.o,但它没有检查添加的文件是否存在名称冲突。

其他情况:ar rcs lib.a foo/a.oar rcs lib.a bar/a.o会在归档中存储第一个ao,然后第二个ar会在归档中找到旧a.o并替换旧文件

答案 2 :(得分:1)

我只能解决你问题的一部分问题。从Makefile语法中我们看到它曾经是一种常规方式 - 只更新一个对象。但是,例如,即使一个文件被更改,automake的方法也是从头开始重建库。它现在不会造成大问题......

很抱歉,目前没有手头的unix,所以我们仍然会等待专家回答:)

根据我自己的经验,我不建议在静态库中使用两个具有相同名称的文件。

答案 3 :(得分:0)

GNU ar 修复了这个问题。手册页很好地解释了它:

$ man ar | sed -n '/^       P /,/^       \w/p' | head -n -1;
       P   Use the full path name when matching or storing names in the
           archive.  Archives created with full path names are not POSIX
           compliant, and thus may not work with tools other than up to date
           GNU tools.  Modifying such archives with GNU ar without using P
           will remove the full path names unless the archive is a thin
           archive.  Note that P may be useful when adding files to a thin
           archive since r without P ignores the path when choosing which
           element to replace.  Thus

                   ar rcST archive.a subdir/file1 subdir/file2 file1

           will result in the first "subdir/file1" being replaced with "file1"
           from the current directory.  Adding P will prevent this
           replacement.