14

一点上下文。假设我有源文件,需要在静态库中结束。假设有两个 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。看起来不错。

问题

我可以看到的问题是,如果我ar单独运行命令foo/a.o并将bar/a.o它们放在同一个静态库中。现在后一个对象文件将覆盖前者,所以在运行时nm libfoobar.a我只在库中看到后一个对象。我猜这是由于相同的目标文件名造成的。

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

当一个a.cpp改变并且静态库需要改变时,事情将如何工作?会在图书馆ar找改权吗?a.cpp

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

一般来说,这只是库的组成方式、文件命名方式的糟糕组织,还是有其他东西可以让事情正常工作?

4

4 回答 4

7

您必须将ar其视为非常古老的文件存档器。它甚至对归档目录一无所知。(ar档案是平的)

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

man ar,选项r

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

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

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

会替换 lib.a 中的ar rcs lib.a foo/a.o bar/a.oao,但不会检查添加的文件是否存在名称冲突。

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

于 2011-02-05T14:56:24.320 回答
3

库只是函数和/或数据的集合,这些函数和/或数据恰好按库中的目标文件分组,并且这些目标文件有一个名称。这些名称除了更新/提取/删除之外没有任何作用。

因此,两个或多个目标文件有两个相同的名称是完全合法的。更新库时,图书馆员将第一个对象替换为您要替换的名称,并且不再查看。

但这并不是一件聪明的事情。

于 2011-02-05T14:14:07.980 回答
1

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

抱歉,目前手头没有unix,所以还是等高手解答吧:)

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

于 2011-02-05T13:57:40.723 回答
0

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

$ 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.

于 2021-06-12T10:13:59.213 回答